78 lines
1.7 KiB
C
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);
|
|
}
|