类比半导体ADX923驱动

发布时间 2023-09-07 11:03:52作者: xuyuntong
#include "adx923q.h"
#define PI 3.1415926
uint8_t FIFO_Depth = 10;
Ac_Loff_Data_Format ADX92XQ_Acloff_Data = {0};
Data_Format ADX92XQ_Data_Buff = {0};
extern SPI_HandleTypeDef hspi1;
uint16_t lead_count = 1, sin_flag = 0, cos_flag = 0, adc_flag = 0;
extern uint8_t Pace_Mode_Flag;

#pragma - O0
void Delayus(uint16_t a)
{
	a = a * 5;
	while (a--)
		;
}
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
	uint64_t CH1_IQDEM_AMP = 0, CH2_IQDEM_AMP = 0;

	Delayus(4);
	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
	ADX92XQ_ReadData_fifo();
	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
}
void ADX92XQ_AC_Leadoff_Init(uint32_t threshold)
{
	uint8_t hold_buf[3] = {0x00, 0x00, 0x00};
	hold_buf[0] = threshold & 0xff;
	hold_buf[1] = (threshold & 0xff00) >> 8;
	hold_buf[2] = (threshold & 0xff0000) >> 16;
	ADX92XQ_REG(ADX92XQ_WREG | LOFF, FLEAD_OFF_AC);
	ADX92XQ_REG(ADX92XQ_WREG | GPIO, AC_AMP_SCALE_DIV8);
	ADX92XQ_REG(ADX92XQ_WREG | CONFIG3, AC_MODE_HARD);
	ADX92XQ_REG(ADX92XQ_WREG | LOFF_RLD, EMUX2_VDD_CON_P | EMUX2_VSS_CON_N);
	ADX92XQ_REG(ADX92XQ_WREG | LOFF_AC1, SQUARE_WAVE_SIN | ACDIV_FACTOR | ACDIV_FRQ4KHz);
	ADX92XQ_REG(ADX92XQ_WREG | LON_CFG, DEBOUNCE_117 | AC_EXCT_THD_20nA); //
	ADX92XQ_REG(ADX92XQ_WREG | EPMIX_CFG, AC_CMP_CFG_AC_24 | FSEL_1024K); //
	ADX92XQ_REG_Stream(ADX92XQ_WREG, AC_CMP_THD0, 3, hold_buf);
}
uint8_t ADX92XQ_Init(void)
{
	uint8_t device_id;
	DVDD_EN(GPIO_PIN_SET);
	AVCC_EN(GPIO_PIN_SET);
	XTAL_DIS;
	InternalCLK;
	NSS_H;
	PWDN_H;
	START_L;
	HAL_Delay(10);
	PWDN_L;
	HAL_Delay(30);
	PWDN_H;
	HAL_Delay(30);
	ADX92XQ_CMD(ADX92XQ_SDATAC);
	device_id = ADX92XQ_REG(ADX92XQ_RREG | ECG_ID, 0X00);
	AUTO_Printf(" device_id = 0X%02X \r\n", device_id);
	while (device_id != 0xF3)
	{
		device_id = ADX92XQ_REG(ADX92XQ_RREG | ECG_ID, 0X00);
		HAL_Delay(20);
	}
	return device_id;
}
void ADX92XQ_Config(void)
{
	uint8_t reg_data[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, RESP_CLK_HALF_DIV2};//呼吸时钟减半

	ADX92XQ_CMD(ADX92XQ_SDATAC);
	/********SYSTEM********/
	ADX92XQ_REG_Stream(ADX92XQ_WREG, AC_CMP_THD0, 10, reg_data); //流写入后10个寄存器
	ADX92XQ_REG(ADX92XQ_WREG | CONFIG2, 0X80 | PDB_REFBUF_EN | PDB_LOFF_COMP_EN);
	ADX92XQ_REG(ADX92XQ_WREG | GPIO, GPIO2_IN | GPIO1_IN);
	ADX92XQ_REG(ADX92XQ_WREG | LON_CFG, DEBOUNCE_117);//LEAD OFF开启 117ms滤波器
	ADX92XQ_REG(ADX92XQ_WREG | ERM_CFG, WMODE);
	ADX92XQ_REG(ADX92XQ_WREG | EPMIX_CFG, FSEL_1024K);//配置系统时钟为1024K
	/********ADC********/
	ADX92XQ_REG(ADX92XQ_WREG | CONFIG1, DR_250); // 1024K时钟下的500sps
	ADX92XQ_REG(ADX92XQ_WREG | CH1SET, PD_EN | GAIN6 | MUX_NORMAL);
	ADX92XQ_REG(ADX92XQ_WREG | CH2SET, PD_EN | GAIN6 | MUX_NORMAL);
	ADX92XQ_REG(ADX92XQ_WREG | RLD_SENS, PDB_RLD_EN | RLD1N_CON | RLD1P_CON); //RLD打开并连接至CH1
	/********LEAD OFF********/
	ADX92XQ_REG(ADX92XQ_WREG | LOFF, 0xfd & (COMP_TH_70 | 0x10));// DC LEAD OFF比较器阈值
	ADX92XQ_REG(ADX92XQ_WREG | LOFF_SENSE, EMUX1_VSS_CON_P | EMUX1_VDD_CON_N);
	ADX92XQ_REG(ADX92XQ_WREG | LOFF_RLD, EMUX2_VSS_CON_P | EMUX2_VDD_CON_N);
	ADX92XQ_REG(ADX92XQ_WREG | LOFF_ISETP, CUR_LEVEL_EN | ISTEP_nA(4.4));//4.4nA LEAD OFF电流
	/********RES********/
	ADX92XQ_REG(ADX92XQ_WREG | RESP1, RESP_DEMOD_ON | RESP_MOD_ON | RESP_PH_112 | 0x02);
	ADX92XQ_REG(ADX92XQ_WREG | RESP2, CALIB_ON | RESP_FREQ_DIV2 | RLDREF_INT | 0x01);
	/********FIFO********/
	ADX92XQ_REG(ADX92XQ_WREG | FIFO_CFG1, FRAME_CFG_2CH_ECG | FIFO_EN);
	ADX92XQ_REG(ADX92XQ_WREG | FIFO_CFG2, STATUS_SEL_GPIO1_2 | DEPTH(FIFO_Depth));
	/********PACE********/
	ADX92XQ_REG(ADX92XQ_WREG | CONFIG4, RLDIN2RAMPP_CON);
	ADX92XQ_REG(ADX92XQ_WREG | PACE_CFG, PACE_MUX_IN2 | PACE_GAIN_4 | PACEOUT_ON_EN | PACE_EN);
	/********************/
	START_H;
	ADX92XQ_CMD(ADX92XQ_OFFSETCAL); //自矫正
	HAL_Delay(200);
	START_L;

	__HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_PIN_9);
	HAL_Delay(10);
	HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
