zoom/firmware/dac.c
2013-06-12 18:40:40 -04:00

78 lines
1.7 KiB
C

#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);
}