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 09:53:34 2015 +0000
Revision:
10:42e390f304fc
Parent:
9:8136aea421e3
Child:
11:e80e38508fe6
FastIO integrated, 4 seconds sampling, repair swapped compare operator.

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