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