1 /*******************************************************************
2 Motion and Robotic System (MARS) aplication components.
4 appl_pxmc.c - position controller subsystem core generic
5 and LP_MPW1 hardware specific support
7 Copyright (C) 2001-2013 by Pavel Pisa - originator
9 (C) 2001-2013 by PiKRON Ltd. - originator
12 This file can be used and copied according to next
14 - GPL - GNU Public License
15 - other license provided by project originators
17 *******************************************************************/
20 #include <system_def.h>
22 #include <pxmc_lpc_qei.h>
23 #include <pxmc_internal.h>
24 #include <pxmc_inp_common.h>
25 #include <pxmc_gen_info.h>
27 #include <hal_machperiph.h>
33 #include "appl_defs.h"
34 #include "appl_fpga.h"
35 #include "pxmcc_types.h"
36 #include "pxmcc_interface.h"
38 #define PXMC_AXIS_MODE_BLDC_PXMCC (PXMC_AXIS_MODE_BLDC + 1)
40 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
41 unsigned long index_irc, int diff2err);
43 #ifndef pxmc_fast_tick_time
44 #define pxmc_fast_tick_time() (LPC_TIM0->TC)
47 #define PXML_MAIN_CNT 8
49 #define PXMC_WITH_PT_ZIC 1
50 #define PXMC_PT_ZIC_MASK 0x8000
52 #define LPCPWM1_FREQ 20000
54 #define HAL_ERR_SENSITIVITY 20
55 #define HAL_ERR_MAX_COUNT 5
57 #define LXPWR_WITH_SIROLADC 1
59 #define LX_MASTER_DATA_OFFS 8
61 #define PXMC_LXPWR_PWM_CYCLE 2500
63 unsigned pxmc_rocon_pwm_magnitude = PXMC_LXPWR_PWM_CYCLE;
65 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
66 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
68 const uint8_t onesin10bits[1024]={
69 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
70 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
71 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
72 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
73 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
74 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
75 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
76 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
77 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
78 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
79 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
80 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
81 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
82 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
83 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
84 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
85 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
86 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
87 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
88 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
89 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
90 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
91 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
92 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
93 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
94 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
95 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
96 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
97 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
98 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
99 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
100 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10
104 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
106 int chan=mcs->pxms_inp_info;
110 /* read position from hardware */
111 irc = fpga_irc[chan]->count;
112 irc += pxmc_rocon_irc_offset[chan];
113 pos = irc << PXMC_SUBDIV(mcs);
114 mcs->pxms_as = pos - mcs->pxms_ap;
117 /* Running of the motor commutator */
118 if (mcs->pxms_flg & PXMS_PTI_m)
119 pxmc_irc_16bit_commindx(mcs, irc);
125 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
130 int chan=mcs->pxms_inp_info;
132 irc_state = *fpga_irc_state[chan];
134 mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
135 (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
137 filt = pxmc_rocon_mark_filt[chan];
138 filt = (filt << 1) | mark;
139 pxmc_rocon_mark_filt[chan] = filt;
141 return onesin10bits[filt & 0x03ff];
145 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
149 int chan=mcs->pxms_inp_info;
151 irc_state = *fpga_irc_state[chan];
152 *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
154 index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
160 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
162 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
164 mcs->pxms_ptofs += irc_diff;
166 mcs->pxms_ap += pos_diff;
167 mcs->pxms_rp += pos_diff;
172 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
174 int chan=mcs->pxms_inp_info;
178 irc_offset = -fpga_irc[chan]->count_index;
179 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
180 pxmc_rocon_irc_offset[chan] = irc_offset;
181 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
185 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
187 int chan=mcs->pxms_inp_info;
191 irc_offset = -fpga_irc[chan]->count;
192 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
193 pxmc_rocon_irc_offset[chan] = irc_offset;
194 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
198 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
200 int chan=mcs->pxms_inp_info;
204 irc = fpga_irc[chan]->count;
205 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
207 irc = pos_diff >> PXMC_SUBDIV(mcs);
209 /* Adjust phase table alignemt to modified IRC readout */
210 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
212 pxmc_rocon_irc_offset[chan] = irc;
217 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
219 int chan=mcs->pxms_inp_info;
223 if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
226 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
227 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
229 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
232 uint32_t pxmc_rocon_receiver_dummy_reg;
234 static inline volatile uint32_t *
235 pxmc_rocon_receiver_chan2reg(unsigned chan)
237 volatile uint32_t *rec_reg;
240 return &pxmc_rocon_receiver_dummy_reg;
242 rec_reg = fpga_lx_master_receiver_base;
244 #ifdef LXPWR_WITH_SIROLADC
245 rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) * 3 + chan * 2;
246 #else /*LXPWR_WITH_SIROLADC*/
247 rec_reg += LX_MASTER_DATA_OFFS + chan;
248 #endif /*LXPWR_WITH_SIROLADC*/
254 pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
257 volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
258 int chan = mcs->pxms_out_info;
261 #ifdef LXPWR_WITH_SIROLADC
263 #else /*LXPWR_WITH_SIROLADC*/
265 #endif /*LXPWR_WITH_SIROLADC*/
267 rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
268 rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
269 rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
271 h = (rec_reg_a[hal_offs] >> 14) & 1;
272 h |= (rec_reg_b[hal_offs] >> 13) & 2;
273 h |= (rec_reg_c[hal_offs] >> 12) & 4;
275 /* return 3 bits corresponding to the HAL senzor input */
280 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
292 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
305 uint32_t pxmc_rocon_pwm_dummy_reg;
307 static inline volatile uint32_t *
308 pxmc_rocon_pwm_chan2reg(unsigned chan)
310 volatile uint32_t *pwm_reg;
313 return &pxmc_rocon_pwm_dummy_reg;
315 pwm_reg = fpga_lx_master_transmitter_base;
317 #ifdef LXPWR_WITH_SIROLADC
318 pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) + chan;
319 #else /*LXPWR_WITH_SIROLADC*/
320 pwm_reg += LX_MASTER_DATA_OFFS + chan;
321 #endif /*LXPWR_WITH_SIROLADC*/
327 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
328 * @mcs: Motion controller state information
330 /*static*/ inline void
331 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
333 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
334 int chan = mcs->pxms_out_info;
336 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
337 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
338 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
346 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
348 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
350 pxmc_set_errno(mcs, PXMS_E_HAL);
355 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
359 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
360 * @mcs: Motion controller state information
363 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
365 typeof(mcs->pxms_ptvang) ptvang;
367 unsigned char hal_pos;
375 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
376 (mcs->pxms_flg & PXMS_PRA_m))
379 short ptirc = mcs->pxms_ptirc;
380 short divisor = mcs->pxms_ptper * 6;
383 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
388 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
390 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
392 pxmc_set_flag(mcs, PXMS_PTI_b);
393 pxmc_set_flag(mcs, PXMS_PHA_b);
398 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
403 pxmc_rocon_process_hal_error(mcs);
407 if (mcs->pxms_halerc)
410 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
412 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
414 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
416 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
418 if ((ptindx > ptindx_prev + ptirc / 2) ||
419 (ptindx_prev > ptindx + ptirc / 2))
421 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
428 ptindx = (ptindx_prev + ptindx) / 2;
431 mcs->pxms_ptindx = ptindx;
433 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
435 pxmc_set_flag(mcs, PXMS_PTI_b);
436 pxmc_clear_flag(mcs, PXMS_PRA_b);
440 if (!(mcs->pxms_flg & PXMS_PTI_m))
441 mcs->pxms_ptindx = ptindx;
444 /* if phase table position to mask is know do fine phase table alignment */
445 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
447 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
449 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
451 pxmc_set_flag(mcs, PXMS_PTI_b);
452 pxmc_set_flag(mcs, PXMS_PHA_b);
456 mcs->pxms_hal = hal_pos;
462 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
463 /* FIXME - check winding current against limit */
464 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
468 ptvang = mcs->pxms_ptvang;
472 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
476 indx = mcs->pxms_ptindx;
478 /* tuning of magnetic field/voltage advance angle */
479 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
484 /* Generating direction of stator mag. field for backward torque */
487 if ((indx -= ptvang) < 0)
488 indx += mcs->pxms_ptirc;
492 /* Generating direction of stator mag. field for forward torque */
493 if ((indx += ptvang) >= mcs->pxms_ptirc)
494 indx -= mcs->pxms_ptirc;
497 if (mcs->pxms_ptscale_mult)
498 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
500 pwm1 = mcs->pxms_ptptr1[indx];
501 pwm2 = mcs->pxms_ptptr2[indx];
502 pwm3 = mcs->pxms_ptptr3[indx];
504 #ifdef PXMC_WITH_PT_ZIC
505 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
507 pwm1 &= ~PXMC_PT_ZIC_MASK;
508 pwm2 &= ~PXMC_PT_ZIC_MASK;
509 pwm3 &= ~PXMC_PT_ZIC_MASK;
511 #endif /*PXMC_WITH_PT_ZIC*/
513 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
514 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
516 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
517 if (pwm1 & PXMC_PT_ZIC_MASK)
520 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
521 if (pwm2 & PXMC_PT_ZIC_MASK)
524 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
525 if (pwm3 & PXMC_PT_ZIC_MASK)
528 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
530 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
534 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
541 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
542 * @mcs: Motion controller state information
544 /*static*/ inline void
545 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
547 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
548 int chan = mcs->pxms_out_info;
550 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
551 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
552 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
553 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
556 *pwm_reg_bp = pwm2 | 0x4000;
560 *pwm_reg_bn = -pwm2 | 0x4000;
564 *pwm_reg_ap = pwm1 | 0x4000;
568 *pwm_reg_an = -pwm1 | 0x4000;
573 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
574 * @mcs: Motion controller state information
577 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
579 typeof(mcs->pxms_ptvang) ptvang;
587 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
588 (mcs->pxms_flg&PXMS_PRA_m)){
590 short ptirc=mcs->pxms_ptirc;
593 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
598 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
600 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
602 pxmc_set_flag(mcs, PXMS_PTI_b);
603 pxmc_set_flag(mcs, PXMS_PHA_b);
608 ptindx = mcs->pxms_ptindx;
610 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
612 mcs->pxms_ptindx = ptindx;
614 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
616 pxmc_set_flag(mcs, PXMS_PTI_b);
617 pxmc_clear_flag(mcs, PXMS_PRA_b);
619 /* if phase table position to mask is know do fine phase table alignment */
620 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
621 // lpc_qei_setup_index_catch(&lpc_qei_state);
624 if(!(mcs->pxms_flg&PXMS_PTI_m))
625 mcs->pxms_ptindx = ptindx;
631 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
632 /* FIXME - check winding current against limit */
633 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
637 ptvang = mcs->pxms_ptvang;
641 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
645 indx = mcs->pxms_ptindx;
647 /* tuning of magnetic field/voltage advance angle */
648 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
651 /* Generating direction of stator mag. field for backward torque */
653 if ((indx -= ptvang)<0)
654 indx += mcs->pxms_ptirc;
656 /* Generating direction of stator mag. field for forward torque */
657 if ((indx += ptvang) >= mcs->pxms_ptirc)
658 indx -= mcs->pxms_ptirc;
661 if (mcs->pxms_ptscale_mult)
662 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
664 pwm1 = mcs->pxms_ptptr1[indx];
665 pwm2 = mcs->pxms_ptptr2[indx];
667 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
668 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
670 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
671 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
672 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
674 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
676 /*pxmc_lpc_wind_current_over_cnt = 0;*/
677 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
684 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
685 * @mcs: Motion controller state information
688 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
690 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
691 int chan = mcs->pxms_out_info;
692 int ene = mcs->pxms_ene;
694 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
695 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
701 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
703 *pwm_reg_b = ene | 0x4000;
707 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
709 *pwm_reg_a = ene | 0x4000;
715 /*******************************************************************/
716 /* PXMCC - PXMC coprocessor support and communication */
719 pxmc_pxmcc_pwm3ph_out(pxmc_state_t *mcs)
721 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
722 (mcs->pxms_flg & PXMS_PRA_m)) {
724 short ptirc = mcs->pxms_ptirc;
725 short divisor = mcs->pxms_ptper * 6;
726 unsigned char hal_pos;
728 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
730 if (hal_pos == 0xff) {
732 pxmc_rocon_process_hal_error(mcs);
734 if (mcs->pxms_halerc)
737 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
739 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m)) {
740 int set_ptofs_fl = 0;
742 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1) {
743 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
745 if ((ptindx > ptindx_prev + ptirc / 2) ||
746 (ptindx_prev > ptindx + ptirc / 2)) {
747 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
752 ptindx = (ptindx_prev + ptindx) / 2;
757 pxmc_set_flag(mcs, PXMS_PTI_b);
758 pxmc_clear_flag(mcs, PXMS_PRA_b);
760 if (!(mcs->pxms_flg & PXMS_PTI_m))
764 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
768 mcs->pxms_ptindx = ptindx;
769 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
771 irc = fpga_irc[mcs->pxms_inp_info]->count;
772 ptofs = (int16_t)(mcs->pxms_ptofs - irc) + irc;
773 mcc_axis->ptofs = ptofs;
776 /* if phase table position to mask is know do fine phase table alignment */
777 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
780 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
782 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
784 pxmc_set_flag(mcs, PXMS_PTI_b);
785 pxmc_set_flag(mcs, PXMS_PHA_b);
789 mcs->pxms_hal = hal_pos;
794 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
795 /* FIXME - check winding current against limit */
796 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
800 int ene, pwm_d, pwm_q;
804 pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
806 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
808 if (mcs->pxms_flg & PXMS_ERR_m)
809 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
816 int pxmcc_axis_setup(pxmc_state_t *mcs, int mode)
818 volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
819 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
825 uint32_t pwmtx_info_dummy = 27;
831 if (mcc_axis == NULL)
835 mcc_axis->mode = PXMCC_MODE_IDLE;
837 mcc_data->common.pwm_cycle = PXMC_LXPWR_PWM_CYCLE;
839 irc = fpga_irc[mcs->pxms_inp_info]->count;
840 ptofs = (int16_t)(mcs->pxms_ptofs - irc) + irc;
842 ptirc = mcs->pxms_ptirc;
843 ull = (1ULL << 32) * mcs->pxms_ptper;
844 ptreci = (ull + ptirc / 2) / ptirc;
846 mcc_axis->ptirc = ptirc;
847 mcc_axis->ptreci = ptreci;
848 mcc_axis->ptofs = ptofs;
851 case PXMCC_MODE_IDLE:
854 case PXMCC_MODE_MODE_BLDC:
857 case PXMCC_MODE_STEPPER_WITH_IRC:
862 mcc_axis->inp_info = mcs->pxms_inp_info;
863 mcc_axis->out_info = mcs->pxms_out_info;
865 pwm_chan = mcs->pxms_out_info;
867 pwmtx_info = (pwmtx_info_dummy << 0) | (pwmtx_info_dummy << 8) |
868 (pwmtx_info_dummy << 16) | (pwmtx_info_dummy << 24);
870 for (i = phcnt; --i >= 0; ) {
871 volatile uint32_t *pwm_reg;
872 volatile uint32_t *pwm_reg_base = fpga_lx_master_transmitter_base;
876 pwm_reg = pxmc_rocon_pwm_chan2reg(pwm_chan + i);
877 if (pwm_reg == &pxmc_rocon_pwm_dummy_reg) {
878 pwmtx_info |= pwmtx_info_dummy;
880 pwmtx_info |= pwm_reg - pwm_reg_base;
884 mcc_axis->pwmtx_info = pwmtx_info;
886 mcc_axis->mode = mode;
889 mcc_axis->pwm_dq = 0;
894 /*******************************************************************/
896 volatile void *pxmc_rocon_rx_data_hist_buff;
897 volatile void *pxmc_rocon_rx_data_hist_buff_end;
898 int pxmc_rocon_rx_data_hist_mode;
900 uint32_t pxmc_rocon_rx_last_irq;
901 uint32_t pxmc_rocon_rx_cycle_time;
902 uint32_t pxmc_rocon_rx_irq_latency;
903 uint32_t pxmc_rocon_rx_irq_latency_max;
905 IRQ_HANDLER_FNC(pxmc_rocon_rx_done_isr)
909 ir = ROCON_RX_TIM->IR & LPC_TIM_IR_ALL_m;
910 ROCON_RX_TIM->IR = ir;
911 if (ir & LPC_TIM_IR_CR1INT_m) {
913 cr0 = ROCON_RX_TIM->CR0;
914 cr1 = ROCON_RX_TIM->CR1;
916 pxmc_rocon_rx_cycle_time = cr1 - pxmc_rocon_rx_last_irq;
917 pxmc_rocon_rx_last_irq = cr1;
919 hal_gpio_set_value(T2MAT0_PIN, 1);
920 hal_gpio_set_value(T2MAT1_PIN, 0);
921 hal_gpio_set_value(T2MAT0_PIN, 0);
923 if (pxmc_rocon_rx_data_hist_buff >= pxmc_rocon_rx_data_hist_buff_end)
924 pxmc_rocon_rx_data_hist_buff = NULL;
926 if (pxmc_rocon_rx_data_hist_buff != NULL) {
927 if (pxmc_rocon_rx_data_hist_mode == 0) {
929 volatile uint32_t *pwm_reg = fpga_lx_master_transmitter_base + 8;
930 volatile uint32_t *rec_reg = fpga_lx_master_receiver_base + 8;
931 uint16_t *pbuf = (uint16_t *)pxmc_rocon_rx_data_hist_buff;
932 for (i = 0; i < 8; i++) {
933 *(pbuf++) = *(rec_reg++);
935 for (i = 0; i < 8; i++) {
936 *(pbuf++) = *(pwm_reg++);
938 pxmc_rocon_rx_data_hist_buff = pbuf;
939 } else if (pxmc_rocon_rx_data_hist_mode == 1) {
941 uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
942 pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
943 pxmcc_axis_data_t *mcc_axis = mcc_data->axis + 0;
944 uint32_t *ptumbl = (uint32_t *)mcc_axis;
946 for (i = 0; i < 16; i++)
947 *(pbuf++) = *(ptumbl++);
949 pxmc_rocon_rx_data_hist_buff = pbuf;
953 pxmc_rocon_rx_irq_latency = ROCON_RX_TIM->TC - cr1;
954 if (pxmc_rocon_rx_irq_latency > pxmc_rocon_rx_irq_latency_max)
955 pxmc_rocon_rx_irq_latency_max = pxmc_rocon_rx_irq_latency;
957 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
960 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
967 pxmc_rocon_rx_done_isr_setup(irq_handler_t rx_done_isr_handler)
970 disable_irq(ROCON_RX_IRQn);
972 hal_pin_conf_set(T2MAT0_PIN, PORT_CONF_GPIO_OUT_LO);
973 hal_pin_conf_set(T2MAT1_PIN, PORT_CONF_GPIO_OUT_LO);
974 hal_pin_conf(T2CAP0_PIN);
975 hal_pin_conf(T2CAP1_PIN);
977 hal_gpio_direction_output(T2MAT0_PIN, 1);
978 hal_gpio_direction_output(T2MAT1_PIN, 0);
979 hal_gpio_set_value(T2MAT0_PIN, 0);
981 /* Enable CLKOUT pin function, source CCLK, divide by 1 */
982 LPC_SC->CLKOUTCFG = 0x0100;
984 request_irq(ROCON_RX_IRQn, rx_done_isr_handler, 0, NULL,NULL);
986 ROCON_RX_TIM->TCR = 0;
987 ROCON_RX_TIM->CTCR = 0;
988 ROCON_RX_TIM->PR = 0; /* Divide by 1 */
990 ROCON_RX_TIM->CCR = LPC_TIM_CCR_CAP0RE_m | LPC_TIM_CCR_CAP1FE_m |
993 ROCON_RX_TIM->EMR = __val2mfld(LPC_TIM_EMR_EMC0_m, LPC_TIM_EMR_NOP) |
994 __val2mfld(LPC_TIM_EMR_EMC1_m, LPC_TIM_EMR_NOP);
996 ROCON_RX_TIM->MCR = 0; /* No IRQ on MRx */
997 ROCON_RX_TIM->TCR = LPC_TIM_TCR_CEN_m; /* Enable timer counting */
998 enable_irq(ROCON_RX_IRQn); /* Enable interrupt */
1005 pxmc_rocon_pwm_master_init(void)
1011 unsigned receiver_done_div = 1;
1012 #ifdef LXPWR_WITH_SIROLADC
1013 unsigned lxpwr_header = 1;
1014 unsigned lxpwr_words = 1 + 8 * 2 + 2;
1015 unsigned lxpwr_chips = 2;
1016 unsigned lxpwr_chip_pwm_cnt = 8;
1017 #else /*LXPWR_WITH_SIROLADC*/
1018 unsigned lxpwr_header = 0;
1019 unsigned lxpwr_words = 8;
1020 unsigned lxpwr_chips = 2;
1021 unsigned lxpwr_chip_pwm_cnt = 8;
1022 #endif /*LXPWR_WITH_SIROLADC*/
1024 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1025 receiver_done_div = 5;
1026 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1028 *fpga_lx_master_reset = 1;
1029 *fpga_lx_master_transmitter_reg = 0;
1030 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1031 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1033 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1034 fpga_lx_master_receiver_base[i] = 0;
1036 word_slot = LX_MASTER_DATA_OFFS;
1037 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
1038 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
1040 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1041 fpga_lx_master_transmitter_base[i] = 0;
1043 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
1044 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1045 #ifdef LXPWR_WITH_SIROLADC
1046 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1047 #endif /*LXPWR_WITH_SIROLADC*/
1049 word_slot = LX_MASTER_DATA_OFFS + 0;
1050 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1051 #ifdef LXPWR_WITH_SIROLADC
1052 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1053 #endif /*LXPWR_WITH_SIROLADC*/
1055 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
1057 *fpga_lx_master_reset = 0;
1058 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1059 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1064 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
1065 unsigned long index_irc, int diff2err)
1070 ofs = ofsl = index_irc - mcs->pxms_ptmark;
1074 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
1075 if (diff >= mcs->pxms_ptirc / 2)
1076 diff -= mcs->pxms_ptirc;
1077 if (diff <= -mcs->pxms_ptirc / 2)
1078 diff += mcs->pxms_ptirc;
1081 if(diff >= mcs->pxms_ptirc / 6) {
1086 diff = (unsigned long)ofsl - irc;
1087 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
1090 mcs->pxms_ptofs = ofs;
1096 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
1097 * @mcs: Motion controller state information
1100 pxmc_dummy_con(pxmc_state_t *mcs)
1105 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
1106 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
1107 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
1108 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
1109 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
1110 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
1112 /* initialize for hard home */
1114 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
1116 pxmc_set_flag(mcs,PXMS_BSY_b);
1117 #if 0 /* config and speed already set in pxmc_hh */
1119 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
1121 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
1123 mcs->pxms_gen_hsp = spd;
1126 mcs->pxms_gen_htim = 16;
1127 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
1128 return pxmc_rocon_hh_gd10(mcs);
1131 /* fill initial mark filter and then decide */
1133 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
1137 if(mcs->pxms_flg & PXMS_ERR_m)
1138 return pxmc_spdnext_gend(mcs);
1140 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
1141 mcs->pxms_rp += mcs->pxms_rs;
1143 mark = pxmc_inp_rocon_is_mark(mcs);
1145 if (mcs->pxms_gen_htim) {
1146 mcs->pxms_gen_htim--;
1150 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
1151 /* limit switch is not used */
1152 pxmc_inp_rocon_is_index_edge(mcs);
1153 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1158 /* go out from switch */
1159 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
1161 /* switch is off -> look for it */
1162 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1167 /* go out from switch */
1169 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
1173 if(mcs->pxms_flg & PXMS_ERR_m)
1174 return pxmc_spdnext_gend(mcs);
1176 mark = pxmc_inp_rocon_is_mark(mcs);
1179 /* switch is off -> look for it again */
1180 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1183 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1184 mcs->pxms_rp += mcs->pxms_rs;
1189 /* switch is off -> look for it */
1191 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
1196 if (mcs->pxms_flg & PXMS_ERR_m)
1197 return pxmc_spdnext_gend(mcs);
1199 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1200 mcs->pxms_rp += mcs->pxms_rs;
1202 mark = pxmc_inp_rocon_is_mark(mcs);
1205 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
1208 mcs->pxms_gen_hsp = spd;
1209 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
1215 /* switch is on -> find edge */
1217 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
1221 if (mcs->pxms_flg & PXMS_ERR_m)
1222 return pxmc_spdnext_gend(mcs);
1224 mark = pxmc_inp_rocon_is_mark(mcs);
1227 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
1228 pxmc_inp_rocon_is_index_edge(mcs);
1229 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1231 pxmc_inp_rocon_ap_zero(mcs);
1232 mcs->pxms_do_gen = pxmc_stop_gi;
1236 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1237 mcs->pxms_rp += mcs->pxms_rs;
1242 /* calibrate on revolution index */
1244 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
1246 if (mcs->pxms_flg & PXMS_ERR_m)
1247 return pxmc_spdnext_gend(mcs);
1249 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1250 mcs->pxms_rp += mcs->pxms_rs;
1252 if (pxmc_inp_rocon_is_index_edge(mcs)){
1253 pxmc_inp_rocon_irc_offset_from_index(mcs);
1254 mcs->pxms_do_gen = pxmc_stop_gi;
1260 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
1262 return pxmc_rocon_hh_gi;
1272 pxmc_pid_con /*pxmc_dummy_con*/,
1274 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
1278 pxmc_inp_rocon_ap2hw,
1279 pxms_ap: 0, pxms_as: 0,
1280 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1281 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1284 pxms_ene: 0, pxms_erc: 0,
1285 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1286 pxms_me: 0x7e00/*0x7fff*/,
1288 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1289 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1290 PXMS_CFG_I2PT_m * 0 | 0x2,
1295 /*pxms_ptamp: 0x7fff,*/
1309 pxmc_rocon_pwm_dc_out,
1313 pxmc_inp_rocon_ap2hw,
1314 pxms_ap: 0, pxms_as: 0,
1315 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1316 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1319 pxms_ene: 0, pxms_erc: 0,
1320 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1321 pxms_me: 0x7e00/*0x7fff*/,
1323 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1324 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1325 PXMS_CFG_I2PT_m * 0 | 0x2,
1329 /*pxms_ptamp: 0x7fff,*/
1343 pxmc_rocon_pwm_dc_out,
1347 pxmc_inp_rocon_ap2hw,
1348 pxms_ap: 0, pxms_as: 0,
1349 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1350 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1353 pxms_ene: 0, pxms_erc: 0,
1354 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1355 pxms_me: 0x7e00/*0x7fff*/,
1357 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1358 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1359 PXMS_CFG_HDIR_m | 0x2,
1363 /*pxms_ptamp: 0x7fff,*/
1377 pxmc_rocon_pwm_dc_out,
1381 pxmc_inp_rocon_ap2hw,
1382 pxms_ap: 0, pxms_as: 0,
1383 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1384 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1387 pxms_ene: 0, pxms_erc: 0,
1388 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1389 pxms_me: 0x7e00/*0x7fff*/,
1391 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1392 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1393 PXMS_CFG_HDIR_m * 0 | 0x2,
1397 /*pxms_ptamp: 0x7fff,*/
1411 pxmc_rocon_pwm_dc_out,
1415 pxmc_inp_rocon_ap2hw,
1416 pxms_ap: 0, pxms_as: 0,
1417 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1418 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1421 pxms_ene: 0, pxms_erc: 0,
1422 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1423 pxms_me: 0x7e00/*0x7fff*/,
1425 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1426 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1427 PXMS_CFG_HDIR_m | 0x2,
1431 /*pxms_ptamp: 0x7fff,*/
1445 pxmc_rocon_pwm_dc_out,
1449 pxmc_inp_rocon_ap2hw,
1450 pxms_ap: 0, pxms_as: 0,
1451 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1452 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1455 pxms_ene: 0, pxms_erc: 0,
1456 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1457 pxms_me: 0x7e00/*0x7fff*/,
1459 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1460 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1461 PXMS_CFG_HDIR_m | 0x2,
1465 /*pxms_ptamp: 0x7fff,*/
1479 pxmc_rocon_pwm_dc_out,
1483 pxmc_inp_rocon_ap2hw,
1484 pxms_ap: 0, pxms_as: 0,
1485 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1486 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1489 pxms_ene: 0, pxms_erc: 0,
1490 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1491 pxms_me: 0x7e00/*0x7fff*/,
1493 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1498 /*pxms_ptamp: 0x7fff,*/
1512 pxmc_rocon_pwm_dc_out,
1516 pxmc_inp_rocon_ap2hw,
1517 pxms_ap: 0, pxms_as: 0,
1518 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1519 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1522 pxms_ene: 0, pxms_erc: 0,
1523 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1524 pxms_me: 0x7e00/*0x7fff*/,
1526 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1531 /*pxms_ptamp: 0x7fff,*/
1537 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1538 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1541 pxmc_state_list_t pxmc_main_list =
1548 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1550 pxmc_state_t *mcs = (pxmc_state_t *)context;
1553 irc = qst->index_pos;
1555 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1558 ofs = irc - mcs->pxms_ptmark;
1559 diff = ofs - mcs->pxms_ptofs;
1561 if (diff >= mcs->pxms_ptirc / 2)
1562 diff -= mcs->pxms_ptirc;
1564 if (diff <= -mcs->pxms_ptirc / 2)
1565 diff += mcs->pxms_ptirc;
1570 if (diff >= mcs->pxms_ptirc / 6)
1572 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1576 mcs->pxms_ptofs = ofs;
1577 pxmc_set_flag(mcs, PXMS_PHA_b);
1581 ofs=irc-mcs->pxms_ptofs;
1582 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1584 ofs-=mcs->pxms_ptirc;
1586 ofs+=mcs->pxms_ptirc;
1589 mcs->pxms_ptmark=ofs;
1592 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1595 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1599 lpc_qei_state_t *qst = &lpc_qei_state;
1600 int irc = lpc_qei_get_pos(qst);
1603 if (!qst->index_occ)
1606 idx_rel = qst->index_pos - irc;
1607 idx_rel %= mcs->pxms_ptirc;
1610 idx_rel += mcs->pxms_ptirc;
1612 ptofs = irc - mcs->pxms_ptofs;
1613 ptmark = ptofs + idx_rel;
1615 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1618 ptmark -= mcs->pxms_ptirc;
1620 ptmark += mcs->pxms_ptirc;
1623 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1625 mcs->pxms_ptmark = ptmark;
1631 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1636 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1637 lpc_qei_state_t *qst = &lpc_qei_state;
1639 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1640 lpc_qei_setup_index_catch(qst);
1642 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1643 spd = 1 << PXMC_SUBDIV(mcs);
1645 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1650 int pxmc_lpc_pthalalign_run(void)
1652 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1655 static inline void pxmc_sfi_input(void)
1659 pxmc_for_each_mcs(var, mcs)
1661 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1662 if (mcs->pxms_flg & PXMS_ENI_m)
1664 pxmc_call(mcs, mcs->pxms_do_inp);
1669 static inline void pxmc_sfi_controller_and_output(void)
1673 pxmc_for_each_mcs(var, mcs)
1675 /* PXMS_ENR_m - check if controller is enabled */
1676 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1679 /* If output only is enabled, we skip the controller */
1680 if (mcs->pxms_flg & PXMS_ENR_m)
1683 pxmc_call(mcs, mcs->pxms_do_con);
1685 /* PXMS_ERR_m - if axis in error state */
1686 if (mcs->pxms_flg & PXMS_ERR_m)
1690 /* for bushless motors, it is necessary to call do_out
1691 even if the controller is not enabled and PWM should be provided. */
1692 pxmc_call(mcs, mcs->pxms_do_out);
1697 static inline void pxmc_sfi_generator(void)
1701 pxmc_for_each_mcs(var, mcs)
1703 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1704 if (mcs->pxms_flg & PXMS_ENG_m)
1706 pxmc_call(mcs, mcs->pxms_do_gen);
1711 static inline void pxmc_sfi_dbg(void)
1715 pxmc_for_each_mcs(var, mcs)
1717 if (mcs->pxms_flg & PXMS_DBG_m)
1719 pxmc_call(mcs, mcs->pxms_do_deb);
1724 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1728 int inp_chan = mcs->pxms_inp_info;
1730 long irc = fpga_irc[inp_chan]->count;
1732 if (!pxmc_inp_rocon_is_index_edge(mcs))
1735 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1736 idx_rel %= mcs->pxms_ptirc;
1738 idx_rel += mcs->pxms_ptirc;
1740 ptofs = irc-mcs->pxms_ptofs;
1741 ptmark = ptofs+idx_rel;
1743 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1745 ptmark -= mcs->pxms_ptirc;
1747 ptmark += mcs->pxms_ptirc;
1750 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1751 mcs->pxms_ptmark = ptmark;
1756 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1761 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1763 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1765 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1766 spd=1<<PXMC_SUBDIV(mcs);
1768 /* clear bit indicating previous index */
1769 pxmc_inp_rocon_is_index_edge(mcs);
1771 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1776 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1778 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1779 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1780 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1781 return PXMC_AXIS_MODE_DC;
1782 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1783 return PXMC_AXIS_MODE_BLDC;
1784 if (mcs->pxms_do_out == pxmc_pxmcc_pwm3ph_out)
1785 return PXMC_AXIS_MODE_BLDC_PXMCC;
1791 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1793 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1796 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1797 mode = pxmc_axis_rdmode(mcs);
1802 /*case PXMC_AXIS_MODE_STEPPER:*/
1803 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1804 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1806 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1807 case PXMC_AXIS_MODE_DC:
1808 /*profive some sane dummy values*/
1809 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1810 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1811 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1813 mcs->pxms_ptscale_mult=1;
1814 mcs->pxms_ptscale_shift=15;
1816 case PXMC_AXIS_MODE_BLDC:
1817 case PXMC_AXIS_MODE_BLDC_PXMCC:
1818 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1819 #ifndef PXMC_WITH_PT_ZIC
1820 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1821 #else /*PXMC_WITH_PT_ZIC*/
1822 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1823 #endif /*PXMC_WITH_PT_ZIC*/
1829 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1835 * pxmc_axis_mode - Sets axis mode.[extern API]
1836 * @mcs: Motion controller state information
1837 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1838 * 2 .. stepper motor with IRC feedback and PWM ,
1839 * 3 .. stepper motor with PWM control
1840 * 4 .. DC motor with IRC feedback and PWM
1844 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1848 pxmc_set_const_out(mcs, 0);
1849 pxmc_clear_flag(mcs, PXMS_ENI_b);
1850 pxmc_clear_flags(mcs,PXMS_ENO_m);
1851 /* Clear possible stall index flags from hardware */
1852 pxmc_inp_rocon_is_index_edge(mcs);
1853 pxmc_clear_flag(mcs, PXMS_PHA_b);
1854 pxmc_clear_flag(mcs, PXMS_PTI_b);
1857 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1858 mode = pxmc_axis_rdmode(mcs);
1862 mode = PXMC_AXIS_MODE_DC;
1864 res = pxmc_axis_pt4mode(mcs, mode);
1869 /*case PXMC_AXIS_MODE_STEPPER:*/
1870 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1871 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1873 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1874 case PXMC_AXIS_MODE_DC:
1875 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1877 case PXMC_AXIS_MODE_BLDC:
1878 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1880 case PXMC_AXIS_MODE_BLDC_PXMCC:
1881 if (pxmcc_axis_setup(mcs, PXMCC_MODE_MODE_BLDC) < 0)
1883 pxmcc_axis_enable(mcs, 1);
1884 mcs->pxms_do_out = pxmc_pxmcc_pwm3ph_out;
1890 /* Clear possible stall index flags from hardware */
1891 pxmc_inp_rocon_is_index_edge(mcs);
1892 /* Request new phases alignment for changed parameters */
1893 pxmc_clear_flag(mcs, PXMS_PHA_b);
1894 pxmc_clear_flag(mcs, PXMS_PTI_b);
1895 pxmc_set_flag(mcs, PXMS_ENI_b);
1899 void pxmc_sfi_isr(void)
1901 unsigned long spent = pxmc_fast_tick_time();
1904 pxmc_sfi_controller_and_output();
1905 pxmc_sfi_generator();
1907 /* Kick LX Master watchdog */
1908 if (pxmc_main_list.pxml_cnt != 0)
1909 *fpga_lx_master_transmitter_wdog = 1;
1911 spent = pxmc_fast_tick_time() - spent;
1913 if(spent > pxmc_sfi_spent_time_max)
1914 pxmc_sfi_spent_time_max = spent;
1918 int pxmc_clear_power_stop(void)
1923 int pxmc_process_state_check(unsigned long *pbusy_bits,
1924 unsigned long *perror_bits)
1927 unsigned short chan;
1928 unsigned long busy_bits = 0;
1929 unsigned long error_bits = 0;
1932 pxmc_for_each_mcs(chan, mcs) {
1934 flg |= mcs->pxms_flg;
1935 if (mcs->pxms_flg & PXMS_BSY_m)
1936 busy_bits |= 1 << chan;
1937 if (mcs->pxms_flg & PXMS_ERR_m)
1938 error_bits |= 1 << chan;
1941 if (appl_errstop_mode) {
1942 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
1943 pxmc_for_each_mcs(chan, mcs) {
1944 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
1951 if (pbusy_bits != NULL)
1952 *pbusy_bits = busy_bits;
1953 if (error_bits != NULL)
1954 *perror_bits = error_bits;
1964 if (!pxmc_main_list.pxml_cnt)
1967 pxmc_for_each_mcs(var, mcs)
1969 pxmc_set_const_out(mcs,0);
1972 pxmc_main_list.pxml_cnt = 0;
1978 int pxmc_initialize(void)
1983 pxmc_state_t *mcs = &mcs0;
1984 lpc_qei_state_t *qst = &lpc_qei_state;
1986 *fpga_irc_reset = 1;
1988 for (i = 0; i < 8; i++) {
1989 fpga_irc[i]->count = 0;
1990 fpga_irc[i]->count_index = 0;
1991 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
1994 /* Initialize QEI module for IRC counting */
1995 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1997 /* Initialize QEI events processing */
1998 if (lpc_qei_setup_irq(qst) < 0)
2001 *fpga_irc_reset = 0;
2003 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
2005 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
2006 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
2008 pxmc_rocon_pwm_master_init();
2009 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
2010 pxmc_rocon_rx_done_isr_setup(pxmc_rocon_rx_done_isr);
2011 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
2013 pxmc_main_list.pxml_cnt = 0;
2014 pxmc_dbg_hist = NULL;
2016 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;