1 /**************************************************************************//**
2 *
3 * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2022-9-1 Wayne First version
10 *
11 ******************************************************************************/
12
13 #include <rtthread.h>
14
15 #include <sys/time.h>
16 #include "sensor_nct7717u.h"
17
18 #define DBG_ENABLE
19 #define DBG_LEVEL DBG_LOG
20 #define DBG_SECTION_NAME "sensor.nct7717u"
21 #define DBG_COLOR
22 #include <rtdbg.h>
23
24 #define NCT7717U_I2C_SLAVE_ADDR 0x48
25
26 #define REG_NCT7717U_LDT 0x0
27 #define REG_NCT7717U_ALERT_STATUS 0x2
28 #define REG_NCT7717U_CONFIGURATION_R 0x3
29 #define REG_NCT7717U_CONVERSION_RATE_R 0x4
30 #define REG_NCT7717U_LH_HAT_R 0x5
31
32 #define REG_NCT7717U_CONFIGURATION_W 0x9
33 #define REG_NCT7717U_CONVERSION_RATE_W 0xA
34 #define REG_NCT7717U_LH_HAT_W 0xB
35 #define REG_NCT7717U_ONESHOT_CONVERSION 0xF
36 #define REG_NCT7717U_CUSTOMER_LOG_1 0x2D
37 #define REG_NCT7717U_CUSTOMER_LOG_2 0x2E
38 #define REG_NCT7717U_CUSTOMER_LOG_3 0x2F
39 #define REG_NCT7717U_ALERT_MODE 0xBF
40
41 #define REG_NCT7717U_CID 0xFD
42 #define REG_NCT7717U_VID 0xFE
43 #define REG_NCT7717U_DID 0xFF
44
nct7717u_i2c_read_reg(struct rt_i2c_bus_device * i2c_bus_dev,const char * reg,int reg_length,char * data,int length)45 static rt_err_t nct7717u_i2c_read_reg(struct rt_i2c_bus_device *i2c_bus_dev, const char *reg, int reg_length, char *data, int length)
46 {
47 struct rt_i2c_msg msgs[2];
48
49 msgs[0].addr = NCT7717U_I2C_SLAVE_ADDR; /* Slave address */
50 msgs[0].flags = RT_I2C_WR; /* Write flag */
51 msgs[0].buf = (rt_uint8_t *)reg; /* Slave register address */
52 msgs[0].len = reg_length; /* Number of bytes sent */
53
54 msgs[1].addr = NCT7717U_I2C_SLAVE_ADDR; /* Slave address */
55 msgs[1].flags = RT_I2C_RD; /* Read flag without READ_ACK */
56 msgs[1].buf = (rt_uint8_t *)data; /* Read data pointer */
57 msgs[1].len = length; /* Number of bytes read */
58
59 if (rt_i2c_transfer(i2c_bus_dev, &msgs[0], 2) != 2)
60 {
61 return -RT_ERROR;
62 }
63
64 return RT_EOK;
65 }
66
nct7717u_read_cid(struct rt_i2c_bus_device * i2c_bus_dev,uint8_t * u8Temp)67 static rt_err_t nct7717u_read_cid(struct rt_i2c_bus_device *i2c_bus_dev, uint8_t *u8Temp)
68 {
69 uint8_t u8Reg = REG_NCT7717U_CID;
70 return nct7717u_i2c_read_reg(i2c_bus_dev, (const char *)&u8Reg, sizeof(u8Reg), (char *)u8Temp, sizeof(uint8_t));
71 }
72
nct7717u_read_vid(struct rt_i2c_bus_device * i2c_bus_dev,uint8_t * u8Temp)73 static rt_err_t nct7717u_read_vid(struct rt_i2c_bus_device *i2c_bus_dev, uint8_t *u8Temp)
74 {
75 uint8_t u8Reg = REG_NCT7717U_VID;
76 return nct7717u_i2c_read_reg(i2c_bus_dev, (const char *)&u8Reg, sizeof(u8Reg), (char *)u8Temp, sizeof(uint8_t));
77 }
78
nct7717u_read_did(struct rt_i2c_bus_device * i2c_bus_dev,uint8_t * u8Temp)79 static rt_err_t nct7717u_read_did(struct rt_i2c_bus_device *i2c_bus_dev, uint8_t *u8Temp)
80 {
81 uint8_t u8Reg = REG_NCT7717U_DID;
82 return nct7717u_i2c_read_reg(i2c_bus_dev, (const char *)&u8Reg, sizeof(u8Reg), (char *)u8Temp, sizeof(uint8_t));
83 }
84
nct7717u_probe(struct rt_i2c_bus_device * i2c_bus_dev)85 static rt_err_t nct7717u_probe(struct rt_i2c_bus_device *i2c_bus_dev)
86 {
87 uint8_t u8Cid, u8Vid, u8Did;
88
89 if (nct7717u_read_cid(i2c_bus_dev, &u8Cid) != RT_EOK)
90 goto exit_nct7717u_probe;
91
92 if (nct7717u_read_vid(i2c_bus_dev, &u8Vid) != RT_EOK)
93 goto exit_nct7717u_probe;
94
95 if (nct7717u_read_did(i2c_bus_dev, &u8Did) != RT_EOK)
96 goto exit_nct7717u_probe;
97
98 LOG_I("CID=%02x VID=%02x DID=%02x", u8Cid, u8Vid, u8Did);
99
100 if ((u8Cid != 0x50) || (u8Vid != 0x50) || ((u8Did & 0x90) != 0x90))
101 {
102 LOG_E("Failed to detect NCT7717U");
103 goto exit_nct7717u_probe;
104 }
105 return RT_EOK;
106
107 exit_nct7717u_probe:
108
109 return -RT_ERROR;
110 }
111
nct7717u_ldt_readout(struct rt_i2c_bus_device * i2c_bus_dev,uint8_t * u8Temp)112 static rt_err_t nct7717u_ldt_readout(struct rt_i2c_bus_device *i2c_bus_dev, uint8_t *u8Temp)
113 {
114 uint8_t u8Reg = REG_NCT7717U_LDT;
115 return nct7717u_i2c_read_reg(i2c_bus_dev, (const char *)&u8Reg, sizeof(u8Reg), (char *)u8Temp, sizeof(uint8_t));
116 }
117
nct7717u_fetch_data(rt_sensor_t sensor,rt_sensor_data_t data,rt_size_t len)118 static rt_ssize_t nct7717u_fetch_data(rt_sensor_t sensor, rt_sensor_data_t data, rt_size_t len)
119 {
120 RT_ASSERT(data);
121
122 if (sensor->info.type == RT_SENSOR_TYPE_TEMP)
123 {
124 rt_int8_t i8Temp;
125 struct rt_i2c_bus_device *i2c_bus_dev = sensor->config.intf.arg;
126
127 if (nct7717u_ldt_readout(i2c_bus_dev, (uint8_t *)&i8Temp) == RT_EOK)
128 {
129 rt_int32_t i32TempValue = i8Temp;
130 data->type = RT_SENSOR_TYPE_TEMP;
131 data->data.temp = i32TempValue * 10;
132 data->timestamp = rt_sensor_get_ts();
133 return 1;
134 }
135 }
136 return 0;
137 }
138
nct7717u_control(struct rt_sensor_device * sensor,int cmd,void * args)139 static rt_err_t nct7717u_control(struct rt_sensor_device *sensor, int cmd, void *args)
140 {
141 switch (cmd)
142 {
143 case RT_SENSOR_CTRL_GET_ID:
144 {
145 struct rt_i2c_bus_device *i2c_bus_dev = sensor->config.intf.arg;
146 uint8_t u8Did;
147
148 RT_ASSERT(args);
149 nct7717u_read_did(i2c_bus_dev, &u8Did);
150 *((uint8_t *)args) = u8Did;
151 }
152 break;
153
154 default:
155 return -RT_ERROR;
156 }
157
158 return RT_EOK;
159 }
160
161 static struct rt_sensor_ops sensor_ops =
162 {
163 nct7717u_fetch_data,
164 nct7717u_control
165 };
166
rt_hw_nct7717u_temp_init(const char * name,struct rt_sensor_config * cfg)167 int rt_hw_nct7717u_temp_init(const char *name, struct rt_sensor_config *cfg)
168 {
169 rt_int8_t result;
170 rt_sensor_t sensor = RT_NULL;
171
172 sensor = rt_calloc(1, sizeof(struct rt_sensor_device));
173 if (sensor == RT_NULL)
174 return -(RT_ENOMEM);
175
176 sensor->info.type = RT_SENSOR_TYPE_TEMP;
177 sensor->info.vendor = RT_SENSOR_VENDOR_UNKNOWN;
178 sensor->info.name = "nct7717u_temp";
179 sensor->info.unit = RT_SENSOR_UNIT_CELSIUS;
180 sensor->info.intf_type = RT_SENSOR_INTF_I2C;
181 sensor->info.scale.range_max = 127;
182 sensor->info.scale.range_min = -128;
183 sensor->info.acquire_min = 100; //100ms
184
185 rt_memcpy(&sensor->config, cfg, sizeof(struct rt_sensor_config));
186 sensor->ops = &sensor_ops;
187
188 result = rt_hw_sensor_register(sensor, name, RT_DEVICE_FLAG_RDWR, RT_NULL);
189 if (result != RT_EOK)
190 {
191 LOG_E("device register: %d", result);
192 rt_free(sensor);
193 return -RT_ERROR;
194 }
195
196 return RT_EOK;
197 }
198
rt_hw_nct7717u_init(const char * name,struct rt_sensor_config * cfg)199 int rt_hw_nct7717u_init(const char *name, struct rt_sensor_config *cfg)
200 {
201 struct rt_sensor_intf *intf;
202 struct rt_i2c_bus_device *i2c_bus_dev;
203
204 RT_ASSERT(name != NULL);
205 RT_ASSERT(cfg != NULL);
206
207 intf = &cfg->intf;
208
209 /* Find I2C bus */
210 i2c_bus_dev = (struct rt_i2c_bus_device *)rt_device_find(intf->dev_name);
211 if (i2c_bus_dev == RT_NULL)
212 {
213 goto exit_rt_hw_nct7717u_init;
214 }
215 intf->arg = i2c_bus_dev;
216
217 if (nct7717u_probe(i2c_bus_dev) != RT_EOK)
218 goto exit_rt_hw_nct7717u_init;
219
220 return rt_hw_nct7717u_temp_init(name, cfg);
221
222 exit_rt_hw_nct7717u_init:
223
224 return -(RT_ERROR);
225 }
226