#include "config.h" #include "dac.h" /* Initialize DAC (AD5542) */ void dac_init(void) { /* SPI2 */ IEC2bits.SPI2IE = 0; SPI2CON1bits.DISSCK = 0; SPI2CON1bits.DISSDO = 0; SPI2CON1bits.MODE16 = 1; SPI2CON1bits.SMP = 0; SPI2CON1bits.CKE = 0; SPI2CON1bits.SSEN = 0; SPI2CON1bits.CKP = IO_HIGH; SPI2CON1bits.MSTEN = 1; SPI2CON1bits.SPRE = 4; SPI2CON1bits.PPRE = 3; /* There's no framed mode that does the normal "chip select" behavior, so control /SS2 manually */ SPI2CON2bits.FRMEN = 0; LATGbits.LATG9 = IO_HIGH; TRISGbits.TRISG9 = 0; SPI2STATbits.SPISIDL = 0; SPI2STATbits.SPIEN = 1; dac_write(0x0000); } static const uint16_t dac_lookup[1024] = { #include "lookup.inc" }; /* Write raw 16-bit desired value to DAC: DAC_HIGH 4.9998v DAC_MID 0v DAC_LOW -5v */ void dac_write(uint16_t val) { LATGbits.LATG9 = IO_LOW; if (IO_HIGH == 1) SPI2BUF = __dac_to_spi_cmd(val); else SPI2BUF = ~__dac_to_spi_cmd(val); while (!SPI2STATbits.SPIRBF) continue; (void) SPI2BUF; LATGbits.LATG9 = IO_HIGH; } /* Given a DAC command between DAC_LOW and DAC_HIGH, get the actual expected output voltage as a 16-bit value, where: 0xffff = 4.9998v 0x8000 = 0v 0x0000 = -5v */ uint16_t dac_get_actual_16bit(uint16_t val) { return __dac_to_16bit_equiv(val); } /* Given a DAC command between DAC_LOW and DAC_HIGH, get the actual expected output voltage as a FLOAT, where: DAC_HIGH = 4.9998v DAC_MID = 0v DAC_LOW = -5v Example: for 10-bit DAC, convert integer command 123 into the more accurate 123.45 using known lower bits. */ float dac_get_actual_float(uint16_t val) { return __dac_to_16bit_equiv(val) * (DAC_RANGE / 65536.0); }