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 */
55 typedef struct pxmcc_curadc_data_t {
58 uint16_t siroladc_offs;
59 uint16_t siroladc_last;
60 } pxmcc_curadc_data_t;
62 pxmcc_axis_data_t pxmcc_axis[1];
64 pxmcc_curadc_data_t pxmcc_curadc[PXMCC_CURADC_CHANNELS];
66 void init_defvals(void)
74 void find_sin_lat(void)
77 register uint32_t a0, a1, a2, a3, a4, a5;
79 *FPGA_FNCAPPROX_SIN = 0;
81 for (i = 0; i < 20; i++)
82 asm volatile("": : : "memory");
84 *FPGA_FNCAPPROX_SIN = 0x40000000;
85 a0 = *FPGA_FNCAPPROX_SIN;
86 a1 = *FPGA_FNCAPPROX_SIN;
87 a2 = *FPGA_FNCAPPROX_SIN;
88 a3 = *FPGA_FNCAPPROX_SIN;
89 a4 = *FPGA_FNCAPPROX_SIN;
90 a5 = *FPGA_FNCAPPROX_SIN;
91 asm volatile("": : : "memory");
107 uint32_t last_rx_done_sqn = 0;
108 pxmcc_axis_data_t *pxmcc = pxmcc_axis;
112 /*pxmcc->ptofs = *FPGA_IRC0;*/
114 pxmcc->ptreci = 4294967; /* (1LL<<32)*ptper/ptirc */
117 pxmcc->pwm_cycle = 2500;
118 pxmcc_curadc[0].siroladc_offs = 0x0c17;
119 pxmcc_curadc[1].siroladc_offs = 0x0c66;
120 pxmcc_curadc[2].siroladc_offs = 0x0c66;
122 asm volatile("": : : "memory");
129 uint32_t irc = *FPGA_IRC0;
130 uint32_t ofs = pxmcc->ptofs;
131 uint32_t per = pxmcc->ptirc;
137 if ((uint32_t)pti >= per) {
148 pta = pti * pxmcc->ptreci;
150 *FPGA_FNCAPPROX_SIN = pta;
152 dummy = *FPGA_FNCAPPROX_SIN;
153 dummy = *FPGA_FNCAPPROX_SIN;
154 dummy = *FPGA_FNCAPPROX_SIN;
155 pxmcc->ptsin = *FPGA_FNCAPPROX_SIN;
156 dummy = *FPGA_FNCAPPROX_COS;
157 pxmcc->ptcos = *FPGA_FNCAPPROX_COS;
162 int32_t pwm_bet_div_2_k3;
168 #if defined(COMPUTE_PHASE_SECTOR) || !defined(SUPPRESS_CONDITIONALS)
170 #endif /*COMPUTE_PHASE_SECTOR*/
172 pwm_d = (volatile uint32_t)pxmcc->pwm_dq;
173 pwm_q = (pwm_d << 16) >> 16;
176 pwm_alp = pwm_d * pxmcc->ptcos - pwm_q * pxmcc->ptsin;
177 pwm_bet = pwm_d * pxmcc->ptsin + pwm_q * pxmcc->ptcos;
179 pwm_bet_div_2_k3 = RECI16_2_K3 * (pwm_bet >> 16);
181 #ifndef SUPPRESS_CONDITIONALS
184 /* pwm_bet > 2 * k3 * pwm_alp */
185 if (pwm_bet_div_2_k3 > pwm_alp)
190 /* -pwm_bet > 2 * k3 * pwm_alp */
191 if (pwm_bet_div_2_k3 < -pwm_alp)
197 /* pwm_bet > -2 * k3 * pwm_alp */
198 if (pwm_bet_div_2_k3 > -pwm_alp)
203 /* pwm_bet > 2 * k3 * u_alp */
204 if (pwm_bet_div_2_k3 > pwm_alp)
210 /* pwm1 = pwm_alp + 1.0/(2.0*k3) * pwm_bet */
211 pwm1 = (pwm_alp + pwm_bet_div_2_k3) >> 16;
212 /* pwm2 = 1/k3 * pwm_bet */
213 pwm2 = pwm_bet_div_2_k3 >> 15;
215 } else if (phs <= 3) {
217 /* pwm2 = 1.0/(2.0*k3) * pwm_bet - pwm_alp */
218 pwm2 = (pwm_bet_div_2_k3 - pwm_alp) >> 16;
219 /* pwm3 = -1.0/(2.0*k3) * pwm_bet - pwm_alp */
220 pwm3 = (-pwm_bet_div_2_k3 - pwm_alp) >>16;
222 /* pwm1 = pwm_alp - 1.0/(2.0*k3) * pwm_bet */
223 pwm1 = (pwm_alp - pwm_bet_div_2_k3) >>16;
225 /* pwm3 = -1/k3 * pwm_bet */
226 pwm3 = -pwm_bet_div_2_k3 >> 15;
228 #else /*SUPPRESS_CONDITIONALS*/
230 int32_t alp_m_bet_d2k3;
231 uint32_t state23_msk;
232 uint32_t pwm23_shift;
233 uint32_t bet_sgn = pwm_bet >> 31;
234 uint32_t alp_sgn = pwm_alp >> 31;
235 #ifdef COMPUTE_PHASE_SECTOR
236 uint32_t bet_sgn_cpl = ~bet_sgn;
237 #endif /*COMPUTE_PHASE_SECTOR*/
239 alp_m_bet_d2k3 = (alp_sgn ^ pwm_alp) - (bet_sgn ^ (pwm_bet_div_2_k3 + bet_sgn));
240 alp_m_bet_d2k3 = alp_m_bet_d2k3 >> 31;
242 state23_msk = alp_sgn & ~alp_m_bet_d2k3;
247 * 0 0 -1 0 -> 1 (001)
248 * -1 0 -1 0 -> 1 (001)
249 * -1 0 0 -1 -> 2 (010)
250 * -1 -1 0 -1 -> 3 (011)
251 * -1 -1 -1 0 -> 4 (100)
252 * 0 -1 -1 0 -> 4 (100)
253 * 0 -1 0 0 -> 5 (101)
256 #ifdef COMPUTE_PHASE_SECTOR
257 phs = (bet_sgn & 5) + (bet_sgn_cpl ^ ((alp_m_bet_d2k3 + 2 * state23_msk) + bet_sgn_cpl));
258 #endif /*COMPUTE_PHASE_SECTOR*/
260 pwm1 = pwm_alp & state23_msk;
261 pwm2 = pwm_bet_div_2_k3 - pwm1;
262 pwm3 = -pwm_bet_div_2_k3 - pwm1;
263 pwm2 &= (~bet_sgn | state23_msk);
264 pwm3 &= (bet_sgn | state23_msk);
265 pwm1 = pwm_alp + pwm2 + pwm3;
266 pwm1 &= ~state23_msk;
268 pwm23_shift = 15 - state23_msk;
269 pwm2 >>= pwm23_shift;
270 pwm3 >>= pwm23_shift;
272 #endif /*SUPPRESS_CONDITIONALS*/
274 #ifdef COMPUTE_PHASE_SECTOR
276 #endif /*COMPUTE_PHASE_SECTOR*/
278 asm volatile("": : : "memory");
280 *FPGA_LX_MASTER_TX_PWM0 = pwm2 | 0x4000;
281 *FPGA_LX_MASTER_TX_PWM1 = pwm3 | 0x4000;
282 *FPGA_LX_MASTER_TX_PWM2 = pwm1 | 0x4000;
285 asm volatile("": : : "memory");
288 uint32_t idlecnt = 0;
291 sqn = *FPGA_LX_MASTER_RX_DDIV;
293 } while (sqn == last_rx_done_sqn);
294 pxmcc->act_idle = idlecnt;
295 if (((idlecnt < pxmcc->min_idle) ||
296 (pxmcc->min_idle == 0)) &&
298 pxmcc->min_idle = idlecnt;
300 last_rx_done_sqn = sqn;
301 pxmcc->rx_done_sqn = last_rx_done_sqn;
302 asm volatile("": : : "memory");
306 pxmcc_curadc_data_t *curadc = pxmcc_curadc;
307 volatile uint32_t *siroladc = FPGA_LX_MASTER_RX_ADC0;
310 for (i = 0; i < PXMCC_CURADC_CHANNELS; ) {
313 curadc->cur_val = val - curadc->siroladc_last
314 - curadc->siroladc_offs;
315 curadc->siroladc_last = val;
316 curadc->reserved1=0x11aa;
321 /* additional 3 required for 7 -> 8 change */
339 uint32_t curmult_idx;
341 #if defined(COMPUTE_PHASE_SECTOR) || !defined(SUPPRESS_CONDITIONALS)
343 #ifdef COMPUTE_PHASE_SECTOR
345 #endif /*COMPUTE_PHASE_SECTOR*/
346 #endif /*COMPUTE_PHASE_SECTOR*/
348 pwm[1] = *FPGA_LX_MASTER_TX_PWM0 & 0x3fff;
349 pwm[2] = *FPGA_LX_MASTER_TX_PWM1 & 0x3fff;
350 pwm[0] = *FPGA_LX_MASTER_TX_PWM2 & 0x3fff;
352 cur[1] = pxmcc_curadc[0].cur_val;
353 cur[2] = pxmcc_curadc[1].cur_val;
354 cur[0] = pxmcc_curadc[2].cur_val;
360 #ifndef SUPPRESS_CONDITIONALS
361 #ifndef COMPUTE_PHASE_SECTOR
365 else if (pwm1 > pwm3)
372 else if (pwm1 < pwm3)
376 #endif /*COMPUTE_PHASE_SECTOR*/
378 curmult_idx = (0x00102102 >> (4 * phs)) & 3;
379 pwm_reci = pxmcc->pwm_cycle - pwm[curmult_idx];
380 pwm_reci = (pxmcc->pwm_cycle << 16) / pwm_reci;
381 cur[curmult_idx] = (int32_t)(pwm_reci * cur[curmult_idx]) >> 16;
387 if ((phs == 5) || (phs == 0))
388 cur_alp = -(cur2 + cur3);
392 if ((phs == 5) || (phs == 0))
393 cur_bet = cur2 - cur3;
394 else if ((phs == 3) || (phs == 4))
395 cur_bet = 2 * cur2 + cur1;
397 cur_bet = -(2 * cur3 + cur1);
398 #else /*SUPPRESS_CONDITIONALS*/
401 * u1>u2 u2>u3 u1>u3 cm
402 * 0 1 1 -> 1 (1, 0, 2) 2
403 * 0 1 0 -> 2 (1, 2, 0) 0
404 * 0 0 0 -> 3 (2, 1, 0) 1
405 * 1 0 0 -> 4 (2, 0, 1) 2
406 * 1 0 1 -> 5 (0, 2, 1) 0
407 * 1 1 1 -> 0 (0, 1, 2) 1
410 uint32_t u1gtu2 = (int32_t)(pwm2 - pwm1) >> 31;
411 uint32_t u1gtu3 = (int32_t)(pwm3 - pwm1) >> 31;
412 uint32_t u2gtu3 = (int32_t)(pwm3 - pwm2) >> 31;
413 uint32_t state50_msk = u1gtu2 & u1gtu3;
414 uint32_t pwm_reci_bits;
416 curmult_idx = (((u1gtu3 ^ u1gtu2) | 1) ^ u2gtu3 ^ u1gtu2) & 3;
417 pwm_reci = pxmcc->pwm_cycle - pwm[curmult_idx];
419 pwm_reci_bits = __builtin_clzl(pwm_reci);
421 asm("clz %0,%1\n":"=r"(pwm_reci_bits):"r"(pwm_reci));
423 pwm_reci <<= pwm_reci_bits;
424 *FPGA_FNCAPPROX_RECI = pwm_reci;
425 dummy = *FPGA_FNCAPPROX_RECI;
426 dummy = *FPGA_FNCAPPROX_RECI;
427 dummy = *FPGA_FNCAPPROX_RECI;
428 pwm_reci = *FPGA_FNCAPPROX_RECI;
430 pwm_reci *= pxmcc->pwm_cycle;
431 pwm_reci >>= 30 - pwm_reci_bits;
432 cur[curmult_idx] = (int32_t)(pwm_reci * cur[curmult_idx]) >> 16;
438 cur_alp = -(cur2 + cur3); /* 5 0 */
439 cur_alp &= state50_msk; /* 1 2 3 4 */
440 cur_alp |= cur1 & ~state50_msk;
442 cur_bet = (-2 * cur3 - cur1) & u2gtu3; /* 1 2 */
443 cur_bet |= (2 * cur2 + cur1) & ~u2gtu3; /* 3 4 */
444 cur_bet &= ~state50_msk;
445 cur_bet |= (cur2 - cur3) & state50_msk; /* 5 0 */
447 #endif /*SUPPRESS_CONDITIONALS*/
452 cur_bet *= CONST16_K3;
455 cur_d = cur_alp * pxmcc->ptcos + cur_bet * pxmcc->ptsin;
456 cur_q = -cur_alp * pxmcc->ptsin + cur_bet * pxmcc->ptcos;
458 pxmcc->cur_dq = (cur_d & 0xffff0000) | ((cur_q >> 16) & 0xffff);