A simple example.

Dependencies:   mbed FastIO

How does it work?

Oversampling

The core loop of the sampling does only one thing: it continuously looks at the input pin and increments a counter. Only when the input toggles, the counter value is used as an index and the histogram is updated and the counter is reset. By doing so the histogram will contain the run length of observed zeroes or ones, expressed in the time grid of the sampler. For a 1MHz bit stream the LPC 1768 should be capable to over sample approximately four times.

Grouping of run length

A filled histogram of run lengths, of both the zero and one symbols, will contain groups of adjacent run lengths values separated by empty spaces. If the sigma delta is connected to an analog voltage at exactly 25% of the range, the output pattern of the bit stream, expressed in the time grid of the ADC, will be close to 000100001000100001000100001... With approximately four times oversampling the LPC board may capture a data stream like: 0000, or expressed in run lengths: 10, 4, 16, 3, 12, 3, 15, 3, 11, 3, 16, 4. The histogram of zeroes will be filled with 1 at positions 10, 11, 12, 15 and 16, while the histogram of ones will be filled with 4 and 2 respectively at position 3 and 4.

Assign values to groups

After captured the data, the histogram will be scanned for groups of adjacent run lengths. A begin and end pointer/index of each will be stored in object type "Recovered". Once the whole histogram is scanned, a list of run length groups is determined. For each groups the average value of the run length will be determined.

Calculate Over Sample Ratio and Offset

The minimum distance between two average values will be a reasonable accurate value of the over sample factor. In our example the group of symbols consists of ADC run lengths of:

  • one: occurs 4 times with length 3 and 2 times 4, thus the average is 3.333.
  • three: consists of 11, 12 and 13 and thus an average of 12.0.
  • four: consists of one time 15 and two times 16: average equals 15.666.

The average distance between one and three is now 8.666. Therefore the average distance between three and four, only 3.666, a reasonable approximation of the over sample ratio. When acquiring more data, the average values will approximate the oversampling ratio better. An alternative method would be two take the shortest symbol as a value of the oversample factor, as this is the unit. However, as the loop requires some pre-processing before actively it can start counting, the average run length of the symbol with run length one will always be to lower than the actual over sample ratio. This creates an offset in the correlation of bit stream symbol to over sample data..

Known limitations

  • The amount of samples is only approximated, or more accurate, taken as a minimum value. As only the counter is compared once a complete run length of the same symbols is seen, it will be always slightly above the require value.
  • The amount of samples taken is hard coded. No means to vary this while running the application.
  • When the ADC input is very close or the maximum input voltage (or very close tot the minimum input voltage) the resulting bit stream will contain mostly very long run length of one's and hardly any zero (or vice versa). As no clock is connected, the stream may become out of synchronization for these cases.
  • Only the DC level is calculated, as a sum of all ones divided by the amount of symbols. Technically one could add Fourier transform in the post-processing and calculate SNR, THD, SINAD, ENOB etc, This requires another data structure of the histogram: store run length in the sequence they appear.
  • The algorithm works only correct given two assumptions. There should be exactly one group of empty spaces between two groups of captured run lengths (each representing a different bit stream run length). And each group of run lengths may not contain any empty position. Another decoder http://en.wikipedia.org/wiki/Viterbi_algorithm would possibly do better and even could estimate a qualification number.
