/******************************************************************************* * @file ad5272_i2c.c * @author CandyPops Co. * @version V1.0.0 * @date 2022-09-05 * @brief ******************************************************************************/ /* board driver */ #include #include #include #include #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(); }