1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #include <stdio.h>
22 #include "mxc_device.h"
23 #include "mxc_errors.h"
24 #include "mxc_assert.h"
25 #include "mxc_sys.h"
26 #include "mxc_lock.h"
27 #include "qdec.h"
28 #include "qdec_reva.h"
29 
30 #define QDEC_IE_MASK                                                                            \
31     (MXC_F_QDEC_REVA_INTEN_INDEX | MXC_F_QDEC_REVA_INTEN_QERR | MXC_F_QDEC_REVA_INTEN_COMPARE | \
32      MXC_F_QDEC_REVA_INTEN_MAXCNT | MXC_F_QDEC_REVA_INTEN_CAPTURE | MXC_F_QDEC_REVA_INTEN_DIR | \
33      MXC_F_QDEC_REVA_INTEN_MOVE)
34 
35 #define QDEC_IF_MASK                                                                            \
36     (MXC_F_QDEC_REVA_INTFL_INDEX | MXC_F_QDEC_REVA_INTFL_QERR | MXC_F_QDEC_REVA_INTFL_COMPARE | \
37      MXC_F_QDEC_REVA_INTFL_MAXCNT | MXC_F_QDEC_REVA_INTFL_CAPTURE | MXC_F_QDEC_REVA_INTFL_DIR | \
38      MXC_F_QDEC_REVA_INTFL_MOVE)
39 
40 static mxc_qdec_cb_t async_callback;
41 
MXC_QDEC_RevA_Init(mxc_qdec_reva_regs_t * qdec,mxc_qdec_req_t * req)42 int MXC_QDEC_RevA_Init(mxc_qdec_reva_regs_t *qdec, mxc_qdec_req_t *req)
43 {
44     // Disable QDEC to configure
45     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
46 
47     // Set count mode
48     qdec->ctrl |= ((req->mode << MXC_F_QDEC_REVA_CTRL_MODE_POS) & MXC_F_QDEC_REVA_CTRL_MODE);
49 
50     // Phase swap
51     if (req->swap) {
52         qdec->ctrl |= MXC_F_QDEC_REVA_CTRL_SWAP;
53     } else {
54         qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_SWAP;
55     }
56 
57     // Set sticky state
58     qdec->ctrl |= ((req->sticky << MXC_F_QDEC_REVA_CTRL_STICKY_POS) & MXC_F_QDEC_REVA_CTRL_STICKY);
59 
60     qdec->ctrl |= ((req->clkdiv << MXC_F_QDEC_REVA_CTRL_PSC_POS) & MXC_F_QDEC_REVA_CTRL_PSC);
61 
62     // Set max and min count values
63     MXC_QDEC_RevA_SetMaxCount(qdec, req->maxcnt);
64     MXC_QDEC_RevA_SetInitial(qdec, req->initial);
65 
66     qdec->ctrl &= ~(MXC_F_QDEC_REVA_CTRL_RST_MAXCNT | MXC_F_QDEC_REVA_CTRL_RST_INDEX);
67 
68     // Reset on Max Count Match
69     if (req->rst == MXC_QDEC_RST_ON_MAXCNT) {
70         qdec->ctrl |= MXC_F_QDEC_REVA_CTRL_RST_MAXCNT;
71 
72         // Clear flag before enabling interrupt
73         qdec->intfl |= MXC_F_QDEC_REVA_INTFL_MAXCNT;
74         qdec->inten |= MXC_F_QDEC_REVA_INTEN_MAXCNT;
75 
76         // Reset on Index
77     } else if (req->rst == MXC_QDEC_RST_ON_INDEX) {
78         qdec->ctrl |= MXC_F_QDEC_REVA_CTRL_RST_INDEX;
79 
80         // Clear flag before enabling interrupt
81         qdec->intfl |= MXC_F_QDEC_REVA_INTFL_INDEX;
82         qdec->inten |= MXC_F_QDEC_REVA_INTEN_INDEX;
83 
84     } else {
85         return E_BAD_PARAM;
86     }
87 
88     // Enable capture or compare function before enabling
89     if (req->func == MXC_QDEC_CAPTURE) {
90         // Clear flag before enabling interrupt
91         qdec->intfl |= MXC_F_QDEC_REVA_INTFL_CAPTURE;
92         qdec->inten |= MXC_F_QDEC_REVA_INTEN_CAPTURE;
93 
94     } else if (req->func == MXC_QDEC_COMPARE) {
95         MXC_QDEC_RevA_SetCompare(qdec, req->compare);
96 
97         // Clear flag before enabling interrupt
98         qdec->intfl |= MXC_F_QDEC_REVA_INTFL_COMPARE;
99         qdec->inten |= MXC_F_QDEC_REVA_INTEN_COMPARE;
100     }
101 
102     // Save for callback
103     if (req->callback != NULL) {
104         async_callback = req->callback;
105     }
106 
107     qdec->ctrl |= MXC_F_QDEC_REVA_CTRL_EN;
108 
109     return E_NO_ERROR;
110 }
111 
MXC_QDEC_RevA_Shutdown(mxc_qdec_reva_regs_t * qdec)112 int MXC_QDEC_RevA_Shutdown(mxc_qdec_reva_regs_t *qdec)
113 {
114     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
115 
116     // Disable and Clear interupts
117     qdec->inten = 0;
118     qdec->intfl = QDEC_IF_MASK;
119 
120     // Clear registers
121     qdec->ctrl = 0;
122     qdec->maxcnt = 0xFFFFFFFF;
123     qdec->initial = 0;
124 
125     return E_NO_ERROR;
126 }
127 
MXC_QDEC_RevA_EnableInt(mxc_qdec_reva_regs_t * qdec,uint32_t flags)128 void MXC_QDEC_RevA_EnableInt(mxc_qdec_reva_regs_t *qdec, uint32_t flags)
129 {
130     int save_state = qdec->ctrl;
131 
132     // Disable QDEC to configure
133     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
134 
135     // Clear flag before enabling interrupt
136     qdec->intfl |= (flags & QDEC_IF_MASK);
137     qdec->inten |= (flags & QDEC_IE_MASK);
138 
139     qdec->ctrl = save_state;
140 }
141 
MXC_QDEC_RevA_DisableInt(mxc_qdec_reva_regs_t * qdec,uint32_t flags)142 void MXC_QDEC_RevA_DisableInt(mxc_qdec_reva_regs_t *qdec, uint32_t flags)
143 {
144     int save_state = qdec->ctrl;
145 
146     // Disable QDEC to configure
147     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
148 
149     qdec->inten &= ~(flags & QDEC_IE_MASK);
150 
151     qdec->ctrl = save_state;
152 }
153 
MXC_QDEC_RevA_GetFlags(mxc_qdec_reva_regs_t * qdec)154 int MXC_QDEC_RevA_GetFlags(mxc_qdec_reva_regs_t *qdec)
155 {
156     return (qdec->intfl & QDEC_IF_MASK);
157 }
158 
MXC_QDEC_RevA_ClearFlags(mxc_qdec_reva_regs_t * qdec,uint32_t flags)159 void MXC_QDEC_RevA_ClearFlags(mxc_qdec_reva_regs_t *qdec, uint32_t flags)
160 {
161     // Write 1 to clear flags
162     qdec->intfl |= (flags & QDEC_IF_MASK);
163 }
164 
MXC_QDEC_RevA_SetMaxCount(mxc_qdec_reva_regs_t * qdec,uint32_t maxCount)165 void MXC_QDEC_RevA_SetMaxCount(mxc_qdec_reva_regs_t *qdec, uint32_t maxCount)
166 {
167     int save_state = qdec->ctrl;
168 
169     // Disable QDEC to configure
170     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
171 
172     qdec->maxcnt = maxCount;
173 
174     qdec->ctrl = save_state;
175 }
176 
MXC_QDEC_RevA_GetMaxCount(mxc_qdec_reva_regs_t * qdec)177 int MXC_QDEC_RevA_GetMaxCount(mxc_qdec_reva_regs_t *qdec)
178 {
179     return qdec->maxcnt;
180 }
181 
MXC_QDEC_RevA_SetInitial(mxc_qdec_reva_regs_t * qdec,uint32_t initial)182 void MXC_QDEC_RevA_SetInitial(mxc_qdec_reva_regs_t *qdec, uint32_t initial)
183 {
184     int save_state = qdec->ctrl;
185 
186     // Disable QDEC to configure
187     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
188 
189     qdec->initial = initial;
190 
191     qdec->ctrl = save_state;
192 }
193 
MXC_QDEC_RevA_GetInitial(mxc_qdec_reva_regs_t * qdec)194 int MXC_QDEC_RevA_GetInitial(mxc_qdec_reva_regs_t *qdec)
195 {
196     return qdec->initial;
197 }
198 
MXC_QDEC_RevA_SetCompare(mxc_qdec_reva_regs_t * qdec,uint32_t compare)199 void MXC_QDEC_RevA_SetCompare(mxc_qdec_reva_regs_t *qdec, uint32_t compare)
200 {
201     int save_state = qdec->ctrl;
202 
203     // Disable QDEC to configure
204     qdec->ctrl &= ~MXC_F_QDEC_REVA_CTRL_EN;
205 
206     qdec->compare = compare;
207 
208     qdec->ctrl = save_state;
209 }
210 
MXC_QDEC_RevA_GetCompare(mxc_qdec_reva_regs_t * qdec)211 int MXC_QDEC_RevA_GetCompare(mxc_qdec_reva_regs_t *qdec)
212 {
213     return qdec->compare;
214 }
215 
MXC_QDEC_RevA_GetIndex(mxc_qdec_reva_regs_t * qdec)216 int MXC_QDEC_RevA_GetIndex(mxc_qdec_reva_regs_t *qdec)
217 {
218     return qdec->index;
219 }
220 
MXC_QDEC_RevA_GetCapture(mxc_qdec_reva_regs_t * qdec)221 int MXC_QDEC_RevA_GetCapture(mxc_qdec_reva_regs_t *qdec)
222 {
223     return qdec->capture;
224 }
225 
MXC_QDEC_RevA_Handler(mxc_qdec_reva_regs_t * qdec)226 int MXC_QDEC_RevA_Handler(mxc_qdec_reva_regs_t *qdec)
227 {
228     uint32_t flags;
229 
230     // Clear Flags
231     flags = MXC_QDEC_GetFlags();
232     qdec->intfl = flags;
233 
234     if (async_callback != NULL) {
235         async_callback(NULL, E_NO_ERROR);
236     }
237 
238     return E_NO_ERROR;
239 }
240 
241 // ************************************* Function to Read QDEC Data *******************************************
MXC_QDEC_RevA_GetPosition(mxc_qdec_reva_regs_t * qdec)242 int MXC_QDEC_RevA_GetPosition(mxc_qdec_reva_regs_t *qdec)
243 {
244     return qdec->position;
245 }
246 
MXC_QDEC_RevA_GetDirection(mxc_qdec_reva_regs_t * qdec)247 int MXC_QDEC_RevA_GetDirection(mxc_qdec_reva_regs_t *qdec)
248 {
249     return (qdec->status & MXC_F_QDEC_REVA_STATUS_DIR);
250 }
251