Contiki-NG
Loading...
Searching...
No Matches
max44009.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014, OpenMote Technologies, S.L.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 */
32/*---------------------------------------------------------------------------*/
33/**
34 * \addtogroup openmote-max44009-sensor
35 * @{
36 *
37 * \file
38 * Driver for the MAX44009 light sensor
39 *
40 * \author
41 * Pere Tuset <peretuset@openmote.com>
42 */
43/*---------------------------------------------------------------------------*/
44#include "dev/i2c.h"
45#include "dev/max44009.h"
46#include "lib/sensors.h"
47/*---------------------------------------------------------------------------*/
48#define DEBUG 1
49#if DEBUG
50#define PRINTF(...) printf(__VA_ARGS__)
51#else
52#define PRINTF(...)
53#endif
54/*---------------------------------------------------------------------------*/
55/**
56 * \name MAX44009 address and device identifier
57 * @{
58 */
59#define MAX44009_ADDRESS (0x4A)
60#define MAX44009_NOT_FOUND (0x00)
61/** @} */
62/*---------------------------------------------------------------------------*/
63/**
64 * \name MAX44009 register addresses
65 * @{
66 */
67#define MAX44009_INT_STATUS_ADDR (0x00) /* R */
68#define MAX44009_INT_ENABLE_ADDR (0x01) /* R/W */
69#define MAX44009_CONFIG_ADDR (0x02) /* R/W */
70#define MAX44009_LUX_HIGH_ADDR (0x03) /* R */
71#define MAX44009_LUX_LOW_ADDR (0x04) /* R */
72#define MAX44009_THR_HIGH_ADDR (0x05) /* R/W */
73#define MAX44009_THR_LOW_ADDR (0x06) /* R/W */
74#define MAX44009_THR_TIMER_ADDR (0x07) /* R/W */
75/** @} */
76/*---------------------------------------------------------------------------*/
77/**
78 * \name MAX44009 register values
79 * @{
80 */
81#define MAX44009_INT_STATUS_OFF (0x00)
82#define MAX44009_INT_STATUS_ON (0x01)
83#define MAX44009_INT_DISABLED (0x00)
84#define MAX44009_INT_ENABLED (0x01)
85
86#define MAX44009_CONFIG_DEFAULT (0 << 7)
87#define MAX44009_CONFIG_CONTINUOUS (1 << 7)
88#define MAX44009_CONFIG_AUTO (0 << 6)
89#define MAX44009_CONFIG_MANUAL (1 << 6)
90#define MAX44009_CONFIG_CDR_NORMAL (0 << 5)
91#define MAX44009_CONFIG_CDR_DIVIDED (1 << 5)
92#define MAX44009_CONFIG_INTEGRATION_800ms (0 << 0)
93#define MAX44009_CONFIG_INTEGRATION_400ms (1 << 0)
94#define MAX44009_CONFIG_INTEGRATION_200ms (2 << 0)
95#define MAX44009_CONFIG_INTEGRATION_100ms (3 << 0)
96#define MAX44009_CONFIG_INTEGRATION_50ms (4 << 0)
97#define MAX44009_CONFIG_INTEGRATION_25ms (5 << 0)
98#define MAX44009_CONFIG_INTEGRATION_12ms (6 << 0)
99#define MAX44009_CONFIG_INTEGRATION_6ms (7 << 0)
100
101#define MAX44009_DEFAULT_CONFIGURATION (MAX44009_CONFIG_DEFAULT | \
102 MAX44009_CONFIG_AUTO | \
103 MAX44009_CONFIG_CDR_NORMAL | \
104 MAX44009_CONFIG_INTEGRATION_100ms)
105
106#define MAX44009_USER_CONFIGURATION (MAX44009_CONFIG_DEFAULT | \
107 MAX44009_CONFIG_AUTO | \
108 MAX44009_CONFIG_CDR_NORMAL | \
109 MAX44009_CONFIG_INTEGRATION_800ms)
110
111/** @} */
112/*---------------------------------------------------------------------------*/
113static uint8_t enabled;
114/*---------------------------------------------------------------------------*/
115static void
116max44009_init(void)
117{
118 uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \
119 MAX44009_THR_HIGH_ADDR, MAX44009_THR_LOW_ADDR, \
120 MAX44009_THR_TIMER_ADDR };
121 uint8_t max44009_value[5];
122 uint8_t max44009_data[2];
123 uint8_t i;
124
125 max44009_value[0] = (MAX44009_INT_STATUS_OFF);
126 max44009_value[1] = (MAX44009_USER_CONFIGURATION);
127 max44009_value[2] = (0xFF);
128 max44009_value[3] = (0x00);
129 max44009_value[4] = (0xFF);
130
131 for(i = 0; i < sizeof(max44009_address) / sizeof(max44009_address[0]); i++) {
132 max44009_data[0] = max44009_address[i];
133 max44009_data[1] = max44009_value[i];
134 i2c_burst_send(MAX44009_ADDRESS, max44009_data, 2);
135 }
136}
137/*---------------------------------------------------------------------------*/
138static void
139max44009_reset(void)
140{
141 uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \
142 MAX44009_THR_HIGH_ADDR, MAX44009_THR_LOW_ADDR, \
143 MAX44009_THR_TIMER_ADDR };
144 uint8_t max44009_value[5] = { 0x00, 0x03, 0xFF, 0x00, 0xFF };
145 uint8_t max44009_data[2];
146 uint8_t i;
147
148 for(i = 0; i < sizeof(max44009_address) / sizeof(max44009_address[0]); i++) {
149 max44009_data[0] = max44009_address[i];
150 max44009_data[1] = max44009_value[i];
151 i2c_burst_send(MAX44009_ADDRESS, max44009_data, 2);
152 }
153}
154/*---------------------------------------------------------------------------*/
155static uint8_t
156max44009_is_present(void)
157{
158 uint8_t status;
159 uint8_t is_present;
160
161 i2c_single_send(MAX44009_ADDRESS, MAX44009_CONFIG_ADDR);
162 status = i2c_single_receive(MAX44009_ADDRESS, &is_present);
163 if(status != I2C_MASTER_ERR_NONE) {
164 return 0;
165 }
166
167 return is_present != MAX44009_NOT_FOUND;
168}
169/*---------------------------------------------------------------------------*/
170static uint16_t
171max44009_read_light(void)
172{
173 uint8_t exponent, mantissa;
174 uint8_t max44009_data[2];
175 uint32_t result;
176
177 i2c_single_send(MAX44009_ADDRESS, MAX44009_LUX_HIGH_ADDR);
178 i2c_single_receive(MAX44009_ADDRESS, &max44009_data[0]);
179 i2c_single_send(MAX44009_ADDRESS, MAX44009_LUX_LOW_ADDR);
180 i2c_single_receive(MAX44009_ADDRESS, &max44009_data[1]);
181
182 exponent = ((max44009_data[0] >> 4) & 0x0E);
183 mantissa = ((max44009_data[0] & 0x0F) << 4) | (max44009_data[1] & 0x0F);
184
185 result = ((uint16_t)exponent << 8) | ((uint16_t)mantissa << 0);
186
187 return result;
188}
189/*---------------------------------------------------------------------------*/
190static uint16_t
191max44009_convert_light(uint16_t lux)
192{
193 uint8_t exponent, mantissa;
194 uint32_t result;
195
196 exponent = (lux >> 8) & 0xFF;
197 exponent = (exponent == 0x0F ? exponent & 0x0E : exponent);
198 mantissa = (lux >> 0) & 0xFF;
199
200 result = 45 * (2 ^ exponent * mantissa) / 10;
201
202 return (uint16_t)result;
203}
204/*---------------------------------------------------------------------------*/
205static int
206status(int type)
207{
208 switch(type) {
209 case SENSORS_ACTIVE:
210 case SENSORS_READY:
211 return enabled;
212 }
213 return 0;
214}
215/*---------------------------------------------------------------------------*/
216static int
217value(int type)
218{
219 uint16_t value;
220
221 if(!enabled) {
222 PRINTF("MAX44009: sensor not started\n");
223 return MAX44009_ERROR;
224 }
225
226 if(type == MAX44009_READ_RAW_LIGHT) {
227 return max44009_read_light();
228 } else if(type == MAX44009_READ_LIGHT) {
229 value = max44009_read_light();
230 return max44009_convert_light(value);
231 } else {
232 PRINTF("MAX44009: invalid value requested\n");
233 return MAX44009_ERROR;
234 }
235}
236/*---------------------------------------------------------------------------*/
237static int
238configure(int type, int value)
239{
240 if(type == MAX44009_ACTIVATE) {
241 if(!max44009_is_present()) {
242 return MAX44009_ERROR;
243 } else {
244 max44009_init();
245 enabled = 1;
246 return MAX44009_SUCCESS;
247 }
248 }
249
250 if((type == MAX44009_RESET) && enabled) {
251 max44009_reset();
252 return MAX44009_SUCCESS;
253 } else {
254 PRINTF("MAX44009: is not enabled\n");
255 return MAX44009_ERROR;
256 }
257
258 return MAX44009_ERROR;
259}
260/*---------------------------------------------------------------------------*/
261SENSORS_SENSOR(max44009, MAX44009_SENSOR, value, configure, status);
262/*---------------------------------------------------------------------------*/
263/** @} */
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.
Definition i2c.c:188
uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data)
Perform all operations to receive a byte from a slave.
Definition i2c.c:172
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
Definition i2c.c:159
Header file with declarations for the I2C Control module.
Header file for the MAX44009 light sensor driver.