Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Revision:
0:345b3bc7a0ea
Child:
10:6f8e48dca1bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardwareIO/hardwareIO.cpp	Wed Mar 28 14:40:01 2012 +0000
@@ -0,0 +1,264 @@
+#include "hardwareIO.h"
+
+HardwareIO IO; // preintantiation of cross-file global object IO
+
+// --------------------------------------  (0) SETUP ALL IO (call this in the setup() function in main program)
+
+Serial pc(USBTX, USBRX); // tx, rx
+LocalFileSystem local("local");               // Create the local filesystem under the name "local"
+
+ SPI spiDAC(MOSI_PIN, MISO_PIN, SCK_PIN); // mosi, miso, sclk
+ DigitalOut csDAC(CS_DAC_MIRRORS);
+    
+ DigitalOut Laser_Red(LASER_RED_PIN);
+ DigitalOut Laser_Green(LASER_GREEN_PIN);
+ DigitalOut Laser_Blue(LASER_BLUE_PIN);
+
+void HardwareIO::init(void) {
+    Laser_Red = 1;
+    Laser_Green = 0;
+    Laser_Blue = 0;
+    
+    //Serial Communication setup:
+    pc.baud(921600);//115200);//
+    
+    // Setup for lock-in amplifier and pwm references:
+    lockin.init();
+    
+    // Setup the spi for 8 bit data, high steady state clock,
+    // second edge capture, with a 10MHz clock rate
+    csDAC = 1;
+    spiDAC.format(16,0);
+    spiDAC.frequency(16000000);
+   
+   // default initial mirror position: 
+    writeOutX(CENTER_AD_MIRROR_X);
+    writeOutY(CENTER_AD_MIRROR_Y);
+    
+    // Load LUT table:
+    setLUT();
+}
+
+//write on the first DAC, output A (mirror X)
+void HardwareIO::writeOutX(int value){
+ if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS;
+ if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS;
+ 
+ value |= 0x7000;
+ value &= 0x7FFF;
+ 
+ csDAC = 0;
+ spiDAC.write(value);
+ csDAC = 1;
+}
+
+//write on the first DAC, output B (mirror Y)
+void HardwareIO::writeOutY(int value){
+ if(value > MAX_AD_MIRRORS) value = MAX_AD_MIRRORS;
+ if(value < MIN_AD_MIRRORS) value = MIN_AD_MIRRORS;
+ 
+ value |= 0xF000;
+ value &= 0xFFFF;
+ 
+ csDAC = 0;
+ spiDAC.write(value);
+ csDAC = 1;
+}
+
+void HardwareIO::setRedPower(int powerValue){
+    if(powerValue > 0){
+       lockin.setLaserPower(true);
+    }
+    else{
+       lockin.setLaserPower(false);
+    }
+}
+void HardwareIO::setGreenPower(int powerValue){
+    if(powerValue > 0){
+        Laser_Green = 1;
+    }
+    else{
+        Laser_Green = 0;
+    }
+}
+void HardwareIO::setBluePower(int powerValue){
+    if(powerValue > 0){
+        Laser_Blue = 1;
+    }
+    else{
+        Laser_Blue = 0;
+    }
+}
+
+void HardwareIO::setRGBPower(char color) {
+    lockin.setLaserPower(color&0x04);
+    Laser_Green=(color&0x02)>>1;
+    Laser_Blue =(color&0x01); 
+}
+
+void HardwareIO::scan_serial(int pointsPerLine){
+      //scan the total surface with a custom resolution
+      //send the lockin value for each point as a byte on the serial port to the PC
+      //use "scanSLP_save" to see the data on processing
+      
+      
+      int shiftX = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
+      int shiftY = (MAX_AD_MIRRORS - MIN_AD_MIRRORS) / pointsPerLine;
+      
+      for(int j=0; j<pointsPerLine; j++){
+        writeOutX(MIN_AD_MIRRORS);
+        writeOutY(j*shiftY + MIN_AD_MIRRORS);
+        
+        wait_us(300);//begining of line delay
+        for(int i=0; i<pointsPerLine; i++){
+          writeOutX(i*shiftX + MIN_AD_MIRRORS);
+
+          wait_us(100);//delay between each points
+          pc.putc(int(255.0*lockin.getMedianValue()/4095));//printf("%dL",int(valueLockin*255));//pc.putc(int(lockin*255));//
+        }
+      }
+}
+
+//load Look-up Table from LUT.TXT file
+//or create the file with scanLUT() if not existing.
+void HardwareIO::setLUT(){
+
+    FILE *fp = fopen(LUT_FILENAME, "r");  // Open file on the local file system for writing
+    if(fp){
+        //load the file into the lut table; keep the SAME resolution!
+        fread(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp);
+        fclose(fp);
+    }
+    else{
+        //fclose(fp);
+        //if the file "LUT.TXT" doesn't exist, create one with scanLUT()
+        lockin.setLaserPower(true);
+        scanLUT();
+    }
+    
+}
+
+//scan the total surface with a fixed 2^x resolution
+//create the Look-Up Table used to "flatten" the scan according to the position
+//
+//To Do: maybe detect high frequency to be sure the area is clean and empty?
+void HardwareIO::scanLUT(){
+
+    //reset lut table
+    for(int j=0; j<LUT_RESOLUTION; j++){
+      for(int i=0; i<LUT_RESOLUTION; i++){
+        lut[i][j] =0;
+      }
+    }
+    
+    int delayScanning = 300; //in us
+    
+    //define the distance between each points (from 0 to 4096) and the offset (here 0)
+    float shiftX = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1);
+    float shiftY = 1.0*(MAX_AD_MIRRORS - MIN_AD_MIRRORS) / (LUT_RESOLUTION-1);
+    float offsetX = MIN_AD_MIRRORS;
+    float offsetY = MIN_AD_MIRRORS;
+    
+    //move the mirrors to the first position
+    writeOutX(MAX_AD_MIRRORS);writeOutY(MIN_AD_MIRRORS);
+    wait_us(500);
+      
+    float x, y;
+    
+    //scan the surface 8 times 
+    //the total value in lut[i][j] shouldn't exceed uint16 !!! 
+    for(int loop=0; loop<8; loop++){
+      for(int j=0; j<LUT_RESOLUTION; j++){
+        y = shiftY*j + offsetY ;
+        writeOutY(int(y));
+        //scan from right to left
+        for(int i=LUT_RESOLUTION-1; i>=0; i--){
+          x = shiftX*i + offsetX;
+          writeOutX(int(x));
+          wait_us(delayScanning);
+          lut[i][j] += lockin_read();
+        }
+        //re-scan from left to right
+        for(int i=0; i<LUT_RESOLUTION; i++){
+          x = shiftX*i + offsetX;
+          writeOutX(int(x));
+          wait_us(delayScanning);
+          lut[i][j] += lockin_read();
+        }
+      }
+    }
+    
+    
+    //save tab in file
+    FILE *fp;
+#ifdef LUT_FILENAME
+    fp = fopen(LUT_FILENAME, "w");  // Open file on the local file system for writing
+    fwrite(lut,sizeof(uint16),LUT_RESOLUTION*LUT_RESOLUTION,fp);
+    fclose(fp); //close the file (the mBed will appear connected again)
+#endif
+    
+#ifdef LUT_H_FILENAME    
+    //save tab in human readable file
+    fp = fopen(LUT_H_FILENAME, "w");  // Open file on the local file system for writing
+    fprintf(fp, "scan resolution: %d x %d\r\n",LUT_RESOLUTION, LUT_RESOLUTION);
+    for(int j=0; j<LUT_RESOLUTION; j++){
+      for(int i=0; i<LUT_RESOLUTION; i++){
+            fprintf(fp, "X=%d,\tY=%d,\tI=%d\t \r\n", int(shiftX*i + offsetX), int(shiftY*j + offsetY), lut[i][j] );
+      }
+    }
+    fclose(fp); //close the file (the mBed will appear connected again)
+#endif
+    
+}
+
+
+//return the lockin value corrected with the Look-UpTable
+float HardwareIO::lockInCorrectedValue(int x, int y){
+//*******Correction using DIRECT approximation
+#ifdef LUT_DIRECT
+    return 16.0 * lockin_read() / (lut[x >> LUT_BITS_SHIFT][y >> LUT_BITS_SHIFT]);
+    
+#else 
+//*******Correction using BILINEAR approximation
+#ifdef LUT_BILINEAR
+    int X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17
+    int Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17
+    float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm) 
+    float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm)
+    
+    //Wheighted mean approximation of the Look-Up Table at the position (x,y):
+    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] );
+    
+    return 16.0 * lockin_read() / wmLUT;//16.0 is the number of recorded sample added to one position of the LUT
+    
+#else
+//*******Correction using LINEAR approximation
+#ifdef LUT_LINEAR
+    int X = x >> LUT_BITS_SHIFT; //mirror "x" is 12bits, LUT "X" needs 4bits when lut is 17x17
+    int Y = y >> LUT_BITS_SHIFT; //mirror "y" is 12bits, LUT "Y" needs 4bits when lut is 17x17
+    float dx = 1.0*(x & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on X (mask with 255 and norm) 
+    float dy = 1.0*(y & LUT_BITS_MASK)/(LUT_BITS_MASK+1); //weight to apply on Y (mask with 255 and norm)
+    float linearLUT, dzx, dzy;
+    
+    if(dx>dy){ //if the position is on the "top-right" triangle
+        dzx = (lut[X+1][Y] - lut[X][Y]) * dx;
+        dzy = (lut[X+1][Y+1] - lut[X+1][Y]) * dy;
+    }
+    else{ //if the position is on the "bottom-left" triangle
+        dzy = (lut[X][Y+1] - lut[X][Y]) * dy;
+        dzx = (lut[X+1][Y+1] - lut[X][Y+1]) * dx;
+    }
+    
+    //linear approximation of the Look-Up Table at the position (x,y):
+    linearLUT = lut[X][Y] + dzx + dzy;
+    return 16.0 * lockin_read() / linearLUT; //16.0 is the number of recorded sample added to one position of the LUT
+    
+#else
+//*******No corrections, just return the normalized value
+    return lockin_read()/4096;
+    
+#endif //LUT_LINEAR
+#endif //LUT_BILINEAR
+#endif //LUT_DIRECT
+}
+