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"
36 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
37 unsigned long index_irc, int diff2err);
39 #ifndef pxmc_fast_tick_time
40 #define pxmc_fast_tick_time() (LPC_TIM0->TC)
43 #define PXML_MAIN_CNT 8
45 #define PXMC_WITH_PT_ZIC 1
46 #define PXMC_PT_ZIC_MASK 0x8000
48 #define LPCPWM1_FREQ 20000
50 #define HAL_ERR_SENSITIVITY 20
51 #define HAL_ERR_MAX_COUNT 5
53 #define LXPWR_WITH_SIROLADC 1
55 #define LX_MASTER_DATA_OFFS 8
57 unsigned pxmc_rocon_pwm_magnitude = 2500;
59 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
60 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
62 const uint8_t onesin10bits[1024]={
63 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,
64 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,
65 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,
66 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,
67 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,
68 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,
69 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,
70 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,
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 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,
74 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,
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 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,
78 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,
79 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,
80 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,
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 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,
84 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,
85 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,
86 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,
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 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,
90 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,
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 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,
94 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
98 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
100 int chan=mcs->pxms_inp_info;
104 /* read position from hardware */
105 irc = fpga_irc[chan]->count;
106 irc += pxmc_rocon_irc_offset[chan];
107 pos = irc << PXMC_SUBDIV(mcs);
108 mcs->pxms_as = pos - mcs->pxms_ap;
111 /* Running of the motor commutator */
112 if (mcs->pxms_flg & PXMS_PTI_m)
113 pxmc_irc_16bit_commindx(mcs, irc);
119 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
124 int chan=mcs->pxms_inp_info;
126 irc_state = *fpga_irc_state[chan];
128 mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
129 (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
131 filt = pxmc_rocon_mark_filt[chan];
132 filt = (filt << 1) | mark;
133 pxmc_rocon_mark_filt[chan] = filt;
135 return onesin10bits[filt & 0x03ff];
139 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
143 int chan=mcs->pxms_inp_info;
145 irc_state = *fpga_irc_state[chan];
146 *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
148 index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
154 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
156 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
158 mcs->pxms_ptofs += irc_diff;
160 mcs->pxms_ap += pos_diff;
161 mcs->pxms_rp += pos_diff;
166 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
168 int chan=mcs->pxms_inp_info;
172 irc_offset = -fpga_irc[chan]->count_index;
173 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
174 pxmc_rocon_irc_offset[chan] = irc_offset;
175 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
179 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
181 int chan=mcs->pxms_inp_info;
185 irc_offset = -fpga_irc[chan]->count;
186 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
187 pxmc_rocon_irc_offset[chan] = irc_offset;
188 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
192 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
194 int chan=mcs->pxms_inp_info;
198 irc = fpga_irc[chan]->count;
199 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
201 irc = pos_diff >> PXMC_SUBDIV(mcs);
203 /* Adjust phase table alignemt to modified IRC readout */
204 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
206 pxmc_rocon_irc_offset[chan] = irc;
211 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
213 int chan=mcs->pxms_inp_info;
217 if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
220 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
221 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
223 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
226 uint32_t pxmc_rocon_receiver_dummy_reg;
228 static inline volatile uint32_t *
229 pxmc_rocon_receiver_chan2reg(unsigned chan)
231 volatile uint32_t *rec_reg;
234 return &pxmc_rocon_receiver_dummy_reg;
236 rec_reg = fpga_lx_master_receiver_base;
238 #ifdef LXPWR_WITH_SIROLADC
239 rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) * 3 + chan * 2;
240 #else /*LXPWR_WITH_SIROLADC*/
241 rec_reg += LX_MASTER_DATA_OFFS + chan;
242 #endif /*LXPWR_WITH_SIROLADC*/
248 pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
251 volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
252 int chan = mcs->pxms_out_info;
255 #ifdef LXPWR_WITH_SIROLADC
257 #else /*LXPWR_WITH_SIROLADC*/
259 #endif /*LXPWR_WITH_SIROLADC*/
261 rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
262 rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
263 rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
265 h = (rec_reg_a[hal_offs] >> 14) & 1;
266 h |= (rec_reg_b[hal_offs] >> 13) & 2;
267 h |= (rec_reg_c[hal_offs] >> 12) & 4;
269 /* return 3 bits corresponding to the HAL senzor input */
274 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
286 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
299 uint32_t pxmc_rocon_pwm_dummy_reg;
301 static inline volatile uint32_t *
302 pxmc_rocon_pwm_chan2reg(unsigned chan)
304 volatile uint32_t *pwm_reg;
307 return &pxmc_rocon_pwm_dummy_reg;
309 pwm_reg = fpga_lx_master_transmitter_base;
311 #ifdef LXPWR_WITH_SIROLADC
312 pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) + chan;
313 #else /*LXPWR_WITH_SIROLADC*/
314 pwm_reg += LX_MASTER_DATA_OFFS + chan;
315 #endif /*LXPWR_WITH_SIROLADC*/
321 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
322 * @mcs: Motion controller state information
324 /*static*/ inline void
325 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
327 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
328 int chan = mcs->pxms_out_info;
330 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
331 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
332 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
340 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
342 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
344 pxmc_set_errno(mcs, PXMS_E_HAL);
349 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
353 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
354 * @mcs: Motion controller state information
357 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
359 typeof(mcs->pxms_ptvang) ptvang;
361 unsigned char hal_pos;
369 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
370 (mcs->pxms_flg & PXMS_PRA_m))
373 short ptirc = mcs->pxms_ptirc;
374 short divisor = mcs->pxms_ptper * 6;
377 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
382 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
384 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
386 pxmc_set_flag(mcs, PXMS_PTI_b);
387 pxmc_set_flag(mcs, PXMS_PHA_b);
392 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
397 pxmc_rocon_process_hal_error(mcs);
401 if (mcs->pxms_halerc)
404 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
406 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
408 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
410 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
412 if ((ptindx > ptindx_prev + ptirc / 2) ||
413 (ptindx_prev > ptindx + ptirc / 2))
415 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
422 ptindx = (ptindx_prev + ptindx) / 2;
425 mcs->pxms_ptindx = ptindx;
427 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
429 pxmc_set_flag(mcs, PXMS_PTI_b);
430 pxmc_clear_flag(mcs, PXMS_PRA_b);
434 if (!(mcs->pxms_flg & PXMS_PTI_m))
435 mcs->pxms_ptindx = ptindx;
438 /* if phase table position to mask is know do fine phase table alignment */
439 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
441 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
443 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
445 pxmc_set_flag(mcs, PXMS_PTI_b);
446 pxmc_set_flag(mcs, PXMS_PHA_b);
450 mcs->pxms_hal = hal_pos;
456 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
457 /* FIXME - check winding current against limit */
458 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
462 ptvang = mcs->pxms_ptvang;
466 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
470 indx = mcs->pxms_ptindx;
472 /* tuning of magnetic field/voltage advance angle */
473 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
478 /* Generating direction of stator mag. field for backward torque */
481 if ((indx -= ptvang) < 0)
482 indx += mcs->pxms_ptirc;
486 /* Generating direction of stator mag. field for forward torque */
487 if ((indx += ptvang) >= mcs->pxms_ptirc)
488 indx -= mcs->pxms_ptirc;
491 if (mcs->pxms_ptscale_mult)
492 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
494 pwm1 = mcs->pxms_ptptr1[indx];
495 pwm2 = mcs->pxms_ptptr2[indx];
496 pwm3 = mcs->pxms_ptptr3[indx];
498 #ifdef PXMC_WITH_PT_ZIC
499 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
501 pwm1 &= ~PXMC_PT_ZIC_MASK;
502 pwm2 &= ~PXMC_PT_ZIC_MASK;
503 pwm3 &= ~PXMC_PT_ZIC_MASK;
505 #endif /*PXMC_WITH_PT_ZIC*/
507 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
508 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
510 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
511 if (pwm1 & PXMC_PT_ZIC_MASK)
514 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
515 if (pwm2 & PXMC_PT_ZIC_MASK)
518 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
519 if (pwm3 & PXMC_PT_ZIC_MASK)
522 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
524 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
528 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
535 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
536 * @mcs: Motion controller state information
538 /*static*/ inline void
539 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
541 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
542 int chan = mcs->pxms_out_info;
544 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
545 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
546 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
547 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
550 *pwm_reg_bp = pwm2 | 0x4000;
554 *pwm_reg_bn = -pwm2 | 0x4000;
558 *pwm_reg_ap = pwm1 | 0x4000;
562 *pwm_reg_an = -pwm1 | 0x4000;
567 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
568 * @mcs: Motion controller state information
571 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
573 typeof(mcs->pxms_ptvang) ptvang;
581 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
582 (mcs->pxms_flg&PXMS_PRA_m)){
584 short ptirc=mcs->pxms_ptirc;
587 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
592 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
594 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
596 pxmc_set_flag(mcs, PXMS_PTI_b);
597 pxmc_set_flag(mcs, PXMS_PHA_b);
602 ptindx = mcs->pxms_ptindx;
604 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
606 mcs->pxms_ptindx = ptindx;
608 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
610 pxmc_set_flag(mcs, PXMS_PTI_b);
611 pxmc_clear_flag(mcs, PXMS_PRA_b);
613 /* if phase table position to mask is know do fine phase table alignment */
614 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
615 // lpc_qei_setup_index_catch(&lpc_qei_state);
618 if(!(mcs->pxms_flg&PXMS_PTI_m))
619 mcs->pxms_ptindx = ptindx;
625 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
626 /* FIXME - check winding current against limit */
627 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
631 ptvang = mcs->pxms_ptvang;
635 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
639 indx = mcs->pxms_ptindx;
641 /* tuning of magnetic field/voltage advance angle */
642 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
645 /* Generating direction of stator mag. field for backward torque */
647 if ((indx -= ptvang)<0)
648 indx += mcs->pxms_ptirc;
650 /* Generating direction of stator mag. field for forward torque */
651 if ((indx += ptvang) >= mcs->pxms_ptirc)
652 indx -= mcs->pxms_ptirc;
655 if (mcs->pxms_ptscale_mult)
656 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
658 pwm1 = mcs->pxms_ptptr1[indx];
659 pwm2 = mcs->pxms_ptptr2[indx];
661 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
662 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
664 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
665 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
666 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
668 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
670 /*pxmc_lpc_wind_current_over_cnt = 0;*/
671 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
678 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
679 * @mcs: Motion controller state information
682 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
684 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
685 int chan = mcs->pxms_out_info;
686 int ene = mcs->pxms_ene;
688 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
689 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
695 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
697 *pwm_reg_b = ene | 0x4000;
701 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
703 *pwm_reg_a = ene | 0x4000;
709 volatile void *pxmc_rocon_rx_data_hist_buff;
710 volatile void *pxmc_rocon_rx_data_hist_buff_end;
711 int pxmc_rocon_rx_data_hist_mode;
713 uint32_t pxmc_rocon_rx_last_irq;
714 uint32_t pxmc_rocon_rx_cycle_time;
715 uint32_t pxmc_rocon_rx_irq_latency;
716 uint32_t pxmc_rocon_rx_irq_latency_max;
718 IRQ_HANDLER_FNC(pxmc_rocon_rx_done_isr)
722 ir = ROCON_RX_TIM->IR & LPC_TIM_IR_ALL_m;
723 ROCON_RX_TIM->IR = ir;
724 if (ir & LPC_TIM_IR_CR1INT_m) {
726 cr0 = ROCON_RX_TIM->CR0;
727 cr1 = ROCON_RX_TIM->CR1;
729 pxmc_rocon_rx_cycle_time = cr1 - pxmc_rocon_rx_last_irq;
730 pxmc_rocon_rx_last_irq = cr1;
732 hal_gpio_set_value(T2MAT0_PIN, 1);
733 hal_gpio_set_value(T2MAT1_PIN, 0);
734 hal_gpio_set_value(T2MAT0_PIN, 0);
736 if (pxmc_rocon_rx_data_hist_buff >= pxmc_rocon_rx_data_hist_buff_end)
737 pxmc_rocon_rx_data_hist_buff = NULL;
739 if (pxmc_rocon_rx_data_hist_buff != NULL) {
740 if (pxmc_rocon_rx_data_hist_mode == 0) {
742 volatile uint32_t *pwm_reg = fpga_lx_master_transmitter_base + 8;
743 volatile uint32_t *rec_reg = fpga_lx_master_receiver_base + 8;
744 uint16_t *pbuf = (uint16_t *)pxmc_rocon_rx_data_hist_buff;
745 for (i = 0; i < 8; i++) {
746 *(pbuf++) = *(rec_reg++);
748 for (i = 0; i < 8; i++) {
749 *(pbuf++) = *(pwm_reg++);
751 pxmc_rocon_rx_data_hist_buff = pbuf;
752 } else if (pxmc_rocon_rx_data_hist_mode == 1) {
754 uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
756 for (i = 0; i < 16; i++)
757 *(pbuf++) = fpga_tumbl_dmem[i];
759 pxmc_rocon_rx_data_hist_buff = pbuf;
763 pxmc_rocon_rx_irq_latency = ROCON_RX_TIM->TC - cr1;
764 if (pxmc_rocon_rx_irq_latency > pxmc_rocon_rx_irq_latency_max)
765 pxmc_rocon_rx_irq_latency_max = pxmc_rocon_rx_irq_latency;
767 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
770 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
777 pxmc_rocon_rx_done_isr_setup(irq_handler_t rx_done_isr_handler)
780 disable_irq(ROCON_RX_IRQn);
782 hal_pin_conf_set(T2MAT0_PIN, PORT_CONF_GPIO_OUT_LO);
783 hal_pin_conf_set(T2MAT1_PIN, PORT_CONF_GPIO_OUT_LO);
784 hal_pin_conf(T2CAP0_PIN);
785 hal_pin_conf(T2CAP1_PIN);
787 hal_gpio_direction_output(T2MAT0_PIN, 1);
788 hal_gpio_direction_output(T2MAT1_PIN, 0);
789 hal_gpio_set_value(T2MAT0_PIN, 0);
791 /* Enable CLKOUT pin function, source CCLK, divide by 1 */
792 LPC_SC->CLKOUTCFG = 0x0100;
794 request_irq(ROCON_RX_IRQn, rx_done_isr_handler, 0, NULL,NULL);
796 ROCON_RX_TIM->TCR = 0;
797 ROCON_RX_TIM->CTCR = 0;
798 ROCON_RX_TIM->PR = 0; /* Divide by 1 */
800 ROCON_RX_TIM->CCR = LPC_TIM_CCR_CAP0RE_m | LPC_TIM_CCR_CAP1FE_m |
803 ROCON_RX_TIM->EMR = __val2mfld(LPC_TIM_EMR_EMC0_m, LPC_TIM_EMR_NOP) |
804 __val2mfld(LPC_TIM_EMR_EMC1_m, LPC_TIM_EMR_NOP);
806 ROCON_RX_TIM->MCR = 0; /* No IRQ on MRx */
807 ROCON_RX_TIM->TCR = LPC_TIM_TCR_CEN_m; /* Enable timer counting */
808 enable_irq(ROCON_RX_IRQn); /* Enable interrupt */
815 pxmc_rocon_pwm_master_init(void)
821 unsigned receiver_done_div = 1;
822 #ifdef LXPWR_WITH_SIROLADC
823 unsigned lxpwr_header = 1;
824 unsigned lxpwr_words = 1 + 8 * 2 + 2;
825 unsigned lxpwr_chips = 2;
826 unsigned lxpwr_chip_pwm_cnt = 8;
827 #else /*LXPWR_WITH_SIROLADC*/
828 unsigned lxpwr_header = 0;
829 unsigned lxpwr_words = 8;
830 unsigned lxpwr_chips = 2;
831 unsigned lxpwr_chip_pwm_cnt = 8;
832 #endif /*LXPWR_WITH_SIROLADC*/
834 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
835 receiver_done_div = 5;
836 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
838 *fpga_lx_master_reset = 1;
839 *fpga_lx_master_transmitter_reg = 0;
840 *fpga_lx_master_transmitter_cycle = 2500; /* 50 MHz -> 20 kHz */
841 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
843 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
844 fpga_lx_master_receiver_base[i] = 0;
846 word_slot = LX_MASTER_DATA_OFFS;
847 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
848 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
850 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
851 fpga_lx_master_transmitter_base[i] = 0;
853 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
854 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
855 #ifdef LXPWR_WITH_SIROLADC
856 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
857 #endif /*LXPWR_WITH_SIROLADC*/
859 word_slot = LX_MASTER_DATA_OFFS + 0;
860 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
861 #ifdef LXPWR_WITH_SIROLADC
862 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
863 #endif /*LXPWR_WITH_SIROLADC*/
865 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
867 *fpga_lx_master_reset = 0;
868 *fpga_lx_master_transmitter_cycle = 2500; /* 50 MHz -> 20 kHz */
869 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
874 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
875 unsigned long index_irc, int diff2err)
880 ofs = ofsl = index_irc - mcs->pxms_ptmark;
884 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
885 if (diff >= mcs->pxms_ptirc / 2)
886 diff -= mcs->pxms_ptirc;
887 if (diff <= -mcs->pxms_ptirc / 2)
888 diff += mcs->pxms_ptirc;
891 if(diff >= mcs->pxms_ptirc / 6) {
896 diff = (unsigned long)ofsl - irc;
897 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
900 mcs->pxms_ptofs = ofs;
906 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
907 * @mcs: Motion controller state information
910 pxmc_dummy_con(pxmc_state_t *mcs)
915 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
916 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
917 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
918 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
919 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
920 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
922 /* initialize for hard home */
924 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
926 pxmc_set_flag(mcs,PXMS_BSY_b);
927 #if 0 /* config and speed already set in pxmc_hh */
929 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
931 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
933 mcs->pxms_gen_hsp = spd;
936 mcs->pxms_gen_htim = 16;
937 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
938 return pxmc_rocon_hh_gd10(mcs);
941 /* fill initial mark filter and then decide */
943 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
947 if(mcs->pxms_flg & PXMS_ERR_m)
948 return pxmc_spdnext_gend(mcs);
950 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
951 mcs->pxms_rp += mcs->pxms_rs;
953 mark = pxmc_inp_rocon_is_mark(mcs);
955 if (mcs->pxms_gen_htim) {
956 mcs->pxms_gen_htim--;
960 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
961 /* limit switch is not used */
962 pxmc_inp_rocon_is_index_edge(mcs);
963 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
968 /* go out from switch */
969 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
971 /* switch is off -> look for it */
972 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
977 /* go out from switch */
979 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
983 if(mcs->pxms_flg & PXMS_ERR_m)
984 return pxmc_spdnext_gend(mcs);
986 mark = pxmc_inp_rocon_is_mark(mcs);
989 /* switch is off -> look for it again */
990 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
993 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
994 mcs->pxms_rp += mcs->pxms_rs;
999 /* switch is off -> look for it */
1001 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
1006 if (mcs->pxms_flg & PXMS_ERR_m)
1007 return pxmc_spdnext_gend(mcs);
1009 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1010 mcs->pxms_rp += mcs->pxms_rs;
1012 mark = pxmc_inp_rocon_is_mark(mcs);
1015 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
1018 mcs->pxms_gen_hsp = spd;
1019 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
1025 /* switch is on -> find edge */
1027 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
1031 if (mcs->pxms_flg & PXMS_ERR_m)
1032 return pxmc_spdnext_gend(mcs);
1034 mark = pxmc_inp_rocon_is_mark(mcs);
1037 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
1038 pxmc_inp_rocon_is_index_edge(mcs);
1039 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1041 pxmc_inp_rocon_ap_zero(mcs);
1042 mcs->pxms_do_gen = pxmc_stop_gi;
1046 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1047 mcs->pxms_rp += mcs->pxms_rs;
1052 /* calibrate on revolution index */
1054 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
1056 if (mcs->pxms_flg & PXMS_ERR_m)
1057 return pxmc_spdnext_gend(mcs);
1059 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1060 mcs->pxms_rp += mcs->pxms_rs;
1062 if (pxmc_inp_rocon_is_index_edge(mcs)){
1063 pxmc_inp_rocon_irc_offset_from_index(mcs);
1064 mcs->pxms_do_gen = pxmc_stop_gi;
1070 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
1072 return pxmc_rocon_hh_gi;
1082 pxmc_pid_con /*pxmc_dummy_con*/,
1084 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
1088 pxmc_inp_rocon_ap2hw,
1089 pxms_ap: 0, pxms_as: 0,
1090 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1091 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1094 pxms_ene: 0, pxms_erc: 0,
1095 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1096 pxms_me: 0x7e00/*0x7fff*/,
1098 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1099 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1100 PXMS_CFG_I2PT_m * 0 | 0x2,
1105 /*pxms_ptamp: 0x7fff,*/
1119 pxmc_rocon_pwm_dc_out,
1123 pxmc_inp_rocon_ap2hw,
1124 pxms_ap: 0, pxms_as: 0,
1125 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1126 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1129 pxms_ene: 0, pxms_erc: 0,
1130 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1131 pxms_me: 0x7e00/*0x7fff*/,
1133 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1134 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1135 PXMS_CFG_I2PT_m * 0 | 0x2,
1139 /*pxms_ptamp: 0x7fff,*/
1153 pxmc_rocon_pwm_dc_out,
1157 pxmc_inp_rocon_ap2hw,
1158 pxms_ap: 0, pxms_as: 0,
1159 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1160 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1163 pxms_ene: 0, pxms_erc: 0,
1164 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1165 pxms_me: 0x7e00/*0x7fff*/,
1167 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1168 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1169 PXMS_CFG_HDIR_m | 0x2,
1173 /*pxms_ptamp: 0x7fff,*/
1187 pxmc_rocon_pwm_dc_out,
1191 pxmc_inp_rocon_ap2hw,
1192 pxms_ap: 0, pxms_as: 0,
1193 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1194 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1197 pxms_ene: 0, pxms_erc: 0,
1198 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1199 pxms_me: 0x7e00/*0x7fff*/,
1201 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1202 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1203 PXMS_CFG_HDIR_m * 0 | 0x2,
1207 /*pxms_ptamp: 0x7fff,*/
1221 pxmc_rocon_pwm_dc_out,
1225 pxmc_inp_rocon_ap2hw,
1226 pxms_ap: 0, pxms_as: 0,
1227 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1228 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1231 pxms_ene: 0, pxms_erc: 0,
1232 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1233 pxms_me: 0x7e00/*0x7fff*/,
1235 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1236 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1237 PXMS_CFG_HDIR_m | 0x2,
1241 /*pxms_ptamp: 0x7fff,*/
1255 pxmc_rocon_pwm_dc_out,
1259 pxmc_inp_rocon_ap2hw,
1260 pxms_ap: 0, pxms_as: 0,
1261 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1262 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1265 pxms_ene: 0, pxms_erc: 0,
1266 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1267 pxms_me: 0x7e00/*0x7fff*/,
1269 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1270 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1271 PXMS_CFG_HDIR_m | 0x2,
1275 /*pxms_ptamp: 0x7fff,*/
1289 pxmc_rocon_pwm_dc_out,
1293 pxmc_inp_rocon_ap2hw,
1294 pxms_ap: 0, pxms_as: 0,
1295 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1296 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1299 pxms_ene: 0, pxms_erc: 0,
1300 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1301 pxms_me: 0x7e00/*0x7fff*/,
1303 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1308 /*pxms_ptamp: 0x7fff,*/
1322 pxmc_rocon_pwm_dc_out,
1326 pxmc_inp_rocon_ap2hw,
1327 pxms_ap: 0, pxms_as: 0,
1328 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1329 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1332 pxms_ene: 0, pxms_erc: 0,
1333 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1334 pxms_me: 0x7e00/*0x7fff*/,
1336 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1341 /*pxms_ptamp: 0x7fff,*/
1347 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1348 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1351 pxmc_state_list_t pxmc_main_list =
1358 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1360 pxmc_state_t *mcs = (pxmc_state_t *)context;
1363 irc = qst->index_pos;
1365 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1368 ofs = irc - mcs->pxms_ptmark;
1369 diff = ofs - mcs->pxms_ptofs;
1371 if (diff >= mcs->pxms_ptirc / 2)
1372 diff -= mcs->pxms_ptirc;
1374 if (diff <= -mcs->pxms_ptirc / 2)
1375 diff += mcs->pxms_ptirc;
1380 if (diff >= mcs->pxms_ptirc / 6)
1382 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1386 mcs->pxms_ptofs = ofs;
1387 pxmc_set_flag(mcs, PXMS_PHA_b);
1391 ofs=irc-mcs->pxms_ptofs;
1392 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1394 ofs-=mcs->pxms_ptirc;
1396 ofs+=mcs->pxms_ptirc;
1399 mcs->pxms_ptmark=ofs;
1402 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1405 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1409 lpc_qei_state_t *qst = &lpc_qei_state;
1410 int irc = lpc_qei_get_pos(qst);
1413 if (!qst->index_occ)
1416 idx_rel = qst->index_pos - irc;
1417 idx_rel %= mcs->pxms_ptirc;
1420 idx_rel += mcs->pxms_ptirc;
1422 ptofs = irc - mcs->pxms_ptofs;
1423 ptmark = ptofs + idx_rel;
1425 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1428 ptmark -= mcs->pxms_ptirc;
1430 ptmark += mcs->pxms_ptirc;
1433 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1435 mcs->pxms_ptmark = ptmark;
1441 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1446 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1447 lpc_qei_state_t *qst = &lpc_qei_state;
1449 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1450 lpc_qei_setup_index_catch(qst);
1452 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1453 spd = 1 << PXMC_SUBDIV(mcs);
1455 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1460 int pxmc_lpc_pthalalign_run(void)
1462 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1465 static inline void pxmc_sfi_input(void)
1469 pxmc_for_each_mcs(var, mcs)
1471 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1472 if (mcs->pxms_flg & PXMS_ENI_m)
1474 pxmc_call(mcs, mcs->pxms_do_inp);
1479 static inline void pxmc_sfi_controller_and_output(void)
1483 pxmc_for_each_mcs(var, mcs)
1485 /* PXMS_ENR_m - check if controller is enabled */
1486 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1489 /* If output only is enabled, we skip the controller */
1490 if (mcs->pxms_flg & PXMS_ENR_m)
1493 pxmc_call(mcs, mcs->pxms_do_con);
1495 /* PXMS_ERR_m - if axis in error state */
1496 if (mcs->pxms_flg & PXMS_ERR_m)
1500 /* for bushless motors, it is necessary to call do_out
1501 even if the controller is not enabled and PWM should be provided. */
1502 pxmc_call(mcs, mcs->pxms_do_out);
1507 static inline void pxmc_sfi_generator(void)
1511 pxmc_for_each_mcs(var, mcs)
1513 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1514 if (mcs->pxms_flg & PXMS_ENG_m)
1516 pxmc_call(mcs, mcs->pxms_do_gen);
1521 static inline void pxmc_sfi_dbg(void)
1525 pxmc_for_each_mcs(var, mcs)
1527 if (mcs->pxms_flg & PXMS_DBG_m)
1529 pxmc_call(mcs, mcs->pxms_do_deb);
1534 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1538 int inp_chan = mcs->pxms_inp_info;
1540 long irc = fpga_irc[inp_chan]->count;
1542 if (!pxmc_inp_rocon_is_index_edge(mcs))
1545 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1546 idx_rel %= mcs->pxms_ptirc;
1548 idx_rel += mcs->pxms_ptirc;
1550 ptofs = irc-mcs->pxms_ptofs;
1551 ptmark = ptofs+idx_rel;
1553 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1555 ptmark -= mcs->pxms_ptirc;
1557 ptmark += mcs->pxms_ptirc;
1560 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1561 mcs->pxms_ptmark = ptmark;
1566 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1571 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1573 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1575 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1576 spd=1<<PXMC_SUBDIV(mcs);
1578 /* clear bit indicating previous index */
1579 pxmc_inp_rocon_is_index_edge(mcs);
1581 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1586 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1588 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1589 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1590 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1591 return PXMC_AXIS_MODE_DC;
1592 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1593 return PXMC_AXIS_MODE_BLDC;
1599 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1601 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1604 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1605 mode = pxmc_axis_rdmode(mcs);
1610 /*case PXMC_AXIS_MODE_STEPPER:*/
1611 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1612 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1614 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1615 case PXMC_AXIS_MODE_DC:
1616 /*profive some sane dummy values*/
1617 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1618 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1619 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1621 mcs->pxms_ptscale_mult=1;
1622 mcs->pxms_ptscale_shift=15;
1624 case PXMC_AXIS_MODE_BLDC:
1625 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1626 #ifndef PXMC_WITH_PT_ZIC
1627 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1628 #else /*PXMC_WITH_PT_ZIC*/
1629 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1630 #endif /*PXMC_WITH_PT_ZIC*/
1636 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1642 * pxmc_axis_mode - Sets axis mode.[extern API]
1643 * @mcs: Motion controller state information
1644 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1645 * 2 .. stepper motor with IRC feedback and PWM ,
1646 * 3 .. stepper motor with PWM control
1647 * 4 .. DC motor with IRC feedback and PWM
1651 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1655 pxmc_set_const_out(mcs, 0);
1656 pxmc_clear_flag(mcs, PXMS_ENI_b);
1657 pxmc_clear_flags(mcs,PXMS_ENO_m);
1658 /* Clear possible stall index flags from hardware */
1659 pxmc_inp_rocon_is_index_edge(mcs);
1660 pxmc_clear_flag(mcs, PXMS_PHA_b);
1661 pxmc_clear_flag(mcs, PXMS_PTI_b);
1664 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1665 mode = pxmc_axis_rdmode(mcs);
1669 mode = PXMC_AXIS_MODE_DC;
1671 res = pxmc_axis_pt4mode(mcs, mode);
1676 /*case PXMC_AXIS_MODE_STEPPER:*/
1677 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1678 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1680 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1681 case PXMC_AXIS_MODE_DC:
1682 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1684 case PXMC_AXIS_MODE_BLDC:
1685 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1691 /* Clear possible stall index flags from hardware */
1692 pxmc_inp_rocon_is_index_edge(mcs);
1693 /* Request new phases alignment for changed parameters */
1694 pxmc_clear_flag(mcs, PXMS_PHA_b);
1695 pxmc_clear_flag(mcs, PXMS_PTI_b);
1696 pxmc_set_flag(mcs, PXMS_ENI_b);
1700 void pxmc_sfi_isr(void)
1702 unsigned long spent = pxmc_fast_tick_time();
1705 pxmc_sfi_controller_and_output();
1706 pxmc_sfi_generator();
1708 /* Kick LX Master watchdog */
1709 if (pxmc_main_list.pxml_cnt != 0)
1710 *fpga_lx_master_transmitter_wdog = 1;
1712 spent = pxmc_fast_tick_time() - spent;
1714 if(spent > pxmc_sfi_spent_time_max)
1715 pxmc_sfi_spent_time_max = spent;
1719 int pxmc_clear_power_stop(void)
1724 int pxmc_process_state_check(unsigned long *pbusy_bits,
1725 unsigned long *perror_bits)
1728 unsigned short chan;
1729 unsigned long busy_bits = 0;
1730 unsigned long error_bits = 0;
1733 pxmc_for_each_mcs(chan, mcs) {
1735 flg |= mcs->pxms_flg;
1736 if (mcs->pxms_flg & PXMS_BSY_m)
1737 busy_bits |= 1 << chan;
1738 if (mcs->pxms_flg & PXMS_ERR_m)
1739 error_bits |= 1 << chan;
1742 if (appl_errstop_mode) {
1743 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
1744 pxmc_for_each_mcs(chan, mcs) {
1745 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
1752 if (pbusy_bits != NULL)
1753 *pbusy_bits = busy_bits;
1754 if (error_bits != NULL)
1755 *perror_bits = error_bits;
1765 if (!pxmc_main_list.pxml_cnt)
1768 pxmc_for_each_mcs(var, mcs)
1770 pxmc_set_const_out(mcs,0);
1773 pxmc_main_list.pxml_cnt = 0;
1779 int pxmc_initialize(void)
1784 pxmc_state_t *mcs = &mcs0;
1785 lpc_qei_state_t *qst = &lpc_qei_state;
1787 *fpga_irc_reset = 1;
1789 for (i = 0; i < 8; i++) {
1790 fpga_irc[i]->count = 0;
1791 fpga_irc[i]->count_index = 0;
1792 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
1795 /* Initialize QEI module for IRC counting */
1796 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1798 /* Initialize QEI events processing */
1799 if (lpc_qei_setup_irq(qst) < 0)
1802 *fpga_irc_reset = 0;
1804 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1806 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1807 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1809 pxmc_rocon_pwm_master_init();
1810 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1811 pxmc_rocon_rx_done_isr_setup(pxmc_rocon_rx_done_isr);
1812 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1814 pxmc_main_list.pxml_cnt = 0;
1815 pxmc_dbg_hist = NULL;
1817 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;