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;
234 #if 0 /* FPGA design version 2 */
235 pwm_reg += 1 + (chan >> 8) + chan;
236 #else /* FPGA design version 3 */
243 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
244 * @mcs: Motion controller state information
246 /*static*/ inline void
247 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
249 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
250 int chan = mcs->pxms_out_info;
252 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
253 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
254 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 2);
262 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
264 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
266 pxmc_set_errno(mcs, PXMS_E_HAL);
271 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
275 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
276 * @mcs: Motion controller state information
279 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
281 unsigned char hal_pos;
289 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
290 (mcs->pxms_flg & PXMS_PRA_m))
293 short ptirc = mcs->pxms_ptirc;
294 short divisor = mcs->pxms_ptper * 6;
296 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
301 pxmc_rocon_process_hal_error(mcs);
305 if (mcs->pxms_halerc)
308 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
310 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
312 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
314 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
316 if ((ptindx > ptindx_prev + ptirc / 2) ||
317 (ptindx_prev > ptindx + ptirc / 2))
319 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
326 ptindx = (ptindx_prev + ptindx) / 2;
329 mcs->pxms_ptindx = ptindx;
331 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
333 pxmc_set_flag(mcs, PXMS_PTI_b);
334 pxmc_clear_flag(mcs, PXMS_PRA_b);
336 /* if phase table position to mask is know do fine phase table alignment */
337 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m)
338 lpc_qei_setup_index_catch(&lpc_qei_state);
343 if (!(mcs->pxms_flg & PXMS_PTI_m))
344 mcs->pxms_ptindx = ptindx;
348 mcs->pxms_hal = hal_pos;
353 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
354 /* FIXME - check winding current against limit */
355 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
362 indx = mcs->pxms_ptindx;
364 /* tuning of magnetic field/voltage advance angle */
365 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
370 /* Generating direction of stator mag. field for backward torque */
373 if ((indx -= mcs->pxms_ptvang) < 0)
374 indx += mcs->pxms_ptirc;
378 /* Generating direction of stator mag. field for forward torque */
379 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
380 indx -= mcs->pxms_ptirc;
383 if (mcs->pxms_ptscale_mult)
384 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
386 pwm1 = mcs->pxms_ptptr1[indx];
387 pwm2 = mcs->pxms_ptptr2[indx];
388 pwm3 = mcs->pxms_ptptr3[indx];
390 #ifdef PXMC_WITH_PT_ZIC
391 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
393 pwm1 &= ~PXMC_PT_ZIC_MASK;
394 pwm2 &= ~PXMC_PT_ZIC_MASK;
395 pwm3 &= ~PXMC_PT_ZIC_MASK;
397 #endif /*PXMC_WITH_PT_ZIC*/
399 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
400 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
402 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
403 if (pwm1 & PXMC_PT_ZIC_MASK)
406 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
407 if (pwm2 & PXMC_PT_ZIC_MASK)
410 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
411 if (pwm3 & PXMC_PT_ZIC_MASK)
414 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
416 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
420 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
427 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
428 * @mcs: Motion controller state information
430 /*static*/ inline void
431 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
433 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
434 int chan = mcs->pxms_out_info;
436 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 0);
437 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 1);
438 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 2);
439 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 3);
442 *pwm_reg_bp = pwm2 | 0x4000;
446 *pwm_reg_bn = -pwm2 | 0x4000;
450 *pwm_reg_ap = pwm1 | 0x4000;
454 *pwm_reg_an = -pwm1 | 0x4000;
459 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
460 * @mcs: Motion controller state information
463 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
471 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
472 (mcs->pxms_flg&PXMS_PRA_m)){
474 short ptirc=mcs->pxms_ptirc;
476 pxmc_irc_16bit_commindx(mcs,mcs->pxms_rp>>PXMC_SUBDIV(mcs));
478 ptindx = mcs->pxms_ptindx;
480 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
482 mcs->pxms_ptindx = ptindx;
484 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
486 pxmc_set_flag(mcs, PXMS_PTI_b);
487 pxmc_clear_flag(mcs, PXMS_PRA_b);
489 /* if phase table position to mask is know do fine phase table alignment */
490 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
491 // lpc_qei_setup_index_catch(&lpc_qei_state);
494 if(!(mcs->pxms_flg&PXMS_PTI_m))
495 mcs->pxms_ptindx = ptindx;
500 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
501 /* FIXME - check winding current against limit */
502 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
506 //if (ene) { /*FIXME*/
507 if (mcs->pxms_flg&PXMS_BSY_m){
508 ene = mcs->pxms_me; /*FIXME*/
510 indx = mcs->pxms_ptindx;
512 /* tuning of magnetic field/voltage advance angle */
513 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
516 /* Generating direction of stator mag. field for backward torque */
518 if ((indx -= mcs->pxms_ptvang)<0)
519 indx += mcs->pxms_ptirc;
521 /* Generating direction of stator mag. field for forward torque */
522 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
523 indx -= mcs->pxms_ptirc;
526 if (mcs->pxms_ptscale_mult)
527 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
529 pwm1 = mcs->pxms_ptptr1[indx];
530 pwm2 = mcs->pxms_ptptr2[indx];
532 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
533 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
535 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
536 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
537 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
539 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
541 /*pxmc_lpc_wind_current_over_cnt = 0;*/
542 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
549 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
550 * @mcs: Motion controller state information
553 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
555 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
556 int chan = mcs->pxms_out_info;
557 int ene = mcs->pxms_ene;
559 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
560 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
566 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
568 *pwm_reg_b = ene | 0x4000;
572 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
574 *pwm_reg_a = ene | 0x4000;
580 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
582 pxmc_rocon_pwm_master_init(void)
586 *fpga_lx_master_reset = 1;
587 *fpga_lx_master_transmitter_reg = 0;
589 for (i = 0; i < 8 + 16; i ++)
590 fpga_lx_master_transmitter_base[i] = 0;
592 fpga_lx_master_transmitter_base[0] = 0x0808;
593 fpga_lx_master_transmitter_base[1] = 0x0000;
595 *fpga_lx_master_reset = 0;
600 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
601 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
602 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
603 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
604 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
605 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
607 /* initialize for hard home */
609 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
611 pxmc_set_flag(mcs,PXMS_BSY_b);
612 #if 0 /* config and speed already set in pxmc_hh */
614 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
616 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
618 mcs->pxms_gen_hsp = spd;
621 mcs->pxms_gen_htim = 16;
622 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
623 return pxmc_rocon_hh_gd10(mcs);
626 /* fill initial mark filter and then decide */
628 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
632 if(mcs->pxms_flg & PXMS_ERR_m)
633 return pxmc_spdnext_gend(mcs);
635 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
636 mcs->pxms_rp += mcs->pxms_rs;
638 mark = pxmc_inp_rocon_is_mark(mcs);
640 if (mcs->pxms_gen_htim) {
641 mcs->pxms_gen_htim--;
645 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
646 /* limit switch is not used */
647 pxmc_inp_rocon_is_index_edge(mcs);
648 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
653 /* go out from switch */
654 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
656 /* switch is off -> look for it */
657 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
662 /* go out from switch */
664 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
668 if(mcs->pxms_flg & PXMS_ERR_m)
669 return pxmc_spdnext_gend(mcs);
671 mark = pxmc_inp_rocon_is_mark(mcs);
674 /* switch is off -> look for it again */
675 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
678 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
679 mcs->pxms_rp += mcs->pxms_rs;
684 /* switch is off -> look for it */
686 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
691 if (mcs->pxms_flg & PXMS_ERR_m)
692 return pxmc_spdnext_gend(mcs);
694 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
695 mcs->pxms_rp += mcs->pxms_rs;
697 mark = pxmc_inp_rocon_is_mark(mcs);
700 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
703 mcs->pxms_gen_hsp = spd;
704 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
710 /* switch is on -> find edge */
712 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
716 if (mcs->pxms_flg & PXMS_ERR_m)
717 return pxmc_spdnext_gend(mcs);
719 mark = pxmc_inp_rocon_is_mark(mcs);
722 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
723 pxmc_inp_rocon_is_index_edge(mcs);
724 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
726 pxmc_inp_rocon_ap_zero(mcs);
727 mcs->pxms_do_gen = pxmc_stop_gi;
731 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
732 mcs->pxms_rp += mcs->pxms_rs;
737 /* calibrate on revolution index */
739 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
741 if (mcs->pxms_flg & PXMS_ERR_m)
742 return pxmc_spdnext_gend(mcs);
744 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
745 mcs->pxms_rp += mcs->pxms_rs;
747 if (pxmc_inp_rocon_is_index_edge(mcs)){
748 pxmc_inp_rocon_irc_offset_from_index(mcs);
749 mcs->pxms_do_gen = pxmc_stop_gi;
755 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
757 return pxmc_rocon_hh_gi;
769 pxmc_rocon_pwm_dc_out,
773 pxmc_inp_rocon_ap2hw,
774 pxms_ap: 0, pxms_as: 0,
775 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
776 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
779 pxms_ene: 0, pxms_erc: 0,
780 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
781 pxms_me: 0x7e00/*0x7fff*/,
783 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
788 /*pxms_ptamp: 0x7fff,*/
802 pxmc_rocon_pwm_dc_out,
806 pxmc_inp_rocon_ap2hw,
807 pxms_ap: 0, pxms_as: 0,
808 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
809 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
812 pxms_ene: 0, pxms_erc: 0,
813 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
814 pxms_me: 0x7e00/*0x7fff*/,
816 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
821 /*pxms_ptamp: 0x7fff,*/
835 pxmc_rocon_pwm_dc_out,
839 pxmc_inp_rocon_ap2hw,
840 pxms_ap: 0, pxms_as: 0,
841 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
842 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
845 pxms_ene: 0, pxms_erc: 0,
846 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
847 pxms_me: 0x7e00/*0x7fff*/,
849 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
854 /*pxms_ptamp: 0x7fff,*/
868 pxmc_rocon_pwm_dc_out,
872 pxmc_inp_rocon_ap2hw,
873 pxms_ap: 0, pxms_as: 0,
874 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
875 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
878 pxms_ene: 0, pxms_erc: 0,
879 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
880 pxms_me: 0x7e00/*0x7fff*/,
882 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
887 /*pxms_ptamp: 0x7fff,*/
901 pxmc_rocon_pwm_dc_out,
905 pxmc_inp_rocon_ap2hw,
906 pxms_ap: 0, pxms_as: 0,
907 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
908 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
911 pxms_ene: 0, pxms_erc: 0,
912 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
913 pxms_me: 0x7e00/*0x7fff*/,
915 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
920 /*pxms_ptamp: 0x7fff,*/
934 pxmc_rocon_pwm_dc_out,
938 pxmc_inp_rocon_ap2hw,
939 pxms_ap: 0, pxms_as: 0,
940 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
941 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
944 pxms_ene: 0, pxms_erc: 0,
945 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
946 pxms_me: 0x7e00/*0x7fff*/,
948 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
953 /*pxms_ptamp: 0x7fff,*/
967 pxmc_rocon_pwm_dc_out,
971 pxmc_inp_rocon_ap2hw,
972 pxms_ap: 0, pxms_as: 0,
973 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
974 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
977 pxms_ene: 0, pxms_erc: 0,
978 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
979 pxms_me: 0x7e00/*0x7fff*/,
981 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
986 /*pxms_ptamp: 0x7fff,*/
1000 pxmc_rocon_pwm_dc_out,
1004 pxmc_inp_rocon_ap2hw,
1005 pxms_ap: 0, pxms_as: 0,
1006 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1007 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1010 pxms_ene: 0, pxms_erc: 0,
1011 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1012 pxms_me: 0x7e00/*0x7fff*/,
1014 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1019 /*pxms_ptamp: 0x7fff,*/
1025 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1026 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1029 pxmc_state_list_t pxmc_main_list =
1036 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1038 pxmc_state_t *mcs = (pxmc_state_t *)context;
1041 irc = qst->index_pos;
1043 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1046 ofs = irc - mcs->pxms_ptmark;
1047 diff = ofs - mcs->pxms_ptofs;
1049 if (diff >= mcs->pxms_ptirc / 2)
1050 diff -= mcs->pxms_ptirc;
1052 if (diff <= -mcs->pxms_ptirc / 2)
1053 diff += mcs->pxms_ptirc;
1058 if (diff >= mcs->pxms_ptirc / 6)
1060 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1064 mcs->pxms_ptofs = ofs;
1065 pxmc_set_flag(mcs, PXMS_PHA_b);
1069 ofs=irc-mcs->pxms_ptofs;
1070 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1072 ofs-=mcs->pxms_ptirc;
1074 ofs+=mcs->pxms_ptirc;
1077 mcs->pxms_ptmark=ofs;
1080 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1083 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1087 lpc_qei_state_t *qst = &lpc_qei_state;
1088 int irc = lpc_qei_get_pos(qst);
1091 if (!qst->index_occ)
1094 idx_rel = qst->index_pos - irc;
1095 idx_rel %= mcs->pxms_ptirc;
1098 idx_rel += mcs->pxms_ptirc;
1100 ptofs = irc - mcs->pxms_ptofs;
1101 ptmark = ptofs + idx_rel;
1103 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1106 ptmark -= mcs->pxms_ptirc;
1108 ptmark += mcs->pxms_ptirc;
1111 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1113 mcs->pxms_ptmark = ptmark;
1119 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1124 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1125 lpc_qei_state_t *qst = &lpc_qei_state;
1127 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1128 lpc_qei_setup_index_catch(qst);
1130 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1131 spd = 1 << PXMC_SUBDIV(mcs);
1133 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1138 int pxmc_lpc_pthalalign_run(void)
1140 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1143 static inline void pxmc_sfi_input(void)
1147 pxmc_for_each_mcs(var, mcs)
1149 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1150 if (mcs->pxms_flg & PXMS_ENI_m)
1152 pxmc_call(mcs, mcs->pxms_do_inp);
1157 static inline void pxmc_sfi_controller_and_output(void)
1161 pxmc_for_each_mcs(var, mcs)
1163 /* PXMS_ENR_m - check if controller is enabled */
1164 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1167 /* If output only is enabled, we skip the controller */
1168 if (mcs->pxms_flg & PXMS_ENR_m)
1171 pxmc_call(mcs, mcs->pxms_do_con);
1173 /* PXMS_ERR_m - if axis in error state */
1174 if (mcs->pxms_flg & PXMS_ERR_m)
1178 /* for bushless motors, it is necessary to call do_out
1179 even if the controller is not enabled and PWM should be provided. */
1180 pxmc_call(mcs, mcs->pxms_do_out);
1185 static inline void pxmc_sfi_generator(void)
1189 pxmc_for_each_mcs(var, mcs)
1191 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1192 if (mcs->pxms_flg & PXMS_ENG_m)
1194 pxmc_call(mcs, mcs->pxms_do_gen);
1199 static inline void pxmc_sfi_dbg(void)
1203 pxmc_for_each_mcs(var, mcs)
1205 if (mcs->pxms_flg & PXMS_DBG_m)
1207 pxmc_call(mcs, mcs->pxms_do_deb);
1212 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1216 int inp_chan = mcs->pxms_inp_info;
1218 long irc = fpga_irc[inp_chan]->count;
1220 if (!pxmc_inp_rocon_is_index_edge(mcs))
1223 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1224 idx_rel %= mcs->pxms_ptirc;
1226 idx_rel += mcs->pxms_ptirc;
1228 ptofs = irc-mcs->pxms_ptofs;
1229 ptmark = ptofs+idx_rel;
1231 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1233 ptmark -= mcs->pxms_ptirc;
1235 ptmark += mcs->pxms_ptirc;
1238 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1239 mcs->pxms_ptmark = ptmark;
1244 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1249 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1251 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1253 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1254 spd=1<<PXMC_SUBDIV(mcs);
1256 /* clear bit indicating previous index */
1257 pxmc_inp_rocon_is_index_edge(mcs);
1259 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1265 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1269 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1271 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1272 #ifndef PXMC_WITH_PT_ZIC
1273 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1274 #else /*PXMC_WITH_PT_ZIC*/
1275 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1276 #endif /*PXMC_WITH_PT_ZIC*/
1282 * pxmc_axis_mode - Sets axis mode.[extern API]
1283 * @mcs: Motion controller state information
1284 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1285 * 2 .. stepper motor with IRC feedback and PWM ,
1286 * 3 .. stepper motor with PWM control
1287 * 4 .. DC motor with IRC feedback and PWM
1291 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1295 pxmc_set_const_out(mcs, 0);
1296 pxmc_clear_flag(mcs, PXMS_ENI_b);
1297 pxmc_clear_flag(mcs, PXMS_PHA_b);
1298 pxmc_clear_flag(mcs, PXMS_PTI_b);
1302 /*mode=pxmc_axis_rdmode(mcs);*/
1304 mode = PXMC_AXIS_MODE_BLDC;
1307 res = pxmc_axis_pt4mode(mcs, mode);
1309 pxmc_set_flag(mcs, PXMS_ENI_b);
1313 void pxmc_sfi_isr(void)
1316 pxmc_sfi_controller_and_output();
1317 pxmc_sfi_generator();
1319 /* Kick LX Master watchdog */
1320 if (pxmc_main_list.pxml_cnt != 0)
1321 *fpga_lx_master_transmitter_wdog = 1;
1329 if (!pxmc_main_list.pxml_cnt)
1332 pxmc_for_each_mcs(var, mcs)
1334 pxmc_set_const_out(mcs,0);
1337 pxmc_main_list.pxml_cnt = 0;
1343 int pxmc_initialize(void)
1347 pxmc_state_t *mcs = &mcs0;
1348 lpc_qei_state_t *qst = &lpc_qei_state;
1350 *fpga_irc_reset = 1;
1352 /* Initialize QEI module for IRC counting */
1353 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1355 /* Initialize QEI events processing */
1356 if (lpc_qei_setup_irq(qst) < 0)
1359 *fpga_irc_reset = 0;
1361 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1363 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1364 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1366 pxmc_rocon_pwm_master_init();
1368 pxmc_main_list.pxml_cnt = 0;
1369 pxmc_dbg_hist = NULL;
1371 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;