Browse Source

Set up 128 KHz 12-bit ADC sampling with DMA, and send to UART at 0.5 Mbps.

Seems to work well.
Next step is to process ADC data at 128 KHz to determine DAC stepping,
and send DAC + ADC to PC at 8 KHz.




git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@5931 ddd99763-3ecb-0310-9145-efcb8ce7c51f
tags/zoom-1.0
jim 16 years ago
parent
commit
b95491274d
8 changed files with 137 additions and 33 deletions
  1. +83
    -0
      firmware/adc.c
  2. +14
    -0
      firmware/adc.h
  3. +10
    -4
      firmware/adcext.c
  4. +2
    -2
      firmware/adcext.h
  5. +0
    -1
      firmware/config.h
  6. +1
    -1
      firmware/uart.c
  7. +16
    -18
      firmware/zoom.c
  8. +11
    -7
      firmware/zoom.mcp

+ 83
- 0
firmware/adc.c View File

@@ -0,0 +1,83 @@
#include "config.h"
#include "adc.h"
#include "timer.h"
/* Layout of buffer:
adc_dmabuf[x] contains 16 samples of channel AN0
*/
uint16_t adc_dmabuf[16] __attribute__((space(dma)));
void (*adc_adc_callback)(void) = 0;
void (*adc_dma_callback)(void) = 0;
/* ADC1 interrupt after each sample (if enabled) */
void __attribute__((__interrupt__,auto_psv)) _ADC1Interrupt(void)
{
if (adc_adc_callback)
(*adc_adc_callback)();
IFS0bits.AD1IF = 0;
}
/* DMA0 interrupt after 16 samples */
void __attribute__((__interrupt__,auto_psv)) _DMA0Interrupt(void)
{
if (adc_dma_callback)
(*adc_dma_callback)();
IFS0bits.DMA0IF = 0;
}
/* Initialize ADC1 to constantly DMA AN0. */
void adc_init(void)
{
/* AD1CON1 */
AD1CON1bits.ADDMABM = 1; /* Scatter-gather DMA */
AD1CON1bits.AD12B = 1; /* 12-bit, 1 channel */
AD1CON1bits.FORM = 0; /* Integer output 0000dddddddddddd */
AD1CON1bits.SSRC = 2; /* Convert on Timer3 */
AD1CON1bits.ASAM = 1; /* Automatically start sampling */
AD1CON1bits.SIMSAM = 0; /* Simul sampling, N/A when AD12B=1 */
/* AD1CON2 */
AD1CON2bits.VCFG = 0; /* Ref: AVDD / AVSS */
// AD1CON2bits.VCFG = 3; /* Ref: VREF+ / VREF- */
AD1CON2bits.CSCNA = 0; /* Do not scan inputs on Mux A */
AD1CON2bits.CHPS = 0; /* Convert CH0 only, N/A when AD12B=1 */
AD1CON2bits.SMPI = 0; /* Increase DMA address at each sample */
AD1CON2bits.BUFM = 0; /* Fill buffer from start */
AD1CON2bits.ALTS = 0; /* Always use Mux A settings */
/* AD1CON3 */
AD1CON3bits.ADRC = 0; /* Use system clock, not internal RC */
AD1CON3bits.SAMC = 0; /* Sample time, N/A when ADRC = 0 */
AD1CON3bits.ADCS = 0x7; /* Tad = 8 * Tcy */
/* AD1CON4 */
AD1CON4bits.DMABL = 4; /* Each input gets 16 words in DMA buf */
/* Channel 0 setup */
AD1CHS0bits.CH0NA = 0; /* CH0-: Vrefl */
AD1CHS0bits.CH0SA = 0; /* CH0+: AN0 */
/* Set Timer3 to trigger conversion at 128KHz */
timer_setup_16bit(3, 128000, 0);
/* Turn it on */
AD1PCFGL = 0xfffe; /* Analog = AN0 */
AD1PCFGH = 0xffff;
AD2PCFGL = 0xffff;
AD1CON1bits.ADON = 1;
/* DMA0 setup */
DMA0CONbits.AMODE = 0; /* Register indirect, post-increment */
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);
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) */
}

+ 14
- 0
firmware/adc.h View File

@@ -0,0 +1,14 @@
#ifndef ADC_H
#define ADC_H
/* DMA region for the ADC */
extern uint16_t adc_dmabuf[16];
/* Initialize internal ADC */
void adc_init(void);
/* Callback functions */
extern void (*adc_adc_callback)(void);
extern void (*adc_dma_callback)(void);
#endif