void ADX92XQ_CMD(uint8_t cmd)
{
	NSS_L;
	Delayus(4);
	ADX92XQ_SPI_RW(cmd, 1);
	Delayus(4);
	NSS_H;
	Delayus(4);
}
uint8_t ADX92XQ_SPI_RW(uint8_t data, uint8_t len)
{
	uint8_t rx_data = 0;
	HAL_SPI_TransmitReceive(&hspi1, &data, &rx_data, len, 10);
	Delayus(4);
	return rx_data;
}
void ADX92XQ_ReadReg(uint8_t *cmd, uint8_t *data, uint8_t size)
{
	uint8_t i = 0;
	NSS_L;
	Delayus(4);
	ADX92XQ_SPI_RW(cmd[0], 1);
	ADX92XQ_SPI_RW(cmd[1], 1);
	for (i = 0; i < size; i++)
		HAL_SPI_TransmitReceive(&hspi1, &cmd[2] + i, data + i, 1, 10);
	Delayus(4);
	NSS_H;
}
uint8_t ADX92XQ_REG(uint8_t cmd, uint8_t data)
{
	uint8_t rx_data = 0;
	NSS_L;
	ADX92XQ_SPI_RW(cmd, 1);
	ADX92XQ_SPI_RW(0X00, 1);
	if ((cmd & 0x20) == 0x20)
		rx_data = ADX92XQ_SPI_RW(0X00, 1);
	else
		rx_data = ADX92XQ_SPI_RW(data, 1);
	NSS_H;
	return rx_data;
}
uint8_t ADX92XQ_REG_Stream(uint8_t CMD, uint8_t StartAddr, uint8_t StopAddrNum, uint8_t *data)
{
	static uint8_t rx_data[33] = {0};
	uint8_t j = 0, Size = 1, i = 0;
	NSS_L;
	ADX92XQ_SPI_RW(CMD | StartAddr, 1);
	ADX92XQ_SPI_RW(0x1f & (StopAddrNum - 1), 1);
	if ((CMD & 0x20) == 0x20)
	{
		if (hspi1.State != HAL_SPI_STATE_BUSY_RX)
		{
			hspi1.State = HAL_SPI_STATE_BUSY_TX_RX;
		}
		for (j = 0; j < StopAddrNum; j++)
		{
			hspi1.ErrorCode = HAL_SPI_ERROR_NONE;
			hspi1.pRxBuffPtr = &data[j];
			hspi1.RxXferCount = Size;
			hspi1.RxXferSize = Size;
			hspi1.pTxBuffPtr = &i;
			hspi1.TxXferCount = Size;
			hspi1.TxXferSize = Size;
			*((__IO uint8_t *)&hspi1.Instance->DR) = (*hspi1.pTxBuffPtr);
			while (1)
			{
				if ((__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE)) && (hspi1.RxXferCount > 0U))
				{
					(*(uint8_t *)hspi1.pRxBuffPtr) = *(__IO uint8_t *)&hspi1.Instance->DR;
					break;
				}
			}
			hspi1.State = HAL_SPI_STATE_READY;
			Delayus(2);
		}
	}
	else
		i = HAL_SPI_TransmitReceive(&hspi1, data, rx_data, StopAddrNum, 10); //д�Ĵ���
	NSS_H;
	return i;
}
void ADX92XQ_ReadData(void)
{
	__disable_irq();
	uint8_t tempread[9] = {0}, tempbuff[11] = {0};
	tempbuff[9] = 0x0D;
	tempbuff[10] = 0x0A;
	NSS_L;
	HAL_SPI_TransmitReceive(&hspi1, tempbuff, tempbuff, 9, 10);
	ADX92XQ_Data_Buff.Header = (0XF0 & tempbuff[0]) >> 4;
	ADX92XQ_Data_Buff.LEAD_OFF = ((0X0F & tempbuff[0]) << 1) | ((0x80 & tempbuff[1]) >> 7);
	ADX92XQ_Data_Buff.A92X_GPIO = (0X60 & tempbuff[1]) >> 5;
	ADX92XQ_Data_Buff.DATA_1CH = s24tos32((tempbuff[3] << 16) | (tempbuff[4] << 8) | tempbuff[5]);
	ADX92XQ_Data_Buff.DATA_2CH = s24tos32((tempbuff[6] << 16) | (tempbuff[7] << 8) | tempbuff[8]);
	NSS_H;
	AUTO_Printf_DATA(tempbuff, 11);
	__enable_irq();
}
void ADX92XQ_ReadData_fifo(void)
{
	static uint8_t tempbuff[111] = {0};
	uint8_t reg_data[32] = {0};

	uint8_t *tdata;
	uint8_t j = 0, Size = 1, i = 0;
	NSS_L;
	ADX92XQ_SPI_RW(ADX92XQ_RFIFO, 1);
	ADX92XQ_SPI_RW(ADX92XQ_RFIFO_Item(FIFO_Depth) - 1, 1);
	if (hspi1.State != HAL_SPI_STATE_BUSY_RX)
	{
		hspi1.State = HAL_SPI_STATE_BUSY_TX_RX;
	}
	for (j = 0; j < FIFO_Depth * 7; j++)
	{
		hspi1.ErrorCode = HAL_SPI_ERROR_NONE;
		hspi1.pRxBuffPtr = &tempbuff[j];
		hspi1.RxXferCount = Size;
		hspi1.RxXferSize = Size;
		hspi1.pTxBuffPtr = &i;
		hspi1.TxXferCount = Size;
		hspi1.TxXferSize = Size;
		*((__IO uint8_t *)&hspi1.Instance->DR) = (*hspi1.pTxBuffPtr);
		while (1)
		{
			if ((__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE)) && (hspi1.RxXferCount > 0U))
			{
				(*(uint8_t *)hspi1.pRxBuffPtr) = *(__IO uint8_t *)&hspi1.Instance->DR;
				break;
			}
		}
		hspi1.State = HAL_SPI_STATE_READY;
		Delayus(2);
	}
	NSS_H;
	tdata = FIFO_data_transposition(tempbuff, FIFO_Depth);
	AUTO_Printf_DATA(tdata, FIFO_Depth * 11);
}
uint8_t *FIFO_data_transposition(uint8_t *pRxData, uint8_t Item)
{
	static uint8_t buff[111] = {0};
	uint8_t j = 0, i = 0, pace_puls = 0;
	if (Pace_Mode_Flag == ENABLE)
	{
		if (GPIO2 == ENABLE) //当pace_puls为高时
		{
			pace_puls = 1;
			HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
			GPIO1_H; //复位RS触发器
			Delayus(10);
			GPIO1_L;
		}
		else
		{
			HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET);
		}
		for (j = 0; j < Item; j++)
		{
			i = j * 11;
			buff[0 + i] = 0xc0 | (((*pRxData) & 0xf0) >> 4);
			buff[1 + i] = (((*pRxData) & 0x08) << 4) | (((*pRxData & 0x01) | (pace_puls << 1)) << 5);
			buff[2 + i] = 0x00;
			buff[3 + i] = *++pRxData;
			buff[4 + i] = *++pRxData;
			buff[5 + i] = *++pRxData;
			buff[6 + i] = *++pRxData;
			buff[7 + i] = *++pRxData;
			buff[8 + i] = *++pRxData;
			buff[9 + i] = 0x0D;
			buff[10 + i] = 0x0A;
			pRxData++;
		}
	}
	else
	{
		for (j = 0; j < Item; j++)
		{
			i = j * 11;
			buff[0 + i] = 0xc0 | (((*pRxData) & 0xf0) >> 4);
			buff[1 + i] = (((*pRxData) & 0x08) << 4) | (((*pRxData) & 0x03) << 5);
			buff[2 + i] = 0x00;
			buff[3 + i] = *++pRxData;
			buff[4 + i] = *++pRxData;
			buff[5 + i] = *++pRxData;
			buff[6 + i] = *++pRxData;
			buff[7 + i] = *++pRxData;
			buff[8 + i] = *++pRxData;
			buff[9 + i] = 0x0D;
			buff[10 + i] = 0x0A;
			pRxData++;
		}
	}
	return buff;
}
void ShellSort(uint16_t *arr, uint16_t size)
{
	int i = 0, j = 0, tmp = 0, increment = 0;
	for (increment = size / 2; increment > 0; increment /= 2)
	{
		for (i = increment; i < size; i++)
		{
			tmp = arr[i];
			for (j = i - increment; j >= 0 && tmp < arr[j]; j -= increment)
			{
				arr[j + increment] = arr[j];
			}
			arr[j + increment] = tmp;
		}
	}
}
int32_t s24tos32(uint32_t data)
{
	if ((data & 0x800000) == 0x800000)
	{
		data |= 0xff000000;
	}
	return data;
}
#ifndef __ADX923Q_H
#define __ADX923Q_H
#include "stm32g0xx_hal.h"
#include "main.h"
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c,"
#define D_TO_B_INT8(i)            \
    (((i)&0x80) ? '1' : '0'),     \
        (((i)&0x40) ? '1' : '0'), \
        (((i)&0x20) ? '1' : '0'), \
        (((i)&0x10) ? '1' : '0'), \
        (((i)&0x08) ? '1' : '0'), \
        (((i)&0x04) ? '1' : '0'), \
        (((i)&0x02) ? '1' : '0'), \
        (((i)&0x01) ? '1' : '0')

