- BLE peripheral applications - dr_piezo and bladder_patch projects Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
300 lines
7.6 KiB
C
300 lines
7.6 KiB
C
/*******************************************************************************
|
|
* @file ad5272_i2c.c
|
|
* @author CandyPops Co.
|
|
* @version V1.0.0
|
|
* @date 2022-09-05
|
|
* @brief
|
|
******************************************************************************/
|
|
|
|
/* board driver */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
#include "nrf.h"
|
|
#include "app_error.h"
|
|
#include "boards.h"
|
|
#include "nrfx_gpiote.h"
|
|
#include "nrfx_twi.h"
|
|
|
|
#include "nrf_delay.h"
|
|
#include "ad5272_i2c.h"
|
|
#include "debug_print.h"
|
|
|
|
/* I2C number and slave address for AD5272 */
|
|
#define AD5272_I2C_ADDR 0x2F /* Default I2C address if ADDR = GND */
|
|
#define AD5272_MAX_SERIAL_WRITE 16
|
|
|
|
int16_t read_from_ad5272 = 0;
|
|
uint16_t data_16_to_write = 0;
|
|
|
|
|
|
/* TWI instance. */
|
|
const nrfx_twi_t m_twi_ad5272 = NRFX_TWI_INSTANCE(AD5272_I2C_INSTANCE);
|
|
|
|
|
|
void ad5272_i2c_uninit(void){
|
|
nrfx_twi_disable(&m_twi_ad5272);
|
|
nrfx_twi_uninit(&m_twi_ad5272);
|
|
}
|
|
|
|
|
|
void ad5272_i2c_init(void){
|
|
ret_code_t err_code;
|
|
|
|
const nrfx_twi_config_t twi_ad5272_config = {
|
|
.scl = AD5272_I2C_SCL_PIN,
|
|
.sda = AD5272_I2C_SDA_PIN,
|
|
.frequency = NRF_TWI_FREQ_400K,
|
|
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
|
|
};
|
|
|
|
err_code = nrfx_twi_init(&m_twi_ad5272, &twi_ad5272_config, NULL, NULL);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
nrfx_twi_enable(&m_twi_ad5272);
|
|
}
|
|
|
|
|
|
ret_code_t ad5272_twi_tx( uint8_t device_id,
|
|
uint8_t const * p_data,
|
|
uint8_t length,
|
|
bool no_stop)
|
|
{
|
|
ret_code_t ret;
|
|
ret = nrfx_twi_tx(&m_twi_ad5272, device_id, p_data, length, no_stop);
|
|
return ret;
|
|
}
|
|
|
|
|
|
ret_code_t ad5272_twi_rx( uint8_t device_id,
|
|
uint8_t * p_data,
|
|
uint8_t length)
|
|
{
|
|
ret_code_t ret;
|
|
ret = nrfx_twi_rx(&m_twi_ad5272, device_id, p_data, length);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int16_t ad5272_command_read(uint8_t command, uint8_t write_data)
|
|
{
|
|
uint8_t error_count = 0;
|
|
uint8_t data_buff[1+AD5272_MAX_SERIAL_WRITE];
|
|
uint16_t data_to_write = 0;
|
|
int16_t read_data = 0;
|
|
ret_code_t ret;
|
|
|
|
if (AD5272_50TP_WIPER_READ == command)
|
|
{
|
|
// shift the command over into bits 13:10
|
|
data_to_write = command<<10;
|
|
// also need to send 6-bit 50-TP location
|
|
data_to_write |= write_data;
|
|
}
|
|
else if ( (AD5272_RDAC_READ == command) || (AD5272_50TP_LAST_USED == command) || (AD5272_CONTROL_READ == command) )
|
|
{
|
|
// command is in range and something possible to read
|
|
// shift the command over into bits 13:10
|
|
data_to_write = command<<10;
|
|
}
|
|
else
|
|
{
|
|
// It's either a bad command (out of range, > AD5272_SHUTDOWN), or its not a readable command
|
|
// Bad command, we can't reasonably proceed
|
|
error_count = 100;
|
|
}
|
|
|
|
/**
|
|
* At this point, if error_count == 0 we have a valid read command
|
|
*/
|
|
if (0 == error_count)
|
|
{
|
|
memset(data_buff, 0, 1+AD5272_MAX_SERIAL_WRITE);
|
|
data_buff[0] = (data_to_write >> 8); // ms byte to write
|
|
data_buff[1] = data_to_write & 0x0FF; // ls byte to write
|
|
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_rx_1_buff[0]=0x%x, [1]=0x%x\r\n", data_buff[0], data_buff[1]);
|
|
#endif
|
|
ret = ad5272_twi_tx(AD5272_I2C_ADDR, data_buff, 2, true);
|
|
if(ret != NRF_SUCCESS) {
|
|
ret = ad5272_twi_tx(AD5272_I2C_ADDR, data_buff, 2, true);
|
|
if(ret != NRF_SUCCESS) {
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_ERR! i2c read-1\r\n");
|
|
#endif
|
|
//APP_ERROR_CHECK(ret);
|
|
}
|
|
}
|
|
|
|
|
|
memset(data_buff, 0, 1+AD5272_MAX_SERIAL_WRITE);
|
|
|
|
ret = ad5272_twi_rx(AD5272_I2C_ADDR, data_buff, 2);
|
|
if(ret != NRF_SUCCESS) {
|
|
ret = ad5272_twi_rx(AD5272_I2C_ADDR, data_buff, 2);
|
|
if(ret != NRF_SUCCESS) {
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_ERR! i2c read-2\r\n");
|
|
#endif
|
|
//APP_ERROR_CHECK(ret);
|
|
}
|
|
}
|
|
read_data = data_buff[0] << 8; // ms byte
|
|
read_data |= data_buff[1]; // ls byte
|
|
|
|
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_read_data = 0x%x\r\n",read_data);
|
|
#endif
|
|
}else{
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_read_data USELESS!!!\r\n");
|
|
#endif
|
|
}
|
|
|
|
return read_data;
|
|
}
|
|
|
|
|
|
int8_t ad5272_command_write(uint8_t command, uint16_t write_data)
|
|
{
|
|
uint8_t error_count = 0;
|
|
uint8_t data_buff[1+AD5272_MAX_SERIAL_WRITE];
|
|
ret_code_t ret;
|
|
|
|
int8_t return_val = 0;
|
|
uint16_t data_to_write = 0;
|
|
|
|
if (write_data > 0x3FF)
|
|
{
|
|
// data in bits 13:10 will clobber the command when we OR in write_datum16
|
|
write_data &= 0x3FF; // clip off any bad high bits even though we are going to error out and not use them
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_ERR! Input Value wrong!\r\n");
|
|
#endif
|
|
}
|
|
|
|
if ( (AD5272_RDAC_WRITE == command) || (AD5272_CONTROL_WRITE == command) || (AD5272_SHUTDOWN == command) )
|
|
{
|
|
// these commands need to use data we send over
|
|
// shift the command over into bits 13:10
|
|
data_to_write = command<<10;
|
|
// also need to send 10-bit or 8-bit wiper value, or 3 control bits, or shutdown bit
|
|
data_to_write |= write_data;
|
|
}
|
|
else if ( (AD5272_50TP_WRITE == command) || (AD5272_RDAC_REFRESH == command) )
|
|
{
|
|
// shift the command over into bits 13:10
|
|
data_to_write = command<<10;
|
|
// no data needed
|
|
}
|
|
else
|
|
{
|
|
// It's either a bad command (out of range, > AD5272_SHUTDOWN), or its not a writeable command
|
|
// Bad command, we can't reasonably proceed
|
|
error_count = 100;
|
|
}
|
|
|
|
// if no errors so far, command is valid and datum is too
|
|
if (0 == error_count)
|
|
{
|
|
data_buff[0] = (data_to_write >> 8); // ms byte to write
|
|
data_buff[1] = data_to_write & 0x0FF; // ls byte to write
|
|
ret = ad5272_twi_tx(AD5272_I2C_ADDR, data_buff, 2, false);
|
|
if(ret != NRF_SUCCESS) {
|
|
ret = ad5272_twi_tx(AD5272_I2C_ADDR, data_buff, 2, false);
|
|
if(ret != NRF_SUCCESS) {
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_ERR! i2c write\r\n");
|
|
#endif
|
|
//APP_ERROR_CHECK(ret);
|
|
return_val = NRF_ERROR_INTERNAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return return_val;
|
|
}
|
|
|
|
|
|
void ad5272_i2c_is_busy(void)
|
|
{
|
|
uint8_t buffer[3]; /* Addr + data */
|
|
|
|
buffer[0] = AD5272_COMMAND_NOP;
|
|
buffer[1] = 0x00;
|
|
|
|
while(NRF_SUCCESS != ad5272_twi_tx(AD5272_I2C_ADDR, buffer, 1, false))
|
|
{
|
|
#if FEATURE_PRINTF
|
|
DBG_PRINTF("ad5272_BUSY : is Busy\r\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int8_t ad5272_write_and_read_rdac (uint16_t data_16_to_write)
|
|
{
|
|
ret_code_t ret;
|
|
|
|
ret = ad5272_command_write(AD5272_CONTROL_WRITE, AD5272_RDAC_WIPER_WRITE_ENABLE); /* Write Enable */
|
|
ret |= ad5272_command_write(AD5272_RDAC_WRITE, data_16_to_write); /* Write Data */
|
|
ret |= ad5272_command_write(AD5272_CONTROL_WRITE, 0x00); /* Write Disable & Use 50tp value */
|
|
|
|
read_from_ad5272 = ad5272_command_read(AD5272_RDAC_READ, 0x00);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int16_t ad5272_read_rdac (void)
|
|
{
|
|
read_from_ad5272 = ad5272_command_read(AD5272_RDAC_READ, 0x00);
|
|
|
|
return read_from_ad5272;
|
|
}
|
|
|
|
|
|
int8_t ad5272_write_rdac (uint16_t data_16_to_write)
|
|
{
|
|
ret_code_t ret;
|
|
|
|
ret = ad5272_command_write(AD5272_CONTROL_WRITE, AD5272_RDAC_WIPER_WRITE_ENABLE); /* Write Enable */
|
|
ret |= ad5272_command_write(AD5272_RDAC_WRITE, data_16_to_write); /* Write Data */
|
|
ret |= ad5272_command_write(AD5272_CONTROL_WRITE, 0x00); /* Write Disable & Use 50tp value */
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void ad5272_RDAC_refresh(void)
|
|
{
|
|
ad5272_command_write(AD5272_RDAC_REFRESH, 0x00);
|
|
|
|
ad5272_i2c_is_busy();
|
|
}
|
|
|
|
|
|
void ad5272_shutdown_mode(void)
|
|
{
|
|
ad5272_command_write(AD5272_SHUTDOWN, 0x01);
|
|
|
|
ad5272_i2c_is_busy();
|
|
}
|
|
|
|
|
|
void ad5272_normal_mode(void)
|
|
{
|
|
ad5272_command_write(AD5272_SHUTDOWN, 0x00);
|
|
|
|
ad5272_i2c_is_busy();
|
|
}
|
|
|
|
|