Laser Sensing Display for UI interfaces in the real world
Fork of skinGames_forktest by
hardwareIO/hardwareIO.h
- Committer:
- mbedalvaro
- Date:
- 2013-10-16
- Revision:
- 40:3ba2b0ea9f33
- Parent:
- 35:35af5086ab4f
- Child:
- 41:74e24a0e6e50
File content as of revision 40:3ba2b0ea9f33:
#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 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