//#define CRC_OPEN
#define ADX92XQ_WAKEUP 0X02            
#define ADX92XQ_STANDBY 0X04        
#define ADX92XQ_ADSRESET 0X06        
#define ADX92XQ_START 0X08            
#define ADX92XQ_STOP 0X0A            
#define ADX92XQ_OFFSETCAL 0X1A        
#define ADX92XQ_InvalidCommand 0XFF 

#define ADX92XQ_RDATAC 0X10 
#define ADX92XQ_SDATAC 0X11 
#define ADX92XQ_RDATA 0X12    
#define ADX92XQ_RFIFO 0X60    

#define ADX92XQ_RREG 0X20 
#define ADX92XQ_WREG 0X40 
#define ADX92XQ_RFIFO_Item(n) (0x1f & n)

#define ECG_ID 0X00
#define CONFIG1 0X01
#define CONFIG2 0X02
#define CONFIG3 0X0C
#define CONFIG4 0X0D
#define CONFIG5 0X0E
#define LOFF 0X03
#define CH1SET 0X04
#define CH2SET 0X05
#define RLD_SENS 0X06
#define LOFF_SENSE 0X07
#define LOFF_RLD 0X10
#define LOFF_AC1 0x11 // config ac freq using default mode
#define LON_CFG 0X12
#define LOFF_STAT 0X08
#define ERM_CFG 0x13
#define EPMIX_CFG 0X14
#define RESP1 0X09
#define RESP2 0X0A
#define GPIO 0X0B
#define LOFF_ISETP 0x0F
#define FIFO_CFG1 0X16
#define FIFO_CFG2 0X17
#define PACE_CFG 0X15