+ 10
- 4
firmware/adcext.c View File

@@ -12,7 +12,7 @@
interrupt notification if desired */
/* Since the ADC is 5v, ADC SDO must be on a digital-only pin.
All exposed pins on B D and E are digital, so use SPI pins:
All exposed pins on B D and E are analog, so use SPI pins:
ADC SDO = PIC SDI1 = RF7
ADC SCK = PIC SCK1 = RF6
*/
@@ -30,16 +30,22 @@
/* Initialize ADC */
void adcext_init(void)
{
int i;
int32_t i;
TRIS_SDO = 1;
LAT_SCK = 0;
TRIS_SCK = 0;
/* Startup delay CS down to SCK high t4 = 5000ns */
for (i = 0; i < 5000 / 25; i++)
wait_25ns();
/* We need to monitor BUSY, I think. With the 2-wire
interface, we never know if we start in the middle of
a data output phase. For now, consider reading broken..
just return early. XXXX */
return;
/* Trigger a dummy read so we're prepared for the
next conversion */
(void) adcext_read();
@@ -118,7 +124,7 @@ void adcext_start_conversion(void)
LAT_SCK = 0;
/* Wait tKQMAX for SCK down to SDO valid in case we
call adc_is_conversion_finished right away. */
call adcext_is_conversion_ready right away. */
wait_200ns();
}


+ 2
- 2
firmware/adcext.h View File

@@ -1,5 +1,5 @@
#ifndef ADC_H
#define ADC_H
#ifndef ADCEXT_H
#define ADCEXT_H
/* Initialize ADC */
void adcext_init(void);


+ 0
- 1
firmware/config.h View File

@@ -13,7 +13,6 @@ typedef signed long long int64_t;
typedef unsigned long long uint64_t;

#define FCY 40000000
#define TMR1_RATE 8000

void config_init(void);



+ 1
- 1
firmware/uart.c View File

@@ -12,7 +12,7 @@ void uart_init(int uart, int32_t rate)

if (uart == 1) {
U1MODE = 0;
U1MODEbits.BRGH = 0;
U1MODEbits.BRGH = 0; // errata: BRGH=1 is broken
U1BRG = brg;
U1STA = 0;
U1MODEbits.UARTEN = 1;


+ 16
- 18
firmware/zoom.c View File

@@ -1,39 +1,37 @@
#include "config.h"
#include "adc.h"
#include "adcext.h"
#include "dac.h"
#include "uart.h"
#include "timer.h"
#include <stdio.h>
#include <math.h>

int32_t tmr1_ms = 0;
void TISR_HANDLER(1)
int new_data = 0;
uint16_t data;

void callback(void)
{
/* Send most recent sample to PC */
data = adc_dmabuf[15];
new_data = 1;
}

int main(void)
{
config_init();
uart1_init(1000000);
uart1_init(500000);
adcext_init();
dac_init();
timer_setup_16bit(1, 1000, 1);

TRISDbits.TRISD0 = 0;
TRISDbits.TRISD1 = 1;
TRISDbits.TRISD2 = 1;
adc_init();
adc_dma_callback = callback;

while(1) {
/* these are ints, so it should be atomic */
/*
tmp = output_count;
tmp2 = dacval;
uart1_put_hex((tmp & 0x7F) | (LATDbits.LATD0 ? 0x80 : 0x00));
uart1_put_hex((tmp2 & 0xFF00) >> 8);
uart1_put_hex((tmp2 & 0x00FF));
uart1_put('\r');
*/
if (new_data) {
uart1_put_hex16(data);
uart1_crlf();
new_data = 0;
}
}

for(;;) continue;


+ 11
- 7
firmware/zoom.mcp View File

@@ -31,6 +31,8 @@ file_010=no
file_011=no
file_012=no
file_013=no
file_014=no
file_015=no
[FILE_INFO]
file_000=zoom.c
file_001=config.c
@@ -39,13 +41,15 @@ file_003=util.c
file_004=dac.c
file_005=timer.c
file_006=adcext.c
file_007=config.h
file_008=uart.h
file_009=util.h
file_010=dac.h
file_011=timer.h
file_012=adcext.h
file_013=p33fj256gp710.gld
file_007=adc.c
file_008=config.h
file_009=uart.h
file_010=util.h
file_011=dac.h
file_012=timer.h
file_013=adcext.h
file_014=adc.h
file_015=p33fj256gp710.gld
[SUITE_INFO]
suite_guid={479DDE59-4D56-455E-855E-FFF59A3DB57E}
suite_state=


Loading…
Cancel
Save