|
| 1 | +#include "../obk_config.h" |
| 2 | + |
| 3 | +#if ENABLE_DRIVER_LTR_ALS |
| 4 | + |
| 5 | +#include "../new_pins.h" |
| 6 | +#include "../logging/logging.h" |
| 7 | +#include "drv_local.h" |
| 8 | +#include "drv_ltr_als.h" |
| 9 | + |
| 10 | +static softI2C_t g_softI2C; |
| 11 | +static bool is_init = false; |
| 12 | + |
| 13 | +static int ch_lux = -1; |
| 14 | + |
| 15 | +static uint16_t als_ch0 = 0; |
| 16 | +static uint16_t als_ch1 = 0; |
| 17 | +static float als_lux = 0.0f; |
| 18 | + |
| 19 | +static byte sec_left = 0; |
| 20 | +static byte sec_cycle = 4; |
| 21 | + |
| 22 | +static void LTR_WriteReg(byte reg, byte val) |
| 23 | +{ |
| 24 | + Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR); |
| 25 | + Soft_I2C_WriteByte(&g_softI2C, reg); |
| 26 | + Soft_I2C_WriteByte(&g_softI2C, val); |
| 27 | + Soft_I2C_Stop(&g_softI2C); |
| 28 | +} |
| 29 | + |
| 30 | +static byte LTR_Read8(byte reg) |
| 31 | +{ |
| 32 | + byte v; |
| 33 | + Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR); |
| 34 | + Soft_I2C_WriteByte(&g_softI2C, reg); |
| 35 | + Soft_I2C_Stop(&g_softI2C); |
| 36 | + Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR | 1); |
| 37 | + v = Soft_I2C_ReadByte(&g_softI2C, true); |
| 38 | + Soft_I2C_Stop(&g_softI2C); |
| 39 | + return v; |
| 40 | +} |
| 41 | + |
| 42 | +static void LTR_Reset() |
| 43 | +{ |
| 44 | + LTR_WriteReg(LTR_REG_ALS_CONTR, 0x02); |
| 45 | + rtos_delay_milliseconds(10); |
| 46 | +} |
| 47 | + |
| 48 | +static void LTR_Setup() |
| 49 | +{ |
| 50 | + LTR_Reset(); |
| 51 | + byte manufac = LTR_Read8(LTR_REG_MANUFAC_ID); |
| 52 | + if(manufac != 0x05) |
| 53 | + { |
| 54 | + // retry once |
| 55 | + manufac = LTR_Read8(LTR_REG_MANUFAC_ID); |
| 56 | + if(manufac != 0x05) |
| 57 | + { |
| 58 | + ADDLOG_ERROR(LOG_FEATURE_SENSOR, "LTR unknown manufacturer %i", manufac); |
| 59 | + is_init = false; |
| 60 | + return; |
| 61 | + } |
| 62 | + } |
| 63 | + LTR_WriteReg(LTR_REG_ALS_CONTR, 0x01); |
| 64 | + rtos_delay_milliseconds(20); |
| 65 | + // dummy read |
| 66 | + LTR_Read8(LTR_REG_STATUS); |
| 67 | + is_init = true; |
| 68 | +} |
| 69 | + |
| 70 | +static void LTR_ReadData() |
| 71 | +{ |
| 72 | + if(!(LTR_Read8(LTR_REG_STATUS) & 0x04)) return; |
| 73 | + |
| 74 | + byte c1l = LTR_Read8(LTR_REG_CH1_0); |
| 75 | + byte c1h = LTR_Read8(LTR_REG_CH1_1); |
| 76 | + byte c0l = LTR_Read8(LTR_REG_CH0_0); |
| 77 | + byte c0h = LTR_Read8(LTR_REG_CH0_1); |
| 78 | + |
| 79 | + als_ch1 = ((uint16_t)c1h << 8) | c1l; |
| 80 | + als_ch0 = ((uint16_t)c0h << 8) | c0l; |
| 81 | +} |
| 82 | + |
| 83 | +static void LTR_CalcLux() |
| 84 | +{ |
| 85 | + if(als_ch0 == 0 && als_ch1 == 0) |
| 86 | + { |
| 87 | + als_lux = 0; |
| 88 | + return; |
| 89 | + } |
| 90 | + |
| 91 | + float r = (float)als_ch1 / (float)(als_ch0 + als_ch1); |
| 92 | + |
| 93 | + if(r < 0.45f) als_lux = 1.7743f * als_ch0 + 1.1059f * als_ch1; |
| 94 | + else if(r < 0.64f) als_lux = 4.2785f * als_ch0 - 1.9548f * als_ch1; |
| 95 | + else if(r < 0.85f) als_lux = 0.5926f * als_ch0 + 0.1185f * als_ch1; |
| 96 | + else als_lux = 0.0f; |
| 97 | +} |
| 98 | + |
| 99 | +static void LTR_Measure() |
| 100 | +{ |
| 101 | + if(!is_init) return; |
| 102 | + |
| 103 | + LTR_ReadData(); |
| 104 | + LTR_CalcLux(); |
| 105 | + |
| 106 | + if(ch_lux >= 0) CHANNEL_Set(ch_lux, (int)(als_lux * 10), 0); |
| 107 | +} |
| 108 | + |
| 109 | +commandResult_t LTR_ALS(const void* ctx, const char* cmd, const char* args, int flags) |
| 110 | +{ |
| 111 | + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); |
| 112 | + |
| 113 | + if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 3)) return CMD_RES_NOT_ENOUGH_ARGUMENTS; |
| 114 | + |
| 115 | + int gain = Tokenizer_GetArgInteger(0); |
| 116 | + int integ = Tokenizer_GetArgInteger(1); |
| 117 | + int rep = Tokenizer_GetArgInteger(2); |
| 118 | + |
| 119 | + LTR_WriteReg(LTR_REG_ALS_CONTR, 0x01 | (gain << 2)); |
| 120 | + LTR_WriteReg(LTR_REG_MEAS_RATE, (rep & 0x07) | ((integ & 0x07) << 3)); |
| 121 | + return CMD_RES_OK; |
| 122 | +} |
| 123 | + |
| 124 | +commandResult_t LTR_INT(const void* ctx, const char* cmd, const char* args, int flags) |
| 125 | +{ |
| 126 | + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); |
| 127 | + |
| 128 | + if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 4)) return CMD_RES_NOT_ENOUGH_ARGUMENTS; |
| 129 | + |
| 130 | + int en = Tokenizer_GetArgInteger(0); |
| 131 | + int low = Tokenizer_GetArgInteger(1); |
| 132 | + int high = Tokenizer_GetArgInteger(2); |
| 133 | + int persist = Tokenizer_GetArgInteger(3); |
| 134 | + |
| 135 | + LTR_WriteReg(LTR_REG_ALS_THRES_LOW_0, low & 0xFF); |
| 136 | + LTR_WriteReg(LTR_REG_ALS_THRES_LOW_1, low >> 8); |
| 137 | + LTR_WriteReg(LTR_REG_ALS_THRES_UP_0, high & 0xFF); |
| 138 | + LTR_WriteReg(LTR_REG_ALS_THRES_UP_1, high >> 8); |
| 139 | + LTR_WriteReg(LTR_REG_INTERRUPT_PERSIST, persist & 0x0F); |
| 140 | + LTR_WriteReg(LTR_REG_INTERRUPT, en ? 0x02 : 0x00); |
| 141 | + |
| 142 | + return CMD_RES_OK; |
| 143 | +} |
| 144 | + |
| 145 | +commandResult_t LTR_Cycle(const void* ctx, const char* cmd, const char* args, int flags) |
| 146 | +{ |
| 147 | + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); |
| 148 | + |
| 149 | + if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) return CMD_RES_NOT_ENOUGH_ARGUMENTS; |
| 150 | + |
| 151 | + int s = Tokenizer_GetArgInteger(0); |
| 152 | + if(s < 1) return CMD_RES_BAD_ARGUMENT; |
| 153 | + |
| 154 | + sec_cycle = s; |
| 155 | + sec_left = s; |
| 156 | + return CMD_RES_OK; |
| 157 | +} |
| 158 | + |
| 159 | +void LTR_Init() |
| 160 | +{ |
| 161 | + g_softI2C.pin_clk = Tokenizer_GetPin(1, 9); |
| 162 | + g_softI2C.pin_data = Tokenizer_GetPin(2, 14); |
| 163 | + |
| 164 | + ch_lux = Tokenizer_GetArgIntegerDefault(3, -1); |
| 165 | + |
| 166 | + Soft_I2C_PreInit(&g_softI2C); |
| 167 | + rtos_delay_milliseconds(100); |
| 168 | + |
| 169 | + LTR_Setup(); |
| 170 | + |
| 171 | + //cmddetail:{"name":"LTR_ALS","args":"[gain] [integration] [repeat]", |
| 172 | + //cmddetail:"descr":"ALS configuration. Gain mappings: 0-x1 1-x2 2-x4 3-x8 6-x48 7-x96. Integration mappings (ms): 0-100 1-50 2-200 3-400 4-150 5-250 6-300 7-350. Repeat mappings (ms): 0-50 1-100 2-200 3-500 4-1000 5-2000.", |
| 173 | + //cmddetail:"fn":"LTR_ALS","file":"driver/drv_ltr_als.c","requires":"", |
| 174 | + //cmddetail:"examples":LTR_ALS 3 0 3 <br /> gain 8x, integration 100ms, repeat 500ms"} |
| 175 | + CMD_RegisterCommand("LTR_ALS", LTR_ALS, NULL); |
| 176 | + //cmddetail:{"name":"LTR_INT","args":"[enable] [als_low] [als_high] [persistance]", |
| 177 | + //cmddetail:"descr":"Interrupt configuration. Enable = 0-1, persistance (oversampling) = 0-15. als_low/als_high - raw thresholds", |
| 178 | + //cmddetail:"fn":"LTR_INT","file":"driver/drv_ltr_als.c","requires":"", |
| 179 | + //cmddetail:"examples":"LTR_INT 1 200 2000 4 <br /> enable interrupt, when measurement is lower than 200 or higher than 2000 4 times"} |
| 180 | + CMD_RegisterCommand("LTR_INT", LTR_INT, NULL); |
| 181 | + //cmddetail:{"name":"LTR_Cycle","args":"[IntervalSeconds]", |
| 182 | + //cmddetail:"descr":"This is the interval between measurements in seconds, by default 1. Max is 255.", |
| 183 | + //cmddetail:"fn":"LTR_Cycle","file":"driver/drv_ltr_als.c","requires":"", |
| 184 | + //cmddetail:"examples":"LTR_Cycle 60 <br /> measurement is taken every 60 seconds"} |
| 185 | + CMD_RegisterCommand("LTR_Cycle", LTR_Cycle, NULL); |
| 186 | +} |
| 187 | + |
| 188 | +void LTR_OnEverySecond() |
| 189 | +{ |
| 190 | + if(sec_left-- <= 0) |
| 191 | + { |
| 192 | + LTR_Measure(); |
| 193 | + sec_left = sec_cycle; |
| 194 | + } |
| 195 | +} |
| 196 | + |
| 197 | +void LTR_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState) |
| 198 | +{ |
| 199 | + if(bPreState) |
| 200 | + return; |
| 201 | + |
| 202 | + if(!is_init) hprintf255(request, "<b>LTR sensor not detected</b>"); |
| 203 | + else hprintf255(request, "<h2>LTR Lux=%.1f</h2>", als_lux); |
| 204 | +} |
| 205 | + |
| 206 | +#endif |
0 commit comments