#define AC_CMP_THD0 0X1F
#define AC_CMP_THD1 0X20
#define AC_CMP_THD2 0X21
#define FIFO_STAT 0X18
#define MOD_STAT1 0X19
#define MOD_STAT2 0X1A

/****************************************************************/
/*******CONFIG1*******/
/****************************************************************/
#define SINGLE_SHOT_Continuous 0x00
#define SINGLE_SHOT_Single 0x80
#define DR_125 0x00
#define DR_250 0x01
#define DR_500 0x02
#define DR_1000 0x03
#define DR_2000 0x04
#define DR_4000 0x05
#define DR_8000 0x06
#define DR_125_D2 0x00
#define DR_250_D2 0x01
#define DR_500_D2 0x02
#define DR_1000_D2 0x03
#define DR_2000_D2 0x04
#define DR_4000_D2 0x05
#define DR_8000_D2 0x06
#define DR_125_D4 0x00
#define DR_250_D4 0x01
#define DR_500_D4 0x02
#define DR_1000_D4 0x03
#define DR_2000_D4 0x04
#define DR_4000_D4 0x05
#define DR_8000_D4 0x06
/****************************************************************/
/*******CONFIG2*******/
/****************************************************************/
#define PDB_LOFF_COMP_DIS 0x00
#define PDB_LOFF_COMP_EN 0x40
#define PDB_REFBUF_PD 0x00
#define PDB_REFBUF_EN 0x20
#define VREF_2V 0x00
#define VREF_4V 0x10
#define CLK_EN_DIS 0x00
#define CLK_EN_EN 0x08
#define INT_TEST_OFF 0x00
#define INT_TEST_ON 0x02
#define TEST_FREQ_DC 0x00
#define TEST_FREQ_1HZ 0x01
/****************************************************************/
/*******LOFF*******/
/****************************************************************/
#define COMP_TH_95 0x00
#define COMP_TH_92 0x20
#define COMP_TH_90 0x40
#define COMP_TH_87 0x60
#define COMP_TH_85 0x80
#define COMP_TH_80 0xa0
#define COMP_TH_75 0xc0
#define COMP_TH_70 0xe0
#define ILEAD_OFF_5nA 0x00
#define ILEAD_OFF_22nA 0x04
#define FLEAD_OFF_DC 0x00
#define FLEAD_OFF_AC 0x01
/****************************************************************/
/*******CH1SET*******/ /*******CH2SET*******/
/****************************************************************/
#define PD_EN 0x00
#define PD_PD 0x80
#define GAIN6 0x00
#define GAIN1 0x10
#define GAIN2 0x20
#define GAIN3 0x30
#define GAIN4 0x40
#define GAIN8 0x50
#define GAIN12 0x60
#define MUX_NORMAL 0x00
#define MUX_INPUT_SHORT 0x01
#define MUX_RLD_MEASURE 0x02
#define MUX_VDD_MEASURE 0x03
#define MUX_TEMP_SENSOR 0x04
#define MUX_TEST_SIGNAL 0x05
#define MUX_RLD_DRP 0x06
#define MUX_RLD_DRM 0x07
#define MUX_RLD_DRPM 0x08
#define MUX_IN3P_IN3N 0x09
#define MUX1_RLD_OUT 0x0b
#define MUX1_ERM 0x0F
/****************************************************************/
/*******RLD_SENS*******/
/****************************************************************/
#define PDB_RLD_PD 0x00
#define PDB_RLD_EN 0x20
#define RLD_LOFF_SENSE_DIS 0x00
#define RLD_LOFF_SENSE_EN 0x10
#define RLD2N_NOT 0x00
#define RLD2N_CON 0x08
#define RLD2P_NOT 0x00
#define RLD2P_CON 0x04
#define RLD1N_NOT 0x00
#define RLD1N_CON 0x02
#define RLD1P_NOT 0x00
#define RLD1P_CON 0x01
/****************************************************************/
/*******LOFF_SENS*******/
/****************************************************************/
#define CPFS_H 0x00
#define CPFS_L 0x40
#define FLIP2_SYNC 0x00
#define FLIP2_ASYNC 0x20
#define FLIP1_SYNC 0x00
#define FLIP1_ASYNC 0x10
#define EMUX1_VDD_DIS_P 0x00
#define EMUX1_VDD_CON_P 0x01
#define EMUX1_VSS_DIS_N 0x00
#define EMUX1_VSS_CON_N 0x02
#define EMUX1_VDD_DIS_N 0x00
#define EMUX1_VDD_CON_N 0x04
#define EMUX1_VSS_DIS_P 0x00
#define EMUX1_VSS_CON_P 0x08
/****************************************************************/
/*******LOFF_STAT*******/
/****************************************************************/
#if (WMODE != Low_Power_2_mode) 
#define CLK_DIV_4 0x00
#define CLK_DIV_16 0x80
#else 
#define CLK_DIV_4 0x00
#define CLK_DIV_8 0x80
#endif
#define RLD_STAT_CON 0x00
#define RLD_STAT_NOT 0x10
#define IN2N_OFF_CON 0x00
#define IN2N_OFF_NOT 0x08
#define IN2P_OFF_CON 0x00
#define IN2P_OFF_NOT 0x04
#define IN1N_OFF_CON 0x00
#define IN1N_OFF_NOT 0x02
#define IN1P_OFF_CON 0x00
#define IN1P_OFF_NOT 0x01
/****************************************************************/
/*******RESP1*******/
/****************************************************************/
#define RESP_DEMOD_OFF 0x00
#define RESP_DEMOD_ON 0x80
#define RESP_MOD_OFF 0x00
#define RESP_MOD_ON 0x40
#define RESP_PH_0 0x00
#define RESP_PH_11 0x04
#define RESP_PH_22 0x08
#define RESP_PH_33 0x0c
#define RESP_PH_45 0x10
#define RESP_PH_56 0x14
#define RESP_PH_67 0x18
#define RESP_PH_78 0x1c
#define RESP_PH_90 0x20
#define RESP_PH_101 0x24
#define RESP_PH_112 0x28
#define RESP_PH_123 0x2c
#define RESP_PH_135 0x30
#define RESP_PH_146 0x34
#define RESP_PH_157 0x38
#define RESP_PH_168 0x3c
#define RESP_CTRL_INT 0x00
#define RESP_CTRL_EXT 0x01
/****************************************************************/
/*******RESP2*******/
/****************************************************************/
#define CALIB_OFF 0x00
#define CALIB_ON 0x80
#define MOD_CLK_DIV1 0x00
#define MOD_CLK_DIV2 0x40
#define RESP_FREQ_DIV2 0x00
#define RESP_FREQ_DIV1 0x04
#define RLDREF_EXT 0x00
#define RLDREF_INT 0x02
/****************************************************************/
/*******GPIO*******/
/****************************************************************/
#define AC_AMP_SCALE_DIV1 0x00
#define AC_AMP_SCALE_DIV2 0x20
#define AC_AMP_SCALE_DIV4 0x40
#define AC_AMP_SCALE_DIV8 0x60
#define AC_AMP_SCALE_DIV16 0x80
#define GPIO2_OUT 0x00
#define GPIO2_IN 0x08
#define GPIO1_OUT 0x00
#define GPIO1_IN 0x04
#define GPIO1_DIS 0x00
#define GPIO1_EN 0x01
#define GPIO2_DIS 0x02
#define GPIO2_EN 0x03
/****************************************************************/
/*******CONFIG3*******/
/****************************************************************/
#define AC_MODE_SOFT 0x00
#define AC_MODE_HARD 0x80
#define P5VREF_OFF 0x00
#define P5VREF_ON 0x40
#define DIN_CRC_DIS 0x00
#define DIN_CRC_EN 0x08
#define DOUT_CRC_DIS 0x00
#define DOUT_CRC_EN 0x04
#define SPI_TIMEOUT_DIS 0x00
#define SPI_TIMEOUT_255 0x01
#define SPI_TIMEOUT_1023 0x02
#define SPI_TIMEOUT_4095 0x03
/****************************************************************/
/*******CONFIG4*******/
/****************************************************************/
#define DR_INT_DIS 0x00
#define DR_INT_EN 0x80
//#define                ADC_DAT_THD_d0              0x00
//#define                ADC_DAT_THD_d1              0x20
//#define                ADC_DAT_THD_d2              0x40
//#define                ADC_DAT_THD_d3              0x60
#define CLK_MISS_INT_DIS 0x00
#define CLK_MISS_INT_EN 0x08
#define RLDIN2RAMPP_DIS 0x00
#define RLDIN2RAMPP_CON 0x02
#define RAMPOUT2RAMPN_DIS 0x00
#define RAMPOUT2RAMPN_CON 0x01
/****************************************************************/
/*******CONFIG5*******/
/****************************************************************/
#define OSC_2M_DIS 0x00
#define OSC_2M_EN 0x80
/****************************************************************/
/**Interrupt Output to GPIO, including LOFF interrupt INT1,******/
/**ADC data out of range interrupt INT2, FIFO interrupt INT3,****/
/*CLK missing interrupt INT4,invalid SPI command interrupt INT5**/
/****************************************************************/
#define INT2GPIO_D0 0x00 // INT1, INT2, INT3, INT4, INT5 output to external with GPIO1.
#define INT2GPIO_D1 0x10 // INT1, INT2, INT3, INT4, INT5 output to external with GPIO2.
#define INT2GPIO_D2 0x20 // INT1, INT2, INT3, INT5 output to external with GPIO1, INT4 output to external with GPIO2.
#define INT2GPIO_D3 0x30 // INT1, INT2, INT4, INT5 output to external with GPIO1, INT3 output to external with GPIO2.
#define INT2GPIO_D4 0x40 // INT1, INT3, INT4, INT5 output to external with GPIO1, INT2 output to external with GPIO2.
#define INT2GPIO_D5 0x50 // INT2, INT3, INT4, INT5 output to external with GPIO1, INT1 output to external with GPIO2.
#define INT2GPIO_D6 0x60 // INT1, INT2, INT3, INT4 output to external with GPIO1, INT5 output to external with GPIO2.
#define INT2GPIO_NO 0x70 // NO interrupt output to GPIO pin.
#define INV_CMD_INT_DIS 0x00
#define INV_CMD_INT_EN 0x08
#define FRAME_CHK_DIS 0x00
#define FRAME_CHK_EN 0x04
#define IO_3MA_DIS 0x00
#define IO_3MA_EN 0x02
#define IO_SRM_DIS 0x00
#define IO_SRM_EN 0x01
/****************************************************************/
/*******LOFF_ISTEP*******/
/****************************************************************/
#define LOFF_INT_EN 0x00
#define LOFF_INT_DIS 0x80
#define CUR_LEVEL_DIS 0x00
#define CUR_LEVEL_EN 0x40
#define ISTEP_nA(a) (((uint8_t)((a+0.01) / 2.2f)) & 0x3f)
/****************************************************************/
/*******LOFF_RLD*******/
/****************************************************************/
#define EMUX2_VDD_DIS_P 0x00
#define EMUX2_VDD_CON_P 0x10
#define EMUX2_VSS_DIS_N 0x00
#define EMUX2_VSS_CON_N 0x20
#define EMUX2_VDD_DIS_N 0x00
#define EMUX2_VDD_CON_N 0x40
#define EMUX2_VSS_DIS_P 0x00
#define EMUX2_VSS_CON_P 0x80
#define RCOMP_TH_95 0x00
#define RCOMP_TH_92 0x02
#define RCOMP_TH_90 0x04
#define RCOMP_TH_87 0x06
#define RCOMP_TH_85 0x08
#define RCOMP_TH_80 0x0a
#define RCOMP_TH_75 0x0c
#define RCOMP_TH_70 0x0e
#define RLD_DEC_SHARE 0x00 // RLD shares the threshold comparator with the RA, LA, and LL pins
#define RLD_DEC_STAND 0x01 // RLD uses standalone comparator and needs configure RCOMP_TH[2:0] for threshold setting
/****************************************************************/
/*******LOFF_AC1*******/
/****************************************************************/
#define SQUARE_WAVE_SIN 0x00
#define SQUARE_WAVE_SQW 0x80
#define ACDIV_FACTOR ACDIV_FACTOR_DIV1
#define ACDIV_FACTOR_DIV1 0x00
#define ACDIV_FACTOR_DIV8 0x40
#if (ACDIV_FACTOR == ACDIV_FACTOR_DIV1)                  // If ACDIV_FACTOR_DIV1, step=1000Hz. ACDIV_FREQ odd configuration number is suggested
#define ACDIV_FRQ(a) ((uint8_t)(a / 1000) - 1) & 0x07 // 1000HZ~8000HZ
#define ACDIV_FRQ4KHz 0x03
#else                                             // If ACDIV_FACTOR_DIV8, step=125Hz. ACDIV_FREQ odd configuration number is suggested
#define ACDIV_FRQ(a) ((uint8_t)(a / 125)) & 0x1F // 125HZ-4000HZ
#define ACDIV_FRQ4KHz 0x1f
#define ACDIV_FRQ500Hz 0x03
#endif
/****************************************************************/
/*******LON_CFG*******/
/****************************************************************/
#define HPF_DIS 0x00
#define HPF_EN 0x80
#define PF_05Hz 0x00
#define PF_067Hz 0x20
#define PF_7Hz 0x40
#define DEBOUNCE_DIS 0x00
#define DEBOUNCE_117 0x08
#define DEBOUNCE_335 0x10
// Function Offset calibration enable
#define OFC_DIS 0x00
#define OFC_EN 0x04
// AC Excitation amplitude selection
#define AC_EXCT_THD_160nA 0x00
#define AC_EXCT_THD_80nA 0x01
#define AC_EXCT_THD_40nA 0x02
#define AC_EXCT_THD_20nA 0x03
/****************************************************************/
/*******ERM_CFG*******/
/****************************************************************/
#define WMODE Speed_mode
#define Speed_mode 0x00         
#define Resolution_mode 0x40  
#define Low_Power_1_mode 0x80 
#define Low_Power_2_mode 0xc0 
#define AC_DATA_OUT_DIS 0x00
#define AC_DATA_OUT_EN 0x20
#define AC_DATA_OUT_SEL_SIN 0x00
#define AC_DATA_OUT_SEL_COS 0x10
#if (ACDIV_FACTOR == ACDIV_FACTOR_DIV1) // AC Lead-off data output frequency selection
#define AC_DATA_FREQ_4K 0x00
#define AC_DATA_FREQ_16K 0x08
#else
#define AC_DATA_FREQ_500 0x00
#define AC_DATA_FREQ_2K 0x08
#endif
#define ERM_MUX_DIS 0x00
#define ERM_MUX_D1 0x01 // RLD2RA,LL2IN2P,LA2IN2N
#define ERM_MUX_D2 0x02 // RLD2RA,LA2IN2P,LL2IN2N
#define ERM_MUX_D3 0x03 // RLD2LA,RA2IN2P,LL2IN2N
#define ERM_MUX_D4 0x04 // RLD2LA,LL2IN2P,RA2IN2N
#define ERM_MUX_D5 0x05 // RLD2LL,LA2IN2P,RA2IN2N
#define ERM_MUX_D6 0x06 // RLD2LL,RA2IN2P,LA2IN2N
/****************************************************************/
/*******EPMIX_CONFIG*******/
/****************************************************************/
#define PACE_CHOP_DIS 0x00
#define PACE_CHOP_EN 0x80
#define PACE_COMP_DIS 0x00
#define PACE_COMP_EN 0x40
#define SHORT_PROTECT_DIS 0x00
#define SHORT_PROTECT_EN 0x20
#define FSEL_1024K 0x08
#define FSEL_512K 0x10
#define FSEL_256K 0x18
#define DOUT_DO3MA_STRONG 0x00
#define DOUT_DO3MA_LOW 0x04
#define AC_CMP_CFG_AC_24 0x00
#define AC_CMP_CFG_AC_12_H 0x01 // Channel 1 uses the low 12 bits of comparator threshold, and channel 2 uses the high 12 bits of comparator threshold to compare with the high 12-bit AC lead-off result
#define AC_CMP_CFG_AC_12_L 0x02 // Channel 1 uses the low 12 bits of comparator threshold, and channel 2 uses the high 12 bits of comparator threshold to compare with the low 12-bit AC lead-off result.
/****************************************************************/
/*******PACE_CFG*******/
/****************************************************************/
#define PACE_MUX_IN1 0x00
#define PACE_MUX_IN2 0x20
#define PACE_GAIN_4 0x00
#define PACE_GAIN_2_3 0x04
#define PACE_GAIN_4_3 0x08
#define PACE_GAIN_2 0x0c
#define PACE_GAIN_8_3 0x10
#define PACE_GAIN_16_3 0x14
#define PACE_GAIN_8 0x18
#define PACEOUT_ON_DIS 0x00
#define PACEOUT_ON_EN 0x02
#define PACE_DIS 0x00
#define PACE_EN 0x01
/****************************************************************/
/*******FIFO_CFG1*******/
/****************************************************************/
#define FIFO_INT_DIS 0x00
#define FIFO_INT_EN 0x80
#define FIFO_RST_DIS 0x00
#define FIFO_RST_EN 0x10
#define FRAME_CFG_1CH_ECG 0x00
#define FRAME_CFG_ECG_RES 0x02
#define FRAME_CFG_2CH_ECG 0x04
#define FIFO_DIS 0x00
#define FIFO_EN 0x01
/****************************************************************/
/*******FIFO_CFG2*******/
/****************************************************************/
#define STATUS_SEL_NO 0x00
#define STATUS_SEL_GPIO1 0x20
#define STATUS_SEL_GPIO2 0x40
#define STATUS_SEL_GPIO1_2 0x60
#define STATUS_SEL_PACE 0x80
#define DEPTH(a) (a - 1) & 0x0f
/****************************************************************/
/*******DEV_CONFIG1*******/
/****************************************************************/
#define RESP_CLK_HALF_DIV1 0x00
#define RESP_CLK_HALF_DIV2 0x80
#define CP_EN 0x00
#define CP_PD 0x40
#define PGA_CHOP_DIV16 0x00
#define PGA_CHOP_DIV32 0x10
#define PGA_CHOP_DIV64 0x20
#define PGA_CHOP_DIV4 0x30
#define MOD_CHOP_DIV16 0x00
#define MOD_CHOP_DIV2 0x04
#define MOD_CHOP_DIV4 0x08
#define MOD_CHOP_DIV8 0x0c
#define DITHER_NO 0x00
#define DITHER_EN 0x01
//            ECG PIN DEFINE
//            ADC_DRDY                     _> PA0        
//            CLK_SEL                         _> PC3
//            POWERDOWN/RESET        _> PC2
//            START                            _> PC1
//            RCLK/GPIO2                _> PC15
//            RCLK/GPIO1                _> PC14
//            XTAL_EN                        _> PA8
//            AVCC_EN                        _> PC12
//            DVDD_EN                        _> PC10
#define NSSPORT GPIOA
#define NSS_PIN GPIO_PIN_4
#define ADC_DRDY_Port GPIOC
#define ADC_DRDY_Pin GPIO_PIN_9
#define XTAL_EN_Port GPIOA
#define XTAL_EN_Pin GPIO_PIN_7
#define CLK_SEL_Port GPIOC
#define CLK_SEL_Pin GPIO_PIN_3
#define PWDN_Port GPIOC
#define PWDN_Pin GPIO_PIN_2
#define START_Port GPIOC
#define START_Pin GPIO_PIN_1
#define GPIO2_Port GPIOC
#define GPIO2_Pin GPIO_PIN_15
#define GPIO1_Port GPIOC
#define GPIO1_Pin GPIO_PIN_14
#define PIN_ON GPIO_PIN_SET
#define PIN_OFF GPIO_PIN_RESET
#define AVCC_EN_Port GPIOC
#define AVCC_EN_Pin GPIO_PIN_12
#define DVDD_EN_Port GPIOC
#define DVDD_EN_Pin GPIO_PIN_10

