#include "max5136.h" #include "dac_drv_if.h" #include "nrf_log.h" #include "FreeRTOS.h" #include "task.h" #if (DEF_MAX5136_ENABLED) #define MAX5136_NOP_MODE (0x00 << 0) #define MAX5136_LDAC_MODE (0x01 << 0) #define MAX5136_CLR_MODE (0x02 << 0) #define MAX5136_PWR_CTRL_MODE (0x03 << 0) #define MAX5136_LINEARITY_MODE (0x05 << 0) #define MAX5136_WRITE_MODE (0x01 << 4) #define MAX5136_WRITE_THROUGH_MODE (0x03 << 4) #define MAX5136_LINEARITY_SET (0b1000000000) #define MAX5136_LINEARITY_CLR (0b0000000000) typedef struct __PACKED { uint8_t ctrl_bits; uint16_t data_bits; } max5136_opcode_t; static int max5136_ldac_mode(uint32_t channel_mask) { /* Move contents of input to DAC registers indicated by 1's. No effect on registers indicated by 0's. */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_LDAC_MODE, .data_bits = __REVSH((channel_mask & 0b1111) << 8), }; spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); return 0; } static int max5136_power_control_mode(uint32_t channel_mask, uint32_t ready_enable) { /* Power down DACs indicated by 1's. Set READY_EN = 1 to enable READY. */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_PWR_CTRL_MODE | (channel_mask & 0b1111), .data_bits = __REVSH(((channel_mask & 0b1111) << 8) | (ready_enable == 0 ? 0 : 1)), }; spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); return 0; } static int max5136_write_mode(uint32_t channel_mask, int32_t dac_val) { /* Write to selected input registers (DAC output not affected). */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_WRITE_MODE | (channel_mask & 0b1111), .data_bits = __REVSH(dac_val), }; spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); return 0; } static int max5136_write_through_mode(uint32_t channel_mask, int32_t dac_val) { /* Write to selected input and DAC registers, DAC outputs updated (writethrough). */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_WRITE_THROUGH_MODE | (channel_mask & 0b1111), .data_bits = __REVSH(dac_val), }; spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); return 0; } static void max5136_linearity(void) { /* To guarantee DAC linearity, wait until the supplies have settled. Set the LIN bit in the DAC linearity register; wait 10ms, and clear the LIN bit. */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_LINEARITY_MODE }; op_code.data_bits = __REVSH(MAX5136_LINEARITY_SET); spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); vTaskDelay(pdMS_TO_TICKS(10)); op_code.data_bits = __REVSH(MAX5136_LINEARITY_CLR); spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); } static int max5136_soft_reset(void) { /* The software clear command acts as a software POR, erasing the contents of all registers. All outputs return to the state determined by the M/Z input. */ max5136_opcode_t op_code = { .ctrl_bits = MAX5136_CLR_MODE, .data_bits = 0, }; spim_xfer(CS_DAC_PIN, NRF_SPIM_MODE_2, (uint8_t *)&op_code, sizeof(op_code), NULL, 0); return 0; } static int max5136_init(void) { max5136_soft_reset(); max5136_linearity(); return 0; } dac_drv_if_t max5316_drv = { .init = max5136_init, .ldac_mode = max5136_ldac_mode, .reset = max5136_soft_reset, .power_control_mode = max5136_power_control_mode, .write_mode = max5136_write_mode, .write_through_mode = max5136_write_through_mode, }; #endif /* !DEF_MAX5136_ENABLED */