K1Guitar/device/AD85020B/Drv_AD85020B.c

318 lines
9.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: CTW
* @Date: 2025-11-07 14:37:55
* @FilePath: \PhoenixSMGT_Testproject\Drivers\AD85050\Drv_AD85020B.c
* @note: 从 STM32 HAL 库移植到 AT32F403A。
* 同时保留硬件 I2C1官方 i2c_application 库)与软件 GPIO I2C 两套实现,
* 由头文件 AD85020B_I2C_USE_HW 宏选择1=硬件0=软件)。
* - HAL_I2C_Mem_Write -> i2c_memory_write / 软件时序
* - HAL_Delay -> wk_delay_ms
* - HAL_StatusTypeDef -> AD85020B_StatusTypeDef
*/
#include "Drv_AD85020B.h"
#include "wk_system.h"
#include <stdio.h>
/* =====================================================================
* 硬件 I2C1 实现AD85020B_I2C_USE_HW = 1
* 依赖官方 i2c_application 库middlewares/i2c_application_library
* ===================================================================== */
#if AD85020B_I2C_USE_HW
#include "i2c_application.h"
#include "includes.h"
static void AD85020B_I2C_InitImpl(void)
{
wk_i2c1_init();
// gpio_init_type g;
//
// /* 使能 GPIOB / I2C1 时钟 */
// crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
// crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
//
// /* PB6=SCL, PB7=SDA复用开漏 + 上拉 */
// gpio_default_para_init(&g);
// g.gpio_mode = GPIO_MODE_MUX;
// g.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
// g.gpio_pull = GPIO_PULL_UP;
// g.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
// g.gpio_pins = AD85020B_SCL_PIN;
// gpio_init(AD85020B_I2C_PORT, &g);
// g.gpio_pins = AD85020B_SDA_PIN;
// gpio_init(AD85020B_I2C_PORT, &g);
//
// /* I2C1 主机 100kHz */
// i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 100000);
// i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0);
// i2c_ack_enable(I2C1, TRUE);
// i2c_clock_stretch_enable(I2C1, TRUE);
// i2c_general_call_enable(I2C1, FALSE);
// i2c_enable(I2C1, TRUE);
}
static AD85020B_StatusTypeDef AD85020B_I2C_WriteImpl(uint8_t reg, uint8_t data)
{
i2c_handle_type hi2c;
i2c_status_type status;
uint8_t buf = data;
hi2c.i2cx = I2C1;
/* i2c_memory_write: START → 器件地址+W → 寄存器(8bit) → 数据 → STOP
地址传 8 位写地址 0x60库内部 &0xFE 保持为写) */
status = i2c_memory_write(&hi2c,
I2C_MEM_ADDR_WIDIH_8,
AD85020B_I2C_ADDR_W,
reg, &buf, 1,
AD85020B_I2C_TIMEOUT);
if (status != I2C_OK)
{
printf("[AD85020B] HW_Write fail ret=0x%X inner=0x%X\r\n",
(unsigned)status, (unsigned)hi2c.error_code);
return AD85020B_ERROR;
}
return AD85020B_OK;
}
static AD85020B_StatusTypeDef AD85020B_I2C_ReadImpl(uint8_t reg, uint8_t *data)
{
i2c_handle_type hi2c;
i2c_status_type status;
if (data == 0) return AD85020B_ERROR;
hi2c.i2cx = I2C1;
/* i2c_memory_read: START → 地址+W → 寄存器 → RESTART → 地址+R → 数据 → STOP
地址传 8 位写地址 0x60库内部读阶段自动 |0x01 成 0x61 */
status = i2c_memory_read(&hi2c,
I2C_MEM_ADDR_WIDIH_8,
AD85020B_I2C_ADDR_W,
reg, data, 1,
AD85020B_I2C_TIMEOUT);
if (status != I2C_OK)
{
printf("[AD85020B] HW_Read fail ret=0x%X inner=0x%X\r\n",
(unsigned)status, (unsigned)hi2c.error_code);
return AD85020B_ERROR;
}
return AD85020B_OK;
}
/* =====================================================================
* 软件 I2C 实现AD85020B_I2C_USE_HW = 0
* 不依赖硬件 I2C 外设,纯 GPIO 位翻转
* ===================================================================== */
#else
#define I2C_DELAY() { volatile uint32_t i = 8; while (i--); }
static void SCL_High(void) { gpio_bits_set(AD85020B_I2C_PORT, AD85020B_SCL_PIN); }
static void SCL_Low(void) { gpio_bits_reset(AD85020B_I2C_PORT, AD85020B_SCL_PIN); }
static void SDA_High(void) { gpio_bits_set(AD85020B_I2C_PORT, AD85020B_SDA_PIN); }
static void SDA_Low(void) { gpio_bits_reset(AD85020B_I2C_PORT, AD85020B_SDA_PIN); }
static uint8_t SDA_Read(void)
{
return (gpio_input_data_bit_read(AD85020B_I2C_PORT, AD85020B_SDA_PIN) == SET) ? 1 : 0;
}
static void I2C_Start(void)
{
SDA_High(); SCL_High(); I2C_DELAY();
SDA_Low(); I2C_DELAY();
SCL_Low(); I2C_DELAY();
}
static void I2C_Stop(void)
{
SDA_Low(); SCL_High(); I2C_DELAY();
SDA_High(); I2C_DELAY();
}
static uint8_t I2C_SendByte(uint8_t data)
{
uint8_t i, ack;
for (i = 0; i < 8; i++)
{
if (data & 0x80) SDA_High(); else SDA_Low();
data <<= 1;
I2C_DELAY();
SCL_High(); I2C_DELAY();
SCL_Low(); I2C_DELAY();
}
SDA_High(); I2C_DELAY();
SCL_High(); I2C_DELAY();
ack = SDA_Read();
SCL_Low(); I2C_DELAY();
return ack;
}
static uint8_t I2C_RecvByte(uint8_t ack)
{
uint8_t i, data = 0;
SDA_High();
for (i = 0; i < 8; i++)
{
SCL_High(); I2C_DELAY();
data = (data << 1) | SDA_Read();
SCL_Low(); I2C_DELAY();
}
if (ack) SDA_High(); else SDA_Low();
I2C_DELAY();
SCL_High(); I2C_DELAY();
SCL_Low(); I2C_DELAY();
SDA_High(); I2C_DELAY();
return data;
}
static void AD85020B_I2C_InitImpl(void)
{
gpio_init_type g;
gpio_default_para_init(&g);
g.gpio_mode = GPIO_MODE_OUTPUT;
g.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
g.gpio_pull = GPIO_PULL_UP;
g.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
g.gpio_pins = AD85020B_SCL_PIN;
gpio_init(AD85020B_I2C_PORT, &g);
g.gpio_pins = AD85020B_SDA_PIN;
gpio_init(AD85020B_I2C_PORT, &g);
SDA_High();
SCL_High();
}
static AD85020B_StatusTypeDef AD85020B_I2C_WriteImpl(uint8_t reg, uint8_t data)
{
I2C_Start();
if (I2C_SendByte(AD85020B_I2C_ADDR_W)) { printf("[AD85020B] SW ADDR_NACK\r\n"); return AD85020B_ERROR; }
if (I2C_SendByte(reg)) { printf("[AD85020B] SW REG_NACK reg=0x%02X\r\n", reg); return AD85020B_ERROR; }
if (I2C_SendByte(data)) { printf("[AD85020B] SW DATA_NACK\r\n"); return AD85020B_ERROR; }
I2C_Stop();
return AD85020B_OK;
}
static AD85020B_StatusTypeDef AD85020B_I2C_ReadImpl(uint8_t reg, uint8_t *data)
{
if (data == 0) return AD85020B_ERROR;
I2C_Start();
if (I2C_SendByte(AD85020B_I2C_ADDR_W)) return AD85020B_ERROR;
if (I2C_SendByte(reg)) return AD85020B_ERROR;
I2C_Start();
if (I2C_SendByte(AD85020B_I2C_ADDR_R)) return AD85020B_ERROR;
*data = I2C_RecvByte(1);
I2C_Stop();
return AD85020B_OK;
}
#endif /* AD85020B_I2C_USE_HW */
/* =====================================================================
* 对外统一接口(按宏分发到硬件/软件实现)
* ===================================================================== */
void AD85020B_I2C_Init(void)
{
AD85020B_I2C_InitImpl();
}
AD85020B_StatusTypeDef AD85020B_I2C_Write(uint8_t reg, uint8_t data)
{
return AD85020B_I2C_WriteImpl(reg, data);
}
AD85020B_StatusTypeDef AD85020B_I2C_Read(uint8_t reg, uint8_t *data)
{
return AD85020B_I2C_ReadImpl(reg, data);
}
/**
* @brief AD85020B 初始化
* @retval AD85020B_StatusTypeDef: 初始化结果
*/
AD85020B_StatusTypeDef AD85020B_Init(void)
{
AD85020B_StatusTypeDef status;
uint8_t vol = 0x2c;
AD85020B_I2C_Init();
wk_delay_ms(1); // 文档要求 AMP_SDB 拉高后延时≥20ms
/* 步骤2软件复位文档SCTL6寄存器BIT5=0 */
status = AD85020B_I2C_Write(AD85020B_REG_SCTL6, AD85020B_SW_RESET);
if (status != AD85020B_OK) return status;
wk_delay_ms(20); // 等待复位完成文档未明确建议10~50ms
/* 步骤3复位后恢复正常模式BIT5=1 */
status = AD85020B_I2C_Write(AD85020B_REG_SCTL6, AD85020B_SW_NORMAL);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
/* 步骤4配置输入格式文档SCTL1默认I2S格式0x00 */
status = AD85020B_I2C_Write(AD85020B_REG_SCTL1, 0x00);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
// /* 步骤5配置采样率文档SCTL2默认0x9144.1/48kHz64x BCLK */
// status = AD85020B_I2C_Write(AD85020B_REG_SCTL2, 0x91);
// if (status != AD85020B_OK) return status;
// wk_delay_ms(10);
/* 步骤7设置主音量文档MVOL0x18对应0dB避免过载 */
status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(AD85020B_REG_MVOL, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(AD85020B_REG_HEADPHONEVOL, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
/* 步骤8设置通道音量0x04~0x090x18对应0dB避免过载 */
status = AD85020B_I2C_Write(0x04, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(0x05, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(0x06, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(0x07, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(0x08, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
status = AD85020B_I2C_Write(0x09, vol);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
/* 步骤6解除静音文档SCTL3MMUTE=00x00 */
status = AD85020B_I2C_Write(AD85020B_REG_SCTL3, 0x00);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
return AD85020B_OK;
}