#define ADC_DRDY HAL_GPIO_ReadPin(ADC_DRDY_Port, ADC_DRDY_Pin) //

#define NSS_H HAL_GPIO_WritePin(NSSPORT, NSS_PIN, GPIO_PIN_SET)
#define NSS_L HAL_GPIO_WritePin(NSSPORT, NSS_PIN, GPIO_PIN_RESET)

#define XTAL_EN HAL_GPIO_WritePin(XTAL_EN_Port, XTAL_EN_Pin, GPIO_PIN_SET)
#define XTAL_DIS HAL_GPIO_WritePin(XTAL_EN_Port, XTAL_EN_Pin, GPIO_PIN_RESET)

#define ExternalCLK HAL_GPIO_WritePin(CLK_SEL_Port, CLK_SEL_Pin, GPIO_PIN_RESET)
#define InternalCLK HAL_GPIO_WritePin(CLK_SEL_Port, CLK_SEL_Pin, GPIO_PIN_SET)

#define PWDN_L HAL_GPIO_WritePin(PWDN_Port, PWDN_Pin, GPIO_PIN_RESET)
#define PWDN_H HAL_GPIO_WritePin(PWDN_Port, PWDN_Pin, GPIO_PIN_SET)

#define START_L HAL_GPIO_WritePin(START_Port, GPIO_PIN_1, GPIO_PIN_RESET)
#define START_H HAL_GPIO_WritePin(START_Port, GPIO_PIN_1, GPIO_PIN_SET)


