zoom/firmware/adc.c

66 lines
1.1 KiB
C

#include "config.h"
#include "adc.h"
#include "timer.h"
/* Currently using software SPI because it's easy.
Consider using hardware SPI with DMA on a timer, though. */
#define TRIS_SDATA TRISFbits.TRISF7
#define R_SDATA PORTFbits.RF7
#define TRIS_SCLK TRISFbits.TRISF6
#define LAT_SCLK LATFbits.LATF6
#define TRIS_CS TRISBbits.TRISB2
#define LAT_CS LATBbits.LATB2
void adc_init(void)
{
TRIS_SDATA = 1;
LAT_CS = IO_HIGH;
TRIS_CS = 0;
LAT_SCLK = IO_HIGH;
TRIS_SCLK = 0;
}
int16_t adc_get(void)
{
uint16_t v = 0;
int i;
LAT_CS = IO_LOW;
for (i = 0; i < 16; i++) {
v <<= 1;
if (R_SDATA == IO_HIGH)
v |= 1;
LAT_SCLK = IO_LOW;
nop(); nop(); nop();
LAT_SCLK = IO_HIGH;
}
LAT_CS = IO_HIGH;
/* Sign-extend the 12-bit value */
if (v & 0x0800)
v |= 0xF000;
else
v &= ~0xF000;
return (int16_t) v;
}
uint16_t adc_get_raw(void)
{
uint16_t v = 0;
int i;
LAT_CS = IO_LOW;
for (i = 0; i < 16; i++) {
v <<= 1;
if (R_SDATA == IO_HIGH)
v |= 1;
LAT_SCLK = IO_LOW;
nop(); nop(); nop();
LAT_SCLK = IO_HIGH;
}
LAT_CS = IO_HIGH;
return (uint16_t) v;
}