1 /*******************************************************************
2 Components for embedded applications builded for
3 laboratory and medical instruments firmware
5 firmware.c - multi axis motion controller comprocesor
6 firmware for FPGA tumble CPU of lx-rocon system
8 (C) 2001-2014 by Pavel Pisa pisa@cmp.felk.cvut.cz
9 (C) 2002-2014 by PiKRON Ltd. http://www.pikron.com
11 This file can be used and copied according to next
13 - GPL - GNU Public License
14 - other license provided by project originators
16 *******************************************************************/
18 #define SUPPRESS_CONDITIONALS 1
19 #undef COMPUTE_PHASE_SECTOR
21 #define PXMCC_CURADC_CHANNELS 3
24 #include "tumbl_addr.h"
26 /* k3 = math.sqrt(3) / 2 */
28 #define CONST16_K3 56756
32 #define RECI16_K3 75674
34 /* 1 / (2 * k3) * 65536 */
35 #define RECI16_2_K3 37837
37 typedef struct pxmcc_axis_data_t {
39 uint32_t pwm_dq; /* D and Q components of PWM (pwm_d << 16) | (pwm_q) & 0xffff */
40 uint32_t cur_dq; /* D and Q components current (cur_d << 16) | (cur_q) & 0xffff */
41 uint32_t ptindx; /* index into phase table / irc in the cycle */
42 uint32_t ptirc; /* IRC count per phase table */
43 uint32_t ptreci; /* Reciprocal value of ptirc * 63356 */
44 uint32_t ptofs; /* offset between table and IRC counter */
57 typedef struct pxmcc_curadc_data_t {
60 uint16_t siroladc_offs;
61 uint16_t siroladc_last;
62 } pxmcc_curadc_data_t;
64 pxmcc_axis_data_t pxmcc_axis[1];
66 pxmcc_curadc_data_t pxmcc_curadc[PXMCC_CURADC_CHANNELS];
68 void init_defvals(void)
76 void find_sin_lat(void)
79 register uint32_t a0, a1, a2, a3, a4, a5;
81 *FPGA_FNCAPPROX_SIN = 0;
83 for (i = 0; i < 20; i++)
84 asm volatile("": : : "memory");
86 *FPGA_FNCAPPROX_SIN = 0x40000000;
87 a0 = *FPGA_FNCAPPROX_SIN;
88 a1 = *FPGA_FNCAPPROX_SIN;
89 a2 = *FPGA_FNCAPPROX_SIN;
90 a3 = *FPGA_FNCAPPROX_SIN;
91 a4 = *FPGA_FNCAPPROX_SIN;
92 a5 = *FPGA_FNCAPPROX_SIN;
93 asm volatile("": : : "memory");
109 uint32_t last_rx_done_sqn = 0;
110 pxmcc_axis_data_t *pxmcc = pxmcc_axis;
114 /*pxmcc->ptofs = *FPGA_IRC0;*/
116 pxmcc->ptreci = 4294967; /* (1LL<<32)*ptper/ptirc */
119 pxmcc->pwm_cycle = 2500;
120 pxmcc_curadc[0].siroladc_offs = 0x0c17;
121 pxmcc_curadc[1].siroladc_offs = 0x0c66;
122 pxmcc_curadc[2].siroladc_offs = 0x0c66;
124 asm volatile("": : : "memory");
131 uint32_t irc = *FPGA_IRC0;
132 uint32_t ofs = pxmcc->ptofs;
133 uint32_t per = pxmcc->ptirc;
139 if ((uint32_t)pti >= per) {
150 pta = pti * pxmcc->ptreci;
152 *FPGA_FNCAPPROX_SIN = pta;
154 dummy = *FPGA_FNCAPPROX_SIN;
155 dummy = *FPGA_FNCAPPROX_SIN;
156 dummy = *FPGA_FNCAPPROX_SIN;
157 pxmcc->ptsin = *FPGA_FNCAPPROX_SIN;
158 dummy = *FPGA_FNCAPPROX_COS;
159 pxmcc->ptcos = *FPGA_FNCAPPROX_COS;
164 int32_t pwm_bet_div_2_k3;
170 #if defined(COMPUTE_PHASE_SECTOR) || !defined(SUPPRESS_CONDITIONALS)
172 #endif /*COMPUTE_PHASE_SECTOR*/
174 pwm_d = (volatile uint32_t)pxmcc->pwm_dq;
175 pwm_q = (pwm_d << 16) >> 16;
178 pwm_alp = pwm_d * pxmcc->ptcos - pwm_q * pxmcc->ptsin;
179 pwm_bet = pwm_d * pxmcc->ptsin + pwm_q * pxmcc->ptcos;
181 pwm_bet_div_2_k3 = RECI16_2_K3 * (pwm_bet >> 16);
183 #ifndef SUPPRESS_CONDITIONALS
186 /* pwm_bet > 2 * k3 * pwm_alp */
187 if (pwm_bet_div_2_k3 > pwm_alp)
192 /* -pwm_bet > 2 * k3 * pwm_alp */
193 if (pwm_bet_div_2_k3 < -pwm_alp)
199 /* pwm_bet > -2 * k3 * pwm_alp */
200 if (pwm_bet_div_2_k3 > -pwm_alp)
205 /* pwm_bet > 2 * k3 * u_alp */
206 if (pwm_bet_div_2_k3 > pwm_alp)
212 /* pwm1 = pwm_alp + 1.0/(2.0*k3) * pwm_bet */
213 pwm1 = (pwm_alp + pwm_bet_div_2_k3) >> 16;
214 /* pwm2 = 1/k3 * pwm_bet */
215 pwm2 = pwm_bet_div_2_k3 >> 15;
217 } else if (phs <= 3) {
219 /* pwm2 = 1.0/(2.0*k3) * pwm_bet - pwm_alp */
220 pwm2 = (pwm_bet_div_2_k3 - pwm_alp) >> 16;
221 /* pwm3 = -1.0/(2.0*k3) * pwm_bet - pwm_alp */
222 pwm3 = (-pwm_bet_div_2_k3 - pwm_alp) >>16;
224 /* pwm1 = pwm_alp - 1.0/(2.0*k3) * pwm_bet */
225 pwm1 = (pwm_alp - pwm_bet_div_2_k3) >>16;
227 /* pwm3 = -1/k3 * pwm_bet */
228 pwm3 = -pwm_bet_div_2_k3 >> 15;
230 #else /*SUPPRESS_CONDITIONALS*/
232 int32_t alp_m_bet_d2k3;
233 uint32_t state23_msk;
234 uint32_t pwm23_shift;
235 uint32_t bet_sgn = pwm_bet >> 31;
236 uint32_t alp_sgn = pwm_alp >> 31;
237 #ifdef COMPUTE_PHASE_SECTOR
238 uint32_t bet_sgn_cpl = ~bet_sgn;
239 #endif /*COMPUTE_PHASE_SECTOR*/
241 alp_m_bet_d2k3 = (alp_sgn ^ pwm_alp) - (bet_sgn ^ (pwm_bet_div_2_k3 + bet_sgn));
242 alp_m_bet_d2k3 = alp_m_bet_d2k3 >> 31;
244 state23_msk = alp_sgn & ~alp_m_bet_d2k3;
249 * 0 0 -1 0 -> 1 (001)
250 * -1 0 -1 0 -> 1 (001)
251 * -1 0 0 -1 -> 2 (010)
252 * -1 -1 0 -1 -> 3 (011)
253 * -1 -1 -1 0 -> 4 (100)
254 * 0 -1 -1 0 -> 4 (100)
255 * 0 -1 0 0 -> 5 (101)
258 #ifdef COMPUTE_PHASE_SECTOR
259 phs = (bet_sgn & 5) + (bet_sgn_cpl ^ ((alp_m_bet_d2k3 + 2 * state23_msk) + bet_sgn_cpl));
260 #endif /*COMPUTE_PHASE_SECTOR*/
262 pwm1 = pwm_alp & state23_msk;
263 pwm2 = pwm_bet_div_2_k3 - pwm1;
264 pwm3 = -pwm_bet_div_2_k3 - pwm1;
265 pwm2 &= (~bet_sgn | state23_msk);
266 pwm3 &= (bet_sgn | state23_msk);
267 pwm1 = pwm_alp + pwm2 + pwm3;
268 pwm1 &= ~state23_msk;
270 pwm23_shift = 15 - state23_msk;
271 pwm2 >>= pwm23_shift;
272 pwm3 >>= pwm23_shift;
274 #endif /*SUPPRESS_CONDITIONALS*/
276 #ifdef COMPUTE_PHASE_SECTOR
278 #endif /*COMPUTE_PHASE_SECTOR*/
280 asm volatile("": : : "memory");
282 *FPGA_LX_MASTER_TX_PWM0 = pwm2 | 0x4000;
283 *FPGA_LX_MASTER_TX_PWM1 = pwm3 | 0x4000;
284 *FPGA_LX_MASTER_TX_PWM2 = pwm1 | 0x4000;
287 asm volatile("": : : "memory");
290 uint32_t idlecnt = 0;
293 sqn = *FPGA_LX_MASTER_RX_DDIV;
295 } while (sqn == last_rx_done_sqn);
296 pxmcc->act_idle = idlecnt;
297 if (((idlecnt < pxmcc->min_idle) ||
298 (pxmcc->min_idle == 0)) &&
300 pxmcc->min_idle = idlecnt;
302 last_rx_done_sqn = sqn;
303 pxmcc->rx_done_sqn = last_rx_done_sqn;
304 asm volatile("": : : "memory");
308 pxmcc_curadc_data_t *curadc = pxmcc_curadc;
309 volatile uint32_t *siroladc = FPGA_LX_MASTER_RX_ADC0;
312 for (i = 0; i < PXMCC_CURADC_CHANNELS; ) {
315 curadc->cur_val = val - curadc->siroladc_last
316 - curadc->siroladc_offs;
317 curadc->siroladc_last = val;
318 curadc->reserved1=0x11aa;
323 /* additional 3 required for 7 -> 8 change */
341 uint32_t curmult_idx;
343 #if defined(COMPUTE_PHASE_SECTOR) || !defined(SUPPRESS_CONDITIONALS)
345 #ifdef COMPUTE_PHASE_SECTOR
347 #endif /*COMPUTE_PHASE_SECTOR*/
348 #endif /*COMPUTE_PHASE_SECTOR*/
350 pwm[1] = *FPGA_LX_MASTER_TX_PWM0 & 0x3fff;
351 pwm[2] = *FPGA_LX_MASTER_TX_PWM1 & 0x3fff;
352 pwm[0] = *FPGA_LX_MASTER_TX_PWM2 & 0x3fff;
354 cur[1] = pxmcc_curadc[0].cur_val;
355 cur[2] = pxmcc_curadc[1].cur_val;
356 cur[0] = pxmcc_curadc[2].cur_val;
362 #ifndef SUPPRESS_CONDITIONALS
363 #ifndef COMPUTE_PHASE_SECTOR
367 else if (pwm1 > pwm3)
374 else if (pwm1 < pwm3)
378 #endif /*COMPUTE_PHASE_SECTOR*/
380 curmult_idx = (0x00102102 >> (4 * phs)) & 3;
381 pwm_reci = pxmcc->pwm_cycle - pwm[curmult_idx];
382 pwm_reci = (pxmcc->pwm_cycle << 16) / pwm_reci;
383 cur[curmult_idx] = (int32_t)(pwm_reci * cur[curmult_idx]) >> 16;
389 if ((phs == 5) || (phs == 0))
390 cur_alp = -(cur2 + cur3);
394 if ((phs == 5) || (phs == 0))
395 cur_bet = cur2 - cur3;
396 else if ((phs == 3) || (phs == 4))
397 cur_bet = 2 * cur2 + cur1;
399 cur_bet = -(2 * cur3 + cur1);
400 #else /*SUPPRESS_CONDITIONALS*/
403 * u1>u2 u2>u3 u1>u3 cm
404 * 0 1 1 -> 1 (1, 0, 2) 2
405 * 0 1 0 -> 2 (1, 2, 0) 0
406 * 0 0 0 -> 3 (2, 1, 0) 1
407 * 1 0 0 -> 4 (2, 0, 1) 2
408 * 1 0 1 -> 5 (0, 2, 1) 0
409 * 1 1 1 -> 0 (0, 1, 2) 1
412 uint32_t u1gtu2 = (int32_t)(pwm2 - pwm1) >> 31;
413 uint32_t u1gtu3 = (int32_t)(pwm3 - pwm1) >> 31;
414 uint32_t u2gtu3 = (int32_t)(pwm3 - pwm2) >> 31;
415 uint32_t state50_msk = u1gtu2 & u1gtu3;
416 uint32_t pwm_reci_bits;
418 curmult_idx = (((u1gtu3 ^ u1gtu2) | 1) ^ u2gtu3 ^ u1gtu2) & 3;
419 pwm_reci = pxmcc->pwm_cycle - pwm[curmult_idx];
421 pwm_reci_bits = __builtin_clzl(pwm_reci);
423 asm("clz %0,%1\n":"=r"(pwm_reci_bits):"r"(pwm_reci));
425 pwm_reci <<= pwm_reci_bits;
426 *FPGA_FNCAPPROX_RECI = pwm_reci;
427 dummy = *FPGA_FNCAPPROX_RECI;
428 dummy = *FPGA_FNCAPPROX_RECI;
429 dummy = *FPGA_FNCAPPROX_RECI;
430 pwm_reci = *FPGA_FNCAPPROX_RECI;
432 pwm_reci *= pxmcc->pwm_cycle;
433 pwm_reci >>= 30 - pwm_reci_bits;
434 cur[curmult_idx] = (int32_t)(pwm_reci * cur[curmult_idx]) >> 16;
440 cur_alp = -(cur2 + cur3); /* 5 0 */
441 cur_alp &= state50_msk; /* 1 2 3 4 */
442 cur_alp |= cur1 & ~state50_msk;
444 cur_bet = (-2 * cur3 - cur1) & u2gtu3; /* 1 2 */
445 cur_bet |= (2 * cur2 + cur1) & ~u2gtu3; /* 3 4 */
446 cur_bet &= ~state50_msk;
447 cur_bet |= (cur2 - cur3) & state50_msk; /* 5 0 */
449 #endif /*SUPPRESS_CONDITIONALS*/
454 cur_bet *= CONST16_K3;
457 cur_d = cur_alp * pxmcc->ptcos + cur_bet * pxmcc->ptsin;
458 cur_q = -cur_alp * pxmcc->ptsin + cur_bet * pxmcc->ptcos;
460 pxmcc->cur_dq = (cur_d & 0xffff0000) | ((cur_q >> 16) & 0xffff);
462 pxmcc->cur_d_cum = ((pxmcc->cur_d_cum + cur_d) & ~0xff) |
463 (last_rx_done_sqn & 0x1f);
464 pxmcc->cur_q_cum = ((pxmcc->cur_q_cum + cur_q) & ~0xff) |
465 (last_rx_done_sqn & 0x1f);