Moved to Team 9.

Fork of LineScan by Nicholas Gan

Committer:
dnleek
Date:
Tue Apr 28 01:05:47 2015 +0000
Revision:
26:5e70edee216d
Parent:
25:8357ee048ad3
Child:
27:173b2f564143
Good code for run 2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ng3600 0:2d546112b0b8 1 #include "LineScan.h"
ng3600 18:8a65598abf2f 2 #include <string.h>
ng3600 0:2d546112b0b8 3
dnleek 26:5e70edee216d 4 #define THRESH 4000
ng3600 8:b9ec2f3e12b6 5
ng3600 20:e9f0d1483ba1 6 #define MEAN_REF 10000 //ideal mean we should see
dnleek 26:5e70edee216d 7 #define CAM_CTRL_GAIN 0.002 //should be small
ng3600 14:928254a609cb 8
ng3600 14:928254a609cb 9 #define NEUTRAL 0
ng3600 14:928254a609cb 10 #define FIND_PEAK 1
ng3600 14:928254a609cb 11 #define FIND_TROUGH 2
ng3600 14:928254a609cb 12
dnleek 24:774104c34063 13 uint16_t read1Bit(AnalogIn cam, DigitalOut *camClk)
dnleek 24:774104c34063 14 {
ng3600 0:2d546112b0b8 15 uint16_t pixel;
dnleek 24:774104c34063 16
ng3600 0:2d546112b0b8 17 //read pixel n
ng3600 0:2d546112b0b8 18 pixel = cam.read_u16();
dnleek 24:774104c34063 19
ng3600 0:2d546112b0b8 20 //clock pulse for next pixel n + 1
ng3600 0:2d546112b0b8 21 *camClk = 1;
ng3600 14:928254a609cb 22 *camClk = 0;
dnleek 24:774104c34063 23
ng3600 0:2d546112b0b8 24 return pixel; //return result as an uint16_t (16 bit integer)
ng3600 0:2d546112b0b8 25 }
ng3600 0:2d546112b0b8 26
dnleek 24:774104c34063 27 void startRead(DigitalOut *camSi, DigitalOut *camClk)
dnleek 24:774104c34063 28 {
ng3600 0:2d546112b0b8 29 //pulse first clock cycle and start integral pin
ng3600 0:2d546112b0b8 30 *camSi = 1;
ng3600 0:2d546112b0b8 31 *camClk = 1;
ng3600 0:2d546112b0b8 32 *camSi = 0;
ng3600 0:2d546112b0b8 33 *camClk = 0;
ng3600 0:2d546112b0b8 34 }
ng3600 0:2d546112b0b8 35
dnleek 24:774104c34063 36 float processFn(uint16_t *array, int arraySz, int* exposure, telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff)
dnleek 24:774104c34063 37 {
ng3600 15:4bd1c1d2cf94 38 const static int frameLen = NUM_PIX - 2 * SKIP;
ng3600 15:4bd1c1d2cf94 39 int avg[frameLen];
ng3600 15:4bd1c1d2cf94 40 int diff[frameLen];
ng3600 2:6a87b2348245 41 int highest = 0;
ng3600 2:6a87b2348245 42 int lowest = 0;
ng3600 13:c17cf029d899 43 int total = 0;
ng3600 18:8a65598abf2f 44 int h_idx_ary[10];
ng3600 14:928254a609cb 45 int h_idx_pos = 0;
ng3600 18:8a65598abf2f 46 int l_idx_ary[10];
ng3600 14:928254a609cb 47 int l_idx_pos = 0;
ng3600 14:928254a609cb 48 int state = NEUTRAL;
ng3600 14:928254a609cb 49 int *l_walker, *h_walker;
ng3600 15:4bd1c1d2cf94 50 int out_width = frameLen;
ng3600 18:8a65598abf2f 51 int i;
ng3600 14:928254a609cb 52 float out = -1.0;
dnleek 24:774104c34063 53 int thinnest = 128;
dnleek 24:774104c34063 54 int linestart = -1;
dnleek 24:774104c34063 55 int linestop = -1;
dnleek 24:774104c34063 56 int tempstart = 0;
dnleek 24:774104c34063 57
ng3600 3:f31986cb68fd 58 //for AGC
ng3600 3:f31986cb68fd 59 float exposureChange;
dnleek 24:774104c34063 60
ng3600 18:8a65598abf2f 61 h_idx_ary[0] = -1;
ng3600 18:8a65598abf2f 62 l_idx_ary[0] = -1;
dnleek 24:774104c34063 63
dnleek 24:774104c34063 64 if(array) {
ng3600 8:b9ec2f3e12b6 65 avg[0] = array[SKIP - 1]/2 + array[SKIP]/2;
ng3600 2:6a87b2348245 66 diff[0] = 0;
dnleek 24:774104c34063 67 tele_linescan_diff[0] = diff[0];
dnleek 24:774104c34063 68
ng3600 13:c17cf029d899 69 total += avg[0]; //AGC
dnleek 24:774104c34063 70
dnleek 24:774104c34063 71 for(i = 1; i < frameLen; i++) {
ng3600 8:b9ec2f3e12b6 72 avg[i] = array[i - 1 + SKIP]/2 + array[i + SKIP]/2; //smoothing
dnleek 24:774104c34063 73 if ((avg[i] - avg[i-1] >= THRESH) || (avg[i] - avg[i-1] <= -THRESH)) {
dnleek 24:774104c34063 74 diff[i] = avg[i] - avg[i-1]; //differential
dnleek 24:774104c34063 75 } else {
dnleek 24:774104c34063 76 diff[i] = 0;
dnleek 24:774104c34063 77 }
dnleek 24:774104c34063 78 if (diff [i] > 0) {
dnleek 24:774104c34063 79 tele_linescan_diff[i] = 10000;
dnleek 24:774104c34063 80 } else if (diff[i] < 0) {
dnleek 24:774104c34063 81 tele_linescan_diff[i] = 5000;
dnleek 24:774104c34063 82 } else {
dnleek 24:774104c34063 83 tele_linescan_diff[i] = 0;
dnleek 24:774104c34063 84 }
dnleek 24:774104c34063 85
ng3600 13:c17cf029d899 86 total += avg[i]; //AGC
dnleek 24:774104c34063 87
dnleek 24:774104c34063 88
ng3600 14:928254a609cb 89 //Finite State Machine
ng3600 18:8a65598abf2f 90 //problem in this section, rewrite? find peaks and troughs
dnleek 24:774104c34063 91 switch(state) {
ng3600 14:928254a609cb 92 case NEUTRAL:
ng3600 18:8a65598abf2f 93 //serial.printf("Neutral case in processFn\r\n");
dnleek 24:774104c34063 94 if( diff[i] > THRESH ) {
ng3600 14:928254a609cb 95 state = FIND_PEAK;
ng3600 14:928254a609cb 96 highest = diff[i];
ng3600 18:8a65598abf2f 97 h_idx_ary[h_idx_pos] = i;
dnleek 24:774104c34063 98 tempstart = i;
dnleek 24:774104c34063 99 } /*else if( diff[i] < -THRESH ) {
ng3600 14:928254a609cb 100 state = FIND_TROUGH;
ng3600 14:928254a609cb 101 lowest = diff[i];
ng3600 18:8a65598abf2f 102 l_idx_ary[l_idx_pos] = i;
dnleek 24:774104c34063 103 tempstart = i;
dnleek 24:774104c34063 104 }*/
ng3600 14:928254a609cb 105 break;
dnleek 24:774104c34063 106
ng3600 14:928254a609cb 107 case FIND_PEAK:
ng3600 18:8a65598abf2f 108 //serial.printf("Peak case in processFn\r\n");
dnleek 24:774104c34063 109 if( diff[i] <= -THRESH ) {
ng3600 14:928254a609cb 110 state = NEUTRAL;
ng3600 18:8a65598abf2f 111 h_idx_pos++;
ng3600 18:8a65598abf2f 112 h_idx_ary[h_idx_pos] = -1; //last element is always -1
dnleek 24:774104c34063 113 if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
dnleek 24:774104c34063 114 thinnest = i - tempstart;
dnleek 24:774104c34063 115 linestart = tempstart;
dnleek 24:774104c34063 116 linestop = i;
dnleek 24:774104c34063 117 }
dnleek 24:774104c34063 118 } else if(diff[i] > highest) {
ng3600 14:928254a609cb 119 highest = diff[i];
ng3600 18:8a65598abf2f 120 h_idx_ary[h_idx_pos] = i; //insert to array, clobbers
dnleek 24:774104c34063 121 tempstart = i;
ng3600 14:928254a609cb 122 }
ng3600 14:928254a609cb 123 break;
dnleek 24:774104c34063 124
ng3600 14:928254a609cb 125 case FIND_TROUGH:
ng3600 18:8a65598abf2f 126 //serial.printf("Trough case in processFn\r\n");
dnleek 24:774104c34063 127 if( diff[i] >= THRESH ) {
ng3600 14:928254a609cb 128 state = NEUTRAL;
ng3600 18:8a65598abf2f 129 l_idx_pos++;
ng3600 18:8a65598abf2f 130 l_idx_ary[l_idx_pos] = -1; //last element is always -1
dnleek 24:774104c34063 131 if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
dnleek 24:774104c34063 132 thinnest = i - tempstart;
dnleek 24:774104c34063 133 linestart = tempstart;
dnleek 24:774104c34063 134 linestop = i;
dnleek 24:774104c34063 135 }
dnleek 24:774104c34063 136 } else if(diff[i] < lowest) {
ng3600 14:928254a609cb 137 lowest = diff[i];
ng3600 18:8a65598abf2f 138 l_idx_ary[l_idx_pos] = i; //insert to array, clobbers
dnleek 24:774104c34063 139 tempstart = i;
ng3600 14:928254a609cb 140 }
ng3600 14:928254a609cb 141 break;
dnleek 24:774104c34063 142
ng3600 14:928254a609cb 143 default:
ng3600 14:928254a609cb 144 //exit case if exception happened
ng3600 18:8a65598abf2f 145 serial.printf("Default case in processFn\r\n");
ng3600 14:928254a609cb 146 return out;
ng3600 2:6a87b2348245 147 }
ng3600 2:6a87b2348245 148 }
ng3600 13:c17cf029d899 149 //AGC, simple proportional controller
ng3600 15:4bd1c1d2cf94 150 total = total / frameLen;
dnleek 24:774104c34063 151 exposureChange = ((float)(MEAN_REF - total)) * CAM_CTRL_GAIN;
ng3600 3:f31986cb68fd 152 *exposure += (int)exposureChange;
ng3600 14:928254a609cb 153 if(*exposure < 0)
ng3600 14:928254a609cb 154 *exposure = 0;
ng3600 14:928254a609cb 155 else if(*exposure > UPDATE_RATE)
ng3600 14:928254a609cb 156 *exposure = UPDATE_RATE;
ng3600 0:2d546112b0b8 157 }
dnleek 24:774104c34063 158
ng3600 14:928254a609cb 159 l_walker = l_idx_ary;
ng3600 14:928254a609cb 160 h_walker = h_idx_ary;
dnleek 24:774104c34063 161
dnleek 24:774104c34063 162 /*while(*l_walker != -1 && *h_walker != -1){
ng3600 14:928254a609cb 163 //evaluate out and advance if line is white on black and returns center of smallest white band
ng3600 14:928254a609cb 164 //if interval is black on white, advance the pointer for the peak array
ng3600 18:8a65598abf2f 165 //width needs to be larger than 4 pixels wide to be a good read.
dnleek 24:774104c34063 166
ng3600 20:e9f0d1483ba1 167 if(*h_walker > *l_walker && (*h_walker - *l_walker) < out_width && (*h_walker - *l_walker) > 3){
ng3600 14:928254a609cb 168 out_width = *h_walker - *l_walker;
ng3600 15:4bd1c1d2cf94 169 out = ((float)(*h_walker + *l_walker)) / (2.0 * (float)frameLen); //0.5 is center
ng3600 14:928254a609cb 170 l_walker++;
ng3600 14:928254a609cb 171 }
ng3600 14:928254a609cb 172 h_walker++;
dnleek 24:774104c34063 173
ng3600 18:8a65598abf2f 174 //serial.printf("%d %d\r\n", *h_walker, *l_walker);
ng3600 18:8a65598abf2f 175 //serial.printf("%.2f\r\n", out);
dnleek 24:774104c34063 176 }*/
dnleek 24:774104c34063 177
dnleek 24:774104c34063 178 if (linestart != -1) {
dnleek 24:774104c34063 179 out = ((float)(linestart + linestop)) / (2.0 * (float)frameLen);
dnleek 24:774104c34063 180 } else {
dnleek 24:774104c34063 181 out = -1;
ng3600 14:928254a609cb 182 }
dnleek 24:774104c34063 183 return out;
dnleek 24:774104c34063 184 }
dnleek 24:774104c34063 185
dnleek 24:774104c34063 186 float processFn2(uint16_t *array, int arraySz, int* exposure)
dnleek 24:774104c34063 187 {
dnleek 24:774104c34063 188 const static int frameLen = NUM_PIX - 2 * SKIP;
dnleek 24:774104c34063 189 int avg[frameLen];
dnleek 24:774104c34063 190 int diff[frameLen];
dnleek 24:774104c34063 191 int highest = 0;
dnleek 24:774104c34063 192 int lowest = 0;
dnleek 24:774104c34063 193 int total = 0;
dnleek 24:774104c34063 194 int h_idx_ary[10];
dnleek 24:774104c34063 195 int h_idx_pos = 0;
dnleek 24:774104c34063 196 int l_idx_ary[10];
dnleek 24:774104c34063 197 int l_idx_pos = 0;
dnleek 24:774104c34063 198 int state = NEUTRAL;
dnleek 24:774104c34063 199 int *l_walker, *h_walker;
dnleek 24:774104c34063 200 int out_width = frameLen;
dnleek 24:774104c34063 201 int i;
dnleek 24:774104c34063 202 float out = -1.0;
dnleek 24:774104c34063 203 int thinnest = 128;
dnleek 24:774104c34063 204 int linestart = -1;
dnleek 24:774104c34063 205 int linestop = -1;
dnleek 24:774104c34063 206 int tempstart = 0;
dnleek 24:774104c34063 207
dnleek 24:774104c34063 208 //for AGC
dnleek 24:774104c34063 209 float exposureChange;
dnleek 24:774104c34063 210
dnleek 24:774104c34063 211 h_idx_ary[0] = -1;
dnleek 24:774104c34063 212 l_idx_ary[0] = -1;
dnleek 24:774104c34063 213
dnleek 24:774104c34063 214 if(array) {
dnleek 24:774104c34063 215 avg[0] = array[SKIP - 1]/2 + array[SKIP]/2;
dnleek 24:774104c34063 216 diff[0] = 0;
dnleek 24:774104c34063 217 //tele_linescan_diff[0] = diff[0];
dnleek 24:774104c34063 218
dnleek 24:774104c34063 219 total += avg[0]; //AGC
dnleek 24:774104c34063 220
dnleek 24:774104c34063 221 for(i = 1; i < frameLen; i++) {
dnleek 24:774104c34063 222 avg[i] = array[i - 1 + SKIP]/2 + array[i + SKIP]/2; //smoothing
dnleek 24:774104c34063 223 diff[i] = avg[i] - avg[i-1]; //differential
dnleek 24:774104c34063 224 //tele_linescan_diff[i] = diff[i];
dnleek 24:774104c34063 225
dnleek 24:774104c34063 226 total += avg[i]; //AGC
dnleek 24:774104c34063 227
dnleek 24:774104c34063 228
dnleek 24:774104c34063 229 //Finite State Machine
dnleek 24:774104c34063 230 //problem in this section, rewrite? find peaks and troughs
dnleek 24:774104c34063 231 switch(state) {
dnleek 24:774104c34063 232 case NEUTRAL:
dnleek 24:774104c34063 233 //serial.printf("Neutral case in processFn\r\n");
dnleek 24:774104c34063 234 if( diff[i] > THRESH ) {
dnleek 24:774104c34063 235 state = FIND_PEAK;
dnleek 24:774104c34063 236 highest = diff[i];
dnleek 24:774104c34063 237 h_idx_ary[h_idx_pos] = i;
dnleek 24:774104c34063 238 tempstart = i;
dnleek 24:774104c34063 239 } else if( diff[i] < -THRESH ) {
dnleek 24:774104c34063 240 state = FIND_TROUGH;
dnleek 24:774104c34063 241 lowest = diff[i];
dnleek 24:774104c34063 242 l_idx_ary[l_idx_pos] = i;
dnleek 24:774104c34063 243 tempstart = i;
dnleek 24:774104c34063 244 }
dnleek 24:774104c34063 245 break;
dnleek 24:774104c34063 246
dnleek 24:774104c34063 247 case FIND_PEAK:
dnleek 24:774104c34063 248 //serial.printf("Peak case in processFn\r\n");
dnleek 24:774104c34063 249 if( diff[i] <= THRESH ) {
dnleek 24:774104c34063 250 state = NEUTRAL;
dnleek 24:774104c34063 251 h_idx_pos++;
dnleek 24:774104c34063 252 h_idx_ary[h_idx_pos] = -1; //last element is always -1
dnleek 24:774104c34063 253 if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
dnleek 24:774104c34063 254 thinnest = i - tempstart;
dnleek 24:774104c34063 255 linestart = tempstart;
dnleek 24:774104c34063 256 linestop = i;
dnleek 24:774104c34063 257 }
dnleek 24:774104c34063 258 } else if(diff[i] > highest) {
dnleek 24:774104c34063 259 highest = diff[i];
dnleek 24:774104c34063 260 h_idx_ary[h_idx_pos] = i; //insert to array, clobbers
dnleek 24:774104c34063 261 tempstart = i;
dnleek 24:774104c34063 262 }
dnleek 24:774104c34063 263 break;
dnleek 24:774104c34063 264
dnleek 24:774104c34063 265 case FIND_TROUGH:
dnleek 24:774104c34063 266 //serial.printf("Trough case in processFn\r\n");
dnleek 24:774104c34063 267 if( diff[i] >= -THRESH ) {
dnleek 24:774104c34063 268 state = NEUTRAL;
dnleek 24:774104c34063 269 l_idx_pos++;
dnleek 24:774104c34063 270 l_idx_ary[l_idx_pos] = -1; //last element is always -1
dnleek 24:774104c34063 271 if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
dnleek 24:774104c34063 272 thinnest = i - tempstart;
dnleek 24:774104c34063 273 linestart = tempstart;
dnleek 24:774104c34063 274 linestop = i;
dnleek 24:774104c34063 275 }
dnleek 24:774104c34063 276 } else if(diff[i] < lowest) {
dnleek 24:774104c34063 277 lowest = diff[i];
dnleek 24:774104c34063 278 l_idx_ary[l_idx_pos] = i; //insert to array, clobbers
dnleek 24:774104c34063 279 tempstart = i;
dnleek 24:774104c34063 280 }
dnleek 24:774104c34063 281 break;
dnleek 24:774104c34063 282
dnleek 24:774104c34063 283 default:
dnleek 24:774104c34063 284 //exit case if exception happened
dnleek 24:774104c34063 285 serial.printf("Default case in processFn\r\n");
dnleek 24:774104c34063 286 return out;
dnleek 24:774104c34063 287 }
dnleek 24:774104c34063 288 }
dnleek 24:774104c34063 289 //AGC, simple proportional controller
dnleek 24:774104c34063 290 total = total / frameLen;
dnleek 24:774104c34063 291 exposureChange = ((float)(MEAN_REF - total)) * CAM_CTRL_GAIN;
dnleek 24:774104c34063 292 *exposure += (int)exposureChange;
dnleek 24:774104c34063 293 if(*exposure < 0)
dnleek 24:774104c34063 294 *exposure = 0;
dnleek 24:774104c34063 295 else if(*exposure > UPDATE_RATE)
dnleek 24:774104c34063 296 *exposure = UPDATE_RATE;
dnleek 24:774104c34063 297 }
dnleek 24:774104c34063 298
dnleek 24:774104c34063 299 l_walker = l_idx_ary;
dnleek 24:774104c34063 300 h_walker = h_idx_ary;
dnleek 24:774104c34063 301
dnleek 24:774104c34063 302 /*while(*l_walker != -1 && *h_walker != -1){
dnleek 24:774104c34063 303 //evaluate out and advance if line is white on black and returns center of smallest white band
dnleek 24:774104c34063 304 //if interval is black on white, advance the pointer for the peak array
dnleek 24:774104c34063 305 //width needs to be larger than 4 pixels wide to be a good read.
dnleek 24:774104c34063 306
dnleek 24:774104c34063 307 if(*h_walker > *l_walker && (*h_walker - *l_walker) < out_width && (*h_walker - *l_walker) > 3){
dnleek 24:774104c34063 308 out_width = *h_walker - *l_walker;
dnleek 24:774104c34063 309 out = ((float)(*h_walker + *l_walker)) / (2.0 * (float)frameLen); //0.5 is center
dnleek 24:774104c34063 310 l_walker++;
dnleek 24:774104c34063 311 }
dnleek 24:774104c34063 312 h_walker++;
dnleek 24:774104c34063 313
dnleek 24:774104c34063 314 //serial.printf("%d %d\r\n", *h_walker, *l_walker);
dnleek 24:774104c34063 315 //serial.printf("%.2f\r\n", out);
dnleek 24:774104c34063 316 }*/
dnleek 24:774104c34063 317
dnleek 24:774104c34063 318 if (linestart != -1) {
dnleek 24:774104c34063 319 out = ((float)(linestart + linestop)) / (2.0 * (float)frameLen);
dnleek 24:774104c34063 320 } else {
dnleek 24:774104c34063 321 out = -1;
dnleek 24:774104c34063 322 }
ng3600 14:928254a609cb 323 return out;
ng3600 0:2d546112b0b8 324 }
ng3600 0:2d546112b0b8 325
ng3600 3:f31986cb68fd 326 //call after integration time is done, returns index of array line is expected to be at and new exposure time
dnleek 24:774104c34063 327 float getLinePos(AnalogIn cam,
dnleek 24:774104c34063 328 DigitalOut *camSi,
dnleek 24:774104c34063 329 DigitalOut *camClk,
dnleek 24:774104c34063 330 int *exposure,
dnleek 24:774104c34063 331 telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan,
dnleek 24:774104c34063 332 telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff)
dnleek 24:774104c34063 333 {
ng3600 3:f31986cb68fd 334 uint16_t lineAry[NUM_PIX];
ng3600 8:b9ec2f3e12b6 335 float position;
dnleek 24:774104c34063 336
dnleek 24:774104c34063 337 //read
ng3600 0:2d546112b0b8 338 startRead(camSi, camClk);
dnleek 24:774104c34063 339 for(int i = 0; i < NUM_PIX; i++) {
ng3600 0:2d546112b0b8 340 lineAry[i] = read1Bit(cam, camClk);
ng3600 12:ce6d9f7dc76e 341 tele_linescan[i] = lineAry[i];
ng3600 0:2d546112b0b8 342 }
dnleek 24:774104c34063 343
ng3600 0:2d546112b0b8 344 //process line scan data
dnleek 24:774104c34063 345 position = processFn(lineAry, NUM_PIX, exposure, tele_linescan_diff);
dnleek 24:774104c34063 346
ng3600 0:2d546112b0b8 347 return position;
ng3600 0:2d546112b0b8 348 }
ng3600 0:2d546112b0b8 349
dnleek 24:774104c34063 350 float getLinePos2(AnalogIn cam,
dnleek 24:774104c34063 351 DigitalOut *camSi,
dnleek 24:774104c34063 352 DigitalOut *camClk,
dnleek 24:774104c34063 353 int *exposure)
dnleek 24:774104c34063 354 {
dnleek 24:774104c34063 355 uint16_t lineAry[NUM_PIX];
dnleek 24:774104c34063 356 float position;
ng3600 0:2d546112b0b8 357
dnleek 24:774104c34063 358 //read
dnleek 24:774104c34063 359 startRead(camSi, camClk);
dnleek 24:774104c34063 360 for(int i = 0; i < NUM_PIX; i++) {
dnleek 24:774104c34063 361 lineAry[i] = read1Bit(cam, camClk);
dnleek 24:774104c34063 362 }
dnleek 24:774104c34063 363
dnleek 24:774104c34063 364 //process line scan data
dnleek 24:774104c34063 365 position = processFn2(lineAry, NUM_PIX, exposure);//, tele_linescan_diff);
dnleek 24:774104c34063 366
dnleek 24:774104c34063 367 return position;
ng3600 0:2d546112b0b8 368 }