Committer:
pscholtens
Date:
Wed May 27 13:00:37 2015 +0000
Revision:
11:e80e38508fe6
Parent:
10:42e390f304fc
Child:
12:75acace69521
Debug mode added, offset and dutycycle corrected, assigned values cleared too.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pscholtens 0:dc1b041f713e 1 #include "mbed.h"
pscholtens 10:42e390f304fc 2 #include "FastIO.h"
pscholtens 10:42e390f304fc 3
pscholtens 11:e80e38508fe6 4 /* version 0.1.3, P.C.S. Scholtens, Datang NXP, May 27th 2015, Nijmegen, Netherlands
pscholtens 11:e80e38508fe6 5 - Added debug mode via compiler preprocessor directives, just for developers.
pscholtens 11:e80e38508fe6 6 - Repaired bug in calculation of offset.
pscholtens 11:e80e38508fe6 7 - Cleared assined values also in clear_histogram() function.
pscholtens 11:e80e38508fe6 8 - Corrected return value of new synchronization method, dutycycles was calculated
pscholtens 11:e80e38508fe6 9 in wrong way.
pscholtens 11:e80e38508fe6 10 */
pscholtens 11:e80e38508fe6 11
pscholtens 10:42e390f304fc 12 /* version 0.1.2, P.C.S. Scholtens, Datang NXP, May 27th 2015, Nijmegen, Netherlands
pscholtens 10:42e390f304fc 13 - Switched from the default I/O to FastIO library to enables faster reading of the
pscholtens 10:42e390f304fc 14 input. The distinction between various run length should be improved.
pscholtens 10:42e390f304fc 15 - Incremented number of samples to 4x10e7, with a duration of approx. 4 seconds.
pscholtens 10:42e390f304fc 16 - Repaired bug of always clipped values in run length (accidentally swapped compare
pscholtens 10:42e390f304fc 17 operator).
pscholtens 10:42e390f304fc 18 */
pscholtens 0:dc1b041f713e 19
pscholtens 8:38175daee62b 20 /* version 0.1.1, P.C.S. Scholtens, Datang NXP, April 24th 2015, Nijmegen, Netherlands
pscholtens 8:38175daee62b 21 - Average function did not return the calculated average, now repaired.
pscholtens 8:38175daee62b 22 - Offset was subtracted while it should be added to compensate loss of oversampling
pscholtens 8:38175daee62b 23 ratio in the first round of the core loop.
pscholtens 8:38175daee62b 24 - Misleading type cast set to final type as chosen by compiler.
pscholtens 8:38175daee62b 25 */
pscholtens 8:38175daee62b 26
pscholtens 7:5141bd76b08d 27 /* version 0.1.0, P.C.S. Scholtens, Datang NXP, April 22th 2015, Nijmegen, Netherlands
pscholtens 7:5141bd76b08d 28 - Added more sophisticated method to find the correct symbol values. This one should
pscholtens 7:5141bd76b08d 29 be able to interpret the signals even if not all intermediate run length are present.
pscholtens 7:5141bd76b08d 30 This extends the usable input duty cycle range from [1/3,2/3] to [1/128, 127/128],
pscholtens 7:5141bd76b08d 31 if neither analog performance nor timing quantization errors create interference.
pscholtens 7:5141bd76b08d 32 */
pscholtens 7:5141bd76b08d 33
pscholtens 6:a5fc4e2ff34b 34 /* version 0.0.9, P.C.S. Scholtens, Datang NXP, April 21th 2015, Nijmegen, Netherlands
pscholtens 6:a5fc4e2ff34b 35 - Run time counter overflow fill now continue looking for same bit, however
pscholtens 6:a5fc4e2ff34b 36 clipping the actual store value. This prevents underflow occurence of other symbol
pscholtens 6:a5fc4e2ff34b 37 and may create lock if no bitstream is present.
pscholtens 6:a5fc4e2ff34b 38 - Time out function added to prevent lock in case no bitstream is present.
pscholtens 6:a5fc4e2ff34b 39 - Timer object renamed for clarity from t to timer, see http://xkcd.org/1513/
pscholtens 6:a5fc4e2ff34b 40 - Includes updated build of library mbed.
pscholtens 6:a5fc4e2ff34b 41 - Out-of-range of run length moved outside core loop, to speed up bitstream sampling
pscholtens 6:a5fc4e2ff34b 42 and consequently improving accuracy.
pscholtens 6:a5fc4e2ff34b 43 */
pscholtens 6:a5fc4e2ff34b 44
pscholtens 5:1c0bfd69719f 45 /* version 0.0.8, P.C.S. Scholtens, Datang NXP, April 17th 2015, Shanghai, PR China
pscholtens 5:1c0bfd69719f 46 - Corrected assigned synchronized values, as the first appearance wasn't assigned.
pscholtens 5:1c0bfd69719f 47 */
pscholtens 5:1c0bfd69719f 48
pscholtens 4:27a2eaee71ac 49 /* version 0.0.7, P.C.S. Scholtens, Datang NXP, April 16/17th 2015, Shanghai, PR China
pscholtens 4:27a2eaee71ac 50 - Method written to assign synchronized values to run-length.
pscholtens 4:27a2eaee71ac 51 - Added warnings for underflow.
pscholtens 4:27a2eaee71ac 52 - After skipped run-in cycles, copy the current bit, to prevent false single hit.
pscholtens 4:27a2eaee71ac 53 */
pscholtens 4:27a2eaee71ac 54
pscholtens 4:27a2eaee71ac 55 /* version 0.0.6, P.C.S. Scholtens, Datang NXP, April 15th, 2015, Shanghai, PR China
pscholtens 3:8d13bf073e92 56 - Corrected duty-cycle output for actual value of symbols (Thanks to Richard Zhu!).
pscholtens 3:8d13bf073e92 57 - Skipped run-in cycles to avoid pollution of the histogram with the first, most
pscholtens 3:8d13bf073e92 58 likely partial, sequence captured.
pscholtens 3:8d13bf073e92 59 - Added warnings for overflow.
pscholtens 3:8d13bf073e92 60 */
pscholtens 3:8d13bf073e92 61
pscholtens 2:5e37831540c7 62 /* version 0.0.5, P.C.S. Scholtens, Datang NXP, April 14th, 2015, Shanghai, PR China
pscholtens 3:8d13bf073e92 63 Implement histogram to find run lengths of zeroes and ones. */
pscholtens 2:5e37831540c7 64
pscholtens 1:2551859fbc25 65 /* version 0.0.4, P.C.S. Scholtens, Datang NXP, April 14th, 2015, Shanghai, PR China
pscholtens 10:42e390f304fc 66 Implement histogram to find run lengths of zeroes and ones. */
pscholtens 1:2551859fbc25 67
pscholtens 1:2551859fbc25 68 /* version 0.0.3, P.C.S. Scholtens, Datang NXP, April 14th, 2015, Shanghai, PR China
pscholtens 6:a5fc4e2ff34b 69 Initial version. No synchronization of the symbols is done. */
pscholtens 0:dc1b041f713e 70
pscholtens 0:dc1b041f713e 71 /* See also:
pscholtens 0:dc1b041f713e 72 https://developer.mbed.org/forum/bugs-suggestions/topic/3464/
pscholtens 9:8136aea421e3 73 To speed up, maybe bypass the mask function in the gpio_read function of file
pscholtens 9:8136aea421e3 74 ./mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/gpio_object.h
pscholtens 9:8136aea421e3 75 from git
pscholtens 9:8136aea421e3 76 git clone https://github.com/mbedmicro/mbed.git
pscholtens 9:8136aea421e3 77
pscholtens 0:dc1b041f713e 78 */
pscholtens 0:dc1b041f713e 79
pscholtens 11:e80e38508fe6 80 #define DEPTH 1024
pscholtens 10:42e390f304fc 81 #define WATCH_DOG_TIME 10
pscholtens 11:e80e38508fe6 82 #undef DEBUG_MODE
pscholtens 1:2551859fbc25 83
pscholtens 1:2551859fbc25 84 /* Reserve memory space for the histogram */
pscholtens 1:2551859fbc25 85 unsigned int zeros[DEPTH];
pscholtens 1:2551859fbc25 86 unsigned int ones[DEPTH];
pscholtens 4:27a2eaee71ac 87 unsigned int assign[DEPTH];
pscholtens 1:2551859fbc25 88
pscholtens 10:42e390f304fc 89 FastIn<p11> bitstream;
pscholtens 0:dc1b041f713e 90 DigitalOut myled(LED1);
pscholtens 6:a5fc4e2ff34b 91 Serial pc(USBTX, USBRX); // tx, rx
pscholtens 6:a5fc4e2ff34b 92 Timer timer;
pscholtens 6:a5fc4e2ff34b 93 Timeout timeout;
pscholtens 0:dc1b041f713e 94
pscholtens 7:5141bd76b08d 95 class Recovered {
pscholtens 7:5141bd76b08d 96 public:
pscholtens 7:5141bd76b08d 97 Recovered();
pscholtens 7:5141bd76b08d 98 virtual ~Recovered();
pscholtens 7:5141bd76b08d 99 float average;
pscholtens 7:5141bd76b08d 100 void calc_average();
pscholtens 7:5141bd76b08d 101 unsigned int index_start;
pscholtens 7:5141bd76b08d 102 unsigned int index_stop;
pscholtens 7:5141bd76b08d 103 unsigned int assigned_val;
pscholtens 7:5141bd76b08d 104 Recovered *next;
pscholtens 7:5141bd76b08d 105 private:
pscholtens 7:5141bd76b08d 106 };
pscholtens 7:5141bd76b08d 107
pscholtens 7:5141bd76b08d 108 /* Constructor */
pscholtens 7:5141bd76b08d 109 Recovered::Recovered()
pscholtens 7:5141bd76b08d 110 {
pscholtens 7:5141bd76b08d 111 next = NULL;
pscholtens 7:5141bd76b08d 112 };
pscholtens 7:5141bd76b08d 113
pscholtens 7:5141bd76b08d 114
pscholtens 7:5141bd76b08d 115 /* Destructor */
pscholtens 7:5141bd76b08d 116 Recovered::~Recovered()
pscholtens 7:5141bd76b08d 117 {
pscholtens 7:5141bd76b08d 118 if (next != NULL)
pscholtens 7:5141bd76b08d 119 delete next;
pscholtens 7:5141bd76b08d 120 };
pscholtens 7:5141bd76b08d 121
pscholtens 7:5141bd76b08d 122 /* Calculate average function, only call when index start and stop are defined. */
pscholtens 7:5141bd76b08d 123 void Recovered::calc_average()
pscholtens 7:5141bd76b08d 124 {
pscholtens 7:5141bd76b08d 125 unsigned int index = index_start;
pscholtens 7:5141bd76b08d 126 unsigned int sum;
pscholtens 7:5141bd76b08d 127 unsigned int amount = 0;
pscholtens 8:38175daee62b 128 average = 0;
pscholtens 7:5141bd76b08d 129 /* Test assumptions */
pscholtens 7:5141bd76b08d 130 if (index_start > DEPTH-1 ) pc.printf("ERROR: start value to high in average function.\n");
pscholtens 7:5141bd76b08d 131 if (index_stop > DEPTH-1 ) pc.printf("ERROR: stop value to high in average function.\n");
pscholtens 7:5141bd76b08d 132 if (index_start > index_stop) pc.printf("ERROR: start value beyond stop value in average function.\n");
pscholtens 7:5141bd76b08d 133 /* Core function */
pscholtens 7:5141bd76b08d 134 while (index < index_stop) {
pscholtens 8:38175daee62b 135 sum = zeros[index]+ones[index];
pscholtens 8:38175daee62b 136 amount += sum;
pscholtens 8:38175daee62b 137 average += index*sum;
pscholtens 7:5141bd76b08d 138 index++;
pscholtens 7:5141bd76b08d 139 };
pscholtens 8:38175daee62b 140 average /= amount;
pscholtens 7:5141bd76b08d 141 return;
pscholtens 7:5141bd76b08d 142 };
pscholtens 7:5141bd76b08d 143
pscholtens 1:2551859fbc25 144 /* A function to clear the contents of both histograms */
pscholtens 1:2551859fbc25 145 void clear_histogram() {
pscholtens 1:2551859fbc25 146 for(unsigned int i = 0; i < DEPTH; i++) {
pscholtens 11:e80e38508fe6 147 zeros[i] = 0;
pscholtens 11:e80e38508fe6 148 ones[i] = 0;
pscholtens 11:e80e38508fe6 149 assign[i] = 0;
pscholtens 1:2551859fbc25 150 }
pscholtens 1:2551859fbc25 151 }
pscholtens 1:2551859fbc25 152
pscholtens 1:2551859fbc25 153 /* Print the contents of the histogram, excluding the empty values */
pscholtens 1:2551859fbc25 154 void print_histogram() {
pscholtens 4:27a2eaee71ac 155 pc.printf(" Sequence Zeros Ones Assign\n");
pscholtens 4:27a2eaee71ac 156 if ( zeros[0]+ones[0] != 0 ) {
pscholtens 4:27a2eaee71ac 157 pc.printf("Underflow %8i %8i\n",zeros[0],ones[0]);
pscholtens 4:27a2eaee71ac 158 }
pscholtens 4:27a2eaee71ac 159 for (unsigned int i = 1; i < DEPTH-1; i++) {
pscholtens 1:2551859fbc25 160 if ( zeros[i]+ones[i] != 0 ) {
pscholtens 4:27a2eaee71ac 161 pc.printf(" %8i %8i %8i %8i\n",i,zeros[i],ones[i],assign[i]);
pscholtens 1:2551859fbc25 162 }
pscholtens 1:2551859fbc25 163 }
pscholtens 3:8d13bf073e92 164 if ( zeros[DEPTH-1]+ones[DEPTH-1] != 0 ) {
pscholtens 4:27a2eaee71ac 165 pc.printf("Overflow %8i %8i\n",zeros[DEPTH-1],ones[DEPTH-1]);
pscholtens 3:8d13bf073e92 166 }
pscholtens 3:8d13bf073e92 167
pscholtens 1:2551859fbc25 168 }
pscholtens 1:2551859fbc25 169
pscholtens 6:a5fc4e2ff34b 170 /* Will only be called if measurement time exceeds preset watch dog timer. */
pscholtens 6:a5fc4e2ff34b 171 void at_time_out() {
pscholtens 6:a5fc4e2ff34b 172 pc.printf("Input clipped to level %i, no bitstream present.\n", (int) bitstream);
pscholtens 6:a5fc4e2ff34b 173 timeout.attach(&at_time_out, WATCH_DOG_TIME);
pscholtens 6:a5fc4e2ff34b 174 }
pscholtens 6:a5fc4e2ff34b 175
pscholtens 1:2551859fbc25 176 /* Function which fill the histogram */
pscholtens 1:2551859fbc25 177 void fill_histogram(unsigned int num_unsync_samples) {
pscholtens 1:2551859fbc25 178 unsigned int count = 0;
pscholtens 1:2551859fbc25 179 unsigned int run_length = 0;
pscholtens 6:a5fc4e2ff34b 180 /* Switch on watch dog timer */
pscholtens 6:a5fc4e2ff34b 181 timeout.attach(&at_time_out, WATCH_DOG_TIME);
pscholtens 10:42e390f304fc 182 bool previous_bit = (bool) bitstream;
pscholtens 3:8d13bf073e92 183 /* Implements run-in: skip the first sequence as it is only a partial one. */
pscholtens 6:a5fc4e2ff34b 184 while(previous_bit == (bool) bitstream) {
pscholtens 6:a5fc4e2ff34b 185 /* Do nothing, intentionally */;
pscholtens 3:8d13bf073e92 186 };
pscholtens 10:42e390f304fc 187 run_length = 0;
pscholtens 4:27a2eaee71ac 188 previous_bit = !previous_bit;
pscholtens 6:a5fc4e2ff34b 189 /* Start actual counting here, store in variable run_length (will be clipped to DEPTH) */
pscholtens 1:2551859fbc25 190 while(count < num_unsync_samples) {
pscholtens 6:a5fc4e2ff34b 191 /* Core of the loop */
pscholtens 6:a5fc4e2ff34b 192 while(previous_bit == (bool) bitstream) {
pscholtens 1:2551859fbc25 193 run_length++;
pscholtens 1:2551859fbc25 194 };
pscholtens 6:a5fc4e2ff34b 195 /* Increment counter before clipping to preserve accuracy. */
pscholtens 6:a5fc4e2ff34b 196 count += run_length;
pscholtens 6:a5fc4e2ff34b 197 /* Test if run length exceeds depth of histogram, if so assign clip value. */
pscholtens 10:42e390f304fc 198 if (run_length > DEPTH-1) {
pscholtens 6:a5fc4e2ff34b 199 run_length = DEPTH-1;
pscholtens 6:a5fc4e2ff34b 200 }
pscholtens 6:a5fc4e2ff34b 201 /* Now write in histogram array of interest */
pscholtens 1:2551859fbc25 202 if (previous_bit) {
pscholtens 1:2551859fbc25 203 ones[run_length]++;
pscholtens 1:2551859fbc25 204 }
pscholtens 1:2551859fbc25 205 else {
pscholtens 1:2551859fbc25 206 zeros[run_length]++;
pscholtens 1:2551859fbc25 207 }
pscholtens 6:a5fc4e2ff34b 208 /* Reset for next run length counting loop */
pscholtens 2:5e37831540c7 209 run_length = 0;
pscholtens 2:5e37831540c7 210 previous_bit = !previous_bit;
pscholtens 1:2551859fbc25 211 }
pscholtens 6:a5fc4e2ff34b 212 /* Switch off watch dog timer */
pscholtens 6:a5fc4e2ff34b 213 timeout.detach();
pscholtens 1:2551859fbc25 214 }
pscholtens 1:2551859fbc25 215
pscholtens 1:2551859fbc25 216 /* Here we count the number of unsynchronized symbols, mimicing previous implementation */
pscholtens 1:2551859fbc25 217 unsigned int get_num_unsync_symbols(int symbol) {
pscholtens 1:2551859fbc25 218 unsigned int sum = 0;
pscholtens 1:2551859fbc25 219 for (unsigned int i = 0; i < DEPTH; i++) {
pscholtens 1:2551859fbc25 220 if (symbol == 0) {
pscholtens 1:2551859fbc25 221 sum += zeros[i];
pscholtens 1:2551859fbc25 222 } else {
pscholtens 1:2551859fbc25 223 sum += ones[i];
pscholtens 1:2551859fbc25 224 }
pscholtens 1:2551859fbc25 225 }
pscholtens 1:2551859fbc25 226 return sum;
pscholtens 1:2551859fbc25 227 }
pscholtens 1:2551859fbc25 228
pscholtens 3:8d13bf073e92 229 /* Calculate the value, using the unsynchronized method */
pscholtens 3:8d13bf073e92 230 unsigned int get_value_unsync_symbols(int symbol) {
pscholtens 3:8d13bf073e92 231 unsigned int sum = 0;
pscholtens 3:8d13bf073e92 232 for (unsigned int i = 0; i < DEPTH; i++) {
pscholtens 3:8d13bf073e92 233 if (symbol == 0) {
pscholtens 3:8d13bf073e92 234 sum += i*zeros[i];
pscholtens 3:8d13bf073e92 235 } else {
pscholtens 3:8d13bf073e92 236 sum += i*ones[i];
pscholtens 3:8d13bf073e92 237 }
pscholtens 3:8d13bf073e92 238 }
pscholtens 3:8d13bf073e92 239 return sum;
pscholtens 3:8d13bf073e92 240 }
pscholtens 3:8d13bf073e92 241
pscholtens 4:27a2eaee71ac 242 /* Calculate the value, using the synchronization algorithm */
pscholtens 4:27a2eaee71ac 243 unsigned int get_value_synced_symbols(int symbol) {
pscholtens 4:27a2eaee71ac 244 bool presence = false;
pscholtens 4:27a2eaee71ac 245 int value = 0;
pscholtens 4:27a2eaee71ac 246 for (unsigned int i = 0; i < DEPTH; i++) {
pscholtens 4:27a2eaee71ac 247 if ( zeros[i]+ones[i] != 0 ) {
pscholtens 4:27a2eaee71ac 248 if (presence) {
pscholtens 5:1c0bfd69719f 249 assign[i] = value;
pscholtens 4:27a2eaee71ac 250 } else {
pscholtens 4:27a2eaee71ac 251 value++;
pscholtens 5:1c0bfd69719f 252 presence = true;
pscholtens 5:1c0bfd69719f 253 assign[i] = value;
pscholtens 4:27a2eaee71ac 254 }
pscholtens 4:27a2eaee71ac 255 } else {
pscholtens 4:27a2eaee71ac 256 presence = false;
pscholtens 4:27a2eaee71ac 257 }
pscholtens 4:27a2eaee71ac 258 }
pscholtens 4:27a2eaee71ac 259 /* Now do the actual summation of symbol values */
pscholtens 4:27a2eaee71ac 260 unsigned int sum = 0;
pscholtens 4:27a2eaee71ac 261 for (unsigned int i = 0; i < DEPTH; i++) {
pscholtens 4:27a2eaee71ac 262 if (symbol == 0) {
pscholtens 4:27a2eaee71ac 263 sum += assign[i]*zeros[i];
pscholtens 4:27a2eaee71ac 264 } else {
pscholtens 4:27a2eaee71ac 265 sum += assign[i]*ones[i];
pscholtens 4:27a2eaee71ac 266 }
pscholtens 4:27a2eaee71ac 267 }
pscholtens 4:27a2eaee71ac 268 return sum;
pscholtens 4:27a2eaee71ac 269 }
pscholtens 4:27a2eaee71ac 270
pscholtens 7:5141bd76b08d 271 /* Calculate the value, using the new synchronization algorithm */
pscholtens 7:5141bd76b08d 272 float get_dutycycle_synced_symbols_new_method() {
pscholtens 7:5141bd76b08d 273 /* First step (第一步): scan areas of non-zero content in histogram, starting at first non-overflow sequence at the end */
pscholtens 7:5141bd76b08d 274 bool presence = false;
pscholtens 7:5141bd76b08d 275 Recovered *list = NULL;
pscholtens 7:5141bd76b08d 276 Recovered *first = NULL;
pscholtens 7:5141bd76b08d 277 for (signed int i = DEPTH-2; i > -1 ; i--) {
pscholtens 7:5141bd76b08d 278 if ( zeros[i]+ones[i] != 0 ) {
pscholtens 7:5141bd76b08d 279 if (presence) {
pscholtens 7:5141bd76b08d 280 first->index_start = i;
pscholtens 7:5141bd76b08d 281 } else {
pscholtens 7:5141bd76b08d 282 /* Create new Recovered symbol and position it at the beginning of the list of dis(/re)covered symbols */
pscholtens 7:5141bd76b08d 283 first = new Recovered;
pscholtens 7:5141bd76b08d 284 first->next = list;
pscholtens 7:5141bd76b08d 285 first->index_stop = i+1;
pscholtens 7:5141bd76b08d 286 list = first;
pscholtens 7:5141bd76b08d 287 presence = true;
pscholtens 7:5141bd76b08d 288 }
pscholtens 7:5141bd76b08d 289 } else {
pscholtens 7:5141bd76b08d 290 presence = false;
pscholtens 7:5141bd76b08d 291 }
pscholtens 7:5141bd76b08d 292 }
pscholtens 7:5141bd76b08d 293 /* Step two (第二步): for each found area, calculate average values */
pscholtens 7:5141bd76b08d 294 Recovered* index = list;
pscholtens 7:5141bd76b08d 295 while (index != NULL) {
pscholtens 7:5141bd76b08d 296 index->calc_average();
pscholtens 7:5141bd76b08d 297 index = index->next;
pscholtens 7:5141bd76b08d 298 }
pscholtens 11:e80e38508fe6 299 #ifdef DEBUG_MODE
pscholtens 11:e80e38508fe6 300 int j = 0;
pscholtens 11:e80e38508fe6 301 index = list;
pscholtens 11:e80e38508fe6 302 while (index != NULL) {
pscholtens 11:e80e38508fe6 303 pc.printf("Group %i from %i to %i, average = %f\n", j, index->index_start,index->index_stop, index->average);
pscholtens 11:e80e38508fe6 304 index = index->next;
pscholtens 11:e80e38508fe6 305 j++;
pscholtens 11:e80e38508fe6 306 }
pscholtens 11:e80e38508fe6 307 #endif
pscholtens 7:5141bd76b08d 308 /* Step three (第三步): Find smallest distance between two adjacent symbols, e.g. with run length of 0.91, 6.99, 8.01, the last two define the grid/oversample ratio. */
pscholtens 7:5141bd76b08d 309 float oversample = DEPTH;
pscholtens 7:5141bd76b08d 310 Recovered* cmp1 = list;
pscholtens 7:5141bd76b08d 311 Recovered* cmp2 = list->next;
pscholtens 7:5141bd76b08d 312 if (list != NULL) {
pscholtens 7:5141bd76b08d 313 while (cmp2 != NULL) {
pscholtens 7:5141bd76b08d 314 float diff = cmp2->average-cmp1->average;
pscholtens 7:5141bd76b08d 315 if (diff < oversample) {
pscholtens 7:5141bd76b08d 316 oversample = diff;
pscholtens 7:5141bd76b08d 317 }
pscholtens 7:5141bd76b08d 318 cmp1=cmp2;
pscholtens 7:5141bd76b08d 319 cmp2=cmp1->next;
pscholtens 7:5141bd76b08d 320 }
pscholtens 7:5141bd76b08d 321 }
pscholtens 11:e80e38508fe6 322 #ifdef DEBUG_MODE
pscholtens 11:e80e38508fe6 323 pc.printf("Oversample ratio %f\n", oversample);
pscholtens 11:e80e38508fe6 324 #endif
pscholtens 7:5141bd76b08d 325 /* Step four (第四步): Divide the average run length of all found recovered symbol by the found oversample ratio. */
pscholtens 7:5141bd76b08d 326 index = list;
pscholtens 7:5141bd76b08d 327 while (index != NULL) {
pscholtens 7:5141bd76b08d 328 index->average /= oversample;
pscholtens 7:5141bd76b08d 329 index = index->next;
pscholtens 7:5141bd76b08d 330 }
pscholtens 7:5141bd76b08d 331
pscholtens 11:e80e38508fe6 332 /* Step five (第五步): find offset and remove it (Assumption that there are always symbols with run length 1 ) */
pscholtens 7:5141bd76b08d 333 index = list;
pscholtens 11:e80e38508fe6 334 float offset = 1-index->average;
pscholtens 7:5141bd76b08d 335 while (index != NULL) {
pscholtens 8:38175daee62b 336 index->average += offset;
pscholtens 7:5141bd76b08d 337 index = index->next;
pscholtens 7:5141bd76b08d 338 }
pscholtens 11:e80e38508fe6 339 #ifdef DEBUG_MODE
pscholtens 11:e80e38508fe6 340 pc.printf("Offset at initial run-in lengths %f\n", offset);
pscholtens 11:e80e38508fe6 341 #endif
pscholtens 4:27a2eaee71ac 342
pscholtens 7:5141bd76b08d 343 /* Step six (第六步): round to nearest integer and assign value to both arrays */
pscholtens 7:5141bd76b08d 344 index = list;
pscholtens 7:5141bd76b08d 345 while (index != NULL) {
pscholtens 8:38175daee62b 346 index->assigned_val = (unsigned int) (index->average+0.5);
pscholtens 7:5141bd76b08d 347 for (int i = index->index_start; i < index->index_stop; i++ ) {
pscholtens 7:5141bd76b08d 348 assign[i] = index->assigned_val;
pscholtens 7:5141bd76b08d 349 }
pscholtens 7:5141bd76b08d 350 index = index->next;
pscholtens 7:5141bd76b08d 351 }
pscholtens 7:5141bd76b08d 352
pscholtens 7:5141bd76b08d 353 /* Step seven (第七步): Now do the actual summation of symbol values */
pscholtens 7:5141bd76b08d 354 unsigned int sum0 = 0, sum1 = 0;
pscholtens 7:5141bd76b08d 355 for (unsigned int i = 0; i < DEPTH; i++) {
pscholtens 7:5141bd76b08d 356 sum0 += assign[i]*zeros[i];
pscholtens 7:5141bd76b08d 357 sum1 += assign[i]*ones[i];
pscholtens 7:5141bd76b08d 358 }
pscholtens 7:5141bd76b08d 359 /* Step eight (第八步): Delete the recovered symbol object to clear memory. As a destructor is defined
pscholtens 7:5141bd76b08d 360 this will be automatically handled recursively. And of course return the duty cycle */
pscholtens 7:5141bd76b08d 361 delete list;
pscholtens 11:e80e38508fe6 362 return ((float) sum1)/(sum0+sum1);
pscholtens 7:5141bd76b08d 363 }
pscholtens 7:5141bd76b08d 364
pscholtens 7:5141bd76b08d 365 /* The main (主程序) routine of the program */
pscholtens 1:2551859fbc25 366
pscholtens 0:dc1b041f713e 367 int main() {
pscholtens 11:e80e38508fe6 368 #ifdef DEBUG_MODE
pscholtens 7:5141bd76b08d 369 unsigned int num_of_zeros, num_of_ones, value_of_unsync_zeros, value_of_unsync_ones, value_of_synced_zeros, value_of_synced_ones,
pscholtens 7:5141bd76b08d 370 sum_of_unsync_symbols, sum_of_synced_symbols;
pscholtens 11:e80e38508fe6 371 float unsync_voltage, synced_voltage, unsync_dutycycle, synced_dutycycle;
pscholtens 11:e80e38508fe6 372 #endif
pscholtens 11:e80e38508fe6 373
pscholtens 11:e80e38508fe6 374 float synced_dutycycle_new, synced_voltage_new;
pscholtens 1:2551859fbc25 375 pc.baud(115200);
pscholtens 11:e80e38508fe6 376 pc.printf("Bitstream counter, version 0.1.3, P.C.S. Scholtens, May 27th 2015, Nijmegen, Netherlands.\n");
pscholtens 6:a5fc4e2ff34b 377 pc.printf("Build " __DATE__ " " __TIME__ "\n");
pscholtens 0:dc1b041f713e 378 /*LPC_TIM2->PR = 0x0000002F; / * decimal 47 */
pscholtens 0:dc1b041f713e 379 /*LPC_TIM3->PR = 24;*/
pscholtens 0:dc1b041f713e 380 while(1) {
pscholtens 6:a5fc4e2ff34b 381 timer.reset();
pscholtens 0:dc1b041f713e 382 myled = 1;
pscholtens 1:2551859fbc25 383 clear_histogram();
pscholtens 6:a5fc4e2ff34b 384 timer.start();
pscholtens 10:42e390f304fc 385 fill_histogram(4e7);
pscholtens 6:a5fc4e2ff34b 386 timer.stop();
pscholtens 11:e80e38508fe6 387 #ifdef DEBUG_MODE
pscholtens 1:2551859fbc25 388 num_of_zeros = get_num_unsync_symbols(0);
pscholtens 1:2551859fbc25 389 num_of_ones = get_num_unsync_symbols(1);
pscholtens 3:8d13bf073e92 390 value_of_unsync_zeros = get_value_unsync_symbols(0);
pscholtens 3:8d13bf073e92 391 value_of_unsync_ones = get_value_unsync_symbols(1);
pscholtens 7:5141bd76b08d 392 sum_of_unsync_symbols = value_of_unsync_zeros+value_of_unsync_ones;
pscholtens 7:5141bd76b08d 393 unsync_dutycycle = ((float) value_of_unsync_ones)/sum_of_unsync_symbols; /* We need to typecast one of the integers to float, otherwise the result is rounded till zero. */
pscholtens 3:8d13bf073e92 394 unsync_voltage = (0.5*13*unsync_dutycycle+1)*0.9; /* This is the ADC formula, see analysisSigmaDeltaADC.pdf */
pscholtens 4:27a2eaee71ac 395 value_of_synced_zeros = get_value_synced_symbols(0);
pscholtens 4:27a2eaee71ac 396 value_of_synced_ones = get_value_synced_symbols(1);
pscholtens 7:5141bd76b08d 397 sum_of_synced_symbols = value_of_synced_zeros+value_of_synced_ones;
pscholtens 7:5141bd76b08d 398 synced_dutycycle = ((float) value_of_synced_ones)/sum_of_synced_symbols; /* We need to typecast one of the integers to float, otherwise the result is rounded till zero. */
pscholtens 4:27a2eaee71ac 399 synced_voltage = (0.5*13*synced_dutycycle+1)*0.9; /* This is the ADC formula, see analysisSigmaDeltaADC.pdf */
pscholtens 11:e80e38508fe6 400 #endif
pscholtens 7:5141bd76b08d 401 synced_dutycycle_new = get_dutycycle_synced_symbols_new_method();
pscholtens 9:8136aea421e3 402 synced_voltage_new = (0.5*13*synced_dutycycle_new+1)*0.9; /* This is the ADC formula, see analysisSigmaDeltaADC.pdf */
pscholtens 11:e80e38508fe6 403 pc.printf("\n------ Captured Histogram ------\n");
pscholtens 11:e80e38508fe6 404 print_histogram();
pscholtens 11:e80e38508fe6 405 #ifdef DEBUG_MODE
pscholtens 4:27a2eaee71ac 406 pc.printf("------ Unsynchronized Results ------\n");
pscholtens 4:27a2eaee71ac 407 pc.printf("Counted Sequences %8i %8i\n", num_of_zeros , num_of_ones);
pscholtens 4:27a2eaee71ac 408 pc.printf("Summed Values %8i %8i\n", value_of_unsync_zeros, value_of_unsync_ones);
pscholtens 11:e80e38508fe6 409 pc.printf("Duty Cycle %f, = %f Volt\n", unsync_dutycycle , unsync_voltage);
pscholtens 11:e80e38508fe6 410 pc.printf("----- Synchronized Results OLD -----\n");
pscholtens 4:27a2eaee71ac 411 pc.printf("Summed Values %8i %8i\n", value_of_synced_zeros, value_of_synced_ones);
pscholtens 11:e80e38508fe6 412 pc.printf("Duty Cyle %f, = %f Volt\n", synced_dutycycle , synced_voltage);
pscholtens 11:e80e38508fe6 413 #endif
pscholtens 11:e80e38508fe6 414 pc.printf("------- Synchronized Results -------\n");
pscholtens 11:e80e38508fe6 415 pc.printf("Duty Cyle %f, = %f Volt\n", synced_dutycycle_new , synced_voltage_new);
pscholtens 4:27a2eaee71ac 416 pc.printf("------------------------------------\n");
pscholtens 6:a5fc4e2ff34b 417 pc.printf("Measured in %f sec.\n", timer.read());
pscholtens 4:27a2eaee71ac 418 pc.printf("====================================\n");
pscholtens 0:dc1b041f713e 419 myled = 0;
pscholtens 5:1c0bfd69719f 420 wait(0.1);
pscholtens 0:dc1b041f713e 421 }
pscholtens 4:27a2eaee71ac 422 }