Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

hardwareIO/hardwareIO.h

Committer:
mbedalvaro
Date:
2014-04-17
Revision:
47:199042980678
Parent:
41:74e24a0e6e50

File content as of revision 47:199042980678:


#ifndef hardwareIO_h
#define hardwareIO_h

#include "mbed.h"
#include "lockin.h"

//#define USING_EXTENAL_DAC // ... or we can do both at the same time: external plus the output for the mbed DAC pins
// ARG: MBED has only one "true" analog output (p18) - the others are pwm.. but perhaps we can set a fast PWM cycle and have enough resolution?
// 10 bit resolution (0-1023) should be ok (a display 1024x1024...). What is the max pwm cycle then? I want to be able to write a point every 100us or so (see
// laserSensingDisplay.h), which means 10kHz. Assuming I have a low pass filter, and I filter several cycles - at least 10 - this means I need a freq of about
// 100kHz (presumably it will work with less than that). Possible? I found this: http://mbed.org/questions/192/what-is-the-maximum-frequency-of-the-PWM/
// It seems that the minimum step is 1us... so, at 100kHz (period of 10us) we will only have 10 levels! (about 3 bits). More precisely, if I want 10 bits resolution, the max
// frequency will be 2^10x1us = 1024us, or about 1kHz... too slow!! 10kHz? => about two bits less, ie, 8 bits (256 levels). Mmm... Perhaps good for testing 
// on an osciloscope, but not good for mirror control.
// #define mbedAnalogX p18 
// #define mbedAnalogY


// Serial communication speed:
#define SERIAL_SPEED 115200//230400//115200 //230400

// potentiometer to change sensitivity by hand, or other things. 
#define POT_ANALOG_INPUT p15 // note: analog inputs in the mbed are from 15 to 20

// switches triggering interrupt functions:
// (Any of the numbered mbed pins can be used as an InterruptIn, except p19 and p20)
// NOTE: do not use pins from p21 to p26 because they are all set as pwm output (see lockin.h)
#define LED_SWITCH_ONE p9 // digital output pin
#define SWITCH_ONE p10 // interrupt pin
#define SWITCH_TWO p11 // interrupt pin

//SPI library (for DAC chip) uses the following pins, but we don't have to set them and inputs or outputs 
// (this is done when the library is initialized, which is done by pre-instantiation:
#define SCK_PIN   p7 //SPI Clock
#define MISO_PIN  p6 //SPI input (data comming from DAC, here not connected) 
#define MOSI_PIN  p5 //SPI output (data going to DAC)

//**** CHIP SELECT pins for MP4922 DAC (mirrors and red laser)
// VERY IMPORTANT: the chip select for the DACs should be different from the default SPI "SS" pin (Slave Select), which is 53 by default (and will be used by the Ethernet Shield). 
#define CS_DAC_MIRRORS   p8 //Chip Select of the first DAC (mirrors)

//**** LASERS pins:
#define LASER_RED_PIN   p28 // NOT YET USED (TTL control). NOTE: this is NOT the locking sensing laser!
#define LASER_GREEN_PIN p29 // USED (TTL control)
#define LASER_BLUE_PIN  p30 // USED (TTL control)

//**** MIRRORS: 
//The DAC is 12 bytes capable (Max=4096), but we will limit this a little. 
#define MAX_AD_MIRRORS 3845 // note: 4095 is the absolute maximum for the SPI voltage (5V). This is for checking hardware compliance, but max and min angles can be defined for X and Y in each LivingSpot instance.
#define MIN_AD_MIRRORS 250  // note: 0 is 0 volts for the SPI voltage. 
// We assume that the center of the mirror is at MAX_AD_MIRRORS/2 = 2000:
#define CENTER_AD_MIRROR_X 2047 // This MUST BE the direction of the photodetector. 
#define CENTER_AD_MIRROR_Y 2047 // This MUST BE the direction of the photodetector.


//**** Look-Up Table:
#define uint16 unsigned short
#define LUT_RESOLUTION  33   // resolution of the Look-Up Table (power of 2 +1)
#define LUT_BITS_SHIFT  7    // bits shift from mirror DAC (12 bits) to LUT ( root_square(LUT_RESOLUTION - 1) )
#define LUT_BITS_MASK   127   // bits mask to obtain the position remainder ( 2^LUT_BITS_SHIFT - 1 )
//  possible configurations:
//  LUT_RESOLUTION  LUT_BITS_SHIFT  LUT_BITS_MASK
//      9               9               511
//      17              8               255
//      33              7               127
//      65              6               63
//  ...
#define NB_SCANS 8 // number of scans performed to generate the LUT table (actually, each site CUMULATES NB_SCANS values)
                   // IMPORTANT: NB_SCANS*4095 should not exceed the capacity of uint16, this is 2^16-1=65535.
                   // In other terms, NB_SCANS should be < 65535/4095=16

#define LUT_FILENAME "/local/LUT.txt"

// For checking (define if human readable file is required - note: it is not used by the program, just as output for human reading)
#define LUT_H_FILENAME "/local/LUT_pos.txt"

// Current Look-up table approximation (only one at a time!): 
//#define LUT_BILINEAR 
//#define LUT_DIRECT
//#define LUT_LINEAR
#define NO_LUT