#define GPIO2_L HAL_GPIO_WritePin(GPIO2_Port, GPIO2_Pin, GPIO_PIN_RESET)
#define GPIO2_H HAL_GPIO_WritePin(GPIO2_Port, GPIO2_Pin, GPIO_PIN_SET)
#define GPIO2 HAL_GPIO_ReadPin(GPIO2_Port, GPIO2_Pin) //

#define GPIO1_L HAL_GPIO_WritePin(GPIO1_Port, GPIO1_Pin, GPIO_PIN_RESET)
#define GPIO1_H HAL_GPIO_WritePin(GPIO1_Port, GPIO1_Pin, GPIO_PIN_SET)
#define GPIO1 HAL_GPIO_ReadPin(GPIO1_Port, GPIO1_Pin) //

#define AVCC_EN(X) HAL_GPIO_WritePin(AVCC_EN_Port, AVCC_EN_Pin, (X))
#define DVDD_EN(X) HAL_GPIO_WritePin(DVDD_EN_Port, DVDD_EN_Pin, (X))
#define ADX92XQ_GPIO1_H ADX92XQ_REG(ADX92XQ_WREG | GPIO, 0x02);
#define ADX92XQ_GPIO1_L ADX92XQ_REG(ADX92XQ_WREG | GPIO, 0x00);

