libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
cordic_common_v1.c
Go to the documentation of this file.
1/** @addtogroup cordic_file CORDIC peripheral API
2@ingroup peripheral_apis
3
4@brief HW accelerated maths trig/hyperbolic operations.
5@author @htmlonly © @endhtmlonly
62022 Oskar H. Maier <ohma@posteo.de>
7
8This library supports the CORDIC co-processor in the STM32 series of
9ARM Cortex Microcontrollers by ST Microelectronics. This peripheral
10computes trigonometric and hyperbolic functions and converts between
11cartesian and polar coordinates.
12
13
14
15LGPL License Terms @ref lgpl_license
16 */
17
18/*
19 * This file is part of the libopencm3 project.
20 *
21 * Copyright (C) 2022 Oskar H. Maier <ohma@posteo.de>
22 *
23 * This library is free software: you can redistribute it and/or modify
24 * it under the terms of the GNU Lesser General Public License as published by
25 * the Free Software Foundation, either version 3 of the License, or
26 * (at your option) any later version.
27 *
28 * This library is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU Lesser General Public License for more details.
32 *
33 * You should have received a copy of the GNU Lesser General Public License
34 * along with this library. If not, see <http://www.gnu.org/licenses/>.
35 */
36
37/**@{*/
38
40
41
42/** @brief Read CORDIC result ready flag
43 *
44 * This flag is set by hardware when a CORDIC operation completes.
45 * It is automatically cleared when all results have been read.
46 *
47 * @returns Result ready flag.
48 */
51}
52
53/** @brief Set CORDIC to 32 bit argument data width.
54 *
55 * When configured this way, argument(s) are expected with 32 bit width.
56 * Two write operations are required for operations with two arguments.
57 *
58 */
60 CORDIC_CSR &= ~CORDIC_CSR_ARGSIZE;
61}
62
63/** @brief Set CORDIC to 16 bit argument data width.
64 *
65 * When configured this way, argument(s) are expected with 16 bit width.
66 * Only one 32 bit write operation is required even for operations with two arguments
67 * (in this case lower 16 bits contain argument 1, higher 16 bits contain argument 2).
68 *
69 */
72}
73
74/** @brief Set CORDIC to 32 bit result data width.
75 *
76 * When configured this way, results(s) are written with 32 bit width.
77 * Two read operations are required for operations with two results.
78 *
79 */
81 CORDIC_CSR &= ~CORDIC_CSR_RESSIZE;
82}
83
84/** @brief Set CORDIC to 16 bit result data width.
85 *
86 * When configured this way, results are written with 16 bit width.
87 * Only one 32 bit read operation is required even for operations with two results
88 * (in this case lower 16 bits contain result 1, higher 16 bits contain result 2).
89 *
90 */
93}
94
95/** @brief Set number of CORDIC arguments to one 32 bit argument or two 16 bit arguments.
96 *
97 * Use this option for CORDIC operations with only one argument and CORDIC operations
98 * with two 16 bit arguments. In this case the operation is triggered
99 * as soon as one 32bit write to the CORDIC_WDATA register occurred.
100 *
101 */
103 CORDIC_CSR &= ~CORDIC_CSR_NARGS;
104}
105
106/** @brief Set number of CORDIC arguments to two 32 bit arguments.
107 *
108 * Use this option for CORDIC operations with two 32 bit arguments.
109 * In this case the operation is triggered as soon as two 32bit
110 * writes to the CORDIC_WDATA register occurred.
111 *
112 */
115}
116
117/** @brief Set number of CORDIC results to one 32 bit result or two 16 bit results.
118 *
119 * Use this option for CORDIC operations with only one result and CORDIC operations
120 * with two 16 bit results. In this case the result ready flag is cleared and a new operation
121 * can be started as soon as one 32bit read from the CORDIC_RDATA register occurred.
122 *
123 */
125 CORDIC_CSR &= ~CORDIC_CSR_NRES;
126}
127
128/** @brief Set number of CORDIC results to two 32 bit results.
129 *
130 * Use this option for CORDIC operations with two 32 bit results.
131 * In this case the result ready flag is cleared and a new operation can be started
132 * as soon as two 32 bit reads from the CORDIC_RDATA register occurred.
133 *
134 */
137}
138
139/** @brief Enable DMA for writes to CORDIC_WDATA
140 *
141 * When enabled, the peripheral will continue to generate DMA requests
142 * when new arguments can be loaded into the CORDIC_WDATA register.
143 *
144 */
147}
148
149/** @brief Disable DMA for writes to CORDIC_WDATA
150 *
151 * When disabled, the peripheral will not generate DMA requests
152 * when new arguments can be loaded into the CORDIC_WDATA register.
153 *
154 */
156 CORDIC_CSR &= ~CORDIC_CSR_DMAWEN;
157}
158
159/** @brief Enable DMA for read from CORDIC_RDATA
160 *
161 * When enabled, the peripheral will continue to generate DMA requests
162 * when new results can be read from the CORDIC_RDATA register.
163 *
164 */
167}
168
169/** @brief Disable DMA for read from CORDIC_RDATA
170 *
171 * When disabled, the peripheral will not generate DMA requests
172 * when new results can be read from the CORDIC_RDATA register.
173 *
174 */
176 CORDIC_CSR &= ~CORDIC_CSR_DMAREN;
177}
178
179/** @brief Enable interrupt when result is ready
180 *
181 * When enabled, the peripheral will generate an interrupt
182 * when the CORDIC_CSR_RRDY flag is set.
183 *
184 */
187}
188
189/** @brief Set scaling factor for CORDIC operations
190 *
191 * For some operations, the arguments can be multiplied by a factor of 2^-n
192 * to fit in the argument range. The result must then be multiplied by 2^n.
193 * @param[in] n scaling factor of type @ref cordic_csr_scale
194 *
195 */
197 CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_SCALE_MASK) | (n << CORDIC_CSR_SCALE_SHIFT);
198}
199
200/** @brief Set precision for CORDIC operations
201 *
202 * The speed of CORDIC operations can be increased by lowering the
203 * number of iterations. This will decrease precision.
204 * @param[in] precision precision of type @ref cordic_csr_precision
205 *
206 */
207void cordic_set_precision(uint8_t precision) {
208 CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_PRECISION_MASK) | (precision << CORDIC_CSR_PRECISION_SHIFT);
209}
210
211/** @brief Set CORDIC operation type
212 *
213 * Select what operation the CORDIC peripheral performs.
214 * @param[in] function function of type @ref cordic_csr_function
215 *
216 */
217void cordic_set_function(uint8_t function) {
218 CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_FUNC_MASK) | (function << CORDIC_CSR_FUNC_SHIFT);
219}
220
221/** @brief Write single 16 bit argument
222 *
223 * Use this function to set one single 16 bit argument.
224 * The upper 16 bit of the 32 bit result register
225 * (that is the second argument) will be set to zero.
226 * @param[in] argument argument
227 *
228 */
229void cordic_write_16bit_argument(uint16_t argument) {
230 CORDIC_WDATA = argument;
231}
232
233/** @brief Write two 16 bit arguments
234 *
235 * Use this function to set write 16 bit arguments to the 32 bit CORDIC_WDATA register.
236 * @param[in] argument1 argument1
237 * @param[in] argument2 argument2
238 *
239 */
240void cordic_write_16bit_arguments(uint16_t argument1, uint16_t argument2) {
241 CORDIC_WDATA = argument2 << 16 | argument1;
242}
243
244/** @brief Write single 32 bit argument
245 *
246 * Use this function to write a 32 bit argument to the CORDIC_WDATA register.
247 * If the operation needs two arguments call cordic_set_number_of_arguments_2()
248 * before and then use this function twice to write both arguments.
249 * @param[in] argument argument
250 *
251 */
252void cordic_write_32bit_argument(uint32_t argument) {
253 CORDIC_WDATA = argument;
254}
255
256/** @brief Read single 16 bit result
257 *
258 * Use this function to read one single 16 bit result contained
259 * in the lower 16 bit of the CORDIC_RDATA register.
260 * @returns result
261 *
262 */
264 return CORDIC_RDATA;
265}
266
267/** @brief Read two 16 bit results
268 *
269 * Use this function to read both 16 bit results contained
270 * in the 32 bit CORDIC_RDATA register.
271 * @param[out] result1 First result is written to this address
272 * @param[out] result2 Second result is written to this address
273 *
274 */
275void cordic_read_16bit_results(uint16_t *result1, uint16_t *result2) {
276 uint32_t temp = CORDIC_RDATA;
277 *result1 = temp;
278 *result2 = temp >> 16;
279}
280
281/** @brief Read 32 bit result
282 *
283 * Use this function to read the 32 bit CORDIC_RDATA register.
284 * @returns result
285 *
286 */
288 return CORDIC_RDATA;
289}
290
291/** @brief Configure cordic for 16 bit cosine
292 *
293 * Configures cordic peripheral to perform 16 bit cosine operation without triggering it
294 *
295 */
303 /* scale is not applicable for cos */
304}
305
306/** @brief Configure cordic for 32 bit cosine
307 *
308 * Configures cordic peripheral to perform 32 bit cosine operation without triggering it
309 *
310 */
318 /* scale is not applicable for cos */
319}
320
321/** @brief Configure cordic for 16 bit sine
322 *
323 * Configures cordic peripheral to perform 16 bit sine operation without triggering it
324 *
325 */
333 /* scale is not applicable for sin */
334}
335
336/** @brief Configure cordic for 32 bit sine
337 *
338 * Configures cordic peripheral to perform 32 bit sine operation without triggering it
339 *
340 */
348 /* scale is not applicable for sin */
349}
350
351/** @brief Compute 16 bit cosine using CORDIC (blocking)
352 *
353 * Convenience function to calculate 32767*cos(x/32767*pi).
354 * This implementation can be sped up in most applications by configuring the peripheral only once
355 * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register.
356 * Additionally, sine and cosine are always computed in a single operation.
357 * Read the second result to obtain the other value.
358 * @param[in] x argument
359 * @returns result
360 *
361 */
362int16_t cordic_cos_16bit(int16_t x) {
364 cordic_write_16bit_arguments((uint16_t) x, 0x7FFF);
365
366 /* this while loop can be omitted but that will stall the
367 processor while it waits for the CORDIC_RDATA register */
368 while(!cordic_is_result_ready());
369
371}
372
373/** @brief Compute 16 bit cosine using CORDIC (non blocking)
374 *
375 * Convenience function to calculate 32767*cos(x/32767*pi).
376 * Result can be obtained from result register using cordic_read_16bit_result().
377 *
378 * @param[in] x argument
379 *
380 */
381void cordic_cos_16bit_async(int16_t x) {
383 cordic_write_16bit_arguments((uint16_t) x, 0x7FFF);
384}
385
386/** @brief Compute 32 bit cosine using CORDIC (blocking)
387 *
388 * Convenience function to calculate 2147483647*cos(x/2147483647*pi).
389 * This implementation can be sped up in most applications by configuring the peripheral only once
390 * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register.
391 * Additionally, sine and cosine are always computed in a single operation.
392 * Read the second result to obtain the other value.
393 * @param[in] x argument
394 * @returns result
395 *
396 */
397int32_t cordic_cos_32bit(int32_t x) {
399 cordic_write_32bit_argument((uint32_t) x);
400
401 while(!cordic_is_result_ready());
402
404}
405
406/** @brief Compute 32 bit cosine using CORDIC (non blocking)
407 *
408 * Convenience function to calculate 2147483647*cos(x/2147483647*pi).
409 * Result can be obtained from result register using cordic_read_32bit_result().
410 *
411 * @param[in] x argument
412 *
413 */
414void cordic_cos_32bit_async(int32_t x) {
416 cordic_write_32bit_argument((uint32_t) x);
417}
418
419/** @brief Compute 16 bit sine using CORDIC (blocking)
420 *
421 * Convenience function to calculate 32767*sin(x/32767*pi).
422 * This implementation can be sped up in most applications by configuring the peripheral only once
423 * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register.
424 * Additionally, sine and cosine are always computed in a single operation.
425 * Read the second result to obtain the other value.
426 * @param[in] x argument
427 * @returns result
428 *
429 */
430int16_t cordic_sin_16bit(int16_t x) {
432 cordic_write_16bit_arguments((uint16_t) x, 0x7FFF);
433
434 /* this while loop can be omitted but that will stall the
435 processor while it waits for the CORDIC_RDATA register */
436 while(!cordic_is_result_ready());
437
439}
440
441/** @brief Compute 16 bit sine using CORDIC (non blocking)
442 *
443 * Convenience function to calculate 32767*sin(x/32767*pi).
444 * Result can be obtained from result register using cordic_read_16bit_result().
445 *
446 * @param[in] x argument
447 *
448 */
449void cordic_sin_16bit_async(int16_t x) {
451 cordic_write_16bit_arguments((uint16_t) x, 0x7FFF);
452}
453
454/** @brief Compute 32 bit sine using CORDIC (blocking)
455 *
456 * Convenience function to calculate 2147483647*sin(x/2147483647*pi).
457 * This implementation can be sped up in most applications by configuring the peripheral only once
458 * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register.
459 * Additionally, sine and cosine are always computed in a single operation.
460 * Read the second result to obtain the other value.
461 * @param[in] x argument
462 * @returns result
463 *
464 */
465int32_t cordic_sin_32bit(int32_t x) {
467 cordic_write_32bit_argument((uint32_t) x);
468
469 /* this while loop can be omitted but that will stall the
470 processor while it waits for the CORDIC_RDATA register */
471 while(!cordic_is_result_ready());
472
474}
475
476/** @brief Compute 32 bit sine using CORDIC (non blocking)
477 *
478 * Convenience function to calculate 2147483647*sin(x/2147483647*pi).
479 * Result can be obtained from result register using cordic_read_32bit_result().
480 *
481 * @param[in] x argument
482 *
483 */
484void cordic_sin_32bit_async(int32_t x) {
486 cordic_write_32bit_argument((uint32_t) x);
487}
#define CORDIC_CSR_FUNC_COS
#define CORDIC_CSR_FUNC_SIN
#define CORDIC_CSR_PRECISION_ITER_28
#define CORDIC_CSR_PRECISION_ITER_20
#define CORDIC_CSR_NARGS
NARGS: Number of input data writes.
#define CORDIC_CSR_DMAWEN
DMAWEN: DMA write enable.
#define CORDIC_CSR_IEN
DMAREN: Interrupt enable.
#define CORDIC_CSR_DMAREN
DMAREN: DMA write enable.
#define CORDIC_CSR_PRECISION_SHIFT
#define CORDIC_CSR_RRDY
RRDY: result ready flag.
#define CORDIC_CSR_ARGSIZE
ARGSIZE: Width of input data.
#define CORDIC_CSR_FUNC_SHIFT
#define CORDIC_CSR_SCALE_SHIFT
#define CORDIC_CSR_RESSIZE
RESSIZE: Width of result data.
#define CORDIC_CSR_NRES
NRES: Number of result data reads.
int32_t cordic_sin_32bit(int32_t x)
Compute 32 bit sine using CORDIC (blocking)
void cordic_configure_for_cos_16bit(void)
Configure cordic for 16 bit cosine.
void cordic_write_16bit_arguments(uint16_t argument1, uint16_t argument2)
Write two 16 bit arguments.
void cordic_configure_for_sin_16bit(void)
Configure cordic for 16 bit sine.
void cordic_set_number_of_arguments_2(void)
Set number of CORDIC arguments to two 32 bit arguments.
void cordic_configure_for_cos_32bit(void)
Configure cordic for 32 bit cosine.
void cordic_set_result_width_16bit(void)
Set CORDIC to 16 bit result data width.
int16_t cordic_cos_16bit(int16_t x)
Compute 16 bit cosine using CORDIC (blocking)
void cordic_set_number_of_results_2(void)
Set number of CORDIC results to two 32 bit results.
void cordic_enable_interrupt(void)
Enable interrupt when result is ready.
int32_t cordic_cos_32bit(int32_t x)
Compute 32 bit cosine using CORDIC (blocking)
void cordic_set_precision(uint8_t precision)
Set precision for CORDIC operations.
void cordic_cos_32bit_async(int32_t x)
Compute 32 bit cosine using CORDIC (non blocking)
void cordic_disable_dma_write(void)
Disable DMA for writes to CORDIC_WDATA.
void cordic_set_scaling_factor(uint8_t n)
Set scaling factor for CORDIC operations.
bool cordic_is_result_ready(void)
Read CORDIC result ready flag.
void cordic_set_number_of_results_1(void)
Set number of CORDIC results to one 32 bit result or two 16 bit results.
int16_t cordic_sin_16bit(int16_t x)
Compute 16 bit sine using CORDIC (blocking)
void cordic_enable_dma_read(void)
Enable DMA for read from CORDIC_RDATA.
uint16_t cordic_read_16bit_result(void)
Read single 16 bit result.
void cordic_write_32bit_argument(uint32_t argument)
Write single 32 bit argument.
void cordic_read_16bit_results(uint16_t *result1, uint16_t *result2)
Read two 16 bit results.
void cordic_configure_for_sin_32bit(void)
Configure cordic for 32 bit sine.
void cordic_set_argument_width_16bit(void)
Set CORDIC to 16 bit argument data width.
void cordic_set_function(uint8_t function)
Set CORDIC operation type.
void cordic_sin_16bit_async(int16_t x)
Compute 16 bit sine using CORDIC (non blocking)
void cordic_sin_32bit_async(int32_t x)
Compute 32 bit sine using CORDIC (non blocking)
void cordic_write_16bit_argument(uint16_t argument)
Write single 16 bit argument.
void cordic_disable_dma_read(void)
Disable DMA for read from CORDIC_RDATA.
void cordic_enable_dma_write(void)
Enable DMA for writes to CORDIC_WDATA.
void cordic_set_argument_width_32bit(void)
Set CORDIC to 32 bit argument data width.
void cordic_set_number_of_arguments_1(void)
Set number of CORDIC arguments to one 32 bit argument or two 16 bit arguments.
void cordic_cos_16bit_async(int16_t x)
Compute 16 bit cosine using CORDIC (non blocking)
void cordic_set_result_width_32bit(void)
Set CORDIC to 32 bit result data width.
uint32_t cordic_read_32bit_result(void)
Read 32 bit result.
#define CORDIC_WDATA
CORDIC argument register.
#define CORDIC_RDATA
CORDIC result register.
#define CORDIC_CSR
CORDIC control/status register.