//Current method for lockin data acquisition and correction
#define lockin_read() lockin.getMedianValue() // lockin.getSmoothValue(); //return the average of the value stored on the buffer
                                              // lockin.getLastValue(); //return the last conversion of the ADC
                                              // lockin.getMedianValue(); //return the median value of the buffer


extern  DigitalOut Laser_Red, Laser_Green, Laser_Blue;

// LEDS for debugging:
extern DigitalOut myLed1, myLed2, myLed3, myLed4;

// **** REFERENCE SIGNAL: 
/*
#define testPin_OC1A 11 // this is, output compare pin OC1A //connected to CK2 = lockIn clock
#define testPin_OC1B 12 // this is, output compare pin OC1B //connected to CK1 = laser clock
#define testPin_OC1C 13
*/

// ==================================================================================================================================================================

class HardwareIO {
public:


    void init(void);

    //Lock-in acquisition methods:
   // float LockInRead_Volts(); 
   // int LockInRead_AD(); 
  //  float LockInAD_to_Volts(int); 
    
    //Look-Up Table:
    unsigned short lut[LUT_RESOLUTION][LUT_RESOLUTION]; //Look-Up Table (uint16 is "unsigned short")
    void scanLUT(); //create and save the Look-Up Table
    void setLUT(); //set the Look-Up Table: either from scanning, or from the file LUT.TXT (if it is present)
    float lockInCorrectedValue(unsigned short x, unsigned short y); //return the lockin value corrected with the Look-UpTable (this is, a RATIO of reflectivities, and <1)
    
    void scan_serial(unsigned short pointsPerLine = 400);

    void showLimitsMirrors( unsigned short pointsPerLine, unsigned short timeInSeconds );
//    void showLimitsConcentric(int pointsPerSide, int times);
//    void showCircle(int cv, int cy, float radius, int nmpoints, int times);
//    void showGrid(float cx, float cy, int nx, int ny, float pasx, float pasy, int repeat);
//    void gridCircles(float cx, float cy, int nx, int ny, float pasx, float pasy, float radius, int repeat, boolean sym);
//    void showContinuousGrid(int nx, int ny, float cx, float cy, int width, int height, float pasx, float pasy, int repeat);


    // SPI control for DAC for mirrors and red laser power (low level): 
    void writeOutX(unsigned short value);
    void writeOutY(unsigned short value);
    void writeOutXY(unsigned short valueX, unsigned short valueY) {writeOutX(valueX); writeOutY(valueY);};
    
    // mirror degree-to-AD units conversion factors: 
    //float AD_to_Deg_MIRROR_X;//=1.0*(MAX_DEG_MIRROR_X-MIN_DEG_MIRROR_X)/(MAX_AD_MIRRORS-MIN_AD_MIRRORS);
    //float AD_to_Deg_MIRROR_Y;//=1.0*(MAX_DEG_MIRROR_Y-MIN_DEG_MIRROR_Y)/(MAX_AD_MIRRORS-MIN_AD_MIRRORS);

    /*
    // Mirror position:
    void setMirrorX_Deg(float _Az); 
    void setMirrorY_Deg(float _El);
    void setMirrorX_AD(int _AzAD); 
    void setMirrorY_AD(int _ElAD);
    void setMirrorsXY_AD(int _xAD, int _yAD); 
    void setMirrorsCenter();
    void getAnglesFromAD(float &Az, float &El, int _xAD, int _yAD); 
    //void setZoneDelimiters(...) // this could be here, instead on the LivingSpot class
    */
    
    // Setting the laser power of the SENSING LASER (note: for the moment this is TTL, but could be analog): 
    void setLaserLockinPower(int powerLockingLaser);       //if powerValue > 0 ==> 'true'; else 'false'
    // Setting the power of the DISPLAYING  lasers: 
    // Again: for the moment laser are TTL but these could be analog. Now, it is just: powerValue > 0 ==> 'true'; else 'false'
    // Red laser:
    void setRedPower(int powerRed);
    // Green laser: 
    void setGreenPower(int powerGreen);
    // Blue laser: 
    void setBluePower(int powerBlue);
    // Setting all colors at once: 
    void setRGBPower(unsigned char color); // we will use the 3 LSB bits to set each color
    void switchOffDisplayLasers() {setRGBPower(0x00);}
    
    //void setupPWM();
    /* IN ADVANCED HARDWARE: 
    // init PWM for reference generation:
    void initPWM();
    // reference signal: 
    void setRefFreq(int);
    void incRefFreq(int inc=1);
    void decRefFreq(int dec=1);
    */

    //float refFreq; // could be private
    
    bool switchOneChange, switchTwoChange;
    void switchOneInterrupt();
    void switchTwoInterrupt();
    bool switchOneCheck(bool& state);
    bool switchTwoCheck(bool& state);
    void setSwitchOneState(bool newstate);

    unsigned char updatePotValue(); // the value will be ajusted in the range 0-255
    unsigned char potValue;
    
    bool switchOneState, switchTwoState;
    
private:
     //DigitalOut Laser_Red, Laser_Green, Laser_Blue;
};


extern HardwareIO IO; // allows the object IO to be used in other .cpp files (IO is pre-instantiated in hardwareIO.cpp)
// NOTE: IO encapsulates many IO functions, but perhaps it is better not to have an IO object - just use each IO function separatedly (as with pc object for instance)
extern Serial pc; // allows pc to be manipulated by other .cpp files, even if pc is defined in the hardwareIO.cpp


#endif