Files

134 lines
3.9 KiB
C

#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 */