AnalogIn - use median of the sampling data for stabler input value

Dependencies:   mbed

Committer:
yamaguch
Date:
Mon Jun 20 10:47:02 2011 +0000
Revision:
0:bbe67df5e586
0.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yamaguch 0:bbe67df5e586 1 #include "AnalogIn2.h"
yamaguch 0:bbe67df5e586 2
yamaguch 0:bbe67df5e586 3 short int quickSelect(unsigned short arr[], int n);
yamaguch 0:bbe67df5e586 4
yamaguch 0:bbe67df5e586 5 AnalogIn2::AnalogIn2(PinName pinName) : pinName(pinName) {
yamaguch 0:bbe67df5e586 6 switch (pinName) {
yamaguch 0:bbe67df5e586 7 case p15:
yamaguch 0:bbe67df5e586 8 channel = 0;
yamaguch 0:bbe67df5e586 9 break;
yamaguch 0:bbe67df5e586 10 case p16:
yamaguch 0:bbe67df5e586 11 channel = 1;
yamaguch 0:bbe67df5e586 12 break;
yamaguch 0:bbe67df5e586 13 case p17:
yamaguch 0:bbe67df5e586 14 channel = 2;
yamaguch 0:bbe67df5e586 15 break;
yamaguch 0:bbe67df5e586 16 case p18:
yamaguch 0:bbe67df5e586 17 channel = 3;
yamaguch 0:bbe67df5e586 18 break;
yamaguch 0:bbe67df5e586 19 case p19:
yamaguch 0:bbe67df5e586 20 channel = 4;
yamaguch 0:bbe67df5e586 21 break;
yamaguch 0:bbe67df5e586 22 case p20:
yamaguch 0:bbe67df5e586 23 channel = 5;
yamaguch 0:bbe67df5e586 24 break;
yamaguch 0:bbe67df5e586 25 }
yamaguch 0:bbe67df5e586 26 read_u16(1);
yamaguch 0:bbe67df5e586 27 }
yamaguch 0:bbe67df5e586 28
yamaguch 0:bbe67df5e586 29 unsigned short AnalogIn2::read_u16(int nSamples) {
yamaguch 0:bbe67df5e586 30 // power on, clk divider /4
yamaguch 0:bbe67df5e586 31 LPC_SC->PCONP |= (1 << 12);
yamaguch 0:bbe67df5e586 32 LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
yamaguch 0:bbe67df5e586 33
yamaguch 0:bbe67df5e586 34 // software-controlled ADC settings
yamaguch 0:bbe67df5e586 35 LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
yamaguch 0:bbe67df5e586 36 | (25 << 8) // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz
yamaguch 0:bbe67df5e586 37 | (0 << 16) // BURST: 0 = software control
yamaguch 0:bbe67df5e586 38 | (0 << 17) // CLKS: not applicable
yamaguch 0:bbe67df5e586 39 | (1 << 21) // PDN: 1 = operational
yamaguch 0:bbe67df5e586 40 | (0 << 24) // START: 0 = no start
yamaguch 0:bbe67df5e586 41 | (0 << 27); // EDGE: not applicable
yamaguch 0:bbe67df5e586 42
yamaguch 0:bbe67df5e586 43 switch (pinName) {
yamaguch 0:bbe67df5e586 44 case p15:// =p0.23 of LPC1768
yamaguch 0:bbe67df5e586 45 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
yamaguch 0:bbe67df5e586 46 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
yamaguch 0:bbe67df5e586 47 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
yamaguch 0:bbe67df5e586 48 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
yamaguch 0:bbe67df5e586 49 break;
yamaguch 0:bbe67df5e586 50 case p16:// =p0.24 of LPC1768
yamaguch 0:bbe67df5e586 51 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
yamaguch 0:bbe67df5e586 52 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
yamaguch 0:bbe67df5e586 53 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
yamaguch 0:bbe67df5e586 54 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
yamaguch 0:bbe67df5e586 55 break;
yamaguch 0:bbe67df5e586 56 case p17:// =p0.25 of LPC1768
yamaguch 0:bbe67df5e586 57 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
yamaguch 0:bbe67df5e586 58 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
yamaguch 0:bbe67df5e586 59 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
yamaguch 0:bbe67df5e586 60 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
yamaguch 0:bbe67df5e586 61 break;
yamaguch 0:bbe67df5e586 62 case p18:// =p0.26 of LPC1768:
yamaguch 0:bbe67df5e586 63 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
yamaguch 0:bbe67df5e586 64 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
yamaguch 0:bbe67df5e586 65 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
yamaguch 0:bbe67df5e586 66 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
yamaguch 0:bbe67df5e586 67 break;
yamaguch 0:bbe67df5e586 68 case p19:// =p1.30 of LPC1768
yamaguch 0:bbe67df5e586 69 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
yamaguch 0:bbe67df5e586 70 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
yamaguch 0:bbe67df5e586 71 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
yamaguch 0:bbe67df5e586 72 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
yamaguch 0:bbe67df5e586 73 break;
yamaguch 0:bbe67df5e586 74 case p20:// =p1.31 of LPC1768
yamaguch 0:bbe67df5e586 75 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
yamaguch 0:bbe67df5e586 76 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
yamaguch 0:bbe67df5e586 77 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
yamaguch 0:bbe67df5e586 78 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
yamaguch 0:bbe67df5e586 79 break;
yamaguch 0:bbe67df5e586 80 }
yamaguch 0:bbe67df5e586 81
yamaguch 0:bbe67df5e586 82 // Repeatedly get the sample data until DONE bit
yamaguch 0:bbe67df5e586 83 unsigned short a[nSamples];
yamaguch 0:bbe67df5e586 84 for (int i = 0; i < nSamples; i++) {
yamaguch 0:bbe67df5e586 85 unsigned int data;
yamaguch 0:bbe67df5e586 86 // Select channel and start conversion
yamaguch 0:bbe67df5e586 87 LPC_ADC->ADCR &= ~0xFF;
yamaguch 0:bbe67df5e586 88 LPC_ADC->ADCR |= 1 << channel;
yamaguch 0:bbe67df5e586 89 LPC_ADC->ADCR |= 1 << 24;
yamaguch 0:bbe67df5e586 90 do {
yamaguch 0:bbe67df5e586 91 data = LPC_ADC->ADGDR;
yamaguch 0:bbe67df5e586 92 } while ((data & ((unsigned int)1 << 31)) == 0);
yamaguch 0:bbe67df5e586 93 // Stop conversion
yamaguch 0:bbe67df5e586 94 LPC_ADC->ADCR &= ~(1 << 24);
yamaguch 0:bbe67df5e586 95
yamaguch 0:bbe67df5e586 96 a[i] = data & 65535;
yamaguch 0:bbe67df5e586 97 }
yamaguch 0:bbe67df5e586 98
yamaguch 0:bbe67df5e586 99 return quickSelect(a, nSamples);
yamaguch 0:bbe67df5e586 100 }
yamaguch 0:bbe67df5e586 101
yamaguch 0:bbe67df5e586 102 float AnalogIn2::read(int nSamples) {
yamaguch 0:bbe67df5e586 103 return (read_u16(nSamples) >> 4) / 4096.0;
yamaguch 0:bbe67df5e586 104 }
yamaguch 0:bbe67df5e586 105
yamaguch 0:bbe67df5e586 106 AnalogIn2::operator float() {
yamaguch 0:bbe67df5e586 107 return read();
yamaguch 0:bbe67df5e586 108 }
yamaguch 0:bbe67df5e586 109
yamaguch 0:bbe67df5e586 110 /*
yamaguch 0:bbe67df5e586 111 * This Quickselect routine is based on the algorithm described in
yamaguch 0:bbe67df5e586 112 * "Numerical recipes in C", Second Edition,
yamaguch 0:bbe67df5e586 113 * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
yamaguch 0:bbe67df5e586 114 * This code by Nicolas Devillard - 1998. Public domain. */
yamaguch 0:bbe67df5e586 115
yamaguch 0:bbe67df5e586 116 #define SWAP(a,b) {unsigned int t = (a); (a) = (b); (b) = t;}
yamaguch 0:bbe67df5e586 117
yamaguch 0:bbe67df5e586 118 short int quickSelect(unsigned short arr[], int n) {
yamaguch 0:bbe67df5e586 119 int low = 0, high = n - 1;
yamaguch 0:bbe67df5e586 120 unsigned int median = (low + high) / 2;
yamaguch 0:bbe67df5e586 121
yamaguch 0:bbe67df5e586 122 for (;;) {
yamaguch 0:bbe67df5e586 123 if (high <= low) /* One element only */
yamaguch 0:bbe67df5e586 124 return arr[median];
yamaguch 0:bbe67df5e586 125 if (high == low + 1) { /* Two elements only */
yamaguch 0:bbe67df5e586 126 if (arr[low] > arr[high])
yamaguch 0:bbe67df5e586 127 SWAP(arr[low], arr[high]);
yamaguch 0:bbe67df5e586 128 return arr[median];
yamaguch 0:bbe67df5e586 129 }
yamaguch 0:bbe67df5e586 130
yamaguch 0:bbe67df5e586 131 /* Find median of low, middle and high items; swap into position low */
yamaguch 0:bbe67df5e586 132 int middle = (low + high) / 2;
yamaguch 0:bbe67df5e586 133 if (arr[middle] > arr[high])
yamaguch 0:bbe67df5e586 134 SWAP(arr[middle], arr[high]);
yamaguch 0:bbe67df5e586 135 if (arr[low] > arr[high])
yamaguch 0:bbe67df5e586 136 SWAP(arr[low], arr[high]);
yamaguch 0:bbe67df5e586 137 if (arr[middle] > arr[low])
yamaguch 0:bbe67df5e586 138 SWAP(arr[middle], arr[low]);
yamaguch 0:bbe67df5e586 139 /* Swap low item (now in position middle) into position (low + 1) */
yamaguch 0:bbe67df5e586 140 SWAP(arr[middle], arr[low + 1]);
yamaguch 0:bbe67df5e586 141
yamaguch 0:bbe67df5e586 142 /* Nibble from each end towards middle, swapping items when stuck */
yamaguch 0:bbe67df5e586 143 int ll = low + 1;
yamaguch 0:bbe67df5e586 144 int hh = high;
yamaguch 0:bbe67df5e586 145 for (;;) {
yamaguch 0:bbe67df5e586 146 do {
yamaguch 0:bbe67df5e586 147 ll++;
yamaguch 0:bbe67df5e586 148 } while (arr[low] > arr[ll]);
yamaguch 0:bbe67df5e586 149 do {
yamaguch 0:bbe67df5e586 150 hh--;
yamaguch 0:bbe67df5e586 151 } while (arr[hh] > arr[low]);
yamaguch 0:bbe67df5e586 152 if (hh < ll)
yamaguch 0:bbe67df5e586 153 break;
yamaguch 0:bbe67df5e586 154 SWAP(arr[ll], arr[hh]);
yamaguch 0:bbe67df5e586 155 }
yamaguch 0:bbe67df5e586 156
yamaguch 0:bbe67df5e586 157 /* Swap middle item (in position low) back into correct position */
yamaguch 0:bbe67df5e586 158 SWAP(arr[low], arr[hh]);
yamaguch 0:bbe67df5e586 159
yamaguch 0:bbe67df5e586 160 /* Re-set active partition */
yamaguch 0:bbe67df5e586 161 if (hh <= median)
yamaguch 0:bbe67df5e586 162 low = ll;
yamaguch 0:bbe67df5e586 163 if (hh >= median)
yamaguch 0:bbe67df5e586 164 high = hh - 1;
yamaguch 0:bbe67df5e586 165 }
yamaguch 0:bbe67df5e586 166 }