Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Wed Mar 13 12:44:09 2013 +0000
Revision:
38:9b522ef2c519
Parent:
37:fa6b1f15819f
really, pot value not working, but good version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedalvaro 31:5f039cbddee8 1 #include "hardwareIO.h"
mbedalvaro 31:5f039cbddee8 2
mbedalvaro 31:5f039cbddee8 3 HardwareIO IO; // preintantiation of cross-file global object IO
mbedalvaro 31:5f039cbddee8 4
mbedalvaro 31:5f039cbddee8 5 // -------------------------------------- (0) SETUP ALL IO (call this in the setup() function in main program)
mbedalvaro 31:5f039cbddee8 6
mbedalvaro 31:5f039cbddee8 7 Serial pc(USBTX, USBRX); // tx, rx
mbedalvaro 31:5f039cbddee8 8 LocalFileSystem local("local"); // Create the local filesystem under the name "local"
mbedalvaro 31:5f039cbddee8 9
mbedalvaro 31:5f039cbddee8 10 SPI spiDAC(MOSI_PIN, MISO_PIN, SCK_PIN); // mosi, miso, sclk
mbedalvaro 31:5f039cbddee8 11 DigitalOut csDAC(CS_DAC_MIRRORS);
mbedalvaro 34:1244fa3f2559 12
mbedalvaro 31:5f039cbddee8 13 DigitalOut Laser_Red(LASER_RED_PIN); // NOTE: this is NOT the lock in sensing laser (actually, not used yet)
mbedalvaro 31:5f039cbddee8 14 DigitalOut Laser_Green(LASER_GREEN_PIN);
mbedalvaro 31:5f039cbddee8 15 DigitalOut Laser_Blue(LASER_BLUE_PIN);
mbedalvaro 34:1244fa3f2559 16
mbedalvaro 34:1244fa3f2559 17 // Some manual controls over the hardware function:
mbedalvaro 34:1244fa3f2559 18 InterruptIn switchOne(SWITCH_ONE);
mbedalvaro 34:1244fa3f2559 19 DigitalOut ledSwitchOne(LED_SWITCH_ONE);
mbedalvaro 34:1244fa3f2559 20 InterruptIn switchTwo(SWITCH_TWO);
mbedalvaro 37:fa6b1f15819f 21 AnalogIn ainPot(POT_ANALOG_INPUT);
mbedalvaro 31:5f039cbddee8 22
mbedalvaro 31:5f039cbddee8 23 void HardwareIO::init(void) {
mbedalvaro 34:1244fa3f2559 24
mbedalvaro 34:1244fa3f2559 25 // Set laser powers down:
mbedalvaro 34:1244fa3f2559 26 setRedPower(0);// TTL red laser (not used - actually not present)
mbedalvaro 34:1244fa3f2559 27 setGreenPower(0);
mbedalvaro 34:1244fa3f2559 28 setBluePower(0);
mbedalvaro 31:5f039cbddee8 29
mbedalvaro 31:5f039cbddee8 30 //Serial Communication setup:
mbedalvaro 31:5f039cbddee8 31 pc.baud(115200);//
mbedalvaro 31:5f039cbddee8 32 // pc.baud(921600);//115200);//
mbedalvaro 31:5f039cbddee8 33
mbedalvaro 31:5f039cbddee8 34 // Setup for lock-in amplifier and pwm references:
mbedalvaro 34:1244fa3f2559 35 setLaserLockinPower(1);// actually this is the Red laser in the hardware
mbedalvaro 31:5f039cbddee8 36 lockin.init();
mbedalvaro 31:5f039cbddee8 37
mbedalvaro 34:1244fa3f2559 38 // Setup for DAC control to move the mirrors:
mbedalvaro 34:1244fa3f2559 39 // Set spi for 8 bit data, high steady state clock,
mbedalvaro 34:1244fa3f2559 40 // second edge capture, with a 10MHz clock rate:
mbedalvaro 31:5f039cbddee8 41 csDAC = 1;
mbedalvaro 31:5f039cbddee8 42 spiDAC.format(16,0);
mbedalvaro 31:5f039cbddee8 43 spiDAC.frequency(16000000);
mbedalvaro 31:5f039cbddee8 44
mbedalvaro 31:5f039cbddee8 45 // default initial mirror position:
mbedalvaro 31:5f039cbddee8 46 writeOutX(CENTER_AD_MIRROR_X);
mbedalvaro 31:5f039cbddee8 47 writeOutY(CENTER_AD_MIRROR_Y);
mbedalvaro 31:5f039cbddee8 48
mbedalvaro 31:5f039cbddee8 49 // Load LUT table:
mbedalvaro 31:5f039cbddee8 50 setLUT();
mbedalvaro 34:1244fa3f2559 51
mbedalvaro 34:1244fa3f2559 52 // Set interrupts on RAISING edge for button-switch functions:
mbedalvaro 34:1244fa3f2559 53 // Note: The pin input will be logic '0' for any voltage on the pin below 0.8v, and '1' for any voltage above 2.0v.
mbedalvaro 34:1244fa3f2559 54 // By default, the InterruptIn is setup with an internal pull-down resistor, but for security and clarity I will do it explicitly here:
mbedalvaro 34:1244fa3f2559 55 switchOne.mode(PullUp); // pull down seems not very good
mbedalvaro 34:1244fa3f2559 56 switchTwo.mode(PullUp);
mbedalvaro 34:1244fa3f2559 57 switchOne.fall(this, &HardwareIO::switchOneInterrupt); // attach the address of the flip function to the falling edge
mbedalvaro 34:1244fa3f2559 58 switchTwo.fall(this, &HardwareIO::switchTwoInterrupt); // attach the address of the flip function to the falling edge
mbedalvaro 35:35af5086ab4f 59 switchOneState=true;
mbedalvaro 34:1244fa3f2559 60 switchTwoState=false;
mbedalvaro 34:1244fa3f2559 61 switchOneChange=false;
mbedalvaro 34:1244fa3f2559 62 switchTwoChange=false;
mbedalvaro 35:35af5086ab4f 63
mbedalvaro 36:233b12d0b1f0 64 // ATTENTION: initial state of the switch should correspond to the inital state of the threshold mode in the constructor of the laser trajectory objects (not nice):
mbedalvaro 35:35af5086ab4f 65 setSwitchOneState(true); //equal to switchOneState=true, plus set led value. False means fixed threshold, true AUTO THRESHOLD (will be the default mode)
mbedalvaro 34:1244fa3f2559 66
mbedalvaro 34:1244fa3f2559 67 // Read and update pot value:
mbedalvaro 34:1244fa3f2559 68 // updatePotValue(); // the value will be ajusted in the range 0-255
mbedalvaro 34:1244fa3f2559 69 }
mbedalvaro 34:1244fa3f2559 70
mbedalvaro 35:35af5086ab4f 71 void HardwareIO::setSwitchOneState(bool newstate) {
mbedalvaro 35:35af5086ab4f 72 switchOneState=newstate;
mbedalvaro 35:35af5086ab4f 73 ledSwitchOne=(switchOneState? 1 :0);
mbedalvaro 35:35af5086ab4f 74 }
mbedalvaro 35:35af5086ab4f 75
mbedalvaro 34:1244fa3f2559 76 // these ISR could do more (like debouncing).
mbedalvaro 34:1244fa3f2559 77 // For the time being, I will debounce electrically with a small capacitor.
mbedalvaro 34:1244fa3f2559 78 void HardwareIO::switchOneInterrupt() {
mbedalvaro 34:1244fa3f2559 79 switchOneState=!switchOneState;
mbedalvaro 34:1244fa3f2559 80 ledSwitchOne=(switchOneState? 1 :0); // this switch has a built-in led
mbedalvaro 34:1244fa3f2559 81 switchOneChange=true;
mbedalvaro 34:1244fa3f2559 82 }
mbedalvaro 34:1244fa3f2559 83 void HardwareIO::switchTwoInterrupt() {
mbedalvaro 34:1244fa3f2559 84 switchTwoState=!switchTwoState;
mbedalvaro 34:1244fa3f2559 85 switchTwoChange=true;
mbedalvaro 34:1244fa3f2559 86 }
mbedalvaro 34:1244fa3f2559 87
mbedalvaro 34:1244fa3f2559 88 bool HardwareIO::switchOneCheck(bool& state) {
mbedalvaro 34:1244fa3f2559 89 if (switchOneChange) {
mbedalvaro 34:1244fa3f2559 90 switchOneChange=false;
mbedalvaro 34:1244fa3f2559 91 state=switchOneState;
mbedalvaro 34:1244fa3f2559 92 return(true);
mbedalvaro 34:1244fa3f2559 93 } else
mbedalvaro 34:1244fa3f2559 94 return(false);
mbedalvaro 34:1244fa3f2559 95 }
mbedalvaro 34:1244fa3f2559 96
mbedalvaro 34:1244fa3f2559 97 bool HardwareIO::switchTwoCheck(bool& state) {
mbedalvaro 34:1244fa3f2559 98 if (switchTwoChange) {
mbedalvaro 34:1244fa3f2559 99 switchTwoChange=false;
mbedalvaro 34:1244fa3f2559 100 state=switchTwoState;
mbedalvaro 34:1244fa3f2559 101 return(true);
mbedalvaro 34:1244fa3f2559 102 } else return(false);
mbedalvaro 34:1244fa3f2559 103 }
mbedalvaro 34:1244fa3f2559 104
mbedalvaro 37:fa6b1f15819f 105 // THIS IS NOT WORKING!!!!!!
mbedalvaro 34:1244fa3f2559 106 unsigned char HardwareIO::updatePotValue() { // this will update the pot value, and return it too.
mbedalvaro 37:fa6b1f15819f 107 //The value will be ajusted in the range 0-255
mbedalvaro 34:1244fa3f2559 108 //The 0.0v to 3.3v range of the AnalogIn is represented in software as a normalised floating point number from 0.0 to 1.0.
mbedalvaro 37:fa6b1f15819f 109
mbedalvaro 37:fa6b1f15819f 110 // potValue=(unsigned char )(ainPot*255);
mbedalvaro 37:fa6b1f15819f 111 // Attention: go back to burst mode:
mbedalvaro 37:fa6b1f15819f 112 // lockin.setADC_forLockin(1);
mbedalvaro 37:fa6b1f15819f 113 // wait(1);
mbedalvaro 37:fa6b1f15819f 114
mbedalvaro 37:fa6b1f15819f 115 //USING the adc library:
mbedalvaro 37:fa6b1f15819f 116 // unset fast adc for lockin, and set normal adc for conversion from analog input pin:
mbedalvaro 34:1244fa3f2559 117 lockin.setADC_forLockin(0);
mbedalvaro 38:9b522ef2c519 118 // wait(1);
mbedalvaro 37:fa6b1f15819f 119
mbedalvaro 37:fa6b1f15819f 120 //Measure pin POT_ANALOG_INPUT
mbedalvaro 37:fa6b1f15819f 121 adc.select(POT_ANALOG_INPUT);
mbedalvaro 37:fa6b1f15819f 122 //Start ADC conversion
mbedalvaro 37:fa6b1f15819f 123 adc.start();
mbedalvaro 37:fa6b1f15819f 124 //Wait for it to complete
mbedalvaro 37:fa6b1f15819f 125 while(!adc.done(POT_ANALOG_INPUT));
mbedalvaro 37:fa6b1f15819f 126 potValue=adc.read(POT_ANALOG_INPUT);
mbedalvaro 37:fa6b1f15819f 127
mbedalvaro 37:fa6b1f15819f 128 //Unset pin POT_ANALOG_INPUT
mbedalvaro 37:fa6b1f15819f 129 adc.setup(POT_ANALOG_INPUT,0);
mbedalvaro 37:fa6b1f15819f 130
mbedalvaro 37:fa6b1f15819f 131 lockin.setADC_forLockin(1);
mbedalvaro 37:fa6b1f15819f 132 wait(0.5);
mbedalvaro 34:1244fa3f2559 133
mbedalvaro 34:1244fa3f2559 134 return(potValue);
mbedalvaro 31:5f039cbddee8 135 }
mbedalvaro 31:5f039cbddee8 136
mbedalvaro 31:5f039cbddee8 137 //write on the first DAC, output A (mirror X)
mbedalvaro 31:5f039cbddee8 138 void HardwareIO::writeOutX(unsigned short value){
mbedalvaro 31:5f039cbddee8 139 if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 140 if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 141
mbedalvaro 31:5f039cbddee8 142 value |= 0x7000;
mbedalvaro 31:5f039cbddee8 143 value &= 0x7FFF;
mbedalvaro 31:5f039cbddee8 144
mbedalvaro 31:5f039cbddee8 145 csDAC = 0;
mbedalvaro 31:5f039cbddee8 146 spiDAC.write(value);
mbedalvaro 31:5f039cbddee8 147 csDAC = 1;
mbedalvaro 31:5f039cbddee8 148 }
mbedalvaro 31:5f039cbddee8 149
mbedalvaro 31:5f039cbddee8 150 //write on the first DAC, output B (mirror Y)
mbedalvaro 31:5f039cbddee8 151 void HardwareIO::writeOutY(unsigned short value){
mbedalvaro 31:5f039cbddee8 152 if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 153 if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 154
mbedalvaro 31:5f039cbddee8 155 value |= 0xF000;
mbedalvaro 31:5f039cbddee8 156 value &= 0xFFFF;
mbedalvaro 31:5f039cbddee8 157
mbedalvaro 31:5f039cbddee8 158 csDAC = 0;
mbedalvaro 31:5f039cbddee8 159 spiDAC.write(value);
mbedalvaro 31:5f039cbddee8 160 csDAC = 1;
mbedalvaro 31:5f039cbddee8 161 }
mbedalvaro 31:5f039cbddee8 162
mbedalvaro 34:1244fa3f2559 163 void HardwareIO::setLaserLockinPower(int powerValue){
mbedalvaro 31:5f039cbddee8 164 if(powerValue > 0){
mbedalvaro 31:5f039cbddee8 165 lockin.setLaserPower(true);
mbedalvaro 31:5f039cbddee8 166 }
mbedalvaro 31:5f039cbddee8 167 else{
mbedalvaro 31:5f039cbddee8 168 lockin.setLaserPower(false);
mbedalvaro 31:5f039cbddee8 169 }
mbedalvaro 31:5f039cbddee8 170 }
mbedalvaro 34:1244fa3f2559 171 // THE TTL controlled lasers:
mbedalvaro 34:1244fa3f2559 172 // Note: the red one is not used here
mbedalvaro 34:1244fa3f2559 173 void HardwareIO::setRedPower(int powerValue){
mbedalvaro 34:1244fa3f2559 174 if(powerValue > 0){
mbedalvaro 34:1244fa3f2559 175 Laser_Red = 1;
mbedalvaro 34:1244fa3f2559 176 }
mbedalvaro 34:1244fa3f2559 177 else{
mbedalvaro 34:1244fa3f2559 178 Laser_Red = 0;
mbedalvaro 34:1244fa3f2559 179 }
mbedalvaro 34:1244fa3f2559 180 }
mbedalvaro 31:5f039cbddee8 181 void HardwareIO::setGreenPower(int powerValue){
mbedalvaro 31:5f039cbddee8 182 if(powerValue > 0){
mbedalvaro 31:5f039cbddee8 183 Laser_Green = 1;
mbedalvaro 31:5f039cbddee8 184 }
mbedalvaro 31:5f039cbddee8 185 else{
mbedalvaro 31:5f039cbddee8 186 Laser_Green = 0;
mbedalvaro 31:5f039cbddee8 187 }
mbedalvaro 31:5f039cbddee8 188 }
mbedalvaro 31:5f039cbddee8 189 void HardwareIO::setBluePower(int powerValue){
mbedalvaro 31:5f039cbddee8 190 if(powerValue > 0){
mbedalvaro 31:5f039cbddee8 191 Laser_Blue = 1;
mbedalvaro 31:5f039cbddee8 192 }
mbedalvaro 31:5f039cbddee8 193 else{
mbedalvaro 31:5f039cbddee8 194 Laser_Blue = 0;
mbedalvaro 31:5f039cbddee8 195 }
mbedalvaro 31:5f039cbddee8 196 }
mbedalvaro 31:5f039cbddee8 197
mbedalvaro 31:5f039cbddee8 198 void HardwareIO::setRGBPower(unsigned char color) {
mbedalvaro 34:1244fa3f2559 199 lockin.setLaserPower((color&0x04)>0? true : false); // NOTE: here the "red" is the lockin laser, not the TTL one (not used yet)
mbedalvaro 31:5f039cbddee8 200 Laser_Green=(color&0x02)>>1;
mbedalvaro 31:5f039cbddee8 201 Laser_Blue =color&0x01;
mbedalvaro 31:5f039cbddee8 202 }
mbedalvaro 31:5f039cbddee8 203
mbedalvaro 31:5f039cbddee8 204 void HardwareIO::showLimitsMirrors(int times) {
mbedalvaro 31:5f039cbddee8 205 unsigned short pointsPerLine=150;
mbedalvaro 31:5f039cbddee8 206 int shiftX = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
mbedalvaro 31:5f039cbddee8 207 int shiftY = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
mbedalvaro 31:5f039cbddee8 208
mbedalvaro 31:5f039cbddee8 209 Laser_Green=1;
mbedalvaro 31:5f039cbddee8 210
mbedalvaro 31:5f039cbddee8 211 //for (int repeat=0; repeat<times; repeat++) {
mbedalvaro 31:5f039cbddee8 212
mbedalvaro 31:5f039cbddee8 213 Timer t;
mbedalvaro 31:5f039cbddee8 214 t.start();
mbedalvaro 31:5f039cbddee8 215 while(t.read_ms()<times*1000) {
mbedalvaro 31:5f039cbddee8 216
mbedalvaro 31:5f039cbddee8 217 writeOutX(MIN_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 218
mbedalvaro 31:5f039cbddee8 219 for(int j=0; j<pointsPerLine; j++){
mbedalvaro 31:5f039cbddee8 220 wait_us(200);//delay between each points
mbedalvaro 31:5f039cbddee8 221 writeOutY(j*shiftY + MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 222 }
mbedalvaro 31:5f039cbddee8 223
mbedalvaro 31:5f039cbddee8 224 writeOutX(MIN_AD_MIRRORS);writeOutY(MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 225 for(int j=0; j<pointsPerLine; j++) {
mbedalvaro 31:5f039cbddee8 226 wait_us(200);//delay between each points
mbedalvaro 31:5f039cbddee8 227 writeOutX(j*shiftX + MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 228 }
mbedalvaro 31:5f039cbddee8 229
mbedalvaro 31:5f039cbddee8 230 writeOutX(MAX_AD_MIRRORS);writeOutY(MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 231 for(int j=0; j<pointsPerLine; j++) {
mbedalvaro 31:5f039cbddee8 232 wait_us(200);//delay between each points
mbedalvaro 31:5f039cbddee8 233 writeOutY(-j*shiftX + MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 234 }
mbedalvaro 31:5f039cbddee8 235
mbedalvaro 31:5f039cbddee8 236 writeOutX(MAX_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 237 for(int j=0; j<pointsPerLine; j++) {
mbedalvaro 31:5f039cbddee8 238 wait_us(200);//delay between each points
mbedalvaro 31:5f039cbddee8 239 writeOutX(-j*shiftX + MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 240 }
mbedalvaro 31:5f039cbddee8 241
mbedalvaro 31:5f039cbddee8 242 }
mbedalvaro 31:5f039cbddee8 243 t.stop();
mbedalvaro 31:5f039cbddee8 244 Laser_Green=0;
mbedalvaro 31:5f039cbddee8 245 }
mbedalvaro 31:5f039cbddee8 246
mbedalvaro 31:5f039cbddee8 247 void HardwareIO::scan_serial(unsigned short pointsPerLine){
mbedalvaro 31:5f039cbddee8 248 //scan the total surface with a custom resolution
mbedalvaro 31:5f039cbddee8 249 //send the lockin value for each point as a byte on the serial port to the PC
mbedalvaro 31:5f039cbddee8 250 //use "scanSLP_save" to see the data on processing
mbedalvaro 35:35af5086ab4f 251 // First, set the red laser on, and other off:
mbedalvaro 35:35af5086ab4f 252 setRGBPower(0x4);
mbedalvaro 35:35af5086ab4f 253 wait_us(1000); // just to give time to the lockin to set
mbedalvaro 35:35af5086ab4f 254
mbedalvaro 31:5f039cbddee8 255 int shiftX = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
mbedalvaro 31:5f039cbddee8 256 int shiftY = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
mbedalvaro 31:5f039cbddee8 257
mbedalvaro 31:5f039cbddee8 258 for(int j=0; j<pointsPerLine; j++){
mbedalvaro 31:5f039cbddee8 259 writeOutX(MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 260 writeOutY(j*shiftY + MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 261
mbedalvaro 31:5f039cbddee8 262 wait_us(300);//begining of line delay
mbedalvaro 31:5f039cbddee8 263 for(int i=0; i<pointsPerLine; i++){
mbedalvaro 31:5f039cbddee8 264 writeOutX(i*shiftX + MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 265
mbedalvaro 31:5f039cbddee8 266 wait_us(200);//delay between each points
mbedalvaro 31:5f039cbddee8 267
mbedalvaro 31:5f039cbddee8 268 // SEND A VALUE BETWEEN 0 and 255:
mbedalvaro 31:5f039cbddee8 269 pc.putc(int(255.0*lockin.getMedianValue()/4095));//printf("%dL",int(valueLockin*255));//pc.putc(int(lockin*255));//
mbedalvaro 31:5f039cbddee8 270 }
mbedalvaro 31:5f039cbddee8 271 }
mbedalvaro 31:5f039cbddee8 272 }
mbedalvaro 31:5f039cbddee8 273
mbedalvaro 31:5f039cbddee8 274 //load Look-up Table from LUT.TXT file
mbedalvaro 31:5f039cbddee8 275 //or create the file with scanLUT() if not existing.
mbedalvaro 31:5f039cbddee8 276 void HardwareIO::setLUT(){
mbedalvaro 31:5f039cbddee8 277
mbedalvaro 31:5f039cbddee8 278 FILE *fp = fopen(LUT_FILENAME, "r"); // Open file on the local file system for writing
mbedalvaro 31:5f039cbddee8 279 if(fp){
mbedalvaro 31:5f039cbddee8 280 //load the file into the lut table; keep the SAME resolution!
mbedalvaro 31:5f039cbddee8 281 fread(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp);
mbedalvaro 31:5f039cbddee8 282 fclose(fp);
mbedalvaro 31:5f039cbddee8 283 }
mbedalvaro 31:5f039cbddee8 284 else{
mbedalvaro 31:5f039cbddee8 285 //fclose(fp);
mbedalvaro 31:5f039cbddee8 286 //if the file "LUT.TXT" doesn't exist, create one with scanLUT()
mbedalvaro 31:5f039cbddee8 287 lockin.setLaserPower(true);
mbedalvaro 31:5f039cbddee8 288 scanLUT();
mbedalvaro 31:5f039cbddee8 289 }
mbedalvaro 31:5f039cbddee8 290
mbedalvaro 31:5f039cbddee8 291 }
mbedalvaro 31:5f039cbddee8 292
mbedalvaro 31:5f039cbddee8 293 //scan the total surface with a fixed 2^x resolution
mbedalvaro 31:5f039cbddee8 294 //create the Look-Up Table used to "flatten" the scan according to the position
mbedalvaro 31:5f039cbddee8 295 //
mbedalvaro 31:5f039cbddee8 296 //To Do: maybe detect high frequency to be sure the area is clean and empty?
mbedalvaro 31:5f039cbddee8 297 void HardwareIO::scanLUT(){
mbedalvaro 31:5f039cbddee8 298
mbedalvaro 31:5f039cbddee8 299 //reset lut table
mbedalvaro 31:5f039cbddee8 300 for(int j=0; j<LUT_RESOLUTION; j++){
mbedalvaro 31:5f039cbddee8 301 for(int i=0; i<LUT_RESOLUTION; i++){
mbedalvaro 31:5f039cbddee8 302 lut[i][j] =0;
mbedalvaro 31:5f039cbddee8 303 }
mbedalvaro 31:5f039cbddee8 304 }
mbedalvaro 31:5f039cbddee8 305
mbedalvaro 31:5f039cbddee8 306 int delayScanning = 300; //in us
mbedalvaro 31:5f039cbddee8 307
mbedalvaro 31:5f039cbddee8 308 //define the distance between each points (from 0 to 4096) and the offset (here 0)
mbedalvaro 31:5f039cbddee8 309 float shiftX = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1);
mbedalvaro 31:5f039cbddee8 310 float shiftY = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1);
mbedalvaro 31:5f039cbddee8 311 float offsetX = MIN_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 312 float offsetY = MIN_AD_MIRRORS;
mbedalvaro 31:5f039cbddee8 313
mbedalvaro 31:5f039cbddee8 314 //move the mirrors to the first position
mbedalvaro 31:5f039cbddee8 315 writeOutX(MAX_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 316 wait_us(500);
mbedalvaro 31:5f039cbddee8 317
mbedalvaro 31:5f039cbddee8 318 float x, y;
mbedalvaro 31:5f039cbddee8 319
mbedalvaro 31:5f039cbddee8 320 //scan the surface NB_SCANS times
mbedalvaro 31:5f039cbddee8 321 //the total value in lut[i][j] shouldn't exceed uint16 !!!
mbedalvaro 31:5f039cbddee8 322 for(int loop=0; loop<NB_SCANS; loop++){
mbedalvaro 31:5f039cbddee8 323 for(int j=0; j<LUT_RESOLUTION; j++){
mbedalvaro 31:5f039cbddee8 324 y = shiftY*j + offsetY ;
mbedalvaro 31:5f039cbddee8 325 writeOutY(int(y));
mbedalvaro 31:5f039cbddee8 326 //scan from right to left
mbedalvaro 31:5f039cbddee8 327 for(int i=LUT_RESOLUTION-1; i>=0; i--){
mbedalvaro 31:5f039cbddee8 328 x = shiftX*i + offsetX;
mbedalvaro 31:5f039cbddee8 329 writeOutX(int(x));
mbedalvaro 31:5f039cbddee8 330 wait_us(delayScanning);
mbedalvaro 31:5f039cbddee8 331 lut[i][j] += lockin_read();
mbedalvaro 31:5f039cbddee8 332 }
mbedalvaro 31:5f039cbddee8 333 //re-scan from left to right
mbedalvaro 31:5f039cbddee8 334 for(int i=0; i<LUT_RESOLUTION; i++){
mbedalvaro 31:5f039cbddee8 335 x = shiftX*i + offsetX;
mbedalvaro 31:5f039cbddee8 336 writeOutX(int(x));
mbedalvaro 31:5f039cbddee8 337 wait_us(delayScanning);
mbedalvaro 31:5f039cbddee8 338 lut[i][j] += lockin_read();
mbedalvaro 31:5f039cbddee8 339 }
mbedalvaro 31:5f039cbddee8 340 }
mbedalvaro 31:5f039cbddee8 341 }
mbedalvaro 31:5f039cbddee8 342
mbedalvaro 31:5f039cbddee8 343
mbedalvaro 31:5f039cbddee8 344 //save tab in file
mbedalvaro 31:5f039cbddee8 345 FILE *fp;
mbedalvaro 31:5f039cbddee8 346 #ifdef LUT_FILENAME
mbedalvaro 31:5f039cbddee8 347 fp = fopen(LUT_FILENAME, "w"); // Open file on the local file system for writing
mbedalvaro 31:5f039cbddee8 348 fwrite(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp);
mbedalvaro 31:5f039cbddee8 349 fclose(fp); //close the file (the mBed will appear connected again)
mbedalvaro 31:5f039cbddee8 350 #endif
mbedalvaro 31:5f039cbddee8 351
mbedalvaro 31:5f039cbddee8 352 #ifdef LUT_H_FILENAME
mbedalvaro 31:5f039cbddee8 353 //save tab in Human readable file (not used by the program, this is just for checking)
mbedalvaro 31:5f039cbddee8 354 // NOTE: we divide the content of the lut table by NB_SCANS, for easy reading (values should be between 0-4095)
mbedalvaro 31:5f039cbddee8 355 fp = fopen(LUT_H_FILENAME, "w"); // Open file on the local file system for writing
mbedalvaro 31:5f039cbddee8 356 fprintf(fp, "scan resolution: %d x %d\r\n",LUT_RESOLUTION, LUT_RESOLUTION);
mbedalvaro 31:5f039cbddee8 357 for(int j=0; j<LUT_RESOLUTION; j++){
mbedalvaro 31:5f039cbddee8 358 for(int i=0; i<LUT_RESOLUTION; i++){
mbedalvaro 31:5f039cbddee8 359 fprintf(fp, "X=%d,\tY=%d,\tI=%d\t \r\n", int(shiftX*i + offsetX), int(shiftY*j + offsetY), int(1.0*lut[i][j]/NB_SCANS) );
mbedalvaro 31:5f039cbddee8 360 }
mbedalvaro 31:5f039cbddee8 361 }
mbedalvaro 31:5f039cbddee8 362 fclose(fp); //close the file (the mBed will appear connected again)
mbedalvaro 31:5f039cbddee8 363 #endif
mbedalvaro 31:5f039cbddee8 364
mbedalvaro 31:5f039cbddee8 365 }
mbedalvaro 31:5f039cbddee8 366
mbedalvaro 31:5f039cbddee8 367
mbedalvaro 31:5f039cbddee8 368 //Return the lockin value "corrected with the Look-UpTable" - this means a RATIO between two reflectivities (and normally, this is <1).
mbedalvaro 31:5f039cbddee8 369 float HardwareIO::lockInCorrectedValue(unsigned short x, unsigned short y){
mbedalvaro 31:5f039cbddee8 370 //*******Correction using DIRECT approximation
mbedalvaro 31:5f039cbddee8 371 #ifdef LUT_DIRECT
mbedalvaro 31:5f039cbddee8 372 return 2.0* NB_SCANS * lockin_read() / (lut[x >> LUT_BITS_SHIFT][y >> LUT_BITS_SHIFT]); // 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left)
mbedalvaro 31:5f039cbddee8 373 #endif
mbedalvaro 31:5f039cbddee8 374
mbedalvaro 31:5f039cbddee8 375 //*******Correction using BILINEAR approximation
mbedalvaro 31:5f039cbddee8 376 #ifdef LUT_BILINEAR
mbedalvaro 31:5f039cbddee8 377 unsigned short X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17
mbedalvaro 31:5f039cbddee8 378 unsigned short Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17
mbedalvaro 31:5f039cbddee8 379 float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm)
mbedalvaro 31:5f039cbddee8 380 float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm)
mbedalvaro 31:5f039cbddee8 381
mbedalvaro 31:5f039cbddee8 382 //Wheighted mean approximation of the Look-Up Table at the position (x,y):
mbedalvaro 31:5f039cbddee8 383 float wmLUT = (1-dy)*( (1-dx)*lut[X][Y] + dx*lut[X+1][Y] ) + dy*( (1-dx)*lut[X][Y+1] + dx*lut[X+1][Y+1] );
mbedalvaro 31:5f039cbddee8 384
mbedalvaro 31:5f039cbddee8 385 return 2.0* NB_SCANS * lockin_read() / wmLUT;// 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left)
mbedalvaro 31:5f039cbddee8 386 #endif
mbedalvaro 31:5f039cbddee8 387
mbedalvaro 31:5f039cbddee8 388 //*******Correction using LINEAR approximation
mbedalvaro 31:5f039cbddee8 389 #ifdef LUT_LINEAR
mbedalvaro 31:5f039cbddee8 390 unsigned short X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17
mbedalvaro 31:5f039cbddee8 391 unsigned short Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17
mbedalvaro 31:5f039cbddee8 392 float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm)
mbedalvaro 31:5f039cbddee8 393 float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm)
mbedalvaro 31:5f039cbddee8 394 float linearLUT, dzx, dzy;
mbedalvaro 31:5f039cbddee8 395
mbedalvaro 31:5f039cbddee8 396 if(dx>dy){ //if the position is on the "top-right" triangle
mbedalvaro 31:5f039cbddee8 397 dzx = (lut[X+1][Y] - lut[X][Y]) * dx;
mbedalvaro 31:5f039cbddee8 398 dzy = (lut[X+1][Y+1] - lut[X+1][Y]) * dy;
mbedalvaro 31:5f039cbddee8 399 }
mbedalvaro 31:5f039cbddee8 400 else{ //if the position is on the "bottom-left" triangle
mbedalvaro 31:5f039cbddee8 401 dzy = (lut[X][Y+1] - lut[X][Y]) * dy;
mbedalvaro 31:5f039cbddee8 402 dzx = (lut[X+1][Y+1] - lut[X][Y+1]) * dx;
mbedalvaro 31:5f039cbddee8 403 }
mbedalvaro 31:5f039cbddee8 404
mbedalvaro 31:5f039cbddee8 405 //linear approximation of the Look-Up Table at the position (x,y):
mbedalvaro 31:5f039cbddee8 406 linearLUT = lut[X][Y] + dzx + dzy;
mbedalvaro 31:5f039cbddee8 407 return 2.0* NB_SCANS * lockin_read() / linearLUT; // 2 * NB_SCANS is the number of recorded sample added to one position of the LUT (scan is performed twice: left-right and right-left)
mbedalvaro 31:5f039cbddee8 408
mbedalvaro 31:5f039cbddee8 409 #endif
mbedalvaro 31:5f039cbddee8 410
mbedalvaro 31:5f039cbddee8 411 //*******No corrections, just return the value divided by 4096 (this means we are assuming that the surface is everywhere perfectly reflective - we supposedly get the max value always)
mbedalvaro 31:5f039cbddee8 412 #ifdef NO_LUT
mbedalvaro 31:5f039cbddee8 413 return 1.0* lockin_read()/4096;
mbedalvaro 31:5f039cbddee8 414 #endif
mbedalvaro 31:5f039cbddee8 415
mbedalvaro 31:5f039cbddee8 416 }