From 136fb77276681c6147bca3f869a0089f8eba54b6 Mon Sep 17 00:00:00 2001 From: jim Date: Tue, 12 Feb 2008 02:58:54 +0000 Subject: [PATCH] Start refactoring timer stuff for internal ADC git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@5928 ddd99763-3ecb-0310-9145-efcb8ce7c51f --- firmware/{adc.c => adcext.c} | 18 ++++---- firmware/{adc.h => adcext.h} | 10 ++--- firmware/config.h | 1 + firmware/timer.c | 82 ++++++++++++++++++++++++++++++++++++ firmware/timer.h | 31 ++++++++++++++ firmware/zoom.c | 67 ++++++++++------------------- firmware/zoom.mcp | 8 ++-- 7 files changed, 154 insertions(+), 63 deletions(-) rename firmware/{adc.c => adcext.c} (88%) rename firmware/{adc.h => adcext.h} (72%) create mode 100644 firmware/timer.c create mode 100644 firmware/timer.h diff --git a/firmware/adc.c b/firmware/adcext.c similarity index 88% rename from firmware/adc.c rename to firmware/adcext.c index 0069048..916ae6d 100644 --- a/firmware/adc.c +++ b/firmware/adcext.c @@ -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; diff --git a/firmware/adc.h b/firmware/adcext.h similarity index 72% rename from firmware/adc.h rename to firmware/adcext.h index 4c49a93..8b113fc 100644 --- a/firmware/adc.h +++ b/firmware/adcext.h @@ -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 diff --git a/firmware/config.h b/firmware/config.h index 38a7652..fb63bfa 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -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); diff --git a/firmware/timer.c b/firmware/timer.c new file mode 100644 index 0000000..18c3105 --- /dev/null +++ b/firmware/timer.c @@ -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; +} diff --git a/firmware/timer.h b/firmware/timer.h new file mode 100644 index 0000000..ea22b15 --- /dev/null +++ b/firmware/timer.h @@ -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 diff --git a/firmware/zoom.c b/firmware/zoom.c index 625839a..7466494 100644 --- a/firmware/zoom.c +++ b/firmware/zoom.c @@ -6,58 +6,35 @@ #include #include -#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; } diff --git a/firmware/zoom.mcp b/firmware/zoom.mcp index 21d9c70..4d3822c 100644 --- a/firmware/zoom.mcp +++ b/firmware/zoom.mcp @@ -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}