K1Guitar/device/AD85020B/Drv_AD85020B.c

382 lines
12 KiB
C
Raw 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);
}
static AD85020B_StatusTypeDef AD85020B_RamWaitClear(uint8_t mask)
{
uint8_t i;
uint8_t st;
for (i = 0U; i < 20U; i++)
{
if (AD85020B_I2C_Read(AD85020B_REG_CFRW, &st) != AD85020B_OK)
return AD85020B_ERROR;
if ((st & mask) == 0U)
return AD85020B_OK;
wk_delay_ms(1);
}
return AD85020B_TIMEOUT;
}
/* 手册:CFA 只收 7 位;表中 0xA0~0xAE 与 CH1 同址、靠 RBS 分 bank。
Channel-2 EQ16/17/18 用 bank=1。 */
AD85020B_StatusTypeDef AD85020B_RamWrite24(uint8_t ram_addr, uint8_t bank, uint32_t value)
{
uint8_t cfrw;
if (AD85020B_I2C_Write(AD85020B_REG_CFA, (uint8_t)(ram_addr & 0x7FU)) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_I2C_Write(AD85020B_REG_A1_T, (uint8_t)((value >> 16) & 0xFFU)) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_I2C_Write(AD85020B_REG_A1_M, (uint8_t)((value >> 8) & 0xFFU)) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_I2C_Write(AD85020B_REG_A1_B, (uint8_t)(value & 0xFFU)) != AD85020B_OK)
return AD85020B_ERROR;
cfrw = (uint8_t)(AD85020B_CFRW_W1 | (bank ? AD85020B_CFRW_RBS : 0U));
if (AD85020B_I2C_Write(AD85020B_REG_CFRW, cfrw) != AD85020B_OK)
return AD85020B_ERROR;
return AD85020B_RamWaitClear(AD85020B_CFRW_W1);
}
AD85020B_StatusTypeDef AD85020B_RamRead24(uint8_t ram_addr, uint8_t bank, uint32_t *value)
{
uint8_t cfrw;
uint8_t hi, mid, lo;
if (value == 0)
return AD85020B_ERROR;
if (AD85020B_I2C_Write(AD85020B_REG_CFA, (uint8_t)(ram_addr & 0x7FU)) != AD85020B_OK)
return AD85020B_ERROR;
cfrw = (uint8_t)(AD85020B_CFRW_R1 | (bank ? AD85020B_CFRW_RBS : 0U));
if (AD85020B_I2C_Write(AD85020B_REG_CFRW, cfrw) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_RamWaitClear(AD85020B_CFRW_R1) != AD85020B_OK)
return AD85020B_TIMEOUT;
if (AD85020B_I2C_Read(AD85020B_REG_A1_T, &hi) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_I2C_Read(AD85020B_REG_A1_M, &mid) != AD85020B_OK)
return AD85020B_ERROR;
if (AD85020B_I2C_Read(AD85020B_REG_A1_B, &lo) != AD85020B_OK)
return AD85020B_ERROR;
*value = ((uint32_t)hi << 16) | ((uint32_t)mid << 8) | (uint32_t)lo;
return AD85020B_OK;
}
/**
* @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,默认0x91:44.1/48kHz,64x BCLK) */
// status = AD85020B_I2C_Write(AD85020B_REG_SCTL2, 0x91);
// if (status != AD85020B_OK) return status;
// wk_delay_ms(10);
/* 步骤7:设置主音量(文档MVOL,0x18对应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~0x09,0x18对应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:解除静音(文档SCTL3,MMUTE=0,0x00) */
status = AD85020B_I2C_Write(AD85020B_REG_SCTL3, 0x00);
if (status != AD85020B_OK) return status;
wk_delay_ms(10);
return AD85020B_OK;
}