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