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-8-16 Wayne First version
10 *
11 ******************************************************************************/
12
13 #include <rtdevice.h>
14
15 #include "ccap_sensor.h"
16
17 #define DBG_ENABLE
18 #define DBG_LEVEL DBG_LOG
19 #define DBG_SECTION_NAME "ccap.sensor"
20 #define DBG_COLOR
21 #include <rtdbg.h>
22
ccap_sensor_i2c_write(struct rt_i2c_bus_device * i2cdev,rt_uint16_t addr,rt_uint8_t * puBuf,int i32BufLen)23 rt_err_t ccap_sensor_i2c_write(struct rt_i2c_bus_device *i2cdev, rt_uint16_t addr, rt_uint8_t *puBuf, int i32BufLen)
24 {
25 struct rt_i2c_msg msg;
26
27 msg.addr = addr; /* Slave address */
28 msg.flags = RT_I2C_WR; /* Write flag */
29 msg.buf = puBuf; /* Slave register address */
30 msg.len = i32BufLen; /* Number of bytes sent */
31
32 if (i2cdev && rt_i2c_transfer(i2cdev, &msg, 1) != 1)
33 {
34 return -RT_ERROR;
35 }
36 return RT_EOK;
37 }
38
ccap_sensor_i2c_read(struct rt_i2c_bus_device * i2cdev,rt_uint16_t addr,rt_uint8_t * puWBuf,int i32WBufLen,rt_uint8_t * puRBuf,int i32RBufLen)39 rt_err_t ccap_sensor_i2c_read(struct rt_i2c_bus_device *i2cdev, rt_uint16_t addr, rt_uint8_t *puWBuf, int i32WBufLen, rt_uint8_t *puRBuf, int i32RBufLen)
40 {
41 struct rt_i2c_msg msgs[2];
42
43 msgs[0].addr = addr; /* Slave address */
44 msgs[0].flags = RT_I2C_WR; /* Write flag */
45 msgs[0].buf = (rt_uint8_t *)puWBuf; /* Slave register address */
46 msgs[0].len = i32WBufLen; /* Number of bytes sent */
47
48 msgs[1].addr = addr; /* Slave address */
49 msgs[1].flags = RT_I2C_RD; /* Read flag without READ_ACK */
50 msgs[1].buf = (rt_uint8_t *)puRBuf; /* Read data pointer */
51 msgs[1].len = i32RBufLen; /* Number of bytes read */
52
53 if (rt_i2c_transfer(i2cdev, &msgs[0], 2) != 2)
54 {
55 return -RT_ERROR;
56 }
57
58 return RT_EOK;
59 }
60
ccap_sensor_set_mode_general(struct rt_i2c_bus_device * i2cdev,sensor_priv * pdev,sensor_mode_info * psInfo)61 static rt_err_t ccap_sensor_set_mode_general(struct rt_i2c_bus_device *i2cdev, sensor_priv *pdev, sensor_mode_info *psInfo)
62 {
63 uint8_t au8TxData[4];
64 int i;
65
66 RT_ASSERT(i2cdev);
67 RT_ASSERT(pdev);
68 RT_ASSERT(psInfo);
69
70 LOG_I("Selected Sensor ID:%d, Width:%d, Height:%d, FMT:%08x",
71 pdev->eId,
72 psInfo->sViewInfo.u32Width,
73 psInfo->sViewInfo.u32Height,
74 psInfo->sViewInfo.u32PixFmt);
75
76 for (i = 0; i < psInfo->u32RegArrSize; i++)
77 {
78 const sensor_reg_val *psRegVal = &psInfo->psRegArr[i];
79
80 switch (pdev->u16AddrBL)
81 {
82 case 2:
83 au8TxData[0] = (uint8_t)((psRegVal->u16Addr >> 8) & 0x00FF); //addr [15:8]
84 au8TxData[1] = (uint8_t)((psRegVal->u16Addr) & 0x00FF); //addr [ 7:0]
85 break;
86
87 case 1:
88 au8TxData[0] = (uint8_t)((psRegVal->u16Addr) & 0x00FF); //addr [ 7:0]
89 break;
90
91 default:
92 return -RT_ERROR;
93 }
94
95 switch (pdev->u16ValBL)
96 {
97 case 2:
98 au8TxData[pdev->u16AddrBL] = (uint8_t)((psRegVal->u16Val >> 8) & 0x00FF); //data [15:8]
99 au8TxData[pdev->u16AddrBL + 1] = (uint8_t)((psRegVal->u16Val) & 0x00FF); //data [ 7:0]
100 break;
101
102 case 1:
103 au8TxData[pdev->u16AddrBL] = (uint8_t)((psRegVal->u16Val) & 0x00FF); //data [ 7:0]
104 break;
105
106 default:
107 return -RT_ERROR;
108 }
109
110 //LOG_I("SlaveID=0x%02x, Addr: [0x%02X,0x%02X], Value: [0x%02X,0x%02X], Length: %d", msg.addr, au8TxData[0], au8TxData[1], au8TxData[2], au8TxData[3], msg.len );
111 if (ccap_sensor_i2c_write(i2cdev, pdev->u16DevAddr, (rt_uint8_t *)&au8TxData[0], pdev->u16AddrBL + pdev->u16ValBL) != RT_EOK)
112 {
113 LOG_E("[Failed] addr=%x, data=%d\n", psRegVal->u16Addr, psRegVal->u16Val);
114 return -RT_ERROR;
115 }
116 }
117
118 return RT_EOK;
119 }
120
ccap_sensor_setpower(ccap_sensor_dev * pdev,rt_bool_t bOn)121 static rt_err_t ccap_sensor_setpower(ccap_sensor_dev *pdev, rt_bool_t bOn)
122 {
123 ccap_sensor_io_t psIo;
124 sensor_priv_t psSensorPriv;
125
126 if (pdev == RT_NULL)
127 return -RT_ERROR;
128
129 psIo = pdev->psIo;
130 psSensorPriv = (sensor_priv_t)((rt_device_t)pdev)->user_data;
131
132 LOG_I("sensor power pin: %d, Active low: %s", psIo->PwrDwnPin, bOn ? "TRUE" : "FALSE");
133
134 rt_pin_mode(psIo->PwrDwnPin, PIN_MODE_OUTPUT);
135
136 if (bOn == RT_TRUE)
137 {
138 (psSensorPriv->PwrDwnActLow == RT_TRUE) ? rt_pin_write(psIo->PwrDwnPin, PIN_HIGH) : rt_pin_write(psIo->PwrDwnPin, PIN_LOW);
139 }
140 else
141 {
142 (psSensorPriv->PwrDwnActLow == RT_TRUE) ? rt_pin_write(psIo->PwrDwnPin, PIN_LOW) : rt_pin_write(psIo->PwrDwnPin, PIN_HIGH);
143 }
144
145 return RT_EOK;
146 }
147
ccap_sensor_reset(ccap_sensor_dev * pdev)148 static rt_err_t ccap_sensor_reset(ccap_sensor_dev *pdev)
149 {
150 ccap_sensor_io_t psIo;
151 sensor_priv_t psSensorPriv;
152
153 if (pdev == RT_NULL)
154 return -RT_ERROR;
155
156 psIo = pdev->psIo;
157 psSensorPriv = (sensor_priv_t)((rt_device_t)pdev)->user_data;
158
159 LOG_I("sensor reset pin: %d, Active low: %s", psIo->RstPin, psSensorPriv->RstActLow ? "TRUE" : "FALSE");
160
161 rt_pin_mode(psIo->RstPin, PIN_MODE_OUTPUT);
162
163 (psSensorPriv->RstActLow == RT_TRUE) ?
164 rt_pin_write(psIo->RstPin, PIN_LOW) :
165 rt_pin_write(psIo->RstPin, PIN_HIGH);
166
167 rt_thread_mdelay(psSensorPriv->RstHoldTimeInMs);
168
169 (psSensorPriv->RstActLow == RT_TRUE) ?
170 rt_pin_write(psIo->RstPin, PIN_HIGH) :
171 rt_pin_write(psIo->RstPin, PIN_LOW);
172
173 return RT_EOK;
174 }
175
176 /* common device interface */
ccap_sensor_open(rt_device_t dev,rt_uint16_t oflag)177 static rt_err_t ccap_sensor_open(rt_device_t dev, rt_uint16_t oflag)
178 {
179 ccap_sensor_dev *pdev = (ccap_sensor_dev *)dev;
180 rt_err_t ret = -RT_ERROR;
181
182 if (pdev == RT_NULL)
183 goto fail_ccap_sensor_open;
184
185 /* Power-on */
186 ret = ccap_sensor_setpower(pdev, RT_TRUE);
187 if (ret != RT_EOK)
188 goto fail_ccap_sensor_open;
189
190 /* Reset */
191 ret = ccap_sensor_reset(pdev);
192
193 fail_ccap_sensor_open:
194
195 return ret;
196 }
197
ccap_sensor_close(rt_device_t dev)198 static rt_err_t ccap_sensor_close(rt_device_t dev)
199 {
200 ccap_sensor_dev *pdev = (ccap_sensor_dev *)dev;
201
202 if (pdev == RT_NULL)
203 return -RT_ERROR;
204
205 /* Power-off */
206 return ccap_sensor_setpower(pdev, RT_FALSE);
207 }
208
ccap_find_suit_mode(ccap_view_info_t psViewInfo,const sensor_priv_t psSensorPriv)209 static ccap_view_info_t ccap_find_suit_mode(ccap_view_info_t psViewInfo, const sensor_priv_t psSensorPriv)
210 {
211 int i = 0;
212 sensor_mode_info_t psSensorModeInfo = RT_NULL;
213
214 for (i = 0; i < psSensorPriv->ModeInfoSize; i++)
215 {
216 if ((psViewInfo->u32Width <= psSensorPriv->psModeInfo[i].sViewInfo.u32Width) &&
217 (psViewInfo->u32Height <= psSensorPriv->psModeInfo[i].sViewInfo.u32Height))
218 break;
219 }
220
221 if (i != psSensorPriv->ModeInfoSize)
222 psSensorModeInfo = &psSensorPriv->psModeInfo[i];
223 else
224 {
225 /* Failed to get suit mode. Here, we gave latest Sensor mode to user. */
226 psSensorModeInfo = &psSensorPriv->psModeInfo[i - 1];
227 }
228
229 return (ccap_view_info_t)psSensorModeInfo;
230 }
231
ccap_sensor_control(rt_device_t dev,int cmd,void * args)232 static rt_err_t ccap_sensor_control(rt_device_t dev, int cmd, void *args)
233 {
234 rt_err_t result = RT_EOK;
235 ccap_sensor_dev *pdev = (ccap_sensor_dev *)dev;
236
237 RT_ASSERT(dev);
238
239 switch (cmd)
240 {
241 case CCAP_SENSOR_CMD_RESET:
242 result = ccap_sensor_reset(pdev);
243 break;
244
245 case CCAP_SENSOR_CMD_SET_POWER:
246 {
247 rt_bool_t bOn = (rt_bool_t)args;
248 result = ccap_sensor_setpower(pdev, bOn);
249 }
250 break;
251
252 case CCAP_SENSOR_CMD_SET_MODE:
253 {
254 ccap_sensor_io *psIo = pdev->psIo;
255 struct rt_i2c_bus_device *i2cbus;
256 sensor_mode_info *psInfo;
257 sensor_priv *psSensorPriv = (sensor_priv *)dev->user_data;
258
259 RT_ASSERT(args);
260 RT_ASSERT(psIo);
261 RT_ASSERT(psIo->I2cName);
262
263 i2cbus = (struct rt_i2c_bus_device *)rt_device_find(psIo->I2cName);
264 RT_ASSERT(i2cbus);
265
266 psInfo = (sensor_mode_info *) args;
267
268 if (psSensorPriv->pfnSetMode != RT_NULL)
269 result = psSensorPriv->pfnSetMode(i2cbus, psSensorPriv, psInfo);
270 else
271 result = ccap_sensor_set_mode_general(i2cbus, psSensorPriv, psInfo);
272 }
273 break;
274
275 case CCAP_SENSOR_CMD_GET_SUIT_MODE:
276 {
277 /* Get private data of sensor */
278 sensor_priv_t psSensorPriv = (sensor_priv_t)dev->user_data;
279 ccap_view_info_t psViewInfo;
280
281 RT_ASSERT(args);
282 RT_ASSERT(psSensorPriv);
283
284 psViewInfo = *((ccap_view_info_t *)args);
285 RT_ASSERT(psViewInfo);
286
287 psViewInfo = ccap_find_suit_mode(psViewInfo, (sensor_priv_t)psSensorPriv);
288
289 *((ccap_view_info_t *)args) = psViewInfo;
290 }
291 break;
292
293 default:
294 result = -RT_ENOSYS;
295 break;
296 }
297
298 return result;
299 }
300
301 #ifdef RT_USING_DEVICE_OPS
302 static struct rt_device_ops ccap_ops =
303 {
304 .init = RT_NULL,
305 .open = ccap_sensor_open,
306 .close = ccap_sensor_close,
307 .read = RT_NULL,
308 .write = RT_NULL,
309 .control = ccap_sensor_control,
310 }
311 #endif
312
313 rt_err_t ccap_sensor_register(struct rt_device *device, const char *name, void *user_data)
314 {
315 RT_ASSERT(device);
316
317 device->type = RT_Device_Class_Miscellaneous;
318 device->rx_indicate = RT_NULL;
319 device->tx_complete = RT_NULL;
320
321 #ifdef RT_USING_DEVICE_OPS
322 device->ops = &ccap_ops;
323 #else
324 device->init = RT_NULL;
325 device->open = ccap_sensor_open;
326 device->close = ccap_sensor_close;
327 device->read = RT_NULL;
328 device->write = RT_NULL;
329 device->control = ccap_sensor_control;
330 #endif
331 device->user_data = user_data;
332
333 return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE);
334 }
335
336 rt_err_t nu_ccap_sensor_create(ccap_sensor_io *psIo, ccap_sensor_id evSensorId, const char *szName)
337 {
338 static int i32AllocatedSensorId = 0;
339 rt_err_t ret = -RT_ERROR;
340 ccap_sensor_dev_t pdev = RT_NULL;
341
342 RT_ASSERT(psIo);
343 RT_ASSERT((evSensorId >= 0) && (evSensorId < evCCAPSNR_CNT));
344
345 switch (evSensorId)
346 {
347 case evCCAPSNR_HM1055:
348 pdev = nu_create_hm1055(psIo, szName);
349 break;
350
351 case evCCAPSNR_ADV728X:
352 pdev = nu_create_adv728x(psIo, szName);
353 break;
354
355 default:
356 break;
357 }
358
359 if (pdev != RT_NULL)
360 {
361 ccap_sensor_setpower(pdev, RT_FALSE);
362 i32AllocatedSensorId++;
363 ret = RT_EOK;
364 }
365
366 return ret;
367 }
368