I2C hang recover function added

Dependencies:   UniGraphic mbed vt100

In this version, check_i2c_pins function was added in edge_mgr.cpp.

プログラムの起動時、I2Cモジュールを初期化する前に、I2Cに使用するピンの電位を確認し
もし一方でも Low に張り付いていた場合、SCL を GPIO 出力に設定して 
所定回数 (I2C_UNLOCK_TRIAL_CYCLE) 反転させることにより、疑似リセットクロックを生成します。

その後は、通常の起動手順に復帰し、以降はこれまでと同様の動作をします。

Revision:
0:d895cd1cd897
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/VEML6040.cpp	Tue Apr 03 08:30:29 2018 +0000
@@ -0,0 +1,285 @@
+/*
+ * File description here
+ */
+#include "VEML6040.h"
+#include "af_mgr.h"
+
+/* VEML6075 SLAVE ADDRESS AND FUNCTION DESCRIPTION */
+#define REG_COLOR_CONF  0x00
+#define REG_Reserved1  0x01
+#define REG_Reserved2  0x02
+#define REG_Reserved3  0x03
+#define REG_Reserved4  0x04
+#define REG_Reserved5  0x05
+#define REG_Reserved6  0x06
+#define REG_Reserved7  0x07
+#define REG_R_Data  0x08
+#define REG_G_Data  0x09
+#define REG_B_Data  0x0A
+#define REG_W_Data  0x0B
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 4 
+#define LUX_RESOLUTION_0  (0.25168)
+#define LUX_RESOLUTION_1  (0.12584)
+#define LUX_RESOLUTION_2  (0.06292)
+#define LUX_RESOLUTION_3  (0.03146)
+#define LUX_RESOLUTION_4  (0.01573)
+#define LUX_RESOLUTION_5  (0.007865)
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 9 
+#define CORR_COEFF_M0  (0.048403)
+#define CORR_COEFF_M1  (0.183633)
+#define CORR_COEFF_M2  (-0.253589)
+#define CORR_COEFF_M3  (0.022916)
+#define CORR_COEFF_M4  (0.176388)
+#define CORR_COEFF_M5  (-0.183205)
+#define CORR_COEFF_M6  (-0.077436)
+#define CORR_COEFF_M7  (0.124541)
+#define CORR_COEFF_M8  (0.032081)
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 10
+#define CCT_CONST  (4278.6)
+#define OFFSET_OPEN_AIR  (0.5)
+
+VEML6040::VEML6040(I2C *i2c, int addr) : m_addr(addr<<1) {
+    p_i2c = i2c ;
+    p_i2c->frequency(100000); /* 100kHz */
+    // activate the peripheral
+}
+
+VEML6040::~VEML6040() { }
+
+/**
+ * set COLOR Config
+ * @param colorconf uint8_t 8bit register value
+ * @returns 0: success non-0: failure
+ * @note Command Code 0x00 is used to access CONF register
+ * @note bit[7] (reserved)
+ * @note bit[6:4] = IT[2:0] Integration Time Selector
+ * @note bit[3] (reserved)
+ * @note bit[2] TRIG Proceed one detcting cycle at manual force mode
+ * @note bit[1] AF 0: Auto mode 1: manual force mode
+ * @note bit[0] SD 0: normal 1: chip shutdown setting
+ *
+ * @note IT[2:0] 0=40ms, 1=80ms, 2=160ms, 3=320ms, 4=640ms, 5=1280ms
+ * @note as our WatchDog is set to 1sec, 1280ms is invalid
+ * @note and 640ms may not be practical
+ */
+int VEML6040::setCOLORConf(uint8_t colorconf)
+{
+     int result ;
+     uint8_t data[3] ;
+     data[0] = REG_COLOR_CONF ;
+     data[1] = colorconf ;
+     data[2] = 0 ;
+     result = writeRegs(data, 3) ;
+     return( result ) ;
+}
+
+/**
+ * get COLOR Config
+ * @param *colorconf uint8_t refer to setCOLORConf for the value
+ * @returns 0: success non-0: failure
+ */
+int VEML6040::getCOLORConf(uint8_t *colorconf)
+{
+    int result ;
+    uint8_t data[2] ;
+    result = readRegs(REG_COLOR_CONF, data, 2) ;
+    if (result == 0) {
+        *colorconf = data[0] ;
+    }
+    return( result ) ;
+}
+
+
+
+int VEML6040::getRData(uint16_t *rdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_R_Data, data, 2) ;
+    *rdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getGData(uint16_t *gdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_G_Data, data, 2) ;
+    *gdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getBData(uint16_t *bdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_B_Data, data, 2) ;
+    *bdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getWData(uint16_t *wdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_W_Data, data, 2) ;
+    *wdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+// usage
+// fvalue = veml->getUVA() ;
+// printf("%f", fvalue) ;
+float VEML6040::getR(void) 
+{
+    uint16_t data ;
+    float value ;
+    getRData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getG(void) 
+{
+    uint16_t data ;
+    float value ;
+    getGData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getB(void) 
+{
+    uint16_t data ;
+    float value ;
+    getBData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getW(void) 
+{
+    uint16_t data ;
+    float value ;
+    getWData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getX(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M0 * (float)R + (float)CORR_COEFF_M1 * (float)G + (float)CORR_COEFF_M2 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getY(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M3 * (float)R + (float)CORR_COEFF_M4 * (float)G + (float)CORR_COEFF_M5 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getZ(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M6 * (float)R + (float)CORR_COEFF_M7 * (float)G + (float)CORR_COEFF_M8 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getCCTiData(void) 
+{
+    uint16_t rdata ;
+    uint16_t gdata ;
+    uint16_t bdata ;
+    float value ;
+    getRData(&rdata) ;
+    getGData(&gdata) ;
+    getBData(&bdata) ;
+    value = ((float)rdata - (float)bdata) / (float)gdata + (float)OFFSET_OPEN_AIR ;
+    return( value ) ;
+}
+
+float VEML6040::getCCTData(void) 
+{
+//    uint16_t cctidata ;
+    float cctidata ;
+    float value ;
+    cctidata = getCCTiData() ;
+//    getCCTiData(&cctidata) ;
+    value = (float)CCT_CONST * powf( cctidata, -1.2455 ) ;
+    return( value ) ;
+}
+
+float VEML6040::getCIEX(void) 
+{
+    float X ;
+    float Y ;
+    float Z ;
+    float value ;
+    X = getX() ;
+    Y = getY() ;
+    Z = getZ() ; 
+    value = (float)X / ((float)X + (float)Y + (float)Z) ;
+    return( value ) ;
+}
+
+float VEML6040::getCIEY(void) 
+{
+    float X ;
+    float Y ;
+    float Z ;
+    float value ;
+    X = getX() ;
+    Y = getY() ;
+    Z = getZ() ; 
+    value = (float)Y / ((float)X + (float)Y + (float)Z) ;
+    return( value ) ;
+}
+
+int VEML6040::readRegs(int addr, uint8_t * data, int len) {
+    char t[1] = {addr};
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, t, 1, true);
+    if (result == 0) { // write success
+        result = p_i2c->read(m_addr, (char *)data, len, false);
+    }
+    __enable_irq() ; // Enable Interrupts
+    return(result) ;
+}
+
+int VEML6040::writeRegs(uint8_t * data, int len) {
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, (char *)data, len);
+    __enable_irq() ; // Enable Interrupts
+    return(result) ;
+}
\ No newline at end of file