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:
Fri Apr 24 12:00:38 2015 +0000
Revision:
8:38175daee62b
Parent:
7:5141bd76b08d
Child:
9:8136aea421e3
Version 0.1.1 Average function repaired, offset corrected, type cast typo.

Who changed what in which revision?

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