47 #include "lib/sensors.h"
52 #define PRINTF(...) printf(__VA_ARGS__)
57 #define TSL2563_INT_PORT_BASE GPIO_PORT_TO_BASE(I2C_INT_PORT)
58 #define TSL2563_INT_PIN_MASK GPIO_PIN_MASK(I2C_INT_PIN)
60 static uint8_t enabled;
62 static uint8_t timming;
64 void (*tsl2563_int_callback)(uint8_t value);
67 calculate_lux(uint8_t *buf)
69 uint32_t ch0, ch1, chscale = 0;
71 uint32_t lratio, tmp = 0;
79 buffer[0] = (buf[1] << 8 | (buf[0]));
80 buffer[1] = (buf[3] << 8 | (buf[2]));
83 case TSL2563_TIMMING_INTEG_402MS:
86 case TSL2563_TIMMING_INTEG_101MS:
89 case TSL2563_TIMMING_INTEG_13_7MS:
95 chscale = chscale << 4;
98 ch0 = (buffer[0] * chscale) >>
CH_SCALE;
99 ch1 = (buffer[1] * chscale) >>
CH_SCALE;
106 lratio = (ratio + 1) >> 1;
108 if((lratio >= 0) && (lratio <= K1T)) {
109 tmp = (ch0 * B1T) - (ch1 * M1T);
110 }
else if(lratio <= K2T) {
111 tmp = (ch0 * B2T) - (ch1 * M2T);
112 }
else if(lratio <= K3T) {
113 tmp = (ch0 * B3T) - (ch1 * M3T);
114 }
else if(lratio <= K4T) {
115 tmp = (ch0 * B4T) - (ch1 * M4T);
116 }
else if(lratio <= K5T) {
117 tmp = (ch0 * B5T) - (ch1 * M5T);
118 }
else if(lratio <= K6T) {
119 tmp = (ch0 * B6T) - (ch1 * M6T);
120 }
else if(lratio <= K7T) {
121 tmp = (ch0 * B7T) - (ch1 * M7T);
122 }
else if(lratio > K8T) {
123 tmp = (ch0 * B8T) - (ch1 * M8T);
135 tsl2563_read_reg(uint8_t reg, uint8_t *buf, uint8_t regNum)
141 return TSL2563_SUCCESS;
144 return TSL2563_ERROR;
148 tsl2563_write_reg(uint8_t *buf, uint8_t num)
150 if((buf ==
NULL) || (num <= 0)) {
151 PRINTF(
"TSL2563: invalid write values\n");
152 return TSL2563_ERROR;
156 if(
i2c_burst_send(TSL2563_ADDR, buf, num) == I2C_MASTER_ERR_NONE) {
157 return TSL2563_SUCCESS;
159 return TSL2563_ERROR;
166 buf[0] = (TSL2563_COMMAND + TSL2563_CONTROL);
167 buf[1] = TSL2563_CONTROL_POWER_ON;
169 if(tsl2563_write_reg(buf, 2) == I2C_MASTER_ERR_NONE) {
171 if((buf[0] & 0x0F) == TSL2563_CONTROL_POWER_ON) {
172 PRINTF(
"TSL2563: powered on\n");
173 return TSL2563_SUCCESS;
178 PRINTF(
"TSL2563: failed to power on\n");
179 return TSL2563_ERROR;
183 tsl2563_id_register(uint8_t *buf)
185 if(tsl2563_read_reg((TSL2563_COMMAND + TSL2563_ID_REG),
186 buf, 1) == TSL2563_SUCCESS) {
187 PRINTF(
"TSL2563: partnum/revnum 0x%02X\n", *buf);
188 return TSL2563_SUCCESS;
191 return TSL2563_ERROR;
198 buf[0] = (TSL2563_COMMAND + TSL2563_CONTROL);
199 buf[1] = TSL2563_CONTROL_POWER_OFF;
201 if(tsl2563_write_reg(buf, 2) == I2C_MASTER_ERR_NONE) {
202 PRINTF(
"TSL2563: powered off\n");
203 return TSL2563_SUCCESS;
206 PRINTF(
"TSL2563: failed to power off\n");
207 return TSL2563_ERROR;
211 tsl2563_clear_interrupt(
void)
213 uint8_t buf = (TSL2563_COMMAND + TSL2563_CLEAR_INTERRUPT);
214 if(tsl2563_write_reg(&buf, 1) != I2C_MASTER_ERR_NONE) {
215 PRINTF(
"TSL2563: failed to clear the interrupt\n");
216 return TSL2563_ERROR;
218 return TSL2563_SUCCESS;
222 tsl2563_read_sensor(uint16_t *lux)
227 if(tsl2563_read_reg((TSL2563_COMMAND + TSL2563_D0LOW),
228 &buf[0], 2) == TSL2563_SUCCESS) {
229 if(tsl2563_read_reg((TSL2563_COMMAND + TSL2563_D1LOW),
230 &buf[2], 2) == TSL2563_SUCCESS) {
232 PRINTF(
"TSL2563: CH0 0x%02X%02X CH1 0x%02X%02X\n", buf[1], buf[0],
234 *lux = calculate_lux(buf);
235 return TSL2563_SUCCESS;
238 PRINTF(
"TSL2563: failed to read\n");
239 return TSL2563_ERROR;
242 PROCESS(tsl2563_int_process,
"TSL2563 interrupt process handler");
251 tsl2563_clear_interrupt();
252 tsl2563_int_callback(0);
258 tsl2563_interrupt_handler(uint8_t port, uint8_t pin)
267 configure(
int type,
int value)
271 if((type != TSL2563_ACTIVE) && (type != TSL2563_INT_OVER) &&
272 (type != TSL2563_INT_BELOW) && (type != TSL2563_INT_DISABLE) &&
273 (type != TSL2563_TIMMING_CFG)) {
274 PRINTF(
"TSL2563: invalid start value\n");
275 return TSL2563_ERROR;
282 if(type == TSL2563_ACTIVE) {
284 i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
285 I2C_SCL_NORMAL_BUS_SPEED);
288 tsl2563_int_callback =
NULL;
291 if(tsl2563_on() == TSL2563_SUCCESS) {
292 if(tsl2563_id_register(&buf[0]) == TSL2563_SUCCESS) {
293 if((buf[0] & TSL2563_ID_PARTNO_MASK) == TSL2563_EXPECTED_PARTNO) {
296 if(tsl2563_read_reg((TSL2563_COMMAND + TSL2563_TIMMING),
297 &buf[0], 1) == TSL2563_SUCCESS) {
298 gain = buf[0] & TSL2563_TIMMING_GAIN;
299 timming = buf[0] & TSL2563_TIMMING_INTEG_MASK;
300 PRINTF(
"TSL2563: enabled, timming %u gain %u\n", timming, gain);
303 buf[0] = (TSL2563_COMMAND + TSL2563_THRHIGHLOW);
307 if(tsl2563_write_reg(buf, 3) != TSL2563_SUCCESS) {
308 PRINTF(
"TSL2563: failed to clear over interrupt\n");
309 return TSL2563_ERROR;
313 buf[0] = (TSL2563_COMMAND + TSL2563_THRLOWLOW);
317 if(tsl2563_write_reg(buf, 3) != TSL2563_SUCCESS) {
318 PRINTF(
"TSL2563: failed to clear below interrupt\n");
319 return TSL2563_ERROR;
323 if(tsl2563_clear_interrupt() == TSL2563_SUCCESS) {
325 return TSL2563_SUCCESS;
331 return TSL2563_ERROR;
333 if(tsl2563_off() == TSL2563_SUCCESS) {
334 PRINTF(
"TSL2563: stopped\n");
336 return TSL2563_SUCCESS;
338 return TSL2563_ERROR;
343 PRINTF(
"TSL2563: sensor not started\n");
344 return TSL2563_ERROR;
347 if(type == TSL2563_INT_DISABLE) {
358 buf[0] = (TSL2563_COMMAND + TSL2563_INTERRUPT);
359 buf[1] = TSL2563_INTR_DISABLED;
361 if(tsl2563_write_reg(buf, 2) != TSL2563_SUCCESS) {
362 PRINTF(
"TSL2563: failed to disable the interrupt\n");
363 return TSL2563_ERROR;
365 return TSL2563_SUCCESS;
369 if(type == TSL2563_TIMMING_CFG) {
370 if((value != TSL2563_G16X_402MS) && (value != TSL2563_G1X_402MS) &&
371 (value != TSL2563_G1X_101MS) && (value != TSL2563_G1X_13_7MS)) {
372 PRINTF(
"TSL2563: invalid timming configuration values\n");
373 return TSL2563_ERROR;
376 buf[0] = (TSL2563_COMMAND + TSL2563_TIMMING);
379 if(tsl2563_write_reg(buf, 2) == TSL2563_SUCCESS) {
380 if(value == TSL2563_G16X_402MS) {
385 case TSL2563_G16X_402MS:
386 case TSL2563_G1X_402MS:
387 timming = TSL2563_TIMMING_INTEG_402MS;
389 case TSL2563_G1X_101MS:
390 timming = TSL2563_TIMMING_INTEG_101MS;
392 case TSL2563_G1X_13_7MS:
393 timming = TSL2563_TIMMING_INTEG_13_7MS;
397 PRINTF(
"TSL2563: new timming %u gain %u\n", timming, gain);
398 return TSL2563_SUCCESS;
400 PRINTF(
"TSL2563: failed to configure timming\n");
401 return TSL2563_ERROR;
409 buf[1] = ((uint8_t *)&value)[0];
410 buf[2] = ((uint8_t *)&value)[1];
412 if(type == TSL2563_INT_OVER) {
413 buf[0] = (TSL2563_COMMAND + TSL2563_THRHIGHLOW);
414 }
else if(type == TSL2563_INT_BELOW) {
415 buf[0] = (TSL2563_COMMAND + TSL2563_THRLOWLOW);
418 if(tsl2563_write_reg(buf, 3) != TSL2563_SUCCESS) {
419 PRINTF(
"TSL2563: failed to set interrupt level\n");
420 return TSL2563_ERROR;
426 buf[0] = (TSL2563_COMMAND + TSL2563_INTERRUPT);
427 buf[1] = (TSL2563_INTR_LEVEL << TSL2563_INTR_SHIFT);
428 buf[1] += TSL2563_INT_PERSIST_2_CYCLES;
430 if(tsl2563_write_reg(buf, 2) != TSL2563_SUCCESS) {
431 PRINTF(
"TSL2563: failed to enable interrupt\n");
432 return TSL2563_ERROR;
458 PRINTF(
"TSL2563: Interrupt configured\n");
459 return TSL2563_SUCCESS;
479 PRINTF(
"TSL2563: sensor not started\n");
480 return TSL2563_ERROR;
483 if(type == TSL2563_VAL_READ) {
484 if(tsl2563_read_sensor(&lux) != TSL2563_ERROR) {
487 PRINTF(
"TSL2563: fail to read\n");
489 return TSL2563_ERROR;
492 SENSORS_SENSOR(tsl2563, TSL2563_SENSOR, value, configure, status);
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
uint8_t i2c_master_busy(void)
Return the busy state of I2C module.
void process_poll(struct process *p)
Request a process to be polled.
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
#define CHSCALE_TINT1
322/81 * 2^CH_SCALE
#define IOC_OVERRIDE_PUE
Pull Up Enable.
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
void i2c_master_enable(void)
Enable master I2C module.
#define CHSCALE_TINT0
322/11 * 2^CH_SCALE
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define GPIO_DETECT_FALLING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on falling edge.
Implementation of a generic module controlling Zoul sensors.
void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, uint32_t bus_speed)
Initialize the I2C peripheral and pins.
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to send multiple bytes to a slave.
uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data)
Perform all operations to receive a byte from a slave.
#define NULL
The null pointer.
uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to receive multiple bytes from a slave.
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Header file for the external TSL2563 Sensor Driver.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
#define CH_SCALE
scale channel values by 2^10
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
#define LUX_SCALE
scale by 2^14
#define PROCESS_BEGIN()
Define the beginning of a process.