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))); | 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_adc_callback)(void) = 0; | ||||
void (*adc_dma_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) | 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) | if (adc_adc_callback) | ||||
(*adc_adc_callback)(); | (*adc_adc_callback)(); | ||||
IFS0bits.AD1IF = 0; | |||||
} | } | ||||
/* DMA0 interrupt after 16 samples */ | /* DMA0 interrupt after 16 samples */ | ||||
void __attribute__((__interrupt__,auto_psv)) _DMA0Interrupt(void) | void __attribute__((__interrupt__,auto_psv)) _DMA0Interrupt(void) | ||||
{ | { | ||||
IFS0bits.DMA0IF = 0; | |||||
if (adc_dma_callback) | if (adc_dma_callback) | ||||
(*adc_dma_callback)(); | (*adc_dma_callback)(); | ||||
IFS0bits.DMA0IF = 0; | |||||
} | } | ||||
/* Initialize ADC1 to constantly DMA AN0. */ | /* Initialize ADC1 to constantly DMA AN0. */ | ||||
@@ -72,12 +83,12 @@ void adc_init(void) | |||||
DMA0CONbits.MODE = 0; /* Continuous, no ping-pong */ | DMA0CONbits.MODE = 0; /* Continuous, no ping-pong */ | ||||
DMA0PAD = (int)&ADC1BUF0; /* Get addresses from ADC1 */ | DMA0PAD = (int)&ADC1BUF0; /* Get addresses from ADC1 */ | ||||
DMA0CNT = 15; /* 16 transfers before wraparound */ | DMA0CNT = 15; /* 16 transfers before wraparound */ | ||||
DMA0STA = __builtin_dmaoffset(&adc_dmabuf); | |||||
DMA0STA = __builtin_dmaoffset(adc_dmabuf); | |||||
DMA0REQbits.IRQSEL = 13; /* Triggered by ADC1 */ | DMA0REQbits.IRQSEL = 13; /* Triggered by ADC1 */ | ||||
IFS0bits.DMA0IF = 0; | IFS0bits.DMA0IF = 0; | ||||
IEC0bits.DMA0IE = 1; /* DMA interrupt (every 16 samples) */ | IEC0bits.DMA0IE = 1; /* DMA interrupt (every 16 samples) */ | ||||
DMA0CONbits.CHEN = 1; /* enable this DMA channel */ | DMA0CONbits.CHEN = 1; /* enable this DMA channel */ | ||||
IFS0bits.AD1IF = 0; | 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 | #ifndef ADC_H | ||||
#define 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]; | extern uint16_t adc_dmabuf[16]; | ||||
/* Stores the offset of the most recently written DMA sample */ | |||||
extern int adc_offset; | |||||
/* Initialize internal ADC */ | /* Initialize internal ADC */ | ||||
void adc_init(void); | void adc_init(void); | ||||
@@ -7,14 +7,56 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <math.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 */ | /* 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) | int main(void) | ||||
@@ -24,15 +66,13 @@ int main(void) | |||||
adcext_init(); | adcext_init(); | ||||
dac_init(); | dac_init(); | ||||
adc_init(); | adc_init(); | ||||
adc_dma_callback = callback; | |||||
adc_adc_callback = fast_callback; | |||||
adc_dma_callback = slow_callback; | |||||
while(1) { | 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; | |||||
} | } |