#define ADX92XQ_GPIO2_H ADX92XQ_REG(ADX92XQ_WREG | GPIO, 0x01);
#define ADX92XQ_GPIO2_L ADX92XQ_REG(ADX92XQ_WREG | GPIO, 0x00);

typedef struct __Data_Format
{
#ifdef CRC_OPEN
    uint8_t Header;
    uint8_t LEAD_OFF;
    uint8_t A92X_GPIO;
    uint8_t CRC_WORD;
    int32_t DATA_1ch;
    int32_t DATA_2ch;
#else
    uint8_t Header;
    uint8_t LEAD_OFF;
    uint8_t A92X_GPIO;
    int32_t DATA_1CH;
    int32_t DATA_2CH;
#endif

} Data_Format;
typedef struct __Ac_Loff_Data_Format
{
    int32_t STATUS;
    int32_t CH1;
    int32_t CH2;
    int32_t CH1SIN;
    int32_t CH1COS;
    int32_t CH2SIN;
    int32_t CH2COS;
    int32_t CH1AMP;
    int32_t CH1PHA;
    int32_t CH2AMP;
    int32_t CH2PHA;
} Ac_Loff_Data_Format;

extern Data_Format ADX92XQ_Data_Buff;
extern Ac_Loff_Data_Format ADX92XQ_Acloff_Data;
int32_t s24tos32(uint32_t data);
uint8_t ADX92XQ_Init(void);
void ADX92XQ_Config(void);
void ADX92XQ_ReadData(void);
void ADX92XQ_ReadData_fifo(void);
void ADX92XQ_Read_AC_LOFF_Data(void);
void ADX92XQ_Read_AC_LOFF_Mode(uint8_t mode);

void ADX92XQ_CMD(uint8_t cmd);
uint8_t ADX92XQ_SPI_RW(uint8_t data, uint8_t len);
uint8_t ADX92XQ_REG(uint8_t cmd, uint8_t data); 
uint8_t ADX92XQ_REG_Stream(uint8_t CMD, uint8_t StartAddr, uint8_t StopAddrNum, uint8_t *data);
uint8_t *FIFO_data_transposition(uint8_t *pRxData, uint8_t Item);
void ADX92XQ_ReadReg(uint8_t *cmd, uint8_t *data, uint8_t size);
void ADX92XQ_AC_LOFF_Data_Out(uint8_t mode);
void ShellSort(uint16_t *arr, uint16_t size); 

#endif