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 4
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_lpcpwm1_magnitude;
45 long pxmc_irc_offset[PXML_MAIN_CNT];
48 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
50 int chan=mcs->pxms_inp_info;
54 /* read position from hardware */
55 irc = fpga_irc[chan]->count;
56 irc += pxmc_irc_offset[chan];
57 pos = irc << PXMC_SUBDIV(mcs);
58 mcs->pxms_as = pos - mcs->pxms_ap;
61 /* Running of the motor commutator */
62 if (mcs->pxms_flg & PXMS_PTI_m)
63 pxmc_irc_16bit_commindx(mcs, irc);
69 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
71 int chan=mcs->pxms_inp_info;
75 irc = fpga_irc[chan]->count;
76 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
77 pxmc_irc_offset[chan] = pos_diff >> PXMC_SUBDIV(mcs);
82 pxmc_rocon_bdc_hal_rd(pxmc_state_t *mcs)
86 /* return 3 bits corresponding to the HAL senzor input */
91 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
103 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
117 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
118 * @mcs: Motion controller state information
120 /*static*/ inline void
121 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
123 unsigned long out_info = mcs->pxms_out_info;
129 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
131 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
133 pxmc_set_errno(mcs, PXMS_E_HAL);
138 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
142 * pxmc_rocon_pwm_out - Phase output for brush-less 3-phase motor
143 * @mcs: Motion controller state information
146 pxmc_rocon_pwm_out(pxmc_state_t *mcs)
148 unsigned char hal_pos;
156 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
157 (mcs->pxms_flg & PXMS_PRA_m))
160 short ptirc = mcs->pxms_ptirc;
161 short divisor = mcs->pxms_ptper * 6;
163 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
168 pxmc_rocon_process_hal_error(mcs);
172 if (mcs->pxms_halerc)
175 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
177 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
179 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
181 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
183 if ((ptindx > ptindx_prev + ptirc / 2) ||
184 (ptindx_prev > ptindx + ptirc / 2))
186 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
193 ptindx = (ptindx_prev + ptindx) / 2;
196 mcs->pxms_ptindx = ptindx;
198 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
200 pxmc_set_flag(mcs, PXMS_PTI_b);
201 pxmc_clear_flag(mcs, PXMS_PRA_b);
203 /* if phase table position to mask is know do fine phase table alignment */
204 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m)
205 lpc_qei_setup_index_catch(&lpc_qei_state);
210 if (!(mcs->pxms_flg & PXMS_PTI_m))
211 mcs->pxms_ptindx = ptindx;
215 mcs->pxms_hal = hal_pos;
220 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
221 /* FIXME - check winding current against limit */
222 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
229 indx = mcs->pxms_ptindx;
231 /* tuning of magnetic field/voltage advance angle */
232 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
237 /* Generating direction of stator mag. field for backward torque */
240 if ((indx -= mcs->pxms_ptvang) < 0)
241 indx += mcs->pxms_ptirc;
245 /* Generating direction of stator mag. field for forward torque */
246 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
247 indx -= mcs->pxms_ptirc;
250 if (mcs->pxms_ptscale_mult)
251 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
253 pwm1 = mcs->pxms_ptptr1[indx];
254 pwm2 = mcs->pxms_ptptr2[indx];
255 pwm3 = mcs->pxms_ptptr3[indx];
257 #ifdef PXMC_WITH_PT_ZIC
259 if (labs(mcs->pxms_as) > (10 << PXMC_SUBDIV(mcs)))
261 if (pwm1 & PXMC_PT_ZIC_MASK)
263 /*hal_gpio_set_value(PWM2_EN_PIN,0);*/
267 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
270 if (pwm2 & PXMC_PT_ZIC_MASK)
272 /*hal_gpio_set_value(PWM4_EN_PIN,0);*/
276 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
279 if (pwm3 & PXMC_PT_ZIC_MASK)
281 /*hal_gpio_set_value(PWM6_EN_PIN,0);*/
285 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
290 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
291 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
292 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
295 pwm1 &= ~PXMC_PT_ZIC_MASK;
296 pwm2 &= ~PXMC_PT_ZIC_MASK;
297 pwm3 &= ~PXMC_PT_ZIC_MASK;
298 #endif /*PXMC_WITH_PT_ZIC*/
300 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
301 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
303 unsigned long pwm_dc = pxmc_lpcpwm1_magnitude * (unsigned long)ene;
304 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15 + 15);
305 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15 + 15);
306 pwm3 = ((unsigned long long)pwm3 * pwm_dc) >> (15 + 15);
308 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
312 /*pxmc_lpc_wind_current_over_cnt=0;*/
313 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
314 #ifdef PXMC_WITH_PT_ZIC
315 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
316 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
317 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
318 #endif /*PXMC_WITH_PT_ZIC*/
325 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
327 volatile uint32_t *pwm_reg;
328 int chan = mcs->pxms_out_info;
329 int ene = mcs->pxms_ene;
334 pwm_reg = fpga_lx_master_transmitter_base + 1 + chan;
340 ene = (ene * (2500 + 5)) >> 15;
342 pwm_reg[1] = ene | 0x4000;
346 ene = (ene * (2500 + 5)) >> 15;
348 pwm_reg[0] = ene | 0x4000;
354 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
356 pxmc_rocon_pwm_init(pxmc_state_t *mcs, int mode)
359 /* hal_pin_conf(PWM1_EN_PIN); */
361 /* hal_gpio_set_value(PWM1_EN_PIN,1); */
367 pxmc_fpga_is_mark(pxmc_state_t *mcs)
369 int chan = mcs->pxms_out_info;
371 return *fpga_irc_state[chan] & 1;
374 int pxmc_fpga_hh_gd10(pxmc_state_t *mcs);
375 int pxmc_fpga_hh_gd20(pxmc_state_t *mcs);
378 pxmc_fpga_hh_gi(pxmc_state_t *mcs)
381 pxmc_set_flag(mcs,PXMS_BSY_b);
384 spd >>= mcs->pxms_cfg&PXMS_CFG_HSPD_m;
386 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
388 mcs->pxms_gen_hsp = spd;
389 mcs->pxms_do_gen = pxmc_fpga_hh_gd10;
390 return pxmc_fpga_hh_gd10(mcs);
394 pxmc_fpga_hh_gd10(pxmc_state_t *mcs)
397 if(mcs->pxms_flg & PXMS_ERR_m)
398 return pxmc_spdnext_gend(mcs);
400 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
401 mcs->pxms_rp += mcs->pxms_rs;
403 if (!pxmc_fpga_is_mark(mcs)){
404 spd=mcs->pxms_gen_hsp;
412 mcs->pxms_gen_hsp = spd;
413 mcs->pxms_do_gen = pxmc_fpga_hh_gd20;
420 pxmc_fpga_hh_gd20(pxmc_state_t *mcs)
422 if (mcs->pxms_flg & PXMS_ERR_m)
423 return pxmc_spdnext_gend(mcs);
425 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
426 mcs->pxms_rp += mcs->pxms_rs;
428 if (pxmc_fpga_is_mark(mcs)){
429 /* pxmc_axis_set_pos(mcs, 0); */
430 if (mcs->pxms_do_ap2hw != NULL)
431 mcs->pxms_do_ap2hw(mcs);
432 mcs->pxms_do_gen = pxmc_stop_gi;
438 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
440 return pxmc_fpga_hh_gi;
452 pxmc_rocon_pwm_dc_out,
456 pxmc_inp_rocon_ap2hw,
457 pxms_ap: 0, pxms_as: 0,
458 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
459 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
462 pxms_ene: 0, pxms_erc: 0,
463 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
464 pxms_me: 0x7e00/*0x7fff*/,
466 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
471 /*pxms_ptamp: 0x7fff,*/
485 pxmc_rocon_pwm_dc_out,
489 pxmc_inp_rocon_ap2hw,
490 pxms_ap: 0, pxms_as: 0,
491 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
492 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
495 pxms_ene: 0, pxms_erc: 0,
496 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
497 pxms_me: 0x7e00/*0x7fff*/,
499 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
504 /*pxms_ptamp: 0x7fff,*/
518 pxmc_rocon_pwm_dc_out,
522 pxmc_inp_rocon_ap2hw,
523 pxms_ap: 0, pxms_as: 0,
524 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
525 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
528 pxms_ene: 0, pxms_erc: 0,
529 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
530 pxms_me: 0x7e00/*0x7fff*/,
532 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
537 /*pxms_ptamp: 0x7fff,*/
551 pxmc_rocon_pwm_dc_out,
555 pxmc_inp_rocon_ap2hw,
556 pxms_ap: 0, pxms_as: 0,
557 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
558 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
561 pxms_ene: 0, pxms_erc: 0,
562 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
563 pxms_me: 0x7e00/*0x7fff*/,
565 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
570 /*pxms_ptamp: 0x7fff,*/
576 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
577 {&mcs0, &mcs1, &mcs2, &mcs3};
580 pxmc_state_list_t pxmc_main_list =
587 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
589 pxmc_state_t *mcs = (pxmc_state_t *)context;
592 irc = qst->index_pos;
594 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
597 ofs = irc - mcs->pxms_ptmark;
598 diff = ofs - mcs->pxms_ptofs;
600 if (diff >= mcs->pxms_ptirc / 2)
601 diff -= mcs->pxms_ptirc;
603 if (diff <= -mcs->pxms_ptirc / 2)
604 diff += mcs->pxms_ptirc;
609 if (diff >= mcs->pxms_ptirc / 6)
611 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
615 mcs->pxms_ptofs = ofs;
616 pxmc_set_flag(mcs, PXMS_PHA_b);
620 ofs=irc-mcs->pxms_ptofs;
621 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
623 ofs-=mcs->pxms_ptirc;
625 ofs+=mcs->pxms_ptirc;
628 mcs->pxms_ptmark=ofs;
631 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
634 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
638 lpc_qei_state_t *qst = &lpc_qei_state;
639 int irc = lpc_qei_get_pos(qst);
645 idx_rel = qst->index_pos - irc;
646 idx_rel %= mcs->pxms_ptirc;
649 idx_rel += mcs->pxms_ptirc;
651 ptofs = irc - mcs->pxms_ptofs;
652 ptmark = ptofs + idx_rel;
654 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
657 ptmark -= mcs->pxms_ptirc;
659 ptmark += mcs->pxms_ptirc;
662 if ((unsigned short)ptmark < mcs->pxms_ptirc)
664 mcs->pxms_ptmark = ptmark;
670 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
675 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
676 lpc_qei_state_t *qst = &lpc_qei_state;
678 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
679 lpc_qei_setup_index_catch(qst);
681 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
682 spd = 1 << PXMC_SUBDIV(mcs);
684 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
689 int pxmc_lpc_pthalalign_run(void)
691 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
694 static inline void pxmc_sfi_input(void)
698 pxmc_for_each_mcs(var, mcs)
700 /* PXMS_ENI_m - check if input (IRC) update is enabled */
701 if (mcs->pxms_flg & PXMS_ENI_m)
703 pxmc_call(mcs, mcs->pxms_do_inp);
708 static inline void pxmc_sfi_controller_and_output(void)
712 pxmc_for_each_mcs(var, mcs)
714 /* PXMS_ENR_m - check if controller is enabled */
715 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
718 /* If output only is enabled, we skip the controller */
719 if (mcs->pxms_flg & PXMS_ENR_m)
722 pxmc_call(mcs, mcs->pxms_do_con);
724 /* PXMS_ERR_m - if axis in error state */
725 if (mcs->pxms_flg & PXMS_ERR_m)
729 /* for bushless motors, it is necessary to call do_out
730 even if the controller is not enabled and PWM should be provided. */
731 pxmc_call(mcs, mcs->pxms_do_out);
736 static inline void pxmc_sfi_generator(void)
740 pxmc_for_each_mcs(var, mcs)
742 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
743 if (mcs->pxms_flg & PXMS_ENG_m)
745 pxmc_call(mcs, mcs->pxms_do_gen);
750 static inline void pxmc_sfi_dbg(void)
754 pxmc_for_each_mcs(var, mcs)
756 if (mcs->pxms_flg & PXMS_DBG_m)
758 pxmc_call(mcs, mcs->pxms_do_deb);
764 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
768 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
770 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
771 #ifndef PXMC_WITH_PT_ZIC
772 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
773 #else /*PXMC_WITH_PT_ZIC*/
774 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
775 #endif /*PXMC_WITH_PT_ZIC*/
781 * pxmc_axis_mode - Sets axis mode.[extern API]
782 * @mcs: Motion controller state information
783 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
784 * 2 .. stepper motor with IRC feedback and PWM ,
785 * 3 .. stepper motor with PWM control
786 * 4 .. DC motor with IRC feedback and PWM
790 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
794 pxmc_set_const_out(mcs, 0);
795 pxmc_clear_flag(mcs, PXMS_ENI_b);
796 pxmc_clear_flag(mcs, PXMS_PHA_b);
797 pxmc_clear_flag(mcs, PXMS_PTI_b);
801 /*mode=pxmc_axis_rdmode(mcs);*/
803 mode = PXMC_AXIS_MODE_BLDC;
806 res = pxmc_axis_pt4mode(mcs, mode);
808 pxmc_set_flag(mcs, PXMS_ENI_b);
812 void pxmc_sfi_isr(void)
815 pxmc_sfi_controller_and_output();
816 pxmc_sfi_generator();
825 if (!pxmc_main_list.pxml_cnt)
828 pxmc_for_each_mcs(var, mcs)
830 pxmc_set_const_out(mcs,0);
833 pxmc_main_list.pxml_cnt = 0;
839 int pxmc_initialize(void)
843 pxmc_state_t *mcs = &mcs0;
844 lpc_qei_state_t *qst = &lpc_qei_state;
848 /* Initialize QEI module for IRC counting */
849 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
851 /* Initialize QEI events processing */
852 if (lpc_qei_setup_irq(qst) < 0)
857 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
859 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
860 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
862 pxmc_rocon_pwm_init(mcs, 0);
864 pxmc_main_list.pxml_cnt = 0;
865 pxmc_dbg_hist = NULL;
867 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;