µracoli Manual  Version foo
lm73.h
1 /* Copyright (c) 2013 - 2014 Axel Wachtler
2  All rights reserved.
3 
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7 
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * 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  * Neither the name of the authors 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
21  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  POSSIBILITY OF SUCH DAMAGE. */
28 
29 #ifndef LM73_H
30 #define LM73_H
31 
43 /* === includes ============================================================ */
44 #include "sensor_defs.h"
45 
46 /* === macros ============================================================== */
47 #define LM73_DEBUG (0)
48 #if LM73_DEBUG == 1
49 # include "hif.h"
50 # define DBG_LM73(...) PRINTF(__VA_ARGS__)
51 #else
52 # define DBG_LM73(...)
53 #endif
54 
55 #define LM73_ADDR_0 (0x48)
56 #define LM73_ADDR_1 (0x49)
57 #define LM73_ADDR_2 (0x4A)
59 #define LM73_ADDR_3 (0x4C)
60 #define LM73_ADDR_4 (0x4D)
61 #define LM73_ADDR_5 (0x4E)
63 #define LM73_PTR_TEMP (0x00)
64 #define LM73_PTR_CFG (0x01)
65 #define LM73_PTR_THIGH (0x02)
66 #define LM73_PTR_TLOW (0x03)
67 #define LM73_PTR_STATUS (0x04)
68 #define LM73_PTR_ID (0x07)
69 
70 #define LM73_CFG_RESERVED (0x03)
71 #define LM73_CFG_ONE_SHOT (0x04)
72 #define LM73_CFG_ALERT_RST (0x08)
73 #define LM73_CFG_ALERT_POL (0x10)
74 #define LM73_CFG_ALERT_EN (0x20)
75 #define LM73_CFG_PWR_DOWN (0x80)
76 
77 #define LM73_STATUS_DAV (0x01)
78 #define LM73_STATUS_TLOW (0x02)
79 #define LM73_STATUS_THIGH (0x04)
80 #define LM73_STATUS_ALERT (0x08)
81 #define LM73_STATUS_RES (0x60)
82 
88 #define LM73_T_BUS_FREE_US (8)
89 
90 // LM73_TEMP_SCALE = 1/128
91 #define LM73_REG_TO_TEMP_SCALE (0.0078125)
92 #define LM73_TEMP_TO_REG_SCALE (128)
93 /* === types =============================================================== */
94 typedef struct
95 {
97  uint8_t addr;
98  int8_t temp_offset;
99 } lm73_ctx_t;
100 
101 /* === prototypes ========================================================== */
102 #ifdef __cplusplus
103 extern "C" {
104 #endif
105 /* === low level functions ================================================== */
106 
107 static inline uint8_t lm73_byte_read(lm73_ctx_t *pctx, uint8_t addr)
108 {
109  uint8_t buf[1] = {addr,};
110  i2c_master_writeread(pctx->addr, buf, 1, buf, 1);
111  DBG_LM73("d: lm73_byte_read: addr=0x%x val=0x%x\n", addr, buf[0]);
112  return buf[0];
113 }
114 
115 static inline void lm73_byte_write(lm73_ctx_t *pctx, uint8_t addr, uint8_t val)
116 {
117  uint8_t buf[2] = {addr, val};
118  i2c_master_writeread(pctx->addr, buf, 2, NULL, 0);
119  DBG_LM73("d: lm73_byte_write: addr=0x%x val=0x%x\n", addr, val);
120 }
121 
122 static inline uint16_t lm73_word_read(lm73_ctx_t *pctx, uint8_t addr)
123 {
124  uint16_t rv;
125  uint8_t buf[2] = {addr,};
126  i2c_master_writeread(pctx->addr, buf, 1, buf, 2);
127  rv = (buf[0]<<8) | buf[1];
128  DBG_LM73("d: lm73_word_read: addr=0x%x val=0x%x\n", addr, rv);
129  return rv;
130 }
131 
132 static inline void lm73_word_write(lm73_ctx_t *pctx, uint8_t addr, uint16_t val)
133 {
134  uint8_t buf[3] = {addr, ((val>>8) &0xff), (val & 0xff)};
135  i2c_master_writeread(pctx->addr, buf, 3, NULL, 0);
136  DBG_LM73("d: lm73_word_write: addr=0x%x val=0x%x\n", addr, val);
137 }
138 
139 static inline int16_t lm73_get(lm73_ctx_t *pctx)
140 {
141  int16_t rv;
142  rv = lm73_word_read(pctx, LM73_PTR_TEMP);
143  DBG_LM73("d: lm73_get: val=0x%x\n", rv);
144  return rv;
145 }
146 
147 static inline void lm73_set_upper_limit(lm73_ctx_t *pctx, int16_t val)
148 {
149  lm73_word_write(pctx, LM73_PTR_THIGH, val);
150 }
151 
152 static inline void lm73_set_lower_limit(lm73_ctx_t *pctx, int16_t val)
153 {
154  lm73_word_write(pctx, LM73_PTR_TLOW, val);
155 }
156 
157 static inline uint16_t lm73_get_id(lm73_ctx_t *pctx)
158 {
159  uint8_t buf[2] = {7};
160  i2c_master_writeread(pctx->addr, buf, 1, buf, 2);
161  return buf[0] | buf[1]*256;
162 }
163 
164 static inline float lm73_scale(int16_t val)
165 {
166  return LM73_REG_TO_TEMP_SCALE * (val);
167 }
168 
169 
170 /* === high level sensor functions ========================================= */
171 
172 static inline void lm73_trigger(void *pctx, bool one_shot)
173 {
174  uint8_t tmp;
175  tmp = lm73_byte_read(((lm73_ctx_t *)pctx), LM73_PTR_CFG);
176  if (one_shot)
177  {
178  tmp |= (LM73_CFG_PWR_DOWN | LM73_CFG_ONE_SHOT);
179  }
180  else
181  {
182  tmp &= ~LM73_CFG_PWR_DOWN;
183  }
184  tmp &= ~LM73_CFG_RESERVED;
185  tmp |= 1<<6;
187  lm73_byte_write(((lm73_ctx_t *)pctx), LM73_PTR_CFG, tmp);
188  DBG_LM73("d: lm73_trigger: cfg=0x%x, one_shot=%d\n", tmp, one_shot);
189 }
190 
191 static inline uint8_t lm73_get_val(void *pctx, uint8_t *pdata)
192 {
193  uint8_t rv, status;
194  uint16_t temp;
195  rv = sizeof(sensor_temperature_t);
196  if (pdata != NULL)
197  {
198  temp = lm73_get((lm73_ctx_t *)pctx);
199  status = lm73_byte_read(((lm73_ctx_t *)pctx), LM73_PTR_STATUS);
200  if (status & LM73_STATUS_DAV)
201  {
202  ((sensor_temperature_t*)pdata)->type = SENSOR_DATA_TEMPERATURE;
203  ((sensor_temperature_t*)pdata)->sensor = SENSOR_LM73;
204  ((sensor_temperature_t*)pdata)->temp = lm73_scale(temp);
205  }
206  else
207  {
208  rv = 0;
209  }
210  DBG_LM73("d: lm73_get_val: temp=%d, status=0x%x\n", temp, status);
211 
212  }
213  return rv;
214 
215 }
216 static inline uint8_t lm73_get_raw(void *pctx, uint8_t *pdata)
217 {
218  uint8_t rv, status;
219  uint16_t tempi;
220  rv = sizeof(sensor_raw_t) - 1 + sizeof(tempi);
221  if (pdata != NULL)
222  {
223  status = lm73_byte_read(((lm73_ctx_t *)pctx), LM73_PTR_STATUS);
224  if (status & LM73_STATUS_DAV)
225  {
226  ((sensor_raw_t*)pdata)->type = SENSOR_DATA_RAW | sizeof(tempi);
227  ((sensor_raw_t*)pdata)->sensor = SENSOR_LM73;
228  tempi = lm73_get((lm73_ctx_t *)pctx);
229  ((sensor_raw_t*)pdata)->data[0] = tempi & 0xff;
230  ((sensor_raw_t*)pdata)->data[1] = (tempi >> 8) & 0xff;
231  }
232  else
233  {
234  rv = 0;
235  }
236  }
237  return rv;
238 }
239 
240 static inline void lm73_sleep(void *pctx)
241 {
242  uint8_t tmp;
243  tmp = lm73_byte_read(((lm73_ctx_t *)pctx), LM73_PTR_CFG);
244  tmp |= LM73_CFG_PWR_DOWN;
246  lm73_byte_write(((lm73_ctx_t *)pctx), LM73_PTR_CFG, tmp);
247  DBG_LM73("d: lm73_sleep: val=0x%x\n", tmp);
248 }
249 
270 static inline uint8_t sensor_create_lm73(void *pdata,
271  bool raw,
272  uint8_t addr,
273  int8_t temp_offset)
274 {
275  uint8_t rv = sizeof(lm73_ctx_t);
276  lm73_ctx_t *pcfg;
277  uint8_t tst;
278 
279  if (pdata != NULL)
280  {
281  /* init generic sensor data */
282  pcfg = (lm73_ctx_t *)pdata;
283  pcfg->g.id = SENSOR_LM73;
284  pcfg->g.f_trigger = lm73_trigger;
285  pcfg->g.f_get_val = raw ? lm73_get_raw : lm73_get_val;
286  pcfg->g.f_sleep = lm73_sleep;
287  // ... more functions to setup
288 
289  /* init private sensor data */
290  pcfg->addr = addr;
291  pcfg->temp_offset = temp_offset;
292 
293  /* initialize sensor */
294  tst = i2c_probe(pcfg->addr);
295  pcfg->g.last_error = tst ? SENSOR_ERR_OK : SENSOR_ERR_INIT;
296  DBG_LM73("d: lm73_init: addr=0x%x\n", addr);
297  }
298  return rv;
299 }
300 
301 #ifdef __cplusplus
302 } /* extern "C" */
303 #endif
304 
305 #endif /* #ifndef LM73_H */
#define DELAY_US(x)
Macro for delays with us resolution.
Definition: board.h:89
uint8_t i2c_probe(uint8_t devaddr)
#define LM73_T_BUS_FREE_US
Definition: lm73.h:88
uint8_t i2c_master_writeread(uint8_t devaddr, uint8_t *writebuf, uint8_t bytestowrite, uint8_t *readbuf, uint8_t bytestoread)
static uint8_t sensor_create_lm73(void *pdata, bool raw, uint8_t addr, int8_t temp_offset)
Definition: lm73.h:270