#include "msp430x20x2.h" #define OVERSAMPLING_RATIO 4 #define LOG_OVERSAMPLING_RATIO 2 #define MAX_OS_VARIANCE 900 /* 30^2 corresponding to 97mV out of 3.3V */ #define MIN_DELTAV 102 /* 0.33V out of 3.3V */ #define SATURATION_VHIGH 820 /* 2.97V out of 3.3V */ #define HEADER_BYTES 3 #define BITS_PER_BYTE 8 #define LOG_BITS_PER_BYTE 3 #define BYTES_PER_BLOCK 9 unsigned short os_analog_buffer[OVERSAMPLING_RATIO]; unsigned short os_mean; unsigned int os_variance; unsigned short previous_analog_sample; short vhigh_calibrated = 0; short vlow_calibrated = 0; unsigned short byte_number=0; unsigned short bit_number=0; unsigned short os_number=0; unsigned short os_digital_buffer=0; unsigned char current_byte; unsigned char byte_stream[BYTES_PER_BLOCK]; unsigned char previous_digital_sample; unsigned short vhigh=0; unsigned short vlow=0; unsigned short vth; unsigned short low_gain_mode=0; /* 1 for low gain and 0 for high gain */ int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; /* Setup I/O Ports P1.1 : RX Serial Digital Data Input P1.2 : 1-bit I-V gain control (0 for high gain and 1 for high gain) [P1.6(MSB) P1.5 P1.4 P1.3(LSB)]: Discrete Vth binary control bits P1.7 : RX Anglog Input for synchronization */ P1OUT = 0; P1SEL = BIT7; P1DIR = 0xff; P1DIR &= ~(BIT1+BIT7); P1REN = BIT1; /* Clock Setup CPU clock: 16MHz ADC Clock: 16MHz/4=4MHz */ BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; BCSCTL2 = SELM_0+DIVM_0+DIVS_2; /* ADC setup Repeating Single-Channel Sampling */ ADC10CTL1 = INCH_7+ADC10DIV_7+CONSEQ_2+ADC10SSEL_3; ADC10CTL0 = SREF_0+ADC10SHT_3+ADC10ON+ADC10IE; ADC10AE0 = 0x80; /* ADC Starts */ ADC10CTL0 |= ENC+ADC10SC+MSC; /* Wait for interruption and receive */ while(1){ _BIS_SR(GIE); }; } #pragma vector = ADC10_VECTOR __interrupt void adc_isr(void) { int i; if ((vhigh_calibrated==0) || (vlow_calibrated==0)) { /* Analog sampling phase */ P1OUT &= ~BIT0; /* load sampling value */ os_analog_buffer[os_number] = ADC10MEM; /* Point to next oversampling number */ os_number ++; if (os_number>=OVERSAMPLING_RATIO){ /* Enough samples to make decision */ /* Check variation of samples */ os_mean = 0; for (i=0; i>LOG_OVERSAMPLING_RATIO; os_variance = 0; for (i=0; i>LOG_OVERSAMPLING_RATIO; if (os_variance > MAX_OS_VARIANCE) { /* sample-to-sample variance is too large */ /* drop the oldest sample and shift others */ for (i=1; i 0) && ((os_mean > previous_analog_sample+MIN_DELTAV)||(os_mean+MIN_DELTAV < previous_analog_sample))) { /* The current sample is at a different level from the previous one */ /* reset bit_number */ bit_number = 0; vhigh = 0; }//if /* Accumulate Vhigh results */ vhigh += os_mean; previous_analog_sample = os_mean; /* Point to the next bit */ bit_number ++; if (bit_number >= (BITS_PER_BYTE<<1)) { /* This is the last bit of the Vhigh calibration sequence */ /* Averaging */ vhigh = (vhigh>>LOG_BITS_PER_BYTE)>>1; /* Wrap the bit number */ bit_number = 0; /* Vhigh calibration succeeds */ vhigh_calibrated = 1; }//if }//if else { /* vhigh is calibrated but vlow is not */ /* Receive the all-0 pattern at the analog input port P1.7 */ /* Accumulate the multiple Vlow measurement results */ vlow += os_mean; /* Point to the next bit */ bit_number ++; if (bit_number >= BITS_PER_BYTE) { /* This is the last bit for Vlow calibration */ /* Averaging */ vlow = vlow>>LOG_BITS_PER_BYTE; /* Wrap the bit number */ bit_number = 0; /* Calculate Vth whose approx. value is the mean of Vhigh and Vlow*/ vth = (vhigh + vlow)>>1; /* Assign Digital Controll bits [P1.6 - P1.3] */ P1OUT = (low_gain_mode+((vth>>6)<<1))<<2; /* Vlow calibration finished */ vlow_calibrated = 1; /* I-V gain mode adjustment if necessary */ if (vhigh <= vlow+MIN_DELTAV){ /* Peak-to-peak voltage is less than the detectable level */ if (vhigh > SATURATION_VHIGH) { /* Vhigh saturated */ /* switch to low gain mode in the next receiving block */ low_gain_mode = 1; }//if else { /* Vhigh not saturated */ /* switch to high gain mode in the next receiving block */ low_gain_mode = 0; }//else }//if }//if }//else }//if }//if else { /* Digital sampling phase */ /* Start to sample the digital data port P1.1 */ if (P1IN&BIT1) /* The current sample is 1 */ os_digital_buffer ++; /* Point to the next sample */ os_number ++; if (os_number >= OVERSAMPLING_RATIO){ /* This is the last sample of a bit */ /* wrap os_number */ os_number = 0; if (os_digital_buffer>=(OVERSAMPLING_RATIO>>1)) { /* Expected input bit is 1 */ /* Assign 1 to current_byte[bit_number] */ current_byte |= (BIT0<= BITS_PER_BYTE) { /* This is the last bit */ /* Wrap the bit_number */ bit_number = 0; /* Assign the completed byte to the stream */ byte_stream[byte_number] = current_byte; /* Point to the next byte */ byte_number ++; if (byte_number >= BYTES_PER_BLOCK) { /* This is the last byte */ /* Wrap the byte number */ byte_number = 0; /* Reset calibration */ vhigh = 0; vlow = 0; vhigh_calibrated = 0; vlow_calibrated = 0; /* set I-V gain mode in the next block */ switch (low_gain_mode) { case 1: /* set P1.2 for low gain */ P1OUT |= BIT2; break; case 0: /* Reset P1.2 for high gain */ P1OUT &= ~BIT2; break; }//switch }//if }//if }//if }//else }//adc_isr