38#include <util/delay.h>
39#include <avr/interrupt.h>
46#define CHANNEL_BIT 15U
48#define SHUTDOWN_BIT 12U
51#define TWELVE_BIT_LEVEL_OFFSET 0U
52#define TEN_BIT_LEVEL_OFFSET 2U
53#define EIGHT_BIT_LEVEL_OFFSET 4U
56#define TWELVE_BIT_MV_OFFSET 0U
57#define TEN_BIT_MV_OFFSET 1U
58#define EIGHT_BIT_MV_OFFSET 3U
69static uint8_t mv_resolution_shift = 0;
75static uint8_t level_resolution_shift = 0;
92 p_config_global = p_config;
105 DAC_CTRL_DDR |= (1 << DAC_CS);
106 DAC_CTRL_PORT |= (1 << DAC_CS);
107 DAC_CTRL_DDR |= (1 << LDAC);
108 DAC_CTRL_PORT |= (1 << LDAC);
111 if (p_config_global->model == mcp4802)
113 mv_resolution_shift = EIGHT_BIT_MV_OFFSET;
114 level_resolution_shift = EIGHT_BIT_LEVEL_OFFSET;
116 else if (p_config_global->model == mcp4812)
118 mv_resolution_shift = TEN_BIT_MV_OFFSET;
119 level_resolution_shift = TEN_BIT_LEVEL_OFFSET;
123 mv_resolution_shift = TWELVE_BIT_MV_OFFSET;
124 level_resolution_shift = TWELVE_BIT_LEVEL_OFFSET;
128 if (!p_config_global->sync_manually)
130 DAC_CTRL_PORT &= ~(1 << LDAC);
150 if (p_config_global->channel_a.gain_low)
152 p_config_global->channel_a.level =
153 (millivolts >> mv_resolution_shift);
157 p_config_global->channel_a.level =
158 (millivolts >> (mv_resolution_shift + 1));
163 if (p_config_global->channel_b.gain_low)
165 p_config_global->channel_b.level =
166 (millivolts >> mv_resolution_shift);
170 p_config_global->channel_b.level =
171 (millivolts >> (mv_resolution_shift + 1));
195 if(p_config_global->channel_a.gain_low)
197 p_config_global->channel_a.level =
198 (millivolts << (TWELVE_BIT_MV_OFFSET + 1));
200 if (fractional ==
true)
202 p_config_global->channel_a.level += 1;
207 p_config_global->channel_a.level =
208 (millivolts << TWELVE_BIT_MV_OFFSET);
213 if(p_config_global->channel_b.gain_low)
215 p_config_global->channel_b.level =
216 (millivolts << (TWELVE_BIT_MV_OFFSET + 1));
218 if (fractional ==
true)
220 p_config_global->channel_b.level += 1;
225 p_config_global->channel_b.level =
226 (millivolts << TWELVE_BIT_MV_OFFSET);
242 uint16_t channel_a_data = 0;
243 uint16_t channel_b_data = 0;
246 channel_a_data &= ~(1 << CHANNEL_BIT);
247 channel_a_data |= (p_config_global->channel_a.gain_low << GAIN_BIT);
248 channel_a_data |= (p_config_global->channel_a.active << SHUTDOWN_BIT);
250 channel_b_data |= (1 << CHANNEL_BIT);
251 channel_b_data |= (p_config_global->channel_b.gain_low << GAIN_BIT);
252 channel_b_data |= (p_config_global->channel_b.active << SHUTDOWN_BIT);
256 (p_config_global->channel_a.level << level_resolution_shift);
259 (p_config_global->channel_b.level << level_resolution_shift);
273 if (!p_config_global->sync_manually)
288 DAC_CTRL_PORT &= ~(1 << LDAC);
290 DAC_CTRL_PORT |= (1 << LDAC);
304 DAC_CTRL_PORT &= ~(1 << DAC_CS);
313 DAC_CTRL_PORT |= (1 << DAC_CS);
void init_spi(spi_transfer_mode_t transfer_mode, spi_control_mode_t control_mode, spi_polarity_mode_t polarity_mode, spi_phase_mode_t phase_mode, spi_clk_rate_t clk_rate, spi_dbl_clk_mode_t dbl_clock)
Initialisation routine to set up SPI comms.
uint16_t spi_trade_word(uint16_t data)
Sends out a 16bit word of data over spi (in two bytes) and returns the byte it receives.
Driver for SPI communication between the ATmega328P and other SPI compatible devices.
void chip_select(void)
Private helper function - pulls CS line (Chip Select) low in order to begin SPI communication with DA...
void dac_set_voltage(bool channel_a, uint16_t millivolts)
Sends a new millivolts value to be output on DAC (Along with config settings).
void dac_set_voltage_12_bit(bool channel_a, uint16_t millivolts, bool fractional)
Sends a new millivolts value to be output on DAC (Along with config settings).
void init_dac(dac_config_t *p_config)
Initialisation routine (run once at startup).
void dac_reconfigure(void)
Applies new config settings.
void chip_deselect(void)
Private helper function - pulls CS line (Chip Select) high to signal the end of SPI communication wit...
void pulse_latch(void)
Pulses LDAC pin low for a brief time (1uS).
Driver for the MCP4812 10 bit DAC (digital to analog converter) chip.
Definitions for pin mapping (for CCS81 gas sensor)