Browse Source

Simple "zoom nilm" behavior & sending ADC/DAC data to the PC.

git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@5936 ddd99763-3ecb-0310-9145-efcb8ce7c51f
tags/zoom-1.0
jim 16 years ago
parent
commit
b376f39f83
3 changed files with 72 additions and 18 deletions
  1. +16
    -5
      firmware/adc.c
  2. +4
    -1
      firmware/adc.h
  3. +52
    -12
      firmware/zoom.c

+ 16
- 5
firmware/adc.c View File

@@ -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) */
}

+ 4
- 1
firmware/adc.h View File

@@ -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);


+ 52
- 12
firmware/zoom.c View File

@@ -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;
}

Loading…
Cancel
Save