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_pwm_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_pwm_dc_out(pxmc_state_t *mcs)
425 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
426 int chan = mcs->pxms_out_info;
427 int ene = mcs->pxms_ene;
429 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
430 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
436 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
438 *pwm_reg_b = ene | 0x4000;
442 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
444 *pwm_reg_a = ene | 0x4000;
450 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
452 pxmc_rocon_pwm_master_init(void)
456 *fpga_lx_master_reset = 1;
457 *fpga_lx_master_transmitter_reg = 0;
459 for (i = 0; i < 8 + 16; i ++)
460 fpga_lx_master_transmitter_base[i] = 0;
462 fpga_lx_master_transmitter_base[0] = 0x0808;
463 fpga_lx_master_transmitter_base[1] = 0x0000;
465 *fpga_lx_master_reset = 0;
470 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
471 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
472 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
473 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
474 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
475 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
477 /* initialize for hard home */
479 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
481 pxmc_set_flag(mcs,PXMS_BSY_b);
482 #if 0 /* config and speed already set in pxmc_hh */
484 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
486 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
488 mcs->pxms_gen_hsp = spd;
491 mcs->pxms_gen_htim = 16;
492 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
493 return pxmc_rocon_hh_gd10(mcs);
496 /* fill initial mark filter and then decide */
498 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
502 if(mcs->pxms_flg & PXMS_ERR_m)
503 return pxmc_spdnext_gend(mcs);
505 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
506 mcs->pxms_rp += mcs->pxms_rs;
508 mark = pxmc_inp_rocon_is_mark(mcs);
510 if (mcs->pxms_gen_htim) {
511 mcs->pxms_gen_htim--;
515 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
516 /* limit switch is not used */
517 pxmc_inp_rocon_is_index_edge(mcs);
518 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
523 /* go out from switch */
524 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
526 /* switch is off -> look for it */
527 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
532 /* go out from switch */
534 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
538 if(mcs->pxms_flg & PXMS_ERR_m)
539 return pxmc_spdnext_gend(mcs);
541 mark = pxmc_inp_rocon_is_mark(mcs);
544 /* switch is off -> look for it again */
545 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
548 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
549 mcs->pxms_rp += mcs->pxms_rs;
554 /* switch is off -> look for it */
556 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
561 if (mcs->pxms_flg & PXMS_ERR_m)
562 return pxmc_spdnext_gend(mcs);
564 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
565 mcs->pxms_rp += mcs->pxms_rs;
567 mark = pxmc_inp_rocon_is_mark(mcs);
570 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
573 mcs->pxms_gen_hsp = spd;
574 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
580 /* switch is on -> find edge */
582 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
586 if (mcs->pxms_flg & PXMS_ERR_m)
587 return pxmc_spdnext_gend(mcs);
589 mark = pxmc_inp_rocon_is_mark(mcs);
592 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
593 pxmc_inp_rocon_is_index_edge(mcs);
594 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
596 pxmc_inp_rocon_ap_zero(mcs);
597 mcs->pxms_do_gen = pxmc_stop_gi;
601 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
602 mcs->pxms_rp += mcs->pxms_rs;
607 /* calibrate on revolution index */
609 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
611 if (mcs->pxms_flg & PXMS_ERR_m)
612 return pxmc_spdnext_gend(mcs);
614 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
615 mcs->pxms_rp += mcs->pxms_rs;
617 if (pxmc_inp_rocon_is_index_edge(mcs)){
618 pxmc_inp_rocon_irc_offset_from_index(mcs);
619 mcs->pxms_do_gen = pxmc_stop_gi;
625 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
627 return pxmc_rocon_hh_gi;
639 pxmc_rocon_pwm_dc_out,
643 pxmc_inp_rocon_ap2hw,
644 pxms_ap: 0, pxms_as: 0,
645 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
646 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
649 pxms_ene: 0, pxms_erc: 0,
650 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
651 pxms_me: 0x7e00/*0x7fff*/,
653 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
658 /*pxms_ptamp: 0x7fff,*/
672 pxmc_rocon_pwm_dc_out,
676 pxmc_inp_rocon_ap2hw,
677 pxms_ap: 0, pxms_as: 0,
678 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
679 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
682 pxms_ene: 0, pxms_erc: 0,
683 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
684 pxms_me: 0x7e00/*0x7fff*/,
686 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
691 /*pxms_ptamp: 0x7fff,*/
705 pxmc_rocon_pwm_dc_out,
709 pxmc_inp_rocon_ap2hw,
710 pxms_ap: 0, pxms_as: 0,
711 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
712 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
715 pxms_ene: 0, pxms_erc: 0,
716 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
717 pxms_me: 0x7e00/*0x7fff*/,
719 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
724 /*pxms_ptamp: 0x7fff,*/
738 pxmc_rocon_pwm_dc_out,
742 pxmc_inp_rocon_ap2hw,
743 pxms_ap: 0, pxms_as: 0,
744 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
745 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
748 pxms_ene: 0, pxms_erc: 0,
749 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
750 pxms_me: 0x7e00/*0x7fff*/,
752 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
757 /*pxms_ptamp: 0x7fff,*/
771 pxmc_rocon_pwm_dc_out,
775 pxmc_inp_rocon_ap2hw,
776 pxms_ap: 0, pxms_as: 0,
777 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
778 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
781 pxms_ene: 0, pxms_erc: 0,
782 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
783 pxms_me: 0x7e00/*0x7fff*/,
785 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
790 /*pxms_ptamp: 0x7fff,*/
804 pxmc_rocon_pwm_dc_out,
808 pxmc_inp_rocon_ap2hw,
809 pxms_ap: 0, pxms_as: 0,
810 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
811 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
814 pxms_ene: 0, pxms_erc: 0,
815 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
816 pxms_me: 0x7e00/*0x7fff*/,
818 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
823 /*pxms_ptamp: 0x7fff,*/
837 pxmc_rocon_pwm_dc_out,
841 pxmc_inp_rocon_ap2hw,
842 pxms_ap: 0, pxms_as: 0,
843 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
844 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
847 pxms_ene: 0, pxms_erc: 0,
848 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
849 pxms_me: 0x7e00/*0x7fff*/,
851 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
856 /*pxms_ptamp: 0x7fff,*/
870 pxmc_rocon_pwm_dc_out,
874 pxmc_inp_rocon_ap2hw,
875 pxms_ap: 0, pxms_as: 0,
876 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
877 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
880 pxms_ene: 0, pxms_erc: 0,
881 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
882 pxms_me: 0x7e00/*0x7fff*/,
884 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
889 /*pxms_ptamp: 0x7fff,*/
895 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
896 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
899 pxmc_state_list_t pxmc_main_list =
906 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
908 pxmc_state_t *mcs = (pxmc_state_t *)context;
911 irc = qst->index_pos;
913 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
916 ofs = irc - mcs->pxms_ptmark;
917 diff = ofs - mcs->pxms_ptofs;
919 if (diff >= mcs->pxms_ptirc / 2)
920 diff -= mcs->pxms_ptirc;
922 if (diff <= -mcs->pxms_ptirc / 2)
923 diff += mcs->pxms_ptirc;
928 if (diff >= mcs->pxms_ptirc / 6)
930 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
934 mcs->pxms_ptofs = ofs;
935 pxmc_set_flag(mcs, PXMS_PHA_b);
939 ofs=irc-mcs->pxms_ptofs;
940 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
942 ofs-=mcs->pxms_ptirc;
944 ofs+=mcs->pxms_ptirc;
947 mcs->pxms_ptmark=ofs;
950 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
953 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
957 lpc_qei_state_t *qst = &lpc_qei_state;
958 int irc = lpc_qei_get_pos(qst);
964 idx_rel = qst->index_pos - irc;
965 idx_rel %= mcs->pxms_ptirc;
968 idx_rel += mcs->pxms_ptirc;
970 ptofs = irc - mcs->pxms_ptofs;
971 ptmark = ptofs + idx_rel;
973 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
976 ptmark -= mcs->pxms_ptirc;
978 ptmark += mcs->pxms_ptirc;
981 if ((unsigned short)ptmark < mcs->pxms_ptirc)
983 mcs->pxms_ptmark = ptmark;
989 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
994 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
995 lpc_qei_state_t *qst = &lpc_qei_state;
997 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
998 lpc_qei_setup_index_catch(qst);
1000 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1001 spd = 1 << PXMC_SUBDIV(mcs);
1003 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1008 int pxmc_lpc_pthalalign_run(void)
1010 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1013 static inline void pxmc_sfi_input(void)
1017 pxmc_for_each_mcs(var, mcs)
1019 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1020 if (mcs->pxms_flg & PXMS_ENI_m)
1022 pxmc_call(mcs, mcs->pxms_do_inp);
1027 static inline void pxmc_sfi_controller_and_output(void)
1031 pxmc_for_each_mcs(var, mcs)
1033 /* PXMS_ENR_m - check if controller is enabled */
1034 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1037 /* If output only is enabled, we skip the controller */
1038 if (mcs->pxms_flg & PXMS_ENR_m)
1041 pxmc_call(mcs, mcs->pxms_do_con);
1043 /* PXMS_ERR_m - if axis in error state */
1044 if (mcs->pxms_flg & PXMS_ERR_m)
1048 /* for bushless motors, it is necessary to call do_out
1049 even if the controller is not enabled and PWM should be provided. */
1050 pxmc_call(mcs, mcs->pxms_do_out);
1055 static inline void pxmc_sfi_generator(void)
1059 pxmc_for_each_mcs(var, mcs)
1061 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1062 if (mcs->pxms_flg & PXMS_ENG_m)
1064 pxmc_call(mcs, mcs->pxms_do_gen);
1069 static inline void pxmc_sfi_dbg(void)
1073 pxmc_for_each_mcs(var, mcs)
1075 if (mcs->pxms_flg & PXMS_DBG_m)
1077 pxmc_call(mcs, mcs->pxms_do_deb);
1082 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1086 int inp_chan = mcs->pxms_inp_info;
1088 long irc = fpga_irc[inp_chan]->count;
1090 if (!pxmc_inp_rocon_is_index_edge(mcs))
1093 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1094 idx_rel %= mcs->pxms_ptirc;
1096 idx_rel += mcs->pxms_ptirc;
1098 ptofs = irc-mcs->pxms_ptofs;
1099 ptmark = ptofs+idx_rel;
1101 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1103 ptmark -= mcs->pxms_ptirc;
1105 ptmark += mcs->pxms_ptirc;
1108 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1109 mcs->pxms_ptmark = ptmark;
1114 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1119 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1121 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1123 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1124 spd=1<<PXMC_SUBDIV(mcs);
1126 /* clear bit indicating previous index */
1127 pxmc_inp_rocon_is_index_edge(mcs);
1129 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1135 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1139 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1141 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1142 #ifndef PXMC_WITH_PT_ZIC
1143 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1144 #else /*PXMC_WITH_PT_ZIC*/
1145 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1146 #endif /*PXMC_WITH_PT_ZIC*/
1152 * pxmc_axis_mode - Sets axis mode.[extern API]
1153 * @mcs: Motion controller state information
1154 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1155 * 2 .. stepper motor with IRC feedback and PWM ,
1156 * 3 .. stepper motor with PWM control
1157 * 4 .. DC motor with IRC feedback and PWM
1161 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1165 pxmc_set_const_out(mcs, 0);
1166 pxmc_clear_flag(mcs, PXMS_ENI_b);
1167 pxmc_clear_flag(mcs, PXMS_PHA_b);
1168 pxmc_clear_flag(mcs, PXMS_PTI_b);
1172 /*mode=pxmc_axis_rdmode(mcs);*/
1174 mode = PXMC_AXIS_MODE_BLDC;
1177 res = pxmc_axis_pt4mode(mcs, mode);
1179 pxmc_set_flag(mcs, PXMS_ENI_b);
1183 void pxmc_sfi_isr(void)
1186 pxmc_sfi_controller_and_output();
1187 pxmc_sfi_generator();
1189 /* Kick LX Master watchdog */
1190 if (pxmc_main_list.pxml_cnt != 0)
1191 *fpga_lx_master_transmitter_wdog = 1;
1199 if (!pxmc_main_list.pxml_cnt)
1202 pxmc_for_each_mcs(var, mcs)
1204 pxmc_set_const_out(mcs,0);
1207 pxmc_main_list.pxml_cnt = 0;
1213 int pxmc_initialize(void)
1217 pxmc_state_t *mcs = &mcs0;
1218 lpc_qei_state_t *qst = &lpc_qei_state;
1220 *fpga_irc_reset = 1;
1222 /* Initialize QEI module for IRC counting */
1223 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1225 /* Initialize QEI events processing */
1226 if (lpc_qei_setup_irq(qst) < 0)
1229 *fpga_irc_reset = 0;
1231 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1233 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1234 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1236 pxmc_rocon_pwm_master_init();
1238 pxmc_main_list.pxml_cnt = 0;
1239 pxmc_dbg_hist = NULL;
1241 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;