1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  *
4  *
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "aos/kernel.h"
11 #include "sensor_drv_api.h"
12 #include "sensor_hal.h"
13 
14 /* ADI Temperature SENSOR REGISTER MAP */
15 #define ADT7410_BIT(x) ((uint8_t)x)
16 #define ADT7410_I2C_ADDR (0x48)
17 //#define ADT7410_I2C_ADDR_TRANS(n)    ((n)<<1)
18 //#define ADT7410_I2C_ADDR ADT7410_I2C_ADDR_TRANS(ADT7410_I2C_ADDR1)
19 
20 // Who Am I
21 #define ADT7410_WHO_AM_I_REG (uint8_t)0x0B
22 #define ADT7410_WHO_AM_I_VAL (uint8_t)0xCB
23 
24 // ADI Temperature REGISTER
25 #define ADT7410_TEMPREG_MSB (uint8_t)0x00
26 #define ADT7410_TEMPREG_LSB (uint8_t)0x01
27 #define ADT7410_STATUS (uint8_t)0x02
28 #define ADT7410_CONFIG (uint8_t)0x03
29 #define ADT7410_THIGH_MSB (uint8_t)0x04
30 #define ADT7410_THIGH_LSB (uint8_t)0x05
31 #define ADT7410_TLOW_MSB (uint8_t)0x06
32 #define ADT7410_TLOW_LSB (uint8_t)0x07
33 #define ADT7410_TCRIT_MSB (uint8_t)0x08
34 #define ADT7410_TCRIT_LSB (uint8_t)0x09
35 #define ADT7410_THYST (uint8_t)0x0A
36 #define ADT7410_SOFT_RESET (uint8_t)0x2F
37 
38 
39 typedef enum
40 {
41     ADT7410_OD_13bits = (uint8_t)0x00, /*!< Output Data : 13bits */
42     ADT7410_OD_16bits = (uint8_t)0x01, /*!< Output Data : 16bits */
43 } adt7410_od_resolution;
44 
45 typedef enum
46 {
47     ADT7410_OPMODE_CONTINUOUS =
48       (uint8_t)0x00,                        /*!< Operation Mode continuously */
49     ADT7410_OPMODE_ONESHOT = (uint8_t)0x01, /*!< Operation Mode one shot */
50     ADT7410_OPMODE_FASTONESHOT =
51       (uint8_t)0x02,                        /*!< Operation Mode fast one shot */
52     ADT7410_OPMODE_SHUTDOWN = (uint8_t)0x03 /*!< Operation Mode shut down */
53 } adt7410_opmode_s;
54 
55 i2c_dev_t adt7410_ctx = {
56     .port                 = 3,
57     .config.address_width = 8,
58     .config.dev_addr      = ADT7410_I2C_ADDR << 1,
59 };
60 
drv_temp_adi_adt7410_validate_id(i2c_dev_t * drv,uint8_t id_value)61 static int drv_temp_adi_adt7410_validate_id(i2c_dev_t *drv, uint8_t id_value)
62 {
63     uint8_t value = 0x00;
64     int     ret   = 0;
65 
66     if (drv == NULL) {
67         return -1;
68     }
69 
70     ret = sensor_i2c_read(drv, ADT7410_WHO_AM_I_REG, &value, I2C_DATA_LEN,
71                           I2C_OP_RETRIES);
72     if (unlikely(ret)) {
73         return ret;
74     }
75 
76     if (id_value != value) {
77         return -1;
78     }
79     return 0;
80 }
81 
drv_temp_adi_adt7410_set_power_mode(i2c_dev_t * drv,dev_power_mode_e mode)82 static int drv_temp_adi_adt7410_set_power_mode(i2c_dev_t *      drv,
83                                                dev_power_mode_e mode)
84 {
85     uint8_t value = 0x00;
86     int     ret   = 0;
87 
88     ret = sensor_i2c_read(drv, ADT7410_CONFIG, &value, I2C_DATA_LEN,
89                           I2C_OP_RETRIES);
90     if (unlikely(ret)) {
91         return ret;
92     }
93 
94     switch (mode) {
95         case DEV_POWER_ON: {
96             value &= ~(0x03 << 5);
97             value |= (ADT7410_OPMODE_CONTINUOUS << 5);
98             ret = sensor_i2c_write(drv, ADT7410_CONFIG, &value, I2C_DATA_LEN,
99                                    I2C_OP_RETRIES);
100             if (unlikely(ret)) {
101                 return ret;
102             }
103         } break;
104 
105         case DEV_POWER_OFF: {
106             value &= ~(0x03 << 5);
107             value |= (ADT7410_OPMODE_SHUTDOWN << 5);
108             ret = sensor_i2c_write(drv, ADT7410_CONFIG, &value, I2C_DATA_LEN,
109                                    I2C_OP_RETRIES);
110             if (unlikely(ret)) {
111                 return ret;
112             }
113         } break;
114 
115         default:
116             break;
117     }
118     return 0;
119 }
120 
drv_temp_adi_adt7410_set_od_res(i2c_dev_t * drv,adt7410_od_resolution odr)121 static int drv_temp_adi_adt7410_set_od_res(i2c_dev_t *           drv,
122                                            adt7410_od_resolution odr)
123 {
124     uint8_t value = 0x00;
125     int     ret   = 0;
126 
127     ret = sensor_i2c_read(drv, ADT7410_CONFIG, &value, I2C_DATA_LEN,
128                           I2C_OP_RETRIES);
129     if (unlikely(ret)) {
130         return ret;
131     }
132     value &= ~0x80;
133     value |= (uint8_t)(odr << 7);
134 
135     ret = sensor_i2c_write(drv, ADT7410_CONFIG, &value, I2C_DATA_LEN,
136                            I2C_OP_RETRIES);
137     if (unlikely(ret)) {
138         return ret;
139     }
140     return 0;
141 }
142 
drv_temp_adi_adt7410_set_default_config(i2c_dev_t * drv)143 static int drv_temp_adi_adt7410_set_default_config(i2c_dev_t *drv)
144 {
145     int     ret   = 0;
146 
147     ret = drv_temp_adi_adt7410_set_power_mode(drv, DEV_POWER_OFF);
148     if (unlikely(ret)) {
149         return ret;
150     }
151     ret = drv_temp_adi_adt7410_set_od_res(drv, ADT7410_OD_16bits);
152     if (unlikely(ret)) {
153         return ret;
154     }
155 
156     /* you also can set the low-pass filter and cut off config here */
157     return 0;
158 }
159 
160 
drv_temp_adi_adt7410_irq_handle(void)161 static void drv_temp_adi_adt7410_irq_handle(void)
162 {
163     /* no handle so far */
164 }
165 
drv_temp_adi_adt7410_open(void)166 static int drv_temp_adi_adt7410_open(void)
167 {
168     int ret = 0;
169     ret     = drv_temp_adi_adt7410_set_power_mode(&adt7410_ctx, DEV_POWER_ON);
170     if (unlikely(ret)) {
171         return -1;
172     }
173     LOG("%s %s successfully \n", SENSOR_STR, __func__);
174     return 0;
175 }
176 
drv_temp_adi_adt7410_close(void)177 static int drv_temp_adi_adt7410_close(void)
178 {
179     int ret = 0;
180     ret     = drv_temp_adi_adt7410_set_power_mode(&adt7410_ctx, DEV_POWER_OFF);
181     if (unlikely(ret)) {
182         return -1;
183     }
184     LOG("%s %s successfully \n", SENSOR_STR, __func__);
185     return 0;
186 }
187 
188 
drv_temp_adi_adt7410_read(void * buf,size_t len)189 static int drv_temp_adi_adt7410_read(void *buf, size_t len)
190 {
191     int                 ret = 0;
192     size_t              size;
193     uint8_t             data[2], buffer[2];
194     int16_t             tmp;
195     int16_t             temp;
196     temperature_data_t *pdata = (temperature_data_t *)buf;
197     if (buf == NULL) {
198         return -1;
199     }
200 
201     size = sizeof(temperature_data_t);
202     if (len < size) {
203         return -1;
204     }
205 
206     ret = sensor_i2c_read(&adt7410_ctx, ADT7410_TEMPREG_MSB, buffer, 2,
207                           I2C_OP_RETRIES);
208     tmp = (((uint16_t)buffer[0]) << 8) | buffer[1];
209     if (tmp > 0)
210         temp = (tmp * 10) / 128;
211     else
212         temp = ((tmp - 65536) * 10) / 128;
213     data[0] = temp & 0x0FF;
214     data[1] = temp >> 8;
215 
216     if (unlikely(ret)) {
217         return -1;
218     }
219 
220     /* hatch the temp data here*/
221     for (int i = 0; i < 2; i++) {
222         pdata->t |= (((uint32_t)data[i]) << (8 * i));
223     }
224 
225     pdata->timestamp = aos_now_ms();
226 
227     return (int)size;
228 }
229 
drv_temp_adi_adt7410_write(const void * buf,size_t len)230 static int drv_temp_adi_adt7410_write(const void *buf, size_t len)
231 {
232     return 0;
233 }
234 
drv_temp_adi_adt7410_ioctl(int cmd,unsigned long arg)235 static int drv_temp_adi_adt7410_ioctl(int cmd, unsigned long arg)
236 {
237     int ret = 0;
238 
239     switch (cmd) {
240         case SENSOR_IOCTL_ODR_SET: {
241             ret = drv_temp_adi_adt7410_set_od_res(&adt7410_ctx, arg);
242             if (unlikely(ret)) {
243                 return -1;
244             }
245         } break;
246         case SENSOR_IOCTL_SET_POWER: {
247             ret = drv_temp_adi_adt7410_set_power_mode(&adt7410_ctx, arg);
248             if (unlikely(ret)) {
249                 return -1;
250             }
251         } break;
252         case SENSOR_IOCTL_GET_INFO: {
253             /* fill the dev info here */
254             dev_sensor_info_t *info = (dev_sensor_info_t *)arg;
255             info->model             = "adt7410";
256             info->range_max         = 105;
257             info->range_min         = -40;
258             info->unit              = dCelsius;
259 
260         } break;
261 
262         default:
263             break;
264     }
265 
266     LOG("%s %s successfully \n", SENSOR_STR, __func__);
267     return 0;
268 }
269 
drv_temp_adi_adt7410_init(void)270 int drv_temp_adi_adt7410_init(void)
271 {
272     int          ret = 0;
273     sensor_obj_t sensor;
274     memset(&sensor, 0, sizeof(sensor));
275 
276     /* fill the sensor obj parameters here */
277     sensor.tag        = TAG_DEV_TEMP;
278     sensor.path       = dev_temp_path;
279     sensor.io_port    = I2C_PORT;
280     sensor.open       = drv_temp_adi_adt7410_open;
281     sensor.close      = drv_temp_adi_adt7410_close;
282     sensor.read       = drv_temp_adi_adt7410_read;
283     sensor.write      = drv_temp_adi_adt7410_write;
284     sensor.ioctl      = drv_temp_adi_adt7410_ioctl;
285     sensor.irq_handle = drv_temp_adi_adt7410_irq_handle;
286 
287 
288     ret = sensor_create_obj(&sensor);
289     if (unlikely(ret)) {
290         return -1;
291     }
292 
293     ret = drv_temp_adi_adt7410_validate_id(&adt7410_ctx, ADT7410_WHO_AM_I_VAL);
294     if (unlikely(ret)) {
295         return -1;
296     }
297 
298     /* set the default config for the sensor here */
299     ret = drv_temp_adi_adt7410_set_default_config(&adt7410_ctx);
300     if (unlikely(ret)) {
301         return -1;
302     }
303 
304     LOG("%s %s successfully \n", SENSOR_STR, __func__);
305 
306     return 0;
307 }
308 
309 SENSOR_DRV_ADD(drv_temp_adi_adt7410_init);
310 
311