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>
30 #include "appl_defs.h"
31 #include "appl_fpga.h"
33 #define PXML_MAIN_CNT 8
35 #define PXMC_WITH_PT_ZIC 1
36 #define PXMC_PT_ZIC_MASK 0x8000
38 #define LPCPWM1_FREQ 20000
40 #define HAL_ERR_SENSITIVITY 20
41 #define HAL_ERR_MAX_COUNT 5
43 unsigned pxmc_rocon_pwm_magnitude = 2500;
45 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
46 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
48 const uint8_t onesin10bits[1024]={
49 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,
50 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,
51 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,
52 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,
53 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,
54 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,
55 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,
56 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,
57 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,
58 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,
59 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,
60 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,
61 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,
62 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,
63 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,
64 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,
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 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 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,
72 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,
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 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 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,
80 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
84 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
86 int chan=mcs->pxms_inp_info;
90 /* read position from hardware */
91 irc = fpga_irc[chan]->count;
92 irc += pxmc_rocon_irc_offset[chan];
93 pos = irc << PXMC_SUBDIV(mcs);
94 mcs->pxms_as = pos - mcs->pxms_ap;
97 /* Running of the motor commutator */
98 if (mcs->pxms_flg & PXMS_PTI_m)
99 pxmc_irc_16bit_commindx(mcs, irc);
105 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
110 int chan=mcs->pxms_inp_info;
112 irc_state = *fpga_irc_state[chan];
114 mark = (irc_state ^ (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
116 filt = pxmc_rocon_mark_filt[chan];
117 filt = (filt << 1) | mark;
118 pxmc_rocon_mark_filt[chan] = filt;
120 return onesin10bits[filt & 0x03ff];
124 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
128 int chan=mcs->pxms_inp_info;
130 irc_state = *fpga_irc_state[chan];
131 *fpga_irc_state[chan] = 1 << 2;
133 index = (irc_state >> 2) & 1;
139 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
141 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
143 mcs->pxms_ap += pos_diff;
144 mcs->pxms_rp += pos_diff;
149 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
151 int chan=mcs->pxms_inp_info;
155 irc_offset = -fpga_irc[chan]->count_index;
156 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
157 pxmc_rocon_irc_offset[chan] = irc_offset;
158 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
162 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
164 int chan=mcs->pxms_inp_info;
168 irc_offset = -fpga_irc[chan]->count;
169 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
170 pxmc_rocon_irc_offset[chan] = irc_offset;
171 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
175 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
177 int chan=mcs->pxms_inp_info;
181 irc = fpga_irc[chan]->count;
182 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
183 pxmc_rocon_irc_offset[chan] = pos_diff >> PXMC_SUBDIV(mcs);
188 pxmc_rocon_bdc_hal_rd(pxmc_state_t *mcs)
193 /* return 3 bits corresponding to the HAL senzor input */
198 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
210 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
223 uint32_t pxmc_rocon_pwm_dummy_reg;
225 static inline volatile uint32_t *
226 pxmc_rocon_pwm_chan2reg(unsigned chan)
228 volatile uint32_t *pwm_reg;
231 return &pxmc_rocon_pwm_dummy_reg;
233 pwm_reg = fpga_lx_master_transmitter_base;
239 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
240 * @mcs: Motion controller state information
242 /*static*/ inline void
243 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
245 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
246 int chan = mcs->pxms_out_info;
248 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
249 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
250 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 2);
258 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
260 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
262 pxmc_set_errno(mcs, PXMS_E_HAL);
267 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
271 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
272 * @mcs: Motion controller state information
275 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
277 unsigned char hal_pos;
285 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
286 (mcs->pxms_flg & PXMS_PRA_m))
289 short ptirc = mcs->pxms_ptirc;
290 short divisor = mcs->pxms_ptper * 6;
292 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
297 pxmc_rocon_process_hal_error(mcs);
301 if (mcs->pxms_halerc)
304 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
306 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
308 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
310 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
312 if ((ptindx > ptindx_prev + ptirc / 2) ||
313 (ptindx_prev > ptindx + ptirc / 2))
315 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
322 ptindx = (ptindx_prev + ptindx) / 2;
325 mcs->pxms_ptindx = ptindx;
327 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
329 pxmc_set_flag(mcs, PXMS_PTI_b);
330 pxmc_clear_flag(mcs, PXMS_PRA_b);
332 /* if phase table position to mask is know do fine phase table alignment */
333 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m)
334 lpc_qei_setup_index_catch(&lpc_qei_state);
339 if (!(mcs->pxms_flg & PXMS_PTI_m))
340 mcs->pxms_ptindx = ptindx;
344 mcs->pxms_hal = hal_pos;
349 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
350 /* FIXME - check winding current against limit */
351 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
358 indx = mcs->pxms_ptindx;
360 /* tuning of magnetic field/voltage advance angle */
361 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
366 /* Generating direction of stator mag. field for backward torque */
369 if ((indx -= mcs->pxms_ptvang) < 0)
370 indx += mcs->pxms_ptirc;
374 /* Generating direction of stator mag. field for forward torque */
375 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
376 indx -= mcs->pxms_ptirc;
379 if (mcs->pxms_ptscale_mult)
380 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
382 pwm1 = mcs->pxms_ptptr1[indx];
383 pwm2 = mcs->pxms_ptptr2[indx];
384 pwm3 = mcs->pxms_ptptr3[indx];
386 #ifdef PXMC_WITH_PT_ZIC
387 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
389 pwm1 &= ~PXMC_PT_ZIC_MASK;
390 pwm2 &= ~PXMC_PT_ZIC_MASK;
391 pwm3 &= ~PXMC_PT_ZIC_MASK;
393 #endif /*PXMC_WITH_PT_ZIC*/
395 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
396 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
398 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
399 if (pwm1 & PXMC_PT_ZIC_MASK)
402 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
403 if (pwm2 & PXMC_PT_ZIC_MASK)
406 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
407 if (pwm3 & PXMC_PT_ZIC_MASK)
410 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
412 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
416 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
423 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
424 * @mcs: Motion controller state information
426 /*static*/ inline void
427 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
429 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
430 int chan = mcs->pxms_out_info;
432 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 0);
433 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 1);
434 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 2);
435 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 3);
438 *pwm_reg_bp = pwm2 | 0x4000;
442 *pwm_reg_bn = -pwm2 | 0x4000;
446 *pwm_reg_ap = pwm1 | 0x4000;
450 *pwm_reg_an = -pwm1 | 0x4000;
455 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
456 * @mcs: Motion controller state information
459 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
467 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
468 (mcs->pxms_flg&PXMS_PRA_m)){
470 short ptirc=mcs->pxms_ptirc;
472 pxmc_irc_16bit_commindx(mcs,mcs->pxms_rp>>PXMC_SUBDIV(mcs));
474 ptindx = mcs->pxms_ptindx;
476 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
478 mcs->pxms_ptindx = ptindx;
480 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
482 pxmc_set_flag(mcs, PXMS_PTI_b);
483 pxmc_clear_flag(mcs, PXMS_PRA_b);
485 /* if phase table position to mask is know do fine phase table alignment */
486 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
487 // lpc_qei_setup_index_catch(&lpc_qei_state);
490 if(!(mcs->pxms_flg&PXMS_PTI_m))
491 mcs->pxms_ptindx = ptindx;
496 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
497 /* FIXME - check winding current against limit */
498 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
502 //if (ene) { /*FIXME*/
503 if (mcs->pxms_flg&PXMS_BSY_m){
504 ene = mcs->pxms_me; /*FIXME*/
506 indx = mcs->pxms_ptindx;
508 /* tuning of magnetic field/voltage advance angle */
509 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
512 /* Generating direction of stator mag. field for backward torque */
514 if ((indx -= mcs->pxms_ptvang)<0)
515 indx += mcs->pxms_ptirc;
517 /* Generating direction of stator mag. field for forward torque */
518 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
519 indx -= mcs->pxms_ptirc;
522 if (mcs->pxms_ptscale_mult)
523 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
525 pwm1 = mcs->pxms_ptptr1[indx];
526 pwm2 = mcs->pxms_ptptr2[indx];
528 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
529 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
531 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
532 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
533 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
535 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
537 /*pxmc_lpc_wind_current_over_cnt = 0;*/
538 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
545 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
546 * @mcs: Motion controller state information
549 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
551 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
552 int chan = mcs->pxms_out_info;
553 int ene = mcs->pxms_ene;
555 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
556 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
562 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
564 *pwm_reg_b = ene | 0x4000;
568 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
570 *pwm_reg_a = ene | 0x4000;
576 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
578 pxmc_rocon_pwm_master_init(void)
582 *fpga_lx_master_reset = 1;
583 *fpga_lx_master_transmitter_reg = 0;
585 for (i = 0; i < 8 + 16; i ++)
586 fpga_lx_master_transmitter_base[i] = 0;
588 fpga_lx_master_transmitter_base[0] = 0x0808;
589 fpga_lx_master_transmitter_base[1] = 0x0000;
591 *fpga_lx_master_reset = 0;
596 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
597 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
598 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
599 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
600 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
601 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
603 /* initialize for hard home */
605 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
607 pxmc_set_flag(mcs,PXMS_BSY_b);
608 #if 0 /* config and speed already set in pxmc_hh */
610 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
612 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
614 mcs->pxms_gen_hsp = spd;
617 mcs->pxms_gen_htim = 16;
618 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
619 return pxmc_rocon_hh_gd10(mcs);
622 /* fill initial mark filter and then decide */
624 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
628 if(mcs->pxms_flg & PXMS_ERR_m)
629 return pxmc_spdnext_gend(mcs);
631 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
632 mcs->pxms_rp += mcs->pxms_rs;
634 mark = pxmc_inp_rocon_is_mark(mcs);
636 if (mcs->pxms_gen_htim) {
637 mcs->pxms_gen_htim--;
641 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
642 /* limit switch is not used */
643 pxmc_inp_rocon_is_index_edge(mcs);
644 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
649 /* go out from switch */
650 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
652 /* switch is off -> look for it */
653 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
658 /* go out from switch */
660 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
664 if(mcs->pxms_flg & PXMS_ERR_m)
665 return pxmc_spdnext_gend(mcs);
667 mark = pxmc_inp_rocon_is_mark(mcs);
670 /* switch is off -> look for it again */
671 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
674 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
675 mcs->pxms_rp += mcs->pxms_rs;
680 /* switch is off -> look for it */
682 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
687 if (mcs->pxms_flg & PXMS_ERR_m)
688 return pxmc_spdnext_gend(mcs);
690 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
691 mcs->pxms_rp += mcs->pxms_rs;
693 mark = pxmc_inp_rocon_is_mark(mcs);
696 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
699 mcs->pxms_gen_hsp = spd;
700 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
706 /* switch is on -> find edge */
708 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
712 if (mcs->pxms_flg & PXMS_ERR_m)
713 return pxmc_spdnext_gend(mcs);
715 mark = pxmc_inp_rocon_is_mark(mcs);
718 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
719 pxmc_inp_rocon_is_index_edge(mcs);
720 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
722 pxmc_inp_rocon_ap_zero(mcs);
723 mcs->pxms_do_gen = pxmc_stop_gi;
727 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
728 mcs->pxms_rp += mcs->pxms_rs;
733 /* calibrate on revolution index */
735 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
737 if (mcs->pxms_flg & PXMS_ERR_m)
738 return pxmc_spdnext_gend(mcs);
740 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
741 mcs->pxms_rp += mcs->pxms_rs;
743 if (pxmc_inp_rocon_is_index_edge(mcs)){
744 pxmc_inp_rocon_irc_offset_from_index(mcs);
745 mcs->pxms_do_gen = pxmc_stop_gi;
751 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
753 return pxmc_rocon_hh_gi;
765 pxmc_rocon_pwm_dc_out,
769 pxmc_inp_rocon_ap2hw,
770 pxms_ap: 0, pxms_as: 0,
771 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
772 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
775 pxms_ene: 0, pxms_erc: 0,
776 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
777 pxms_me: 0x7e00/*0x7fff*/,
779 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
784 /*pxms_ptamp: 0x7fff,*/
798 pxmc_rocon_pwm_dc_out,
802 pxmc_inp_rocon_ap2hw,
803 pxms_ap: 0, pxms_as: 0,
804 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
805 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
808 pxms_ene: 0, pxms_erc: 0,
809 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
810 pxms_me: 0x7e00/*0x7fff*/,
812 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
817 /*pxms_ptamp: 0x7fff,*/
831 pxmc_rocon_pwm_dc_out,
835 pxmc_inp_rocon_ap2hw,
836 pxms_ap: 0, pxms_as: 0,
837 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
838 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
841 pxms_ene: 0, pxms_erc: 0,
842 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
843 pxms_me: 0x7e00/*0x7fff*/,
845 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
850 /*pxms_ptamp: 0x7fff,*/
864 pxmc_rocon_pwm_dc_out,
868 pxmc_inp_rocon_ap2hw,
869 pxms_ap: 0, pxms_as: 0,
870 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
871 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
874 pxms_ene: 0, pxms_erc: 0,
875 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
876 pxms_me: 0x7e00/*0x7fff*/,
878 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
883 /*pxms_ptamp: 0x7fff,*/
897 pxmc_rocon_pwm_dc_out,
901 pxmc_inp_rocon_ap2hw,
902 pxms_ap: 0, pxms_as: 0,
903 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
904 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
907 pxms_ene: 0, pxms_erc: 0,
908 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
909 pxms_me: 0x7e00/*0x7fff*/,
911 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
916 /*pxms_ptamp: 0x7fff,*/
930 pxmc_rocon_pwm_dc_out,
934 pxmc_inp_rocon_ap2hw,
935 pxms_ap: 0, pxms_as: 0,
936 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
937 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
940 pxms_ene: 0, pxms_erc: 0,
941 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
942 pxms_me: 0x7e00/*0x7fff*/,
944 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
949 /*pxms_ptamp: 0x7fff,*/
963 pxmc_rocon_pwm_dc_out,
967 pxmc_inp_rocon_ap2hw,
968 pxms_ap: 0, pxms_as: 0,
969 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
970 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
973 pxms_ene: 0, pxms_erc: 0,
974 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
975 pxms_me: 0x7e00/*0x7fff*/,
977 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
982 /*pxms_ptamp: 0x7fff,*/
996 pxmc_rocon_pwm_dc_out,
1000 pxmc_inp_rocon_ap2hw,
1001 pxms_ap: 0, pxms_as: 0,
1002 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1003 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1006 pxms_ene: 0, pxms_erc: 0,
1007 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1008 pxms_me: 0x7e00/*0x7fff*/,
1010 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1015 /*pxms_ptamp: 0x7fff,*/
1021 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1022 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1025 pxmc_state_list_t pxmc_main_list =
1032 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1034 pxmc_state_t *mcs = (pxmc_state_t *)context;
1037 irc = qst->index_pos;
1039 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1042 ofs = irc - mcs->pxms_ptmark;
1043 diff = ofs - mcs->pxms_ptofs;
1045 if (diff >= mcs->pxms_ptirc / 2)
1046 diff -= mcs->pxms_ptirc;
1048 if (diff <= -mcs->pxms_ptirc / 2)
1049 diff += mcs->pxms_ptirc;
1054 if (diff >= mcs->pxms_ptirc / 6)
1056 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1060 mcs->pxms_ptofs = ofs;
1061 pxmc_set_flag(mcs, PXMS_PHA_b);
1065 ofs=irc-mcs->pxms_ptofs;
1066 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1068 ofs-=mcs->pxms_ptirc;
1070 ofs+=mcs->pxms_ptirc;
1073 mcs->pxms_ptmark=ofs;
1076 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1079 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1083 lpc_qei_state_t *qst = &lpc_qei_state;
1084 int irc = lpc_qei_get_pos(qst);
1087 if (!qst->index_occ)
1090 idx_rel = qst->index_pos - irc;
1091 idx_rel %= mcs->pxms_ptirc;
1094 idx_rel += mcs->pxms_ptirc;
1096 ptofs = irc - mcs->pxms_ptofs;
1097 ptmark = ptofs + idx_rel;
1099 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1102 ptmark -= mcs->pxms_ptirc;
1104 ptmark += mcs->pxms_ptirc;
1107 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1109 mcs->pxms_ptmark = ptmark;
1115 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1120 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1121 lpc_qei_state_t *qst = &lpc_qei_state;
1123 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1124 lpc_qei_setup_index_catch(qst);
1126 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1127 spd = 1 << PXMC_SUBDIV(mcs);
1129 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1134 int pxmc_lpc_pthalalign_run(void)
1136 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1139 static inline void pxmc_sfi_input(void)
1143 pxmc_for_each_mcs(var, mcs)
1145 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1146 if (mcs->pxms_flg & PXMS_ENI_m)
1148 pxmc_call(mcs, mcs->pxms_do_inp);
1153 static inline void pxmc_sfi_controller_and_output(void)
1157 pxmc_for_each_mcs(var, mcs)
1159 /* PXMS_ENR_m - check if controller is enabled */
1160 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1163 /* If output only is enabled, we skip the controller */
1164 if (mcs->pxms_flg & PXMS_ENR_m)
1167 pxmc_call(mcs, mcs->pxms_do_con);
1169 /* PXMS_ERR_m - if axis in error state */
1170 if (mcs->pxms_flg & PXMS_ERR_m)
1174 /* for bushless motors, it is necessary to call do_out
1175 even if the controller is not enabled and PWM should be provided. */
1176 pxmc_call(mcs, mcs->pxms_do_out);
1181 static inline void pxmc_sfi_generator(void)
1185 pxmc_for_each_mcs(var, mcs)
1187 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1188 if (mcs->pxms_flg & PXMS_ENG_m)
1190 pxmc_call(mcs, mcs->pxms_do_gen);
1195 static inline void pxmc_sfi_dbg(void)
1199 pxmc_for_each_mcs(var, mcs)
1201 if (mcs->pxms_flg & PXMS_DBG_m)
1203 pxmc_call(mcs, mcs->pxms_do_deb);
1208 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1212 int inp_chan = mcs->pxms_inp_info;
1214 long irc = fpga_irc[inp_chan]->count;
1216 if (!pxmc_inp_rocon_is_index_edge(mcs))
1219 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1220 idx_rel %= mcs->pxms_ptirc;
1222 idx_rel += mcs->pxms_ptirc;
1224 ptofs = irc-mcs->pxms_ptofs;
1225 ptmark = ptofs+idx_rel;
1227 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1229 ptmark -= mcs->pxms_ptirc;
1231 ptmark += mcs->pxms_ptirc;
1234 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1235 mcs->pxms_ptmark = ptmark;
1240 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1245 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1247 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1249 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1250 spd=1<<PXMC_SUBDIV(mcs);
1252 /* clear bit indicating previous index */
1253 pxmc_inp_rocon_is_index_edge(mcs);
1255 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1261 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1265 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1267 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1268 #ifndef PXMC_WITH_PT_ZIC
1269 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1270 #else /*PXMC_WITH_PT_ZIC*/
1271 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1272 #endif /*PXMC_WITH_PT_ZIC*/
1278 * pxmc_axis_mode - Sets axis mode.[extern API]
1279 * @mcs: Motion controller state information
1280 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1281 * 2 .. stepper motor with IRC feedback and PWM ,
1282 * 3 .. stepper motor with PWM control
1283 * 4 .. DC motor with IRC feedback and PWM
1287 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1291 pxmc_set_const_out(mcs, 0);
1292 pxmc_clear_flag(mcs, PXMS_ENI_b);
1293 pxmc_clear_flag(mcs, PXMS_PHA_b);
1294 pxmc_clear_flag(mcs, PXMS_PTI_b);
1298 /*mode=pxmc_axis_rdmode(mcs);*/
1300 mode = PXMC_AXIS_MODE_BLDC;
1303 res = pxmc_axis_pt4mode(mcs, mode);
1305 pxmc_set_flag(mcs, PXMS_ENI_b);
1309 void pxmc_sfi_isr(void)
1312 pxmc_sfi_controller_and_output();
1313 pxmc_sfi_generator();
1315 /* Kick LX Master watchdog */
1316 if (pxmc_main_list.pxml_cnt != 0)
1317 *fpga_lx_master_transmitter_wdog = 1;
1325 if (!pxmc_main_list.pxml_cnt)
1328 pxmc_for_each_mcs(var, mcs)
1330 pxmc_set_const_out(mcs,0);
1333 pxmc_main_list.pxml_cnt = 0;
1339 int pxmc_initialize(void)
1343 pxmc_state_t *mcs = &mcs0;
1344 lpc_qei_state_t *qst = &lpc_qei_state;
1346 *fpga_irc_reset = 1;
1348 /* Initialize QEI module for IRC counting */
1349 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1351 /* Initialize QEI events processing */
1352 if (lpc_qei_setup_irq(qst) < 0)
1355 *fpga_irc_reset = 0;
1357 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1359 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1360 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1362 pxmc_rocon_pwm_master_init();
1364 pxmc_main_list.pxml_cnt = 0;
1365 pxmc_dbg_hist = NULL;
1367 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;