Library for Si114x optical sensors. Currently intended for the Si1146, although it will work also for the Si1145, and without full functionality for the Si1147

Dependents:   Si114x_HelloWorld Hello-Uzuki-sensor-shield

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Si114x.cpp Source File

Si114x.cpp

00001 #include "Si114x.h"
00002 #include "Si114x_defs.h"
00003 
00004 #define PS_ADC_GAIN     0x02
00005 
00006 
00007 Si114x::Si114x(PinName sda, PinName scl) : i2c(sda,scl) {
00008     //Wait startup time and enable the device
00009     i2c.frequency(400000);
00010     wait_ms(30);       
00011     write_byte(REG_MEAS_RATE0, 0x00);
00012     write_byte(REG_MEAS_RATE1, 0x00);
00013          
00014     write_cmd(CMD_RESET);
00015     wait_ms(10);
00016     write_byte(REG_HW_KEY, 0x17);
00017     
00018     //Set UV coefficients
00019     write_byte(REG_UCOEF0, 0x29);
00020     write_byte(REG_UCOEF1, 0x89);
00021     write_byte(REG_UCOEF2, 0x02);
00022     write_byte(REG_UCOEF3, 0x00);
00023     
00024     //Set LED current (max, which apparantly is not going to destroy anything)
00025     write_byte(REG_PS_LED21, 0xFF);
00026     
00027     //Set default LED channels
00028     setPSLEDs(1, 0x01);
00029     setPSLEDs(2, 0x02);
00030     
00031     continious = false;
00032     
00033 }
00034 
00035 bool Si114x::verifyConnection(void) {
00036     uint8_t part_id = read_byte(REG_PART_ID);
00037     if ((part_id == 0x45) || (part_id == 0x46) || (part_id == 0x47))
00038         return true;
00039     return false;
00040 }
00041 
00042 //-------------------Get light functions---------------------------
00043 
00044 unsigned short Si114x::getVisibleLight(void) {
00045     if (continious == false) {
00046         //Enable visible light measurement, clear current interrupt, start conversion, wait until done
00047         write_byte(REG_IRQ_STATUS, 0x01);
00048         param_set(RAM_CHLIST, (1<<4));
00049         write_cmd(CMD_ALS_FORCE);
00050         while(read_byte(REG_IRQ_STATUS) & 0x01 != 0x01);
00051     }
00052     return read_word(REG_ALS_VIS_DATA0);
00053 }
00054 
00055 unsigned short Si114x::getIRLight(void) {
00056     if (continious == false) {
00057         //Enable IR light measurement, clear current interrupt, start conversion, wait until done
00058         write_byte(REG_IRQ_STATUS, 0x01);
00059         param_set(RAM_CHLIST, (1<<5));
00060         write_cmd(CMD_ALS_FORCE);
00061         while(read_byte(REG_IRQ_STATUS) & 0x01 != 0x01);
00062     }
00063     return read_word(REG_ALS_IR_DATA0);
00064 }
00065 
00066 unsigned short Si114x::getUVIndex(void) {
00067     if (continious == false) {
00068         //Enable IR light measurement, clear current interrupt, start conversion, wait until done
00069         write_byte(REG_IRQ_STATUS, 0x01);
00070         param_set(RAM_CHLIST, (1<<7));
00071         write_cmd(CMD_ALS_FORCE);
00072         while(read_byte(REG_IRQ_STATUS) & 0x01 != 0x01);
00073     }
00074     return read_word(REG_UV_INDEX0);
00075 }
00076 
00077 //---------------------------------- Proximity -----------------------------------------------------
00078 unsigned short Si114x::getProximity(char pschannel) {
00079     if (continious == false) {
00080         //Enable IR light measurement, clear current interrupt, start conversion, wait until done
00081         write_byte(REG_IRQ_STATUS, 0x04);
00082         param_set(RAM_CHLIST, (1<<(pschannel-1)));
00083         write_cmd(CMD_PS_FORCE);
00084         while(read_byte(REG_IRQ_STATUS) & 0x04 != 0x04);
00085     }
00086     return read_word(REG_PS1_DATA0 + (pschannel - 1)* 2);
00087 }
00088 
00089 void Si114x::setPSLEDs(char pschannel, char ledmask) {
00090     char psled12 = param_query(RAM_PSLED12_SELECT);
00091     if (pschannel == 1) {
00092         psled12 = (psled12 & ~0x0F) | ledmask;
00093     } 
00094     else {
00095         psled12 = (psled12 & ~0xF0) | (ledmask << 4);
00096     }
00097     param_set(RAM_PSLED12_SELECT, psled12);
00098 }
00099         
00100 
00101 //---------------------------------- Read/Write functions ---------------------------------------------
00102     
00103 char Si114x::read_byte(const char reg) {
00104     char retval;
00105     i2c.write(SI114x_ADDRESS, &reg, 1, true);
00106     i2c.read(SI114x_ADDRESS, &retval, 1);
00107     return retval;
00108 }
00109 
00110 unsigned short Si114x::read_word(const char reg) {
00111     unsigned short retval;
00112     i2c.write(SI114x_ADDRESS, &reg, 1, true);
00113     i2c.read(SI114x_ADDRESS, (char*)&retval, 2);    //This actually seems to put them in correct order
00114     return retval;
00115 }
00116 
00117 void Si114x::write_byte(const char reg, const char byte) {
00118     char data[] = {reg, byte};
00119     i2c.write(SI114x_ADDRESS, data, 2);
00120 }
00121 
00122 void Si114x::param_set(const char param, const char value) {
00123     write_byte(REG_PARAM_WR, value);
00124     write_cmd(CMD_PARAM_SET | param);
00125 }
00126 
00127 char Si114x::param_query(const char param) {
00128     write_cmd(CMD_PARAM_QUERY | param);
00129     return read_byte(REG_PARAM_RD);
00130 }
00131 
00132 void Si114x::write_cmd(const char cmd) {
00133     uint8_t old_value = read_byte(REG_RESPONSE);
00134     
00135     write_byte(REG_COMMAND, cmd);
00136     
00137     if (cmd == CMD_RESET) {
00138         return;    
00139     }
00140     
00141     char i = 0;
00142     while(read_byte(REG_RESPONSE) == old_value) {
00143         wait_ms(1);
00144         if (i > 25) {
00145             break;
00146         }
00147         i++;
00148     }
00149 }