• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Chipsea Technologies (Shenzhen) Corp., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "ppg_cs1262_spi.h"
10 #include "spi_if.h"
11 
12 #define HDF_LOG_TAG khdf_sensor_ppg_driver
13 
14 #define CS1262_HEAD_BUF_SINGLEREG_LEN 4
15 #define CS1262_HEAD_BUF_FULL_LEN 6
16 #define OFFSET_BITS_8 8
17 #define OFFSET_BITS_2 2
18 
19 static struct SensorBusCfg *g_busCfg = NULL;
20 
ReverseEndianInt16(uint16_t data)21 static inline uint16_t ReverseEndianInt16(uint16_t data)
22 {
23     return (((data & 0x00FF) << OFFSET_BITS_8) |
24             ((data & 0xFF00) >> OFFSET_BITS_8));
25 }
26 
Cs1262RegAddrConvert(uint16_t reg)27 static inline uint16_t Cs1262RegAddrConvert(uint16_t reg)
28 {
29     /* CS1262 takes the register address from bit[2] to bit[15], bit[1~0] fixed as 00,
30      * so reg needs to be shifted left by 2 bits to convert it to the address format required by CS1262
31      */
32     return (reg << OFFSET_BITS_2) & 0x0FFC;
33 }
34 
Cs1262GetHighByteInt16(uint16_t data)35 static inline uint8_t Cs1262GetHighByteInt16(uint16_t data)
36 {
37     return (data & 0xFF00) >> OFFSET_BITS_8;
38 }
39 
Cs1262GetLowByteInt16(uint16_t data)40 static inline uint8_t Cs1262GetLowByteInt16(uint16_t data)
41 {
42     return data & 0x00FF;
43 }
44 
Cs1262ReleaseSpi(struct SensorBusCfg * busCfg)45 void Cs1262ReleaseSpi(struct SensorBusCfg *busCfg)
46 {
47     SpiClose(busCfg->spiCfg.handle);
48     busCfg->spiCfg.handle = NULL;
49     g_busCfg = NULL;
50 }
51 
Cs1262InitSpi(struct SensorBusCfg * busCfg)52 int32_t Cs1262InitSpi(struct SensorBusCfg *busCfg)
53 {
54     int32_t ret;
55     CHECK_NULL_PTR_RETURN_VALUE(busCfg, HDF_ERR_INVALID_PARAM);
56     struct SpiDevInfo spiDevinfo = {
57         .busNum = busCfg->spiCfg.busNum,
58         .csNum = busCfg->spiCfg.csNum,
59     };
60 
61     HDF_LOGI("%s: SpiOpen busNum = %d, csNum = %d", __func__, spiDevinfo.busNum, spiDevinfo.csNum);
62 
63     busCfg->spiCfg.handle = SpiOpen(&spiDevinfo);
64     if (busCfg->spiCfg.handle == NULL) {
65         HDF_LOGE("%s: SpiOpen failed", __func__);
66         return HDF_FAILURE;
67     }
68 
69     HDF_LOGD("%s: SpiSetCfg: maxSpeedHz:%d, mode=%d, transferMode=%d, bitsPerWord=%d",
70         __func__, busCfg->spiCfg.spi.maxSpeedHz, busCfg->spiCfg.spi.mode,
71         busCfg->spiCfg.spi.transferMode, busCfg->spiCfg.spi.bitsPerWord);
72 
73     ret = SpiSetCfg(busCfg->spiCfg.handle, &busCfg->spiCfg.spi);
74     if (ret != HDF_SUCCESS) {
75         HDF_LOGE("%s: SpiSetCfg failed", __func__);
76         SpiClose(busCfg->spiCfg.handle);
77         return ret;
78     }
79 
80     g_busCfg = busCfg;
81     return HDF_SUCCESS;
82 }
83 
Cs1262ReadFifoReg(Cs1262FifoVal * fifoBuf,uint16_t fifoLen)84 int32_t Cs1262ReadFifoReg(Cs1262FifoVal *fifoBuf, uint16_t fifoLen)
85 {
86     CHECK_NULL_PTR_RETURN_VALUE(fifoBuf, HDF_ERR_INVALID_PARAM);
87     CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
88 
89     uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
90         CS1262_SPI_NOCHECK_CONTINUOUSREAD,
91         0,
92         Cs1262GetHighByteInt16(Cs1262RegAddrConvert(CS1262_FIFO_DATA_REG)),
93         Cs1262GetLowByteInt16(Cs1262RegAddrConvert(CS1262_FIFO_DATA_REG)),
94         Cs1262GetHighByteInt16(fifoLen - 1),
95         Cs1262GetLowByteInt16(fifoLen - 1),
96     };
97 
98     struct SpiMsg msg[] = {
99         {
100             .wbuf = headBuf,
101             .rbuf = NULL,
102             .len = CS1262_HEAD_BUF_FULL_LEN,
103             .keepCs = 0,  // cs low
104             .delayUs = 0,
105             .speed = g_busCfg->spiCfg.spi.maxSpeedHz,
106         },
107         {
108             .wbuf = NULL,
109             .rbuf = (uint8_t *)fifoBuf,
110             .len = fifoLen * sizeof(Cs1262FifoVal),
111             .keepCs = 1,  // cs high
112             .delayUs = 0,
113             .speed = g_busCfg->spiCfg.spi.maxSpeedHz
114         }
115     };
116 
117     if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
118         HDF_LOGE("%s: Read Fifo data use spi failed", __func__);
119         return HDF_FAILURE;
120     }
121 
122     return HDF_SUCCESS;
123 }
124 
Cs1262ReadRegs(uint16_t regAddr,uint16_t * dataBuf,uint16_t dataLen)125 int32_t Cs1262ReadRegs(uint16_t regAddr, uint16_t *dataBuf, uint16_t dataLen)
126 {
127     CHECK_NULL_PTR_RETURN_VALUE(dataBuf, HDF_ERR_INVALID_PARAM);
128     CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
129 
130     uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
131         CS1262_SPI_NOCHECK_SINGLEREAD,
132         0,
133         Cs1262GetHighByteInt16(Cs1262RegAddrConvert(regAddr)),
134         Cs1262GetLowByteInt16(Cs1262RegAddrConvert(regAddr))
135     };
136     uint8_t bufLen = CS1262_HEAD_BUF_SINGLEREG_LEN;
137 
138     if (dataLen > 1) {
139         headBuf[0] = CS1262_SPI_NOCHECK_CONTINUOUSREAD;
140         headBuf[bufLen++] = Cs1262GetHighByteInt16(dataLen - 1);
141         headBuf[bufLen++] = Cs1262GetLowByteInt16(dataLen - 1);
142     }
143 
144     struct SpiMsg msg[] = {
145         {
146             .wbuf = headBuf,
147             .rbuf = NULL,
148             .len = bufLen,
149             .keepCs = 0,
150             .delayUs = 0,
151             .speed = g_busCfg->spiCfg.spi.maxSpeedHz
152         },
153         {
154             .wbuf = NULL,
155             .rbuf = (uint8_t *)dataBuf,
156             .len = dataLen * 2,  // 2 bytes reg
157             .keepCs = 1,  // 1 means enable
158             .delayUs = 0,
159             .speed = g_busCfg->spiCfg.spi.maxSpeedHz
160         }
161     };
162 
163     if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
164         HDF_LOGE("%s: Read data use spi failed", __func__);
165         return HDF_FAILURE;
166     }
167 
168     for (uint16_t index = 0; index < dataLen; index++) {
169         *(dataBuf + index) = ReverseEndianInt16(*(dataBuf + index));
170     }
171 
172     return HDF_SUCCESS;
173 }
174 
Cs1262WriteRegs(uint16_t regAddr,uint16_t * dataBuf,uint16_t dataLen)175 int32_t Cs1262WriteRegs(uint16_t regAddr, uint16_t *dataBuf, uint16_t dataLen)
176 {
177     CHECK_NULL_PTR_RETURN_VALUE(dataBuf, HDF_ERR_INVALID_PARAM);
178     CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
179 
180     uint8_t headBuf[CS1262_HEAD_BUF_FULL_LEN] = {
181         CS1262_SPI_NOCHECK_SINGLEWRITE,
182         0,
183         Cs1262GetHighByteInt16(Cs1262RegAddrConvert(regAddr)),
184         Cs1262GetLowByteInt16(Cs1262RegAddrConvert(regAddr))
185     };
186     uint8_t bufLen = CS1262_HEAD_BUF_SINGLEREG_LEN;
187 
188     if (dataLen > 1) {
189         headBuf[0] = CS1262_SPI_NOCHECK_CONTINUOUSWRITE;
190         headBuf[bufLen++] = Cs1262GetHighByteInt16(dataLen - 1);
191         headBuf[bufLen++] = Cs1262GetLowByteInt16(dataLen - 1);
192     }
193 
194     for (uint16_t index = 0; index < dataLen; index++) {
195         *(dataBuf + index) = ReverseEndianInt16(*(dataBuf + index));
196     }
197 
198     struct SpiMsg msg[] = {
199         {
200             .wbuf = headBuf,
201             .rbuf = NULL,
202             .len = bufLen,
203             .keepCs = 0,
204             .delayUs = 0,
205             .speed = g_busCfg->spiCfg.spi.maxSpeedHz
206         },
207         {
208             .wbuf = (uint8_t *)dataBuf,
209             .rbuf = NULL,
210             .len = dataLen * 2,  // 1 data has 2 bytes
211             .keepCs = 1,  // 1 means enable
212             .delayUs = 0,
213             .speed = g_busCfg->spiCfg.spi.maxSpeedHz
214         }
215     };
216 
217     if (SpiTransfer(g_busCfg->spiCfg.handle, msg, HDF_ARRAY_SIZE(msg)) != HDF_SUCCESS) {
218         HDF_LOGE("%s: Write data use spi failed", __func__);
219         return HDF_FAILURE;
220     }
221 
222     return HDF_SUCCESS;
223 }
224 
Cs1262WriteReg(uint16_t regAddr,uint16_t data)225 inline int32_t Cs1262WriteReg(uint16_t regAddr, uint16_t data)
226 {
227     return Cs1262WriteRegs(regAddr, &data, 1);
228 }
229 
Cs1262WriteData(uint8_t * data,uint16_t dataLen)230 int32_t Cs1262WriteData(uint8_t *data, uint16_t dataLen)
231 {
232     CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
233     CHECK_NULL_PTR_RETURN_VALUE(g_busCfg, HDF_ERR_NOT_SUPPORT);
234     struct SpiMsg msg = {
235         .wbuf = data,
236         .rbuf = NULL,
237         .len = dataLen,
238         .keepCs = 1,  // 1 means enable
239         .delayUs = 0,
240         .speed = g_busCfg->spiCfg.spi.maxSpeedHz
241     };
242     return SpiTransfer(g_busCfg->spiCfg.handle, &msg, 1);
243 }
244 
Cs1262WriteRegbit(uint16_t regAddr,uint16_t setbit,Cs1262BitStatus bitval)245 int32_t Cs1262WriteRegbit(uint16_t regAddr, uint16_t setbit, Cs1262BitStatus bitval)
246 {
247     uint16_t regData = 0;
248 
249     if (Cs1262ReadRegs(regAddr, &regData, 1) != HDF_SUCCESS) {
250         HDF_LOGE("%s: failed", __func__);
251         return HDF_FAILURE;
252     }
253 
254     if (bitval == CS1262_REG_BIT_SET) {
255         regData |= (uint16_t)(1 << setbit);
256     } else {
257         regData &=  (uint16_t)(~(1 << setbit));
258     }
259 
260     return Cs1262WriteRegs(regAddr, &regData, 1);
261 }
262 
Cs1262WriteGroup(Cs1262RegGroup * regGroup,uint16_t groupLen)263 int32_t Cs1262WriteGroup(Cs1262RegGroup *regGroup, uint16_t groupLen)
264 {
265     int32_t ret;
266 
267     CHECK_NULL_PTR_RETURN_VALUE(regGroup, HDF_ERR_INVALID_PARAM);
268 
269     for (uint16_t index = 0; index < groupLen; index++) {
270         if (regGroup[index].regLen == 1) {
271             ret = Cs1262WriteReg(regGroup[index].regAddr, regGroup[index].regVal);
272         } else {
273             ret = Cs1262WriteRegs(regGroup[index].regAddr, regGroup[index].regValGroup, regGroup[index].regLen);
274         }
275 
276         if (ret != HDF_SUCCESS) {
277             HDF_LOGE("%s: failed, index = %u", __func__, index);
278             return HDF_FAILURE;
279         }
280     }
281 
282     return HDF_SUCCESS;
283 }
284