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 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
34 unsigned long index_irc, int diff2err);
36 #define PXML_MAIN_CNT 8
38 #define PXMC_WITH_PT_ZIC 1
39 #define PXMC_PT_ZIC_MASK 0x8000
41 #define LPCPWM1_FREQ 20000
43 #define HAL_ERR_SENSITIVITY 20
44 #define HAL_ERR_MAX_COUNT 5
46 unsigned pxmc_rocon_pwm_magnitude = 2500;
48 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
49 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
51 const uint8_t onesin10bits[1024]={
52 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,
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 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,
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 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,
57 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,
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 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,
60 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,
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 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,
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 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 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,
66 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,
67 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,
68 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,
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 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 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 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
73 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,
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 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,
76 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,
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 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,
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 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 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,
82 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,
83 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
87 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
89 int chan=mcs->pxms_inp_info;
93 /* read position from hardware */
94 irc = fpga_irc[chan]->count;
95 irc += pxmc_rocon_irc_offset[chan];
96 pos = irc << PXMC_SUBDIV(mcs);
97 mcs->pxms_as = pos - mcs->pxms_ap;
100 /* Running of the motor commutator */
101 if (mcs->pxms_flg & PXMS_PTI_m)
102 pxmc_irc_16bit_commindx(mcs, irc);
108 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
113 int chan=mcs->pxms_inp_info;
115 irc_state = *fpga_irc_state[chan];
117 mark = (irc_state ^ (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
119 filt = pxmc_rocon_mark_filt[chan];
120 filt = (filt << 1) | mark;
121 pxmc_rocon_mark_filt[chan] = filt;
123 return onesin10bits[filt & 0x03ff];
127 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
131 int chan=mcs->pxms_inp_info;
133 irc_state = *fpga_irc_state[chan];
134 *fpga_irc_state[chan] = 1 << 2;
136 index = (irc_state >> 2) & 1;
142 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
144 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
146 mcs->pxms_ptofs += irc_diff;
148 mcs->pxms_ap += pos_diff;
149 mcs->pxms_rp += pos_diff;
154 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
156 int chan=mcs->pxms_inp_info;
160 irc_offset = -fpga_irc[chan]->count_index;
161 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
162 pxmc_rocon_irc_offset[chan] = irc_offset;
163 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
167 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
169 int chan=mcs->pxms_inp_info;
173 irc_offset = -fpga_irc[chan]->count;
174 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
175 pxmc_rocon_irc_offset[chan] = irc_offset;
176 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
180 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
182 int chan=mcs->pxms_inp_info;
186 irc = fpga_irc[chan]->count;
187 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
189 irc = pos_diff >> PXMC_SUBDIV(mcs);
191 /* Adjust phase table alignemt to modified IRC readout */
192 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
194 pxmc_rocon_irc_offset[chan] = irc;
199 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
201 int chan=mcs->pxms_inp_info;
205 if (!(*fpga_irc_state[chan] & (1 << 2)))
208 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
209 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
211 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
215 pxmc_rocon_bdc_hal_rd(pxmc_state_t *mcs)
220 /* return 3 bits corresponding to the HAL senzor input */
225 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
237 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
250 uint32_t pxmc_rocon_pwm_dummy_reg;
252 static inline volatile uint32_t *
253 pxmc_rocon_pwm_chan2reg(unsigned chan)
255 volatile uint32_t *pwm_reg;
258 return &pxmc_rocon_pwm_dummy_reg;
260 pwm_reg = fpga_lx_master_transmitter_base;
261 #if 0 /* FPGA design version 2 */
262 pwm_reg += 1 + (chan >> 8) + chan;
263 #else /* FPGA design version 3 */
270 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
271 * @mcs: Motion controller state information
273 /*static*/ inline void
274 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
276 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
277 int chan = mcs->pxms_out_info;
279 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
280 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
281 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
289 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
291 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
293 pxmc_set_errno(mcs, PXMS_E_HAL);
298 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
302 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
303 * @mcs: Motion controller state information
306 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
308 unsigned char hal_pos;
316 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
317 (mcs->pxms_flg & PXMS_PRA_m))
320 short ptirc = mcs->pxms_ptirc;
321 short divisor = mcs->pxms_ptper * 6;
324 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
328 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
330 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
332 pxmc_set_flag(mcs, PXMS_PTI_b);
333 pxmc_set_flag(mcs, PXMS_PHA_b);
338 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
343 pxmc_rocon_process_hal_error(mcs);
347 if (mcs->pxms_halerc)
350 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
352 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
354 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
356 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
358 if ((ptindx > ptindx_prev + ptirc / 2) ||
359 (ptindx_prev > ptindx + ptirc / 2))
361 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
368 ptindx = (ptindx_prev + ptindx) / 2;
371 mcs->pxms_ptindx = ptindx;
373 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
375 pxmc_set_flag(mcs, PXMS_PTI_b);
376 pxmc_clear_flag(mcs, PXMS_PRA_b);
378 /* if phase table position to mask is know do fine phase table alignment */
379 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
380 /*pxmc_inp_rocon_is_index_edge(mcs);*/
385 if (!(mcs->pxms_flg & PXMS_PTI_m))
386 mcs->pxms_ptindx = ptindx;
390 mcs->pxms_hal = hal_pos;
396 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
397 /* FIXME - check winding current against limit */
398 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
404 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
408 indx = mcs->pxms_ptindx;
410 /* tuning of magnetic field/voltage advance angle */
411 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
416 /* Generating direction of stator mag. field for backward torque */
419 if ((indx -= mcs->pxms_ptvang) < 0)
420 indx += mcs->pxms_ptirc;
424 /* Generating direction of stator mag. field for forward torque */
425 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
426 indx -= mcs->pxms_ptirc;
429 if (mcs->pxms_ptscale_mult)
430 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
432 pwm1 = mcs->pxms_ptptr1[indx];
433 pwm2 = mcs->pxms_ptptr2[indx];
434 pwm3 = mcs->pxms_ptptr3[indx];
436 #ifdef PXMC_WITH_PT_ZIC
437 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
439 pwm1 &= ~PXMC_PT_ZIC_MASK;
440 pwm2 &= ~PXMC_PT_ZIC_MASK;
441 pwm3 &= ~PXMC_PT_ZIC_MASK;
443 #endif /*PXMC_WITH_PT_ZIC*/
445 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
446 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
448 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
449 if (pwm1 & PXMC_PT_ZIC_MASK)
452 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
453 if (pwm2 & PXMC_PT_ZIC_MASK)
456 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
457 if (pwm3 & PXMC_PT_ZIC_MASK)
460 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
462 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
466 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
473 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
474 * @mcs: Motion controller state information
476 /*static*/ inline void
477 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
479 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
480 int chan = mcs->pxms_out_info;
482 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 0);
483 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 1);
484 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 2);
485 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 3);
488 *pwm_reg_bp = pwm2 | 0x4000;
492 *pwm_reg_bn = -pwm2 | 0x4000;
496 *pwm_reg_ap = pwm1 | 0x4000;
500 *pwm_reg_an = -pwm1 | 0x4000;
505 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
506 * @mcs: Motion controller state information
509 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
517 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
518 (mcs->pxms_flg&PXMS_PRA_m)){
520 short ptirc=mcs->pxms_ptirc;
522 pxmc_irc_16bit_commindx(mcs,mcs->pxms_rp>>PXMC_SUBDIV(mcs));
524 ptindx = mcs->pxms_ptindx;
526 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
528 mcs->pxms_ptindx = ptindx;
530 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
532 pxmc_set_flag(mcs, PXMS_PTI_b);
533 pxmc_clear_flag(mcs, PXMS_PRA_b);
535 /* if phase table position to mask is know do fine phase table alignment */
536 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
537 // lpc_qei_setup_index_catch(&lpc_qei_state);
540 if(!(mcs->pxms_flg&PXMS_PTI_m))
541 mcs->pxms_ptindx = ptindx;
546 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
547 /* FIXME - check winding current against limit */
548 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
554 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
558 indx = mcs->pxms_ptindx;
560 /* tuning of magnetic field/voltage advance angle */
561 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
564 /* Generating direction of stator mag. field for backward torque */
566 if ((indx -= mcs->pxms_ptvang)<0)
567 indx += mcs->pxms_ptirc;
569 /* Generating direction of stator mag. field for forward torque */
570 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
571 indx -= mcs->pxms_ptirc;
574 if (mcs->pxms_ptscale_mult)
575 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
577 pwm1 = mcs->pxms_ptptr1[indx];
578 pwm2 = mcs->pxms_ptptr2[indx];
580 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
581 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
583 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
584 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
585 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
587 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
589 /*pxmc_lpc_wind_current_over_cnt = 0;*/
590 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
597 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
598 * @mcs: Motion controller state information
601 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
603 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
604 int chan = mcs->pxms_out_info;
605 int ene = mcs->pxms_ene;
607 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
608 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
614 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
616 *pwm_reg_b = ene | 0x4000;
620 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
622 *pwm_reg_a = ene | 0x4000;
628 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
630 pxmc_rocon_pwm_master_init(void)
634 *fpga_lx_master_reset = 1;
635 *fpga_lx_master_transmitter_reg = 0;
637 for (i = 0; i < 8 + 16; i ++)
638 fpga_lx_master_transmitter_base[i] = 0;
640 fpga_lx_master_transmitter_base[0] = 0x0808;
641 fpga_lx_master_transmitter_base[1] = 0x0000;
643 *fpga_lx_master_reset = 0;
648 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
649 unsigned long index_irc, int diff2err)
654 ofs = ofsl = index_irc - mcs->pxms_ptmark;
658 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
659 if (diff >= mcs->pxms_ptirc / 2)
660 diff -= mcs->pxms_ptirc;
661 if (diff <= -mcs->pxms_ptirc / 2)
662 diff += mcs->pxms_ptirc;
665 if(diff >= mcs->pxms_ptirc / 6) {
670 diff = (unsigned long)ofsl - irc;
671 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
674 mcs->pxms_ptofs = ofs;
680 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
681 * @mcs: Motion controller state information
684 pxmc_dummy_con(pxmc_state_t *mcs)
689 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
690 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
691 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
692 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
693 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
694 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
696 /* initialize for hard home */
698 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
700 pxmc_set_flag(mcs,PXMS_BSY_b);
701 #if 0 /* config and speed already set in pxmc_hh */
703 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
705 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
707 mcs->pxms_gen_hsp = spd;
710 mcs->pxms_gen_htim = 16;
711 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
712 return pxmc_rocon_hh_gd10(mcs);
715 /* fill initial mark filter and then decide */
717 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
721 if(mcs->pxms_flg & PXMS_ERR_m)
722 return pxmc_spdnext_gend(mcs);
724 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
725 mcs->pxms_rp += mcs->pxms_rs;
727 mark = pxmc_inp_rocon_is_mark(mcs);
729 if (mcs->pxms_gen_htim) {
730 mcs->pxms_gen_htim--;
734 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
735 /* limit switch is not used */
736 pxmc_inp_rocon_is_index_edge(mcs);
737 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
742 /* go out from switch */
743 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
745 /* switch is off -> look for it */
746 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
751 /* go out from switch */
753 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
757 if(mcs->pxms_flg & PXMS_ERR_m)
758 return pxmc_spdnext_gend(mcs);
760 mark = pxmc_inp_rocon_is_mark(mcs);
763 /* switch is off -> look for it again */
764 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
767 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
768 mcs->pxms_rp += mcs->pxms_rs;
773 /* switch is off -> look for it */
775 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
780 if (mcs->pxms_flg & PXMS_ERR_m)
781 return pxmc_spdnext_gend(mcs);
783 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
784 mcs->pxms_rp += mcs->pxms_rs;
786 mark = pxmc_inp_rocon_is_mark(mcs);
789 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
792 mcs->pxms_gen_hsp = spd;
793 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
799 /* switch is on -> find edge */
801 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
805 if (mcs->pxms_flg & PXMS_ERR_m)
806 return pxmc_spdnext_gend(mcs);
808 mark = pxmc_inp_rocon_is_mark(mcs);
811 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
812 pxmc_inp_rocon_is_index_edge(mcs);
813 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
815 pxmc_inp_rocon_ap_zero(mcs);
816 mcs->pxms_do_gen = pxmc_stop_gi;
820 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
821 mcs->pxms_rp += mcs->pxms_rs;
826 /* calibrate on revolution index */
828 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
830 if (mcs->pxms_flg & PXMS_ERR_m)
831 return pxmc_spdnext_gend(mcs);
833 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
834 mcs->pxms_rp += mcs->pxms_rs;
836 if (pxmc_inp_rocon_is_index_edge(mcs)){
837 pxmc_inp_rocon_irc_offset_from_index(mcs);
838 mcs->pxms_do_gen = pxmc_stop_gi;
844 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
846 return pxmc_rocon_hh_gi;
856 pxmc_pid_con /*pxmc_dummy_con*/,
858 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
862 pxmc_inp_rocon_ap2hw,
863 pxms_ap: 0, pxms_as: 0,
864 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
865 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
868 pxms_ene: 0, pxms_erc: 0,
869 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
870 pxms_me: 0x7e00/*0x7fff*/,
872 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
878 /*pxms_ptamp: 0x7fff,*/
892 pxmc_rocon_pwm_dc_out,
896 pxmc_inp_rocon_ap2hw,
897 pxms_ap: 0, pxms_as: 0,
898 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
899 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
902 pxms_ene: 0, pxms_erc: 0,
903 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
904 pxms_me: 0x7e00/*0x7fff*/,
906 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
911 /*pxms_ptamp: 0x7fff,*/
925 pxmc_rocon_pwm_dc_out,
929 pxmc_inp_rocon_ap2hw,
930 pxms_ap: 0, pxms_as: 0,
931 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
932 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
935 pxms_ene: 0, pxms_erc: 0,
936 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
937 pxms_me: 0x7e00/*0x7fff*/,
939 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
944 /*pxms_ptamp: 0x7fff,*/
958 pxmc_rocon_pwm_dc_out,
962 pxmc_inp_rocon_ap2hw,
963 pxms_ap: 0, pxms_as: 0,
964 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
965 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
968 pxms_ene: 0, pxms_erc: 0,
969 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
970 pxms_me: 0x7e00/*0x7fff*/,
972 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
977 /*pxms_ptamp: 0x7fff,*/
991 pxmc_rocon_pwm_dc_out,
995 pxmc_inp_rocon_ap2hw,
996 pxms_ap: 0, pxms_as: 0,
997 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
998 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1001 pxms_ene: 0, pxms_erc: 0,
1002 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1003 pxms_me: 0x7e00/*0x7fff*/,
1005 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1010 /*pxms_ptamp: 0x7fff,*/
1024 pxmc_rocon_pwm_dc_out,
1028 pxmc_inp_rocon_ap2hw,
1029 pxms_ap: 0, pxms_as: 0,
1030 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1031 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1034 pxms_ene: 0, pxms_erc: 0,
1035 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1036 pxms_me: 0x7e00/*0x7fff*/,
1038 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1043 /*pxms_ptamp: 0x7fff,*/
1057 pxmc_rocon_pwm_dc_out,
1061 pxmc_inp_rocon_ap2hw,
1062 pxms_ap: 0, pxms_as: 0,
1063 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1064 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1067 pxms_ene: 0, pxms_erc: 0,
1068 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1069 pxms_me: 0x7e00/*0x7fff*/,
1071 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1076 /*pxms_ptamp: 0x7fff,*/
1090 pxmc_rocon_pwm_dc_out,
1094 pxmc_inp_rocon_ap2hw,
1095 pxms_ap: 0, pxms_as: 0,
1096 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1097 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1100 pxms_ene: 0, pxms_erc: 0,
1101 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1102 pxms_me: 0x7e00/*0x7fff*/,
1104 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1109 /*pxms_ptamp: 0x7fff,*/
1115 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1116 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1119 pxmc_state_list_t pxmc_main_list =
1126 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1128 pxmc_state_t *mcs = (pxmc_state_t *)context;
1131 irc = qst->index_pos;
1133 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1136 ofs = irc - mcs->pxms_ptmark;
1137 diff = ofs - mcs->pxms_ptofs;
1139 if (diff >= mcs->pxms_ptirc / 2)
1140 diff -= mcs->pxms_ptirc;
1142 if (diff <= -mcs->pxms_ptirc / 2)
1143 diff += mcs->pxms_ptirc;
1148 if (diff >= mcs->pxms_ptirc / 6)
1150 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1154 mcs->pxms_ptofs = ofs;
1155 pxmc_set_flag(mcs, PXMS_PHA_b);
1159 ofs=irc-mcs->pxms_ptofs;
1160 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1162 ofs-=mcs->pxms_ptirc;
1164 ofs+=mcs->pxms_ptirc;
1167 mcs->pxms_ptmark=ofs;
1170 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1173 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1177 lpc_qei_state_t *qst = &lpc_qei_state;
1178 int irc = lpc_qei_get_pos(qst);
1181 if (!qst->index_occ)
1184 idx_rel = qst->index_pos - irc;
1185 idx_rel %= mcs->pxms_ptirc;
1188 idx_rel += mcs->pxms_ptirc;
1190 ptofs = irc - mcs->pxms_ptofs;
1191 ptmark = ptofs + idx_rel;
1193 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1196 ptmark -= mcs->pxms_ptirc;
1198 ptmark += mcs->pxms_ptirc;
1201 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1203 mcs->pxms_ptmark = ptmark;
1209 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1214 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1215 lpc_qei_state_t *qst = &lpc_qei_state;
1217 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1218 lpc_qei_setup_index_catch(qst);
1220 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1221 spd = 1 << PXMC_SUBDIV(mcs);
1223 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1228 int pxmc_lpc_pthalalign_run(void)
1230 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1233 static inline void pxmc_sfi_input(void)
1237 pxmc_for_each_mcs(var, mcs)
1239 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1240 if (mcs->pxms_flg & PXMS_ENI_m)
1242 pxmc_call(mcs, mcs->pxms_do_inp);
1247 static inline void pxmc_sfi_controller_and_output(void)
1251 pxmc_for_each_mcs(var, mcs)
1253 /* PXMS_ENR_m - check if controller is enabled */
1254 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1257 /* If output only is enabled, we skip the controller */
1258 if (mcs->pxms_flg & PXMS_ENR_m)
1261 pxmc_call(mcs, mcs->pxms_do_con);
1263 /* PXMS_ERR_m - if axis in error state */
1264 if (mcs->pxms_flg & PXMS_ERR_m)
1268 /* for bushless motors, it is necessary to call do_out
1269 even if the controller is not enabled and PWM should be provided. */
1270 pxmc_call(mcs, mcs->pxms_do_out);
1275 static inline void pxmc_sfi_generator(void)
1279 pxmc_for_each_mcs(var, mcs)
1281 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1282 if (mcs->pxms_flg & PXMS_ENG_m)
1284 pxmc_call(mcs, mcs->pxms_do_gen);
1289 static inline void pxmc_sfi_dbg(void)
1293 pxmc_for_each_mcs(var, mcs)
1295 if (mcs->pxms_flg & PXMS_DBG_m)
1297 pxmc_call(mcs, mcs->pxms_do_deb);
1302 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1306 int inp_chan = mcs->pxms_inp_info;
1308 long irc = fpga_irc[inp_chan]->count;
1310 if (!pxmc_inp_rocon_is_index_edge(mcs))
1313 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1314 idx_rel %= mcs->pxms_ptirc;
1316 idx_rel += mcs->pxms_ptirc;
1318 ptofs = irc-mcs->pxms_ptofs;
1319 ptmark = ptofs+idx_rel;
1321 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1323 ptmark -= mcs->pxms_ptirc;
1325 ptmark += mcs->pxms_ptirc;
1328 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1329 mcs->pxms_ptmark = ptmark;
1334 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1339 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1341 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1343 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1344 spd=1<<PXMC_SUBDIV(mcs);
1346 /* clear bit indicating previous index */
1347 pxmc_inp_rocon_is_index_edge(mcs);
1349 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1354 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1356 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1357 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1358 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1359 return PXMC_AXIS_MODE_DC;
1360 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1361 return PXMC_AXIS_MODE_BLDC;
1367 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1369 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1372 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1373 mode = pxmc_axis_rdmode(mcs);
1378 /*case PXMC_AXIS_MODE_STEPPER:*/
1379 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1380 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1382 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1383 case PXMC_AXIS_MODE_DC:
1384 /*profive some sane dummy values*/
1385 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1386 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1387 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1389 mcs->pxms_ptscale_mult=1;
1390 mcs->pxms_ptscale_shift=15;
1392 case PXMC_AXIS_MODE_BLDC:
1393 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1394 #ifndef PXMC_WITH_PT_ZIC
1395 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1396 #else /*PXMC_WITH_PT_ZIC*/
1397 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1398 #endif /*PXMC_WITH_PT_ZIC*/
1404 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1410 * pxmc_axis_mode - Sets axis mode.[extern API]
1411 * @mcs: Motion controller state information
1412 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1413 * 2 .. stepper motor with IRC feedback and PWM ,
1414 * 3 .. stepper motor with PWM control
1415 * 4 .. DC motor with IRC feedback and PWM
1419 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1423 pxmc_set_const_out(mcs, 0);
1424 pxmc_clear_flag(mcs, PXMS_ENI_b);
1425 pxmc_clear_flag(mcs, PXMS_PHA_b);
1426 pxmc_clear_flag(mcs, PXMS_PTI_b);
1428 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1429 mode = pxmc_axis_rdmode(mcs);
1433 mode = PXMC_AXIS_MODE_DC;
1435 res = pxmc_axis_pt4mode(mcs, mode);
1440 /*case PXMC_AXIS_MODE_STEPPER:*/
1441 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1442 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1444 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1445 case PXMC_AXIS_MODE_DC:
1446 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1448 case PXMC_AXIS_MODE_BLDC:
1449 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1455 pxmc_set_flag(mcs, PXMS_ENI_b);
1459 void pxmc_sfi_isr(void)
1462 pxmc_sfi_controller_and_output();
1463 pxmc_sfi_generator();
1465 /* Kick LX Master watchdog */
1466 if (pxmc_main_list.pxml_cnt != 0)
1467 *fpga_lx_master_transmitter_wdog = 1;
1470 int pxmc_clear_power_stop(void)
1480 if (!pxmc_main_list.pxml_cnt)
1483 pxmc_for_each_mcs(var, mcs)
1485 pxmc_set_const_out(mcs,0);
1488 pxmc_main_list.pxml_cnt = 0;
1494 int pxmc_initialize(void)
1499 pxmc_state_t *mcs = &mcs0;
1500 lpc_qei_state_t *qst = &lpc_qei_state;
1502 *fpga_irc_reset = 1;
1504 for (i = 0; i < 8; i++) {
1505 fpga_irc[i]->count = 0;
1506 *fpga_irc_state[i] = 1 << 2;
1509 /* Initialize QEI module for IRC counting */
1510 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1512 /* Initialize QEI events processing */
1513 if (lpc_qei_setup_irq(qst) < 0)
1516 *fpga_irc_reset = 0;
1518 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1520 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1521 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1523 pxmc_rocon_pwm_master_init();
1525 pxmc_main_list.pxml_cnt = 0;
1526 pxmc_dbg_hist = NULL;
1528 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;