git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@5928 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/zoom-1.0
@@ -1,5 +1,5 @@ | |||
#include "config.h" | |||
#include "adc.h" | |||
#include "adcext.h" | |||
/* The ADC (AD7846) is tricky, as new conversions start | |||
automatically when the previous data read finishes. | |||
@@ -28,7 +28,7 @@ | |||
#define wait_25ns() nop() | |||
/* Initialize ADC */ | |||
void adc_init(void) | |||
void adcext_init(void) | |||
{ | |||
int i; | |||
@@ -42,13 +42,13 @@ void adc_init(void) | |||
/* Trigger a dummy read so we're prepared for the | |||
next conversion */ | |||
(void) adc_read(); | |||
(void) adcext_read(); | |||
} | |||
/* Start a conversion if it hasn't already been started. | |||
Wait for conversion to finish. | |||
Read the result and return the raw 32-bit value. */ | |||
uint32_t adc_read(void) | |||
uint32_t adcext_read(void) | |||
{ | |||
uint32_t val; | |||
int i; | |||
@@ -91,7 +91,7 @@ uint32_t adc_read(void) | |||
The return value is full int32 range but only the high | |||
24 should be significant: low 3 will always be 0, | |||
and the next 5 will be sub-resolution (see datasheet). */ | |||
int32_t adc_convert(uint32_t raw) | |||
int32_t adcext_convert(uint32_t raw) | |||
{ | |||
int sigmsb = (raw >> 28) & 3; | |||
@@ -107,12 +107,12 @@ int32_t adc_convert(uint32_t raw) | |||
/* Start a new conversion. If a conversion was already started | |||
but the result was not read, this does nothing. */ | |||
void adc_start_conversion(void) | |||
void adcext_start_conversion(void) | |||
{ | |||
/* If we had a previous conversion ready to read, | |||
read it out so we can start a new conversion instead */ | |||
if (adc_is_conversion_ready()) | |||
(void) adc_read(); | |||
if (adcext_is_conversion_ready()) | |||
(void) adcext_read(); | |||
/* Start conversion by completing previous read */ | |||
LAT_SCK = 0; | |||
@@ -123,7 +123,7 @@ void adc_start_conversion(void) | |||
} | |||
/* Return 1 if a conversion is finished and ready to be read, 0 otherwise */ | |||
int adc_is_conversion_ready(void) | |||
int adcext_is_conversion_ready(void) | |||
{ | |||
if (LAT_SCK == 0 && R_SDO == 0) | |||
return 1; |
@@ -2,22 +2,22 @@ | |||
#define ADC_H | |||
/* Initialize ADC */ | |||
void adc_init(void); | |||
void adcext_init(void); | |||
/* Start a conversion if it hasn't already been started. | |||
Wait for conversion to finish. | |||
Read the result and return the raw 32-bit value. */ | |||
uint32_t adc_read(void); | |||
uint32_t adcext_read(void); | |||
/* Convert a raw 32-bit value into a signed result. | |||
The return value range is -(2^31) to (2^31)-1 */ | |||
int32_t adc_convert(uint32_t raw); | |||
int32_t adcext_convert(uint32_t raw); | |||
/* Start a new conversion. If a conversion was already started | |||
but the result was not read, this does nothing. */ | |||
void adc_start_conversion(void); | |||
void adcext_start_conversion(void); | |||
/* Return 1 if a conversion is in progress, 0 otherwise */ | |||
int adc_is_conversion_ready(void); | |||
int adcext_is_conversion_ready(void); | |||
#endif |
@@ -13,6 +13,7 @@ typedef signed long long int64_t; | |||
typedef unsigned long long uint64_t; | |||
#define FCY 40000000 | |||
#define TMR1_RATE 8000 | |||
void config_init(void); | |||
@@ -0,0 +1,82 @@ | |||
#include "config.h" | |||
#include "timer.h" | |||
/* Setup a 16-bit timer to overflow at the specified frequency | |||
timer = 1-9 | |||
freq = Hz, or 0 to disable the timer. | |||
interrupt = 1 to enable interrupt, 0 to disable | |||
*/ | |||
int timer_setup_16bit(int timer, uint32_t freq, int ie) | |||
{ | |||
uint32_t period; | |||
uint16_t prescale; | |||
if (timer < 1 || timer > 9) | |||
return -1; | |||
if (freq == 0) { | |||
switch(timer) { | |||
case 1: T1CONbits.TON = 0; return 0; | |||
case 2: T2CONbits.TON = 0; return 0; | |||
case 3: T3CONbits.TON = 0; return 0; | |||
case 4: T4CONbits.TON = 0; return 0; | |||
case 5: T5CONbits.TON = 0; return 0; | |||
case 6: T6CONbits.TON = 0; return 0; | |||
case 7: T7CONbits.TON = 0; return 0; | |||
case 8: T8CONbits.TON = 0; return 0; | |||
case 9: T9CONbits.TON = 0; return 0; | |||
} | |||
} | |||
/* Figure out timer prescaler and period values. Max period | |||
is 65535 (PRx = 65534) so we can still attain 100% duty | |||
cycle when using a timer for PWM. */ | |||
if ((period = FCY / (freq * 1L)) <= 65535) | |||
prescale = 0; | |||
else if ((period = FCY / (freq * 8L)) <= 65535) | |||
prescale = 1; | |||
else if ((period = FCY / (freq * 64L)) <= 65535) | |||
prescale = 2; | |||
else if ((period = FCY / (freq * 256L)) <= 65535) | |||
prescale = 3; | |||
else | |||
prescale = 3, period = 65535; | |||
if (period > 0) | |||
period -= 1; | |||
switch (timer) { | |||
#define __timer_setup_case(x) \ | |||
case x: \ | |||
T##x##CONbits.TON = 0; \ | |||
T##x##CONbits.TCKPS = prescale; \ | |||
PR##x = period; \ | |||
T##x##CONbits.TON = 1; \ | |||
break | |||
__timer_setup_case(1); | |||
__timer_setup_case(2); | |||
__timer_setup_case(3); | |||
__timer_setup_case(4); | |||
__timer_setup_case(5); | |||
__timer_setup_case(6); | |||
__timer_setup_case(7); | |||
__timer_setup_case(8); | |||
__timer_setup_case(9); | |||
#undef __timer_setup_case | |||
} | |||
/* Enable interrupt if requested */ | |||
timer_clear_txif(timer); | |||
switch (timer) { | |||
case 1: IEC0bits.T1IE = ie; break; | |||
case 2: IEC0bits.T2IE = ie; break; | |||
case 3: IEC0bits.T3IE = ie; break; | |||
case 4: IEC1bits.T4IE = ie; break; | |||
case 5: IEC1bits.T5IE = ie; break; | |||
case 6: IEC2bits.T6IE = ie; break; | |||
case 7: IEC3bits.T7IE = ie; break; | |||
case 8: IEC3bits.T8IE = ie; break; | |||
case 9: IEC3bits.T9IE = ie; break; | |||
} | |||
return 0; | |||
} |
@@ -0,0 +1,31 @@ | |||
#ifndef TIMER_H | |||
#define TIMER_H | |||
#include "config.h" | |||
/* Setup a 16-bit timer to overflow at the specified frequency | |||
timer = 1-9 | |||
freq = Hz, or 0 to disable the timer. | |||
ie = 1 to enable interrupt, 0 to disable | |||
*/ | |||
int timer_setup_16bit(int timer, uint32_t freq, int ie); | |||
#define TISR_HANDLER(x) \ | |||
__attribute__((__interrupt__,auto_psv)) _T##x##Interrupt(void) | |||
/* Clear TxIF corresponding to a timer */ | |||
#define timer_clear_txif(timer) do { \ | |||
if ((timer) == 1) IFS0bits.T1IF = 0; \ | |||
if ((timer) == 2) IFS0bits.T2IF = 0; \ | |||
if ((timer) == 3) IFS0bits.T3IF = 0; \ | |||
if ((timer) == 4) IFS1bits.T4IF = 0; \ | |||
if ((timer) == 5) IFS1bits.T5IF = 0; \ | |||
if ((timer) == 6) IFS2bits.T6IF = 0; \ | |||
if ((timer) == 7) IFS3bits.T7IF = 0; \ | |||
if ((timer) == 8) IFS3bits.T8IF = 0; \ | |||
if ((timer) == 9) IFS3bits.T9IF = 0; \ | |||
} while(0) | |||
#endif |
@@ -6,58 +6,35 @@ | |||
#include <stdio.h> | |||
#include <math.h> | |||
#define TEST_LEN 128 | |||
uint32_t samples[TEST_LEN]; | |||
uint32_t mean; | |||
uint32_t stdev; | |||
/* Read TEST_LEN samples and compute mean & stdev. */ | |||
void test_adc(void) | |||
int32_t tmr1_ms = 0; | |||
void TISR_HANDLER(1) | |||
{ | |||
uint32_t tmp = 0; | |||
int i; | |||
for (i = 0; i < TEST_LEN; i++) { | |||
samples[i] = adc_read(); | |||
tmp += samples[i]; | |||
} | |||
mean = tmp / TEST_LEN; | |||
tmp = 0; | |||
for (i = 0; i < TEST_LEN; i++) | |||
tmp += (samples[i] - mean) * (samples[i] - mean); | |||
stdev = sqrt(tmp); | |||
} | |||
int main(void) | |||
{ | |||
int32_t i; | |||
int32_t j; | |||
config_init(); | |||
uart1_init(115200); | |||
tmr1_init(); | |||
tmr1_wait_ms(100); | |||
adc_init(); | |||
uart1_init(1000000); | |||
adcext_init(); | |||
dac_init(); | |||
uart1_put_string("ADC/DAC test\r\n"); | |||
top: | |||
for (i = 0; i < 32768; i ++) { | |||
dac_write(i); | |||
tmr1_wait_ms(1); | |||
for (j = 0; j < TEST_LEN; j++) { | |||
uart1_put_dec(i); | |||
uart1_put(' '); | |||
uart1_put_dec(adc_convert(adc_read())); | |||
uart1_put_string("\r\n"); | |||
} | |||
timer_setup_16bit(1, 1000, 1); | |||
TRISDbits.TRISD0 = 0; | |||
TRISDbits.TRISD1 = 1; | |||
TRISDbits.TRISD2 = 1; | |||
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'); | |||
*/ | |||
} | |||
uart1_put_string("-----\r\n"); | |||
goto top; | |||
return 0; | |||
for(;;) continue; | |||
} |
@@ -37,14 +37,14 @@ file_001=config.c | |||
file_002=uart.c | |||
file_003=util.c | |||
file_004=dac.c | |||
file_005=adc.c | |||
file_006=timer.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=adc.h | |||
file_012=timer.h | |||
file_011=timer.h | |||
file_012=adcext.h | |||
file_013=p33fj256gp710.gld | |||
[SUITE_INFO] | |||
suite_guid={479DDE59-4D56-455E-855E-FFF59A3DB57E} | |||