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;
728 *fpga_lx_master_transmitter_cycle = 2500; /* 50 MHz -> 20 kHz */
729 *fpga_lx_master_receiver_done_div = 1 << 8;
731 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
732 fpga_lx_master_receiver_base[i] = 0;
734 word_slot = LX_MASTER_DATA_OFFS;
735 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
736 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
738 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
739 fpga_lx_master_transmitter_base[i] = 0;
741 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
742 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
743 #ifdef LXPWR_WITH_SIROLADC
744 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
745 #endif /*LXPWR_WITH_SIROLADC*/
747 word_slot = LX_MASTER_DATA_OFFS + 0;
748 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
749 #ifdef LXPWR_WITH_SIROLADC
750 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
751 #endif /*LXPWR_WITH_SIROLADC*/
753 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
755 *fpga_lx_master_reset = 0;
756 *fpga_lx_master_transmitter_cycle = 2500; /* 50 MHz -> 20 kHz */
757 *fpga_lx_master_receiver_done_div = 1 << 8;
762 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
763 unsigned long index_irc, int diff2err)
768 ofs = ofsl = index_irc - mcs->pxms_ptmark;
772 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
773 if (diff >= mcs->pxms_ptirc / 2)
774 diff -= mcs->pxms_ptirc;
775 if (diff <= -mcs->pxms_ptirc / 2)
776 diff += mcs->pxms_ptirc;
779 if(diff >= mcs->pxms_ptirc / 6) {
784 diff = (unsigned long)ofsl - irc;
785 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
788 mcs->pxms_ptofs = ofs;
794 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
795 * @mcs: Motion controller state information
798 pxmc_dummy_con(pxmc_state_t *mcs)
803 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
804 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
805 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
806 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
807 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
808 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
810 /* initialize for hard home */
812 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
814 pxmc_set_flag(mcs,PXMS_BSY_b);
815 #if 0 /* config and speed already set in pxmc_hh */
817 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
819 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
821 mcs->pxms_gen_hsp = spd;
824 mcs->pxms_gen_htim = 16;
825 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
826 return pxmc_rocon_hh_gd10(mcs);
829 /* fill initial mark filter and then decide */
831 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
835 if(mcs->pxms_flg & PXMS_ERR_m)
836 return pxmc_spdnext_gend(mcs);
838 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
839 mcs->pxms_rp += mcs->pxms_rs;
841 mark = pxmc_inp_rocon_is_mark(mcs);
843 if (mcs->pxms_gen_htim) {
844 mcs->pxms_gen_htim--;
848 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
849 /* limit switch is not used */
850 pxmc_inp_rocon_is_index_edge(mcs);
851 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
856 /* go out from switch */
857 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
859 /* switch is off -> look for it */
860 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
865 /* go out from switch */
867 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
871 if(mcs->pxms_flg & PXMS_ERR_m)
872 return pxmc_spdnext_gend(mcs);
874 mark = pxmc_inp_rocon_is_mark(mcs);
877 /* switch is off -> look for it again */
878 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
881 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
882 mcs->pxms_rp += mcs->pxms_rs;
887 /* switch is off -> look for it */
889 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
894 if (mcs->pxms_flg & PXMS_ERR_m)
895 return pxmc_spdnext_gend(mcs);
897 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
898 mcs->pxms_rp += mcs->pxms_rs;
900 mark = pxmc_inp_rocon_is_mark(mcs);
903 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
906 mcs->pxms_gen_hsp = spd;
907 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
913 /* switch is on -> find edge */
915 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
919 if (mcs->pxms_flg & PXMS_ERR_m)
920 return pxmc_spdnext_gend(mcs);
922 mark = pxmc_inp_rocon_is_mark(mcs);
925 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
926 pxmc_inp_rocon_is_index_edge(mcs);
927 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
929 pxmc_inp_rocon_ap_zero(mcs);
930 mcs->pxms_do_gen = pxmc_stop_gi;
934 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
935 mcs->pxms_rp += mcs->pxms_rs;
940 /* calibrate on revolution index */
942 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
944 if (mcs->pxms_flg & PXMS_ERR_m)
945 return pxmc_spdnext_gend(mcs);
947 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
948 mcs->pxms_rp += mcs->pxms_rs;
950 if (pxmc_inp_rocon_is_index_edge(mcs)){
951 pxmc_inp_rocon_irc_offset_from_index(mcs);
952 mcs->pxms_do_gen = pxmc_stop_gi;
958 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
960 return pxmc_rocon_hh_gi;
970 pxmc_pid_con /*pxmc_dummy_con*/,
972 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
976 pxmc_inp_rocon_ap2hw,
977 pxms_ap: 0, pxms_as: 0,
978 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
979 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
982 pxms_ene: 0, pxms_erc: 0,
983 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
984 pxms_me: 0x7e00/*0x7fff*/,
986 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
987 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
988 PXMS_CFG_I2PT_m * 0 | 0x2,
993 /*pxms_ptamp: 0x7fff,*/
1007 pxmc_rocon_pwm_dc_out,
1011 pxmc_inp_rocon_ap2hw,
1012 pxms_ap: 0, pxms_as: 0,
1013 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1014 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1017 pxms_ene: 0, pxms_erc: 0,
1018 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1019 pxms_me: 0x7e00/*0x7fff*/,
1021 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1022 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1023 PXMS_CFG_I2PT_m * 0 | 0x2,
1027 /*pxms_ptamp: 0x7fff,*/
1041 pxmc_rocon_pwm_dc_out,
1045 pxmc_inp_rocon_ap2hw,
1046 pxms_ap: 0, pxms_as: 0,
1047 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1048 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1051 pxms_ene: 0, pxms_erc: 0,
1052 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1053 pxms_me: 0x7e00/*0x7fff*/,
1055 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1056 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1057 PXMS_CFG_HDIR_m | 0x2,
1061 /*pxms_ptamp: 0x7fff,*/
1075 pxmc_rocon_pwm_dc_out,
1079 pxmc_inp_rocon_ap2hw,
1080 pxms_ap: 0, pxms_as: 0,
1081 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1082 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1085 pxms_ene: 0, pxms_erc: 0,
1086 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1087 pxms_me: 0x7e00/*0x7fff*/,
1089 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1090 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1091 PXMS_CFG_HDIR_m * 0 | 0x2,
1095 /*pxms_ptamp: 0x7fff,*/
1109 pxmc_rocon_pwm_dc_out,
1113 pxmc_inp_rocon_ap2hw,
1114 pxms_ap: 0, pxms_as: 0,
1115 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1116 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1119 pxms_ene: 0, pxms_erc: 0,
1120 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1121 pxms_me: 0x7e00/*0x7fff*/,
1123 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1124 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1125 PXMS_CFG_HDIR_m | 0x2,
1129 /*pxms_ptamp: 0x7fff,*/
1143 pxmc_rocon_pwm_dc_out,
1147 pxmc_inp_rocon_ap2hw,
1148 pxms_ap: 0, pxms_as: 0,
1149 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1150 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1153 pxms_ene: 0, pxms_erc: 0,
1154 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1155 pxms_me: 0x7e00/*0x7fff*/,
1157 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1158 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1159 PXMS_CFG_HDIR_m | 0x2,
1163 /*pxms_ptamp: 0x7fff,*/
1177 pxmc_rocon_pwm_dc_out,
1181 pxmc_inp_rocon_ap2hw,
1182 pxms_ap: 0, pxms_as: 0,
1183 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1184 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1187 pxms_ene: 0, pxms_erc: 0,
1188 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1189 pxms_me: 0x7e00/*0x7fff*/,
1191 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1196 /*pxms_ptamp: 0x7fff,*/
1210 pxmc_rocon_pwm_dc_out,
1214 pxmc_inp_rocon_ap2hw,
1215 pxms_ap: 0, pxms_as: 0,
1216 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1217 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1220 pxms_ene: 0, pxms_erc: 0,
1221 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1222 pxms_me: 0x7e00/*0x7fff*/,
1224 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1229 /*pxms_ptamp: 0x7fff,*/
1235 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1236 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1239 pxmc_state_list_t pxmc_main_list =
1246 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1248 pxmc_state_t *mcs = (pxmc_state_t *)context;
1251 irc = qst->index_pos;
1253 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1256 ofs = irc - mcs->pxms_ptmark;
1257 diff = ofs - mcs->pxms_ptofs;
1259 if (diff >= mcs->pxms_ptirc / 2)
1260 diff -= mcs->pxms_ptirc;
1262 if (diff <= -mcs->pxms_ptirc / 2)
1263 diff += mcs->pxms_ptirc;
1268 if (diff >= mcs->pxms_ptirc / 6)
1270 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1274 mcs->pxms_ptofs = ofs;
1275 pxmc_set_flag(mcs, PXMS_PHA_b);
1279 ofs=irc-mcs->pxms_ptofs;
1280 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1282 ofs-=mcs->pxms_ptirc;
1284 ofs+=mcs->pxms_ptirc;
1287 mcs->pxms_ptmark=ofs;
1290 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1293 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1297 lpc_qei_state_t *qst = &lpc_qei_state;
1298 int irc = lpc_qei_get_pos(qst);
1301 if (!qst->index_occ)
1304 idx_rel = qst->index_pos - irc;
1305 idx_rel %= mcs->pxms_ptirc;
1308 idx_rel += mcs->pxms_ptirc;
1310 ptofs = irc - mcs->pxms_ptofs;
1311 ptmark = ptofs + idx_rel;
1313 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1316 ptmark -= mcs->pxms_ptirc;
1318 ptmark += mcs->pxms_ptirc;
1321 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1323 mcs->pxms_ptmark = ptmark;
1329 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1334 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1335 lpc_qei_state_t *qst = &lpc_qei_state;
1337 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1338 lpc_qei_setup_index_catch(qst);
1340 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1341 spd = 1 << PXMC_SUBDIV(mcs);
1343 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1348 int pxmc_lpc_pthalalign_run(void)
1350 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1353 static inline void pxmc_sfi_input(void)
1357 pxmc_for_each_mcs(var, mcs)
1359 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1360 if (mcs->pxms_flg & PXMS_ENI_m)
1362 pxmc_call(mcs, mcs->pxms_do_inp);
1367 static inline void pxmc_sfi_controller_and_output(void)
1371 pxmc_for_each_mcs(var, mcs)
1373 /* PXMS_ENR_m - check if controller is enabled */
1374 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1377 /* If output only is enabled, we skip the controller */
1378 if (mcs->pxms_flg & PXMS_ENR_m)
1381 pxmc_call(mcs, mcs->pxms_do_con);
1383 /* PXMS_ERR_m - if axis in error state */
1384 if (mcs->pxms_flg & PXMS_ERR_m)
1388 /* for bushless motors, it is necessary to call do_out
1389 even if the controller is not enabled and PWM should be provided. */
1390 pxmc_call(mcs, mcs->pxms_do_out);
1395 static inline void pxmc_sfi_generator(void)
1399 pxmc_for_each_mcs(var, mcs)
1401 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1402 if (mcs->pxms_flg & PXMS_ENG_m)
1404 pxmc_call(mcs, mcs->pxms_do_gen);
1409 static inline void pxmc_sfi_dbg(void)
1413 pxmc_for_each_mcs(var, mcs)
1415 if (mcs->pxms_flg & PXMS_DBG_m)
1417 pxmc_call(mcs, mcs->pxms_do_deb);
1422 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1426 int inp_chan = mcs->pxms_inp_info;
1428 long irc = fpga_irc[inp_chan]->count;
1430 if (!pxmc_inp_rocon_is_index_edge(mcs))
1433 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1434 idx_rel %= mcs->pxms_ptirc;
1436 idx_rel += mcs->pxms_ptirc;
1438 ptofs = irc-mcs->pxms_ptofs;
1439 ptmark = ptofs+idx_rel;
1441 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1443 ptmark -= mcs->pxms_ptirc;
1445 ptmark += mcs->pxms_ptirc;
1448 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1449 mcs->pxms_ptmark = ptmark;
1454 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1459 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1461 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1463 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1464 spd=1<<PXMC_SUBDIV(mcs);
1466 /* clear bit indicating previous index */
1467 pxmc_inp_rocon_is_index_edge(mcs);
1469 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1474 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1476 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1477 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1478 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1479 return PXMC_AXIS_MODE_DC;
1480 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1481 return PXMC_AXIS_MODE_BLDC;
1487 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1489 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1492 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1493 mode = pxmc_axis_rdmode(mcs);
1498 /*case PXMC_AXIS_MODE_STEPPER:*/
1499 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1500 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1502 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1503 case PXMC_AXIS_MODE_DC:
1504 /*profive some sane dummy values*/
1505 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1506 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1507 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1509 mcs->pxms_ptscale_mult=1;
1510 mcs->pxms_ptscale_shift=15;
1512 case PXMC_AXIS_MODE_BLDC:
1513 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1514 #ifndef PXMC_WITH_PT_ZIC
1515 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1516 #else /*PXMC_WITH_PT_ZIC*/
1517 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1518 #endif /*PXMC_WITH_PT_ZIC*/
1524 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1530 * pxmc_axis_mode - Sets axis mode.[extern API]
1531 * @mcs: Motion controller state information
1532 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1533 * 2 .. stepper motor with IRC feedback and PWM ,
1534 * 3 .. stepper motor with PWM control
1535 * 4 .. DC motor with IRC feedback and PWM
1539 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1543 pxmc_set_const_out(mcs, 0);
1544 pxmc_clear_flag(mcs, PXMS_ENI_b);
1545 pxmc_clear_flags(mcs,PXMS_ENO_m);
1546 /* Clear possible stall index flags from hardware */
1547 pxmc_inp_rocon_is_index_edge(mcs);
1548 pxmc_clear_flag(mcs, PXMS_PHA_b);
1549 pxmc_clear_flag(mcs, PXMS_PTI_b);
1552 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1553 mode = pxmc_axis_rdmode(mcs);
1557 mode = PXMC_AXIS_MODE_DC;
1559 res = pxmc_axis_pt4mode(mcs, mode);
1564 /*case PXMC_AXIS_MODE_STEPPER:*/
1565 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1566 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1568 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1569 case PXMC_AXIS_MODE_DC:
1570 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1572 case PXMC_AXIS_MODE_BLDC:
1573 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1579 /* Clear possible stall index flags from hardware */
1580 pxmc_inp_rocon_is_index_edge(mcs);
1581 /* Request new phases alignment for changed parameters */
1582 pxmc_clear_flag(mcs, PXMS_PHA_b);
1583 pxmc_clear_flag(mcs, PXMS_PTI_b);
1584 pxmc_set_flag(mcs, PXMS_ENI_b);
1588 void pxmc_sfi_isr(void)
1590 unsigned long spent = pxmc_fast_tick_time();
1593 pxmc_sfi_controller_and_output();
1594 pxmc_sfi_generator();
1596 /* Kick LX Master watchdog */
1597 if (pxmc_main_list.pxml_cnt != 0)
1598 *fpga_lx_master_transmitter_wdog = 1;
1600 spent = pxmc_fast_tick_time() - spent;
1602 if(spent > pxmc_sfi_spent_time_max)
1603 pxmc_sfi_spent_time_max = spent;
1607 int pxmc_clear_power_stop(void)
1612 int pxmc_process_state_check(unsigned long *pbusy_bits,
1613 unsigned long *perror_bits)
1616 unsigned short chan;
1617 unsigned long busy_bits = 0;
1618 unsigned long error_bits = 0;
1621 pxmc_for_each_mcs(chan, mcs) {
1623 flg |= mcs->pxms_flg;
1624 if (mcs->pxms_flg & PXMS_BSY_m)
1625 busy_bits |= 1 << chan;
1626 if (mcs->pxms_flg & PXMS_ERR_m)
1627 error_bits |= 1 << chan;
1630 if (appl_errstop_mode) {
1631 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
1632 pxmc_for_each_mcs(chan, mcs) {
1633 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
1640 if (pbusy_bits != NULL)
1641 *pbusy_bits = busy_bits;
1642 if (error_bits != NULL)
1643 *perror_bits = error_bits;
1653 if (!pxmc_main_list.pxml_cnt)
1656 pxmc_for_each_mcs(var, mcs)
1658 pxmc_set_const_out(mcs,0);
1661 pxmc_main_list.pxml_cnt = 0;
1667 int pxmc_initialize(void)
1672 pxmc_state_t *mcs = &mcs0;
1673 lpc_qei_state_t *qst = &lpc_qei_state;
1675 *fpga_irc_reset = 1;
1677 for (i = 0; i < 8; i++) {
1678 fpga_irc[i]->count = 0;
1679 fpga_irc[i]->count_index = 0;
1680 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
1683 /* Initialize QEI module for IRC counting */
1684 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1686 /* Initialize QEI events processing */
1687 if (lpc_qei_setup_irq(qst) < 0)
1690 *fpga_irc_reset = 0;
1692 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1694 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1695 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1697 pxmc_rocon_pwm_master_init();
1699 pxmc_main_list.pxml_cnt = 0;
1700 pxmc_dbg_hist = NULL;
1702 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;