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>
31 #include "appl_defs.h"
32 #include "appl_fpga.h"
34 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
35 unsigned long index_irc, int diff2err);
37 #ifndef pxmc_fast_tick_time
38 #define pxmc_fast_tick_time() (LPC_TIM0->TC)
41 #define PXML_MAIN_CNT 8
43 #define PXMC_WITH_PT_ZIC 1
44 #define PXMC_PT_ZIC_MASK 0x8000
46 #define LPCPWM1_FREQ 20000
48 #define HAL_ERR_SENSITIVITY 20
49 #define HAL_ERR_MAX_COUNT 5
51 #define LXPWR_WITH_SIROLADC 1
53 #define LX_MASTER_DATA_OFFS 8
55 unsigned pxmc_rocon_pwm_magnitude = 2500;
57 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
58 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
60 const uint8_t onesin10bits[1024]={
61 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,
62 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,
63 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,
64 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,
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 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,
68 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,
69 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,
70 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,
71 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,
72 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,
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 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,
76 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,
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 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,
86 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,
87 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,
88 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,
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 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,
92 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
96 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
98 int chan=mcs->pxms_inp_info;
102 /* read position from hardware */
103 irc = fpga_irc[chan]->count;
104 irc += pxmc_rocon_irc_offset[chan];
105 pos = irc << PXMC_SUBDIV(mcs);
106 mcs->pxms_as = pos - mcs->pxms_ap;
109 /* Running of the motor commutator */
110 if (mcs->pxms_flg & PXMS_PTI_m)
111 pxmc_irc_16bit_commindx(mcs, irc);
117 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
122 int chan=mcs->pxms_inp_info;
124 irc_state = *fpga_irc_state[chan];
126 mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
127 (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
129 filt = pxmc_rocon_mark_filt[chan];
130 filt = (filt << 1) | mark;
131 pxmc_rocon_mark_filt[chan] = filt;
133 return onesin10bits[filt & 0x03ff];
137 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
141 int chan=mcs->pxms_inp_info;
143 irc_state = *fpga_irc_state[chan];
144 *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
146 index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
152 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
154 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
156 mcs->pxms_ptofs += irc_diff;
158 mcs->pxms_ap += pos_diff;
159 mcs->pxms_rp += pos_diff;
164 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
166 int chan=mcs->pxms_inp_info;
170 irc_offset = -fpga_irc[chan]->count_index;
171 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
172 pxmc_rocon_irc_offset[chan] = irc_offset;
173 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
177 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
179 int chan=mcs->pxms_inp_info;
183 irc_offset = -fpga_irc[chan]->count;
184 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
185 pxmc_rocon_irc_offset[chan] = irc_offset;
186 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
190 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
192 int chan=mcs->pxms_inp_info;
196 irc = fpga_irc[chan]->count;
197 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
199 irc = pos_diff >> PXMC_SUBDIV(mcs);
201 /* Adjust phase table alignemt to modified IRC readout */
202 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
204 pxmc_rocon_irc_offset[chan] = irc;
209 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
211 int chan=mcs->pxms_inp_info;
215 if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
218 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
219 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
221 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
224 uint32_t pxmc_rocon_receiver_dummy_reg;
226 static inline volatile uint32_t *
227 pxmc_rocon_receiver_chan2reg(unsigned chan)
229 volatile uint32_t *rec_reg;
232 return &pxmc_rocon_receiver_dummy_reg;
234 rec_reg = fpga_lx_master_receiver_base;
236 #ifdef LXPWR_WITH_SIROLADC
237 rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 8) * 3 + chan * 2;
238 #else /*LXPWR_WITH_SIROLADC*/
239 rec_reg += LX_MASTER_DATA_OFFS + chan;
240 #endif /*LXPWR_WITH_SIROLADC*/
246 pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
249 volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
250 int chan = mcs->pxms_out_info;
253 #ifdef LXPWR_WITH_SIROLADC
255 #else /*LXPWR_WITH_SIROLADC*/
257 #endif /*LXPWR_WITH_SIROLADC*/
259 rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
260 rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
261 rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
263 h = (rec_reg_a[hal_offs] >> 14) & 1;
264 h |= (rec_reg_b[hal_offs] >> 13) & 2;
265 h |= (rec_reg_c[hal_offs] >> 12) & 4;
267 /* return 3 bits corresponding to the HAL senzor input */
272 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
284 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
297 uint32_t pxmc_rocon_pwm_dummy_reg;
299 static inline volatile uint32_t *
300 pxmc_rocon_pwm_chan2reg(unsigned chan)
302 volatile uint32_t *pwm_reg;
305 return &pxmc_rocon_pwm_dummy_reg;
307 pwm_reg = fpga_lx_master_transmitter_base;
309 #ifdef LXPWR_WITH_SIROLADC
310 pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 8) + chan;
311 #else /*LXPWR_WITH_SIROLADC*/
312 pwm_reg += LX_MASTER_DATA_OFFS + chan;
313 #endif /*LXPWR_WITH_SIROLADC*/
319 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
320 * @mcs: Motion controller state information
322 /*static*/ inline void
323 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
325 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
326 int chan = mcs->pxms_out_info;
328 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
329 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
330 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
338 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
340 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
342 pxmc_set_errno(mcs, PXMS_E_HAL);
347 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
351 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
352 * @mcs: Motion controller state information
355 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
357 typeof(mcs->pxms_ptvang) ptvang;
359 unsigned char hal_pos;
367 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
368 (mcs->pxms_flg & PXMS_PRA_m))
371 short ptirc = mcs->pxms_ptirc;
372 short divisor = mcs->pxms_ptper * 6;
375 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
380 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
382 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
384 pxmc_set_flag(mcs, PXMS_PTI_b);
385 pxmc_set_flag(mcs, PXMS_PHA_b);
390 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
395 pxmc_rocon_process_hal_error(mcs);
399 if (mcs->pxms_halerc)
402 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
404 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
406 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
408 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
410 if ((ptindx > ptindx_prev + ptirc / 2) ||
411 (ptindx_prev > ptindx + ptirc / 2))
413 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
420 ptindx = (ptindx_prev + ptindx) / 2;
423 mcs->pxms_ptindx = ptindx;
425 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
427 pxmc_set_flag(mcs, PXMS_PTI_b);
428 pxmc_clear_flag(mcs, PXMS_PRA_b);
432 if (!(mcs->pxms_flg & PXMS_PTI_m))
433 mcs->pxms_ptindx = ptindx;
436 /* if phase table position to mask is know do fine phase table alignment */
437 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
439 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
441 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
443 pxmc_set_flag(mcs, PXMS_PTI_b);
444 pxmc_set_flag(mcs, PXMS_PHA_b);
448 mcs->pxms_hal = hal_pos;
454 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
455 /* FIXME - check winding current against limit */
456 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
460 ptvang = mcs->pxms_ptvang;
464 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
468 indx = mcs->pxms_ptindx;
470 /* tuning of magnetic field/voltage advance angle */
471 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
476 /* Generating direction of stator mag. field for backward torque */
479 if ((indx -= ptvang) < 0)
480 indx += mcs->pxms_ptirc;
484 /* Generating direction of stator mag. field for forward torque */
485 if ((indx += ptvang) >= mcs->pxms_ptirc)
486 indx -= mcs->pxms_ptirc;
489 if (mcs->pxms_ptscale_mult)
490 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
492 pwm1 = mcs->pxms_ptptr1[indx];
493 pwm2 = mcs->pxms_ptptr2[indx];
494 pwm3 = mcs->pxms_ptptr3[indx];
496 #ifdef PXMC_WITH_PT_ZIC
497 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
499 pwm1 &= ~PXMC_PT_ZIC_MASK;
500 pwm2 &= ~PXMC_PT_ZIC_MASK;
501 pwm3 &= ~PXMC_PT_ZIC_MASK;
503 #endif /*PXMC_WITH_PT_ZIC*/
505 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
506 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
508 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
509 if (pwm1 & PXMC_PT_ZIC_MASK)
512 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
513 if (pwm2 & PXMC_PT_ZIC_MASK)
516 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
517 if (pwm3 & PXMC_PT_ZIC_MASK)
520 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
522 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
526 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
533 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
534 * @mcs: Motion controller state information
536 /*static*/ inline void
537 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
539 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
540 int chan = mcs->pxms_out_info;
542 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
543 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
544 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
545 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
548 *pwm_reg_bp = pwm2 | 0x4000;
552 *pwm_reg_bn = -pwm2 | 0x4000;
556 *pwm_reg_ap = pwm1 | 0x4000;
560 *pwm_reg_an = -pwm1 | 0x4000;
565 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
566 * @mcs: Motion controller state information
569 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
571 typeof(mcs->pxms_ptvang) ptvang;
579 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
580 (mcs->pxms_flg&PXMS_PRA_m)){
582 short ptirc=mcs->pxms_ptirc;
585 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
590 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
592 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
594 pxmc_set_flag(mcs, PXMS_PTI_b);
595 pxmc_set_flag(mcs, PXMS_PHA_b);
600 ptindx = mcs->pxms_ptindx;
602 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
604 mcs->pxms_ptindx = ptindx;
606 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
608 pxmc_set_flag(mcs, PXMS_PTI_b);
609 pxmc_clear_flag(mcs, PXMS_PRA_b);
611 /* if phase table position to mask is know do fine phase table alignment */
612 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
613 // lpc_qei_setup_index_catch(&lpc_qei_state);
616 if(!(mcs->pxms_flg&PXMS_PTI_m))
617 mcs->pxms_ptindx = ptindx;
623 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
624 /* FIXME - check winding current against limit */
625 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
629 ptvang = mcs->pxms_ptvang;
633 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
637 indx = mcs->pxms_ptindx;
639 /* tuning of magnetic field/voltage advance angle */
640 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
643 /* Generating direction of stator mag. field for backward torque */
645 if ((indx -= ptvang)<0)
646 indx += mcs->pxms_ptirc;
648 /* Generating direction of stator mag. field for forward torque */
649 if ((indx += ptvang) >= mcs->pxms_ptirc)
650 indx -= mcs->pxms_ptirc;
653 if (mcs->pxms_ptscale_mult)
654 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
656 pwm1 = mcs->pxms_ptptr1[indx];
657 pwm2 = mcs->pxms_ptptr2[indx];
659 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
660 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
662 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
663 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
664 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
666 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
668 /*pxmc_lpc_wind_current_over_cnt = 0;*/
669 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
676 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
677 * @mcs: Motion controller state information
680 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
682 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
683 int chan = mcs->pxms_out_info;
684 int ene = mcs->pxms_ene;
686 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
687 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
693 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
695 *pwm_reg_b = ene | 0x4000;
699 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
701 *pwm_reg_a = ene | 0x4000;
708 pxmc_rocon_pwm_master_init(void)
714 #ifdef LXPWR_WITH_SIROLADC
715 unsigned lxpwr_header = 1;
716 unsigned lxpwr_words = 1 + 8 * 2 + 2;
717 unsigned lxpwr_chips = 2;
718 unsigned lxpwr_chip_pwm_cnt = 8;
719 #else /*LXPWR_WITH_SIROLADC*/
720 unsigned lxpwr_header = 0;
721 unsigned lxpwr_words = 8;
722 unsigned lxpwr_chips = 2;
723 unsigned lxpwr_chip_pwm_cnt = 8;
724 #endif /*LXPWR_WITH_SIROLADC*/
726 *fpga_lx_master_reset = 1;
727 *fpga_lx_master_transmitter_reg = 0;
729 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
730 fpga_lx_master_receiver_base[i] = 0;
732 word_slot = LX_MASTER_DATA_OFFS;
733 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
734 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
736 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
737 fpga_lx_master_transmitter_base[i] = 0;
739 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
740 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
741 #ifdef LXPWR_WITH_SIROLADC
742 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
743 #endif /*LXPWR_WITH_SIROLADC*/
745 word_slot = LX_MASTER_DATA_OFFS + 0;
746 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
747 #ifdef LXPWR_WITH_SIROLADC
748 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
749 #endif /*LXPWR_WITH_SIROLADC*/
751 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
753 *fpga_lx_master_reset = 0;
758 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
759 unsigned long index_irc, int diff2err)
764 ofs = ofsl = index_irc - mcs->pxms_ptmark;
768 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
769 if (diff >= mcs->pxms_ptirc / 2)
770 diff -= mcs->pxms_ptirc;
771 if (diff <= -mcs->pxms_ptirc / 2)
772 diff += mcs->pxms_ptirc;
775 if(diff >= mcs->pxms_ptirc / 6) {
780 diff = (unsigned long)ofsl - irc;
781 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
784 mcs->pxms_ptofs = ofs;
790 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
791 * @mcs: Motion controller state information
794 pxmc_dummy_con(pxmc_state_t *mcs)
799 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
800 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
801 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
802 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
803 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
804 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
806 /* initialize for hard home */
808 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
810 pxmc_set_flag(mcs,PXMS_BSY_b);
811 #if 0 /* config and speed already set in pxmc_hh */
813 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
815 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
817 mcs->pxms_gen_hsp = spd;
820 mcs->pxms_gen_htim = 16;
821 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
822 return pxmc_rocon_hh_gd10(mcs);
825 /* fill initial mark filter and then decide */
827 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
831 if(mcs->pxms_flg & PXMS_ERR_m)
832 return pxmc_spdnext_gend(mcs);
834 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
835 mcs->pxms_rp += mcs->pxms_rs;
837 mark = pxmc_inp_rocon_is_mark(mcs);
839 if (mcs->pxms_gen_htim) {
840 mcs->pxms_gen_htim--;
844 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
845 /* limit switch is not used */
846 pxmc_inp_rocon_is_index_edge(mcs);
847 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
852 /* go out from switch */
853 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
855 /* switch is off -> look for it */
856 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
861 /* go out from switch */
863 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
867 if(mcs->pxms_flg & PXMS_ERR_m)
868 return pxmc_spdnext_gend(mcs);
870 mark = pxmc_inp_rocon_is_mark(mcs);
873 /* switch is off -> look for it again */
874 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
877 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
878 mcs->pxms_rp += mcs->pxms_rs;
883 /* switch is off -> look for it */
885 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
890 if (mcs->pxms_flg & PXMS_ERR_m)
891 return pxmc_spdnext_gend(mcs);
893 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
894 mcs->pxms_rp += mcs->pxms_rs;
896 mark = pxmc_inp_rocon_is_mark(mcs);
899 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
902 mcs->pxms_gen_hsp = spd;
903 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
909 /* switch is on -> find edge */
911 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
915 if (mcs->pxms_flg & PXMS_ERR_m)
916 return pxmc_spdnext_gend(mcs);
918 mark = pxmc_inp_rocon_is_mark(mcs);
921 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
922 pxmc_inp_rocon_is_index_edge(mcs);
923 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
925 pxmc_inp_rocon_ap_zero(mcs);
926 mcs->pxms_do_gen = pxmc_stop_gi;
930 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
931 mcs->pxms_rp += mcs->pxms_rs;
936 /* calibrate on revolution index */
938 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
940 if (mcs->pxms_flg & PXMS_ERR_m)
941 return pxmc_spdnext_gend(mcs);
943 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
944 mcs->pxms_rp += mcs->pxms_rs;
946 if (pxmc_inp_rocon_is_index_edge(mcs)){
947 pxmc_inp_rocon_irc_offset_from_index(mcs);
948 mcs->pxms_do_gen = pxmc_stop_gi;
954 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
956 return pxmc_rocon_hh_gi;
966 pxmc_pid_con /*pxmc_dummy_con*/,
968 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
972 pxmc_inp_rocon_ap2hw,
973 pxms_ap: 0, pxms_as: 0,
974 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
975 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
978 pxms_ene: 0, pxms_erc: 0,
979 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
980 pxms_me: 0x7e00/*0x7fff*/,
982 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
983 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
984 PXMS_CFG_I2PT_m * 0 | 0x2,
989 /*pxms_ptamp: 0x7fff,*/
1003 pxmc_rocon_pwm_dc_out,
1007 pxmc_inp_rocon_ap2hw,
1008 pxms_ap: 0, pxms_as: 0,
1009 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1010 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1013 pxms_ene: 0, pxms_erc: 0,
1014 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1015 pxms_me: 0x7e00/*0x7fff*/,
1017 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1018 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1019 PXMS_CFG_I2PT_m * 0 | 0x2,
1023 /*pxms_ptamp: 0x7fff,*/
1037 pxmc_rocon_pwm_dc_out,
1041 pxmc_inp_rocon_ap2hw,
1042 pxms_ap: 0, pxms_as: 0,
1043 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1044 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1047 pxms_ene: 0, pxms_erc: 0,
1048 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1049 pxms_me: 0x7e00/*0x7fff*/,
1051 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1052 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1053 PXMS_CFG_HDIR_m | 0x2,
1057 /*pxms_ptamp: 0x7fff,*/
1071 pxmc_rocon_pwm_dc_out,
1075 pxmc_inp_rocon_ap2hw,
1076 pxms_ap: 0, pxms_as: 0,
1077 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1078 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1081 pxms_ene: 0, pxms_erc: 0,
1082 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1083 pxms_me: 0x7e00/*0x7fff*/,
1085 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1086 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1087 PXMS_CFG_HDIR_m * 0 | 0x2,
1091 /*pxms_ptamp: 0x7fff,*/
1105 pxmc_rocon_pwm_dc_out,
1109 pxmc_inp_rocon_ap2hw,
1110 pxms_ap: 0, pxms_as: 0,
1111 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1112 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1115 pxms_ene: 0, pxms_erc: 0,
1116 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1117 pxms_me: 0x7e00/*0x7fff*/,
1119 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1120 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1121 PXMS_CFG_HDIR_m | 0x2,
1125 /*pxms_ptamp: 0x7fff,*/
1139 pxmc_rocon_pwm_dc_out,
1143 pxmc_inp_rocon_ap2hw,
1144 pxms_ap: 0, pxms_as: 0,
1145 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1146 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1149 pxms_ene: 0, pxms_erc: 0,
1150 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1151 pxms_me: 0x7e00/*0x7fff*/,
1153 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1154 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1155 PXMS_CFG_HDIR_m | 0x2,
1159 /*pxms_ptamp: 0x7fff,*/
1173 pxmc_rocon_pwm_dc_out,
1177 pxmc_inp_rocon_ap2hw,
1178 pxms_ap: 0, pxms_as: 0,
1179 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1180 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1183 pxms_ene: 0, pxms_erc: 0,
1184 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1185 pxms_me: 0x7e00/*0x7fff*/,
1187 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1192 /*pxms_ptamp: 0x7fff,*/
1206 pxmc_rocon_pwm_dc_out,
1210 pxmc_inp_rocon_ap2hw,
1211 pxms_ap: 0, pxms_as: 0,
1212 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1213 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1216 pxms_ene: 0, pxms_erc: 0,
1217 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1218 pxms_me: 0x7e00/*0x7fff*/,
1220 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1225 /*pxms_ptamp: 0x7fff,*/
1231 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1232 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1235 pxmc_state_list_t pxmc_main_list =
1242 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1244 pxmc_state_t *mcs = (pxmc_state_t *)context;
1247 irc = qst->index_pos;
1249 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1252 ofs = irc - mcs->pxms_ptmark;
1253 diff = ofs - mcs->pxms_ptofs;
1255 if (diff >= mcs->pxms_ptirc / 2)
1256 diff -= mcs->pxms_ptirc;
1258 if (diff <= -mcs->pxms_ptirc / 2)
1259 diff += mcs->pxms_ptirc;
1264 if (diff >= mcs->pxms_ptirc / 6)
1266 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1270 mcs->pxms_ptofs = ofs;
1271 pxmc_set_flag(mcs, PXMS_PHA_b);
1275 ofs=irc-mcs->pxms_ptofs;
1276 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1278 ofs-=mcs->pxms_ptirc;
1280 ofs+=mcs->pxms_ptirc;
1283 mcs->pxms_ptmark=ofs;
1286 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1289 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1293 lpc_qei_state_t *qst = &lpc_qei_state;
1294 int irc = lpc_qei_get_pos(qst);
1297 if (!qst->index_occ)
1300 idx_rel = qst->index_pos - irc;
1301 idx_rel %= mcs->pxms_ptirc;
1304 idx_rel += mcs->pxms_ptirc;
1306 ptofs = irc - mcs->pxms_ptofs;
1307 ptmark = ptofs + idx_rel;
1309 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1312 ptmark -= mcs->pxms_ptirc;
1314 ptmark += mcs->pxms_ptirc;
1317 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1319 mcs->pxms_ptmark = ptmark;
1325 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1330 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1331 lpc_qei_state_t *qst = &lpc_qei_state;
1333 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1334 lpc_qei_setup_index_catch(qst);
1336 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1337 spd = 1 << PXMC_SUBDIV(mcs);
1339 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1344 int pxmc_lpc_pthalalign_run(void)
1346 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1349 static inline void pxmc_sfi_input(void)
1353 pxmc_for_each_mcs(var, mcs)
1355 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1356 if (mcs->pxms_flg & PXMS_ENI_m)
1358 pxmc_call(mcs, mcs->pxms_do_inp);
1363 static inline void pxmc_sfi_controller_and_output(void)
1367 pxmc_for_each_mcs(var, mcs)
1369 /* PXMS_ENR_m - check if controller is enabled */
1370 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1373 /* If output only is enabled, we skip the controller */
1374 if (mcs->pxms_flg & PXMS_ENR_m)
1377 pxmc_call(mcs, mcs->pxms_do_con);
1379 /* PXMS_ERR_m - if axis in error state */
1380 if (mcs->pxms_flg & PXMS_ERR_m)
1384 /* for bushless motors, it is necessary to call do_out
1385 even if the controller is not enabled and PWM should be provided. */
1386 pxmc_call(mcs, mcs->pxms_do_out);
1391 static inline void pxmc_sfi_generator(void)
1395 pxmc_for_each_mcs(var, mcs)
1397 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1398 if (mcs->pxms_flg & PXMS_ENG_m)
1400 pxmc_call(mcs, mcs->pxms_do_gen);
1405 static inline void pxmc_sfi_dbg(void)
1409 pxmc_for_each_mcs(var, mcs)
1411 if (mcs->pxms_flg & PXMS_DBG_m)
1413 pxmc_call(mcs, mcs->pxms_do_deb);
1418 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1422 int inp_chan = mcs->pxms_inp_info;
1424 long irc = fpga_irc[inp_chan]->count;
1426 if (!pxmc_inp_rocon_is_index_edge(mcs))
1429 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1430 idx_rel %= mcs->pxms_ptirc;
1432 idx_rel += mcs->pxms_ptirc;
1434 ptofs = irc-mcs->pxms_ptofs;
1435 ptmark = ptofs+idx_rel;
1437 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1439 ptmark -= mcs->pxms_ptirc;
1441 ptmark += mcs->pxms_ptirc;
1444 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1445 mcs->pxms_ptmark = ptmark;
1450 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1455 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1457 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1459 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1460 spd=1<<PXMC_SUBDIV(mcs);
1462 /* clear bit indicating previous index */
1463 pxmc_inp_rocon_is_index_edge(mcs);
1465 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1470 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1472 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1473 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1474 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1475 return PXMC_AXIS_MODE_DC;
1476 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1477 return PXMC_AXIS_MODE_BLDC;
1483 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1485 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1488 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1489 mode = pxmc_axis_rdmode(mcs);
1494 /*case PXMC_AXIS_MODE_STEPPER:*/
1495 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1496 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1498 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1499 case PXMC_AXIS_MODE_DC:
1500 /*profive some sane dummy values*/
1501 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1502 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1503 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1505 mcs->pxms_ptscale_mult=1;
1506 mcs->pxms_ptscale_shift=15;
1508 case PXMC_AXIS_MODE_BLDC:
1509 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1510 #ifndef PXMC_WITH_PT_ZIC
1511 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1512 #else /*PXMC_WITH_PT_ZIC*/
1513 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1514 #endif /*PXMC_WITH_PT_ZIC*/
1520 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1526 * pxmc_axis_mode - Sets axis mode.[extern API]
1527 * @mcs: Motion controller state information
1528 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1529 * 2 .. stepper motor with IRC feedback and PWM ,
1530 * 3 .. stepper motor with PWM control
1531 * 4 .. DC motor with IRC feedback and PWM
1535 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1539 pxmc_set_const_out(mcs, 0);
1540 pxmc_clear_flag(mcs, PXMS_ENI_b);
1541 pxmc_clear_flags(mcs,PXMS_ENO_m);
1542 /* Clear possible stall index flags from hardware */
1543 pxmc_inp_rocon_is_index_edge(mcs);
1544 pxmc_clear_flag(mcs, PXMS_PHA_b);
1545 pxmc_clear_flag(mcs, PXMS_PTI_b);
1548 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1549 mode = pxmc_axis_rdmode(mcs);
1553 mode = PXMC_AXIS_MODE_DC;
1555 res = pxmc_axis_pt4mode(mcs, mode);
1560 /*case PXMC_AXIS_MODE_STEPPER:*/
1561 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1562 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1564 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1565 case PXMC_AXIS_MODE_DC:
1566 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1568 case PXMC_AXIS_MODE_BLDC:
1569 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1575 /* Clear possible stall index flags from hardware */
1576 pxmc_inp_rocon_is_index_edge(mcs);
1577 /* Request new phases alignment for changed parameters */
1578 pxmc_clear_flag(mcs, PXMS_PHA_b);
1579 pxmc_clear_flag(mcs, PXMS_PTI_b);
1580 pxmc_set_flag(mcs, PXMS_ENI_b);
1584 void pxmc_sfi_isr(void)
1586 unsigned long spent = pxmc_fast_tick_time();
1589 pxmc_sfi_controller_and_output();
1590 pxmc_sfi_generator();
1592 /* Kick LX Master watchdog */
1593 if (pxmc_main_list.pxml_cnt != 0)
1594 *fpga_lx_master_transmitter_wdog = 1;
1596 spent = pxmc_fast_tick_time() - spent;
1598 if(spent > pxmc_sfi_spent_time_max)
1599 pxmc_sfi_spent_time_max = spent;
1603 int pxmc_clear_power_stop(void)
1608 int pxmc_process_state_check(unsigned long *pbusy_bits,
1609 unsigned long *perror_bits)
1612 unsigned short chan;
1613 unsigned long busy_bits = 0;
1614 unsigned long error_bits = 0;
1617 pxmc_for_each_mcs(chan, mcs) {
1619 flg |= mcs->pxms_flg;
1620 if (mcs->pxms_flg & PXMS_BSY_m)
1621 busy_bits |= 1 << chan;
1622 if (mcs->pxms_flg & PXMS_ERR_m)
1623 error_bits |= 1 << chan;
1626 if (appl_errstop_mode) {
1627 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
1628 pxmc_for_each_mcs(chan, mcs) {
1629 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
1636 if (pbusy_bits != NULL)
1637 *pbusy_bits = busy_bits;
1638 if (error_bits != NULL)
1639 *perror_bits = error_bits;
1649 if (!pxmc_main_list.pxml_cnt)
1652 pxmc_for_each_mcs(var, mcs)
1654 pxmc_set_const_out(mcs,0);
1657 pxmc_main_list.pxml_cnt = 0;
1663 int pxmc_initialize(void)
1668 pxmc_state_t *mcs = &mcs0;
1669 lpc_qei_state_t *qst = &lpc_qei_state;
1671 *fpga_irc_reset = 1;
1673 for (i = 0; i < 8; i++) {
1674 fpga_irc[i]->count = 0;
1675 fpga_irc[i]->count_index = 0;
1676 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
1679 /* Initialize QEI module for IRC counting */
1680 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1682 /* Initialize QEI events processing */
1683 if (lpc_qei_setup_irq(qst) < 0)
1686 *fpga_irc_reset = 0;
1688 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1690 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1691 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1693 pxmc_rocon_pwm_master_init();
1695 pxmc_main_list.pxml_cnt = 0;
1696 pxmc_dbg_hist = NULL;
1698 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;