git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@5936 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/zoom-1.0
@@ -7,23 +7,34 @@ | |||
*/ | |||
uint16_t adc_dmabuf[16] __attribute__((space(dma))); | |||
/* Stores the offset of the most recently written DMA sample */ | |||
int adc_offset = 0; | |||
void (*adc_adc_callback)(void) = 0; | |||
void (*adc_dma_callback)(void) = 0; | |||
/* ADC1 interrupt after each sample (if enabled) */ | |||
/* ADC1 interrupt after each sample */ | |||
void __attribute__((__interrupt__,auto_psv)) _ADC1Interrupt(void) | |||
{ | |||
static int next_adc_offset = 0; | |||
adc_offset = next_adc_offset; | |||
/* DMA0STA points to the next sample that will be written. | |||
Convert that into a buffer offset that we'll for next time */ | |||
next_adc_offset = (DMA0STA - __builtin_dmaoffset(adc_dmabuf)) >> 1; | |||
IFS0bits.AD1IF = 0; | |||
if (adc_adc_callback) | |||
(*adc_adc_callback)(); | |||
IFS0bits.AD1IF = 0; | |||
} | |||
/* DMA0 interrupt after 16 samples */ | |||
void __attribute__((__interrupt__,auto_psv)) _DMA0Interrupt(void) | |||
{ | |||
IFS0bits.DMA0IF = 0; | |||
if (adc_dma_callback) | |||
(*adc_dma_callback)(); | |||
IFS0bits.DMA0IF = 0; | |||
} | |||
/* Initialize ADC1 to constantly DMA AN0. */ | |||
@@ -72,12 +83,12 @@ void adc_init(void) | |||
DMA0CONbits.MODE = 0; /* Continuous, no ping-pong */ | |||
DMA0PAD = (int)&ADC1BUF0; /* Get addresses from ADC1 */ | |||
DMA0CNT = 15; /* 16 transfers before wraparound */ | |||
DMA0STA = __builtin_dmaoffset(&adc_dmabuf); | |||
DMA0STA = __builtin_dmaoffset(adc_dmabuf); | |||
DMA0REQbits.IRQSEL = 13; /* Triggered by ADC1 */ | |||
IFS0bits.DMA0IF = 0; | |||
IEC0bits.DMA0IE = 1; /* DMA interrupt (every 16 samples) */ | |||
DMA0CONbits.CHEN = 1; /* enable this DMA channel */ | |||
IFS0bits.AD1IF = 0; | |||
IEC0bits.AD1IE = 0; /* No ADC interrupt (every sample) */ | |||
IEC0bits.AD1IE = 1; /* ADC interrupt (every sample) */ | |||
} |
@@ -1,9 +1,12 @@ | |||
#ifndef ADC_H | |||
#define ADC_H | |||
/* DMA region for the ADC */ | |||
/* adc_dmabuf[x] contains 16 samples of channel AN0 */ | |||
extern uint16_t adc_dmabuf[16]; | |||
/* Stores the offset of the most recently written DMA sample */ | |||
extern int adc_offset; | |||
/* Initialize internal ADC */ | |||
void adc_init(void); | |||
@@ -7,14 +7,56 @@ | |||
#include <stdio.h> | |||
#include <math.h> | |||
int new_data = 0; | |||
uint16_t data; | |||
int send_data = 0; | |||
uint16_t send_adc, send_dac; | |||
void callback(void) | |||
/* Outside these thresholds, we step the DAC value */ | |||
#define ADC_MIN 0x0100 | |||
#define ADC_MAX 0x0e00 | |||
/* Max/min DAC output value */ | |||
#define DAC_MIN 0x0000 | |||
#define DAC_MAX 0x0fff | |||
/* Shift the DAC value left this far when writing it out */ | |||
#define DAC_SHIFT 4 | |||
uint16_t dac_cmd = ((uint32_t)DAC_MAX + DAC_MIN) / 2; | |||
/* 128 KHz, after each ADC sample */ | |||
void fast_callback(void) | |||
{ | |||
uint16_t v = adc_dmabuf[adc_offset]; | |||
if (v < ADC_MIN && dac_cmd < DAC_MAX) | |||
dac_cmd ++; | |||
if (v > ADC_MAX && dac_cmd > DAC_MIN) | |||
dac_cmd --; | |||
/* Write new value to DAC */ | |||
dac_write(dac_cmd << DAC_SHIFT); | |||
} | |||
/* 8 KHz, after DMA buffer filled */ | |||
void slow_callback(void) | |||
{ | |||
/* Send most recent sample to PC */ | |||
data = adc_dmabuf[15]; | |||
new_data = 1; | |||
send_adc = adc_dmabuf[adc_offset]; | |||
send_dac = dac_cmd; | |||
send_data = 1; | |||
} | |||
void send_to_pc(void) | |||
{ | |||
/* Sent data format: | |||
1Aaa aaaa 0aaa aaDd 0ddd dddd 0ddd dddd | |||
Aaaaaaaaaaaa = 12-bit ADC value | |||
Dddddddddddddddd = 16-bit DAC command | |||
*/ | |||
uart1_put(0x80 | ((send_adc & 0x0FE0) >> 5)); | |||
uart1_put(((send_adc & 0x001F) << 2) | ((send_dac & 0xC000) >> 14)); | |||
uart1_put((send_dac & 0x3F80) >> 7); | |||
uart1_put((send_dac & 0x007F)); | |||
} | |||
int main(void) | |||
@@ -24,15 +66,13 @@ int main(void) | |||
adcext_init(); | |||
dac_init(); | |||
adc_init(); | |||
adc_dma_callback = callback; | |||
adc_adc_callback = fast_callback; | |||
adc_dma_callback = slow_callback; | |||
while(1) { | |||
if (new_data) { | |||
uart1_put_hex16(data); | |||
uart1_crlf(); | |||
new_data = 0; | |||
if (send_data) { | |||
send_to_pc(); | |||
send_data = 0; | |||
} | |||
} | |||
for(;;) continue; | |||
} |