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>
26 #include <hal_machperiph.h>
29 #include "appl_defs.h"
30 #include "appl_fpga.h"
32 #define PXML_MAIN_CNT 4
34 #define PXMC_WITH_PT_ZIC 1
35 #define PXMC_PT_ZIC_MASK 0x8000
37 #define LPCPWM1_FREQ 20000
39 #define HAL_ERR_SENSITIVITY 20
40 #define HAL_ERR_MAX_COUNT 5
42 unsigned pxmc_lpcpwm1_magnitude;
44 int pxmc_hh_gi(pxmc_state_t *mcs);
47 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
49 int chan=mcs->pxms_inp_info;
53 /* read position from hardware */
54 irc = irc1[chan].count;
55 pos = irc << PXMC_SUBDIV(mcs);
56 mcs->pxms_as = pos - mcs->pxms_ap;
59 /* Running of the motor commutator */
60 if (mcs->pxms_flg & PXMS_PTI_m)
61 pxmc_irc_16bit_commindx(mcs, irc);
67 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
69 /* int chan=mcs->pxms_inp_info */
70 /* Optional set of the actual position to the HW */
71 /* We do not want to change real HW counter at any situation */
72 /* It can be used only to set some software maintained offset */
77 pxmc_rocon_bdc_hal_rd(pxmc_state_t *mcs)
81 /* return 3 bits corresponding to the HAL senzor input */
86 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
98 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
112 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
113 * @mcs: Motion controller state information
115 /*static*/ inline void
116 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
118 unsigned long out_info = mcs->pxms_out_info;
124 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
126 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
128 pxmc_set_errno(mcs, PXMS_E_HAL);
133 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
137 * pxmc_rocon_pwm_out - Phase output for brush-less 3-phase motor
138 * @mcs: Motion controller state information
141 pxmc_rocon_pwm_out(pxmc_state_t *mcs)
143 unsigned char hal_pos;
151 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
152 (mcs->pxms_flg & PXMS_PRA_m))
155 short ptirc = mcs->pxms_ptirc;
156 short divisor = mcs->pxms_ptper * 6;
158 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
163 pxmc_rocon_process_hal_error(mcs);
167 if (mcs->pxms_halerc)
170 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
172 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
174 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
176 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
178 if ((ptindx > ptindx_prev + ptirc / 2) ||
179 (ptindx_prev > ptindx + ptirc / 2))
181 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
188 ptindx = (ptindx_prev + ptindx) / 2;
191 mcs->pxms_ptindx = ptindx;
193 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
195 pxmc_set_flag(mcs, PXMS_PTI_b);
196 pxmc_clear_flag(mcs, PXMS_PRA_b);
198 /* if phase table position to mask is know do fine phase table alignment */
199 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m)
200 lpc_qei_setup_index_catch(&lpc_qei_state);
205 if (!(mcs->pxms_flg & PXMS_PTI_m))
206 mcs->pxms_ptindx = ptindx;
210 mcs->pxms_hal = hal_pos;
215 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
216 /* FIXME - check winding current against limit */
217 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
224 indx = mcs->pxms_ptindx;
226 /* tuning of magnetic field/voltage advance angle */
227 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
232 /* Generating direction of stator mag. field for backward torque */
235 if ((indx -= mcs->pxms_ptvang) < 0)
236 indx += mcs->pxms_ptirc;
240 /* Generating direction of stator mag. field for forward torque */
241 if ((indx += mcs->pxms_ptvang) >= mcs->pxms_ptirc)
242 indx -= mcs->pxms_ptirc;
245 if (mcs->pxms_ptscale_mult)
246 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
248 pwm1 = mcs->pxms_ptptr1[indx];
249 pwm2 = mcs->pxms_ptptr2[indx];
250 pwm3 = mcs->pxms_ptptr3[indx];
252 #ifdef PXMC_WITH_PT_ZIC
254 if (labs(mcs->pxms_as) > (10 << PXMC_SUBDIV(mcs)))
256 if (pwm1 & PXMC_PT_ZIC_MASK)
258 /*hal_gpio_set_value(PWM2_EN_PIN,0);*/
262 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
265 if (pwm2 & PXMC_PT_ZIC_MASK)
267 /*hal_gpio_set_value(PWM4_EN_PIN,0);*/
271 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
274 if (pwm3 & PXMC_PT_ZIC_MASK)
276 /*hal_gpio_set_value(PWM6_EN_PIN,0);*/
280 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
285 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
286 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
287 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
290 pwm1 &= ~PXMC_PT_ZIC_MASK;
291 pwm2 &= ~PXMC_PT_ZIC_MASK;
292 pwm3 &= ~PXMC_PT_ZIC_MASK;
293 #endif /*PXMC_WITH_PT_ZIC*/
295 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
296 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
298 unsigned long pwm_dc = pxmc_lpcpwm1_magnitude * (unsigned long)ene;
299 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15 + 15);
300 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15 + 15);
301 pwm3 = ((unsigned long long)pwm3 * pwm_dc) >> (15 + 15);
303 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
307 /*pxmc_lpc_wind_current_over_cnt=0;*/
308 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
309 #ifdef PXMC_WITH_PT_ZIC
310 /*hal_gpio_set_value(PWM2_EN_PIN,1);*/
311 /*hal_gpio_set_value(PWM4_EN_PIN,1);*/
312 /*hal_gpio_set_value(PWM6_EN_PIN,1);*/
313 #endif /*PXMC_WITH_PT_ZIC*/
320 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
322 volatile uint32_t *pwm_reg;
323 int chan = mcs->pxms_out_info;
324 int ene = mcs->pxms_ene;
329 pwm_reg = lx_master_base + 1 + chan;
335 ene = (ene * (2500 + 5)) >> 15;
337 pwm_reg[1] = ene | 0x4000;
341 ene = (ene * (2500 + 5)) >> 15;
343 pwm_reg[0] = ene | 0x4000;
349 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
351 pxmc_rocon_pwm_init(pxmc_state_t *mcs, int mode)
354 /* hal_pin_conf(PWM1_EN_PIN); */
356 /* hal_gpio_set_value(PWM1_EN_PIN,1); */
361 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
363 /*return pxmc_hh_gi;*/
376 pxmc_rocon_pwm_dc_out,
380 pxmc_inp_rocon_ap2hw,
381 pxms_ap: 0, pxms_as: 0,
382 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
383 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
386 pxms_ene: 0, pxms_erc: 0,
387 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
388 pxms_me: 0x7e00/*0x7fff*/,
390 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
395 /*pxms_ptamp: 0x7fff,*/
409 pxmc_rocon_pwm_dc_out,
413 pxmc_inp_rocon_ap2hw,
414 pxms_ap: 0, pxms_as: 0,
415 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
416 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
419 pxms_ene: 0, pxms_erc: 0,
420 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
421 pxms_me: 0x7e00/*0x7fff*/,
423 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
428 /*pxms_ptamp: 0x7fff,*/
442 pxmc_rocon_pwm_dc_out,
446 pxmc_inp_rocon_ap2hw,
447 pxms_ap: 0, pxms_as: 0,
448 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
449 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
452 pxms_ene: 0, pxms_erc: 0,
453 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
454 pxms_me: 0x7e00/*0x7fff*/,
456 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
461 /*pxms_ptamp: 0x7fff,*/
475 pxmc_rocon_pwm_dc_out,
479 pxmc_inp_rocon_ap2hw,
480 pxms_ap: 0, pxms_as: 0,
481 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
482 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
485 pxms_ene: 0, pxms_erc: 0,
486 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
487 pxms_me: 0x7e00/*0x7fff*/,
489 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
494 /*pxms_ptamp: 0x7fff,*/
500 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
501 {&mcs0, &mcs1, &mcs2, &mcs3};
504 pxmc_state_list_t pxmc_main_list =
511 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
513 pxmc_state_t *mcs = (pxmc_state_t *)context;
516 irc = qst->index_pos;
518 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
521 ofs = irc - mcs->pxms_ptmark;
522 diff = ofs - mcs->pxms_ptofs;
524 if (diff >= mcs->pxms_ptirc / 2)
525 diff -= mcs->pxms_ptirc;
527 if (diff <= -mcs->pxms_ptirc / 2)
528 diff += mcs->pxms_ptirc;
533 if (diff >= mcs->pxms_ptirc / 6)
535 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
539 mcs->pxms_ptofs = ofs;
540 pxmc_set_flag(mcs, PXMS_PHA_b);
544 ofs=irc-mcs->pxms_ptofs;
545 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
547 ofs-=mcs->pxms_ptirc;
549 ofs+=mcs->pxms_ptirc;
552 mcs->pxms_ptmark=ofs;
555 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
558 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
562 lpc_qei_state_t *qst = &lpc_qei_state;
563 int irc = lpc_qei_get_pos(qst);
569 idx_rel = qst->index_pos - irc;
570 idx_rel %= mcs->pxms_ptirc;
573 idx_rel += mcs->pxms_ptirc;
575 ptofs = irc - mcs->pxms_ptofs;
576 ptmark = ptofs + idx_rel;
578 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
581 ptmark -= mcs->pxms_ptirc;
583 ptmark += mcs->pxms_ptirc;
586 if ((unsigned short)ptmark < mcs->pxms_ptirc)
588 mcs->pxms_ptmark = ptmark;
594 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
599 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
600 lpc_qei_state_t *qst = &lpc_qei_state;
602 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
603 lpc_qei_setup_index_catch(qst);
605 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
606 spd = 1 << PXMC_SUBDIV(mcs);
608 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
613 int pxmc_lpc_pthalalign_run(void)
615 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
618 static inline void pxmc_sfi_input(void)
622 pxmc_for_each_mcs(var, mcs)
624 /* PXMS_ENI_m - check if input (IRC) update is enabled */
625 if (mcs->pxms_flg & PXMS_ENI_m)
627 pxmc_call(mcs, mcs->pxms_do_inp);
632 static inline void pxmc_sfi_controller_and_output(void)
636 pxmc_for_each_mcs(var, mcs)
638 /* PXMS_ENR_m - check if controller is enabled */
639 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
642 /* If output only is enabled, we skip the controller */
643 if (mcs->pxms_flg & PXMS_ENR_m)
646 pxmc_call(mcs, mcs->pxms_do_con);
648 /* PXMS_ERR_m - if axis in error state */
649 if (mcs->pxms_flg & PXMS_ERR_m)
653 /* for bushless motors, it is necessary to call do_out
654 even if the controller is not enabled and PWM should be provided. */
655 pxmc_call(mcs, mcs->pxms_do_out);
660 static inline void pxmc_sfi_generator(void)
664 pxmc_for_each_mcs(var, mcs)
666 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
667 if (mcs->pxms_flg & PXMS_ENG_m)
669 pxmc_call(mcs, mcs->pxms_do_gen);
674 static inline void pxmc_sfi_dbg(void)
678 pxmc_for_each_mcs(var, mcs)
680 if (mcs->pxms_flg & PXMS_DBG_m)
682 pxmc_call(mcs, mcs->pxms_do_deb);
688 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
692 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
694 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
695 #ifndef PXMC_WITH_PT_ZIC
696 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
697 #else /*PXMC_WITH_PT_ZIC*/
698 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
699 #endif /*PXMC_WITH_PT_ZIC*/
705 * pxmc_axis_mode - Sets axis mode.[extern API]
706 * @mcs: Motion controller state information
707 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
708 * 2 .. stepper motor with IRC feedback and PWM ,
709 * 3 .. stepper motor with PWM control
710 * 4 .. DC motor with IRC feedback and PWM
714 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
718 pxmc_set_const_out(mcs, 0);
719 pxmc_clear_flag(mcs, PXMS_ENI_b);
720 pxmc_clear_flag(mcs, PXMS_PHA_b);
721 pxmc_clear_flag(mcs, PXMS_PTI_b);
725 /*mode=pxmc_axis_rdmode(mcs);*/
727 mode = PXMC_AXIS_MODE_BLDC;
730 res = pxmc_axis_pt4mode(mcs, mode);
732 pxmc_set_flag(mcs, PXMS_ENI_b);
736 void pxmc_sfi_isr(void)
739 pxmc_sfi_controller_and_output();
740 pxmc_sfi_generator();
744 int pxmc_initialize(void)
748 pxmc_state_t *mcs = &mcs0;
749 lpc_qei_state_t *qst = &lpc_qei_state;
753 /* Initialize QEI module for IRC counting */
754 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
756 /* Initialize QEI events processing */
757 if (lpc_qei_setup_irq(qst) < 0)
762 res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
764 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
765 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
767 pxmc_rocon_pwm_init(mcs, 0);
769 pxmc_main_list.pxml_cnt = 0;
770 pxmc_dbg_hist = NULL;
772 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;