Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Thu Apr 17 08:04:14 2014 +0000
Revision:
47:199042980678
Parent:
41:74e24a0e6e50
publishing for sharing with Ken Iwasaki

Who changed what in which revision?

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