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*/
319 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
321 pxmc_rocon_pwm_init(pxmc_state_t *mcs, int mode)
324 /* hal_pin_conf(PWM1_EN_PIN); */
326 /* hal_gpio_set_value(PWM1_EN_PIN,1); */
331 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
333 /*return pxmc_hh_gi;*/
350 pxmc_inp_rocon_ap2hw,
351 pxms_ap: 0, pxms_as: 0,
352 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
353 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
356 pxms_ene: 0, pxms_erc: 0,
357 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
358 pxms_me: 0x7e00/*0x7fff*/,
360 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
365 /*pxms_ptamp: 0x7fff,*/
383 pxmc_inp_rocon_ap2hw,
384 pxms_ap: 0, pxms_as: 0,
385 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
386 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
389 pxms_ene: 0, pxms_erc: 0,
390 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
391 pxms_me: 0x7e00/*0x7fff*/,
393 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
398 /*pxms_ptamp: 0x7fff,*/
416 pxmc_inp_rocon_ap2hw,
417 pxms_ap: 0, pxms_as: 0,
418 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
419 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
422 pxms_ene: 0, pxms_erc: 0,
423 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
424 pxms_me: 0x7e00/*0x7fff*/,
426 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
431 /*pxms_ptamp: 0x7fff,*/
449 pxmc_inp_rocon_ap2hw,
450 pxms_ap: 0, pxms_as: 0,
451 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
452 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
455 pxms_ene: 0, pxms_erc: 0,
456 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
457 pxms_me: 0x7e00/*0x7fff*/,
459 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
464 /*pxms_ptamp: 0x7fff,*/
470 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
471 {&mcs0, &mcs1, &mcs2, &mcs3};
474 pxmc_state_list_t pxmc_main_list =
481 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
483 pxmc_state_t *mcs = (pxmc_state_t *)context;
486 irc = qst->index_pos;
488 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
491 ofs = irc - mcs->pxms_ptmark;
492 diff = ofs - mcs->pxms_ptofs;
494 if (diff >= mcs->pxms_ptirc / 2)
495 diff -= mcs->pxms_ptirc;
497 if (diff <= -mcs->pxms_ptirc / 2)
498 diff += mcs->pxms_ptirc;
503 if (diff >= mcs->pxms_ptirc / 6)
505 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
509 mcs->pxms_ptofs = ofs;
510 pxmc_set_flag(mcs, PXMS_PHA_b);
514 ofs=irc-mcs->pxms_ptofs;
515 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
517 ofs-=mcs->pxms_ptirc;
519 ofs+=mcs->pxms_ptirc;
522 mcs->pxms_ptmark=ofs;
525 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
528 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
532 lpc_qei_state_t *qst = &lpc_qei_state;
533 int irc = lpc_qei_get_pos(qst);
539 idx_rel = qst->index_pos - irc;
540 idx_rel %= mcs->pxms_ptirc;
543 idx_rel += mcs->pxms_ptirc;
545 ptofs = irc - mcs->pxms_ptofs;
546 ptmark = ptofs + idx_rel;
548 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
551 ptmark -= mcs->pxms_ptirc;
553 ptmark += mcs->pxms_ptirc;
556 if ((unsigned short)ptmark < mcs->pxms_ptirc)
558 mcs->pxms_ptmark = ptmark;
564 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
569 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
570 lpc_qei_state_t *qst = &lpc_qei_state;
572 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
573 lpc_qei_setup_index_catch(qst);
575 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
576 spd = 1 << PXMC_SUBDIV(mcs);
578 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
583 int pxmc_lpc_pthalalign_run(void)
585 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
588 static inline void pxmc_sfi_input(void)
592 pxmc_for_each_mcs(var, mcs)
594 /* PXMS_ENI_m - check if input (IRC) update is enabled */
595 if (mcs->pxms_flg & PXMS_ENI_m)
597 pxmc_call(mcs, mcs->pxms_do_inp);
602 static inline void pxmc_sfi_controller_and_output(void)
606 pxmc_for_each_mcs(var, mcs)
608 /* PXMS_ENR_m - check if controller is enabled */
609 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
612 /* If output only is enabled, we skip the controller */
613 if (mcs->pxms_flg & PXMS_ENR_m)
616 pxmc_call(mcs, mcs->pxms_do_con);
618 /* PXMS_ERR_m - if axis in error state */
619 if (mcs->pxms_flg & PXMS_ERR_m)
623 /* for bushless motors, it is necessary to call do_out
624 even if the controller is not enabled and PWM should be provided. */
625 pxmc_call(mcs, mcs->pxms_do_out);
630 static inline void pxmc_sfi_generator(void)
634 pxmc_for_each_mcs(var, mcs)
636 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
637 if (mcs->pxms_flg & PXMS_ENG_m)
639 pxmc_call(mcs, mcs->pxms_do_gen);
644 static inline void pxmc_sfi_dbg(void)
648 pxmc_for_each_mcs(var, mcs)
650 if (mcs->pxms_flg & PXMS_DBG_m)
652 pxmc_call(mcs, mcs->pxms_do_deb);
658 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
662 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
664 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
665 #ifndef PXMC_WITH_PT_ZIC
666 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
667 #else /*PXMC_WITH_PT_ZIC*/
668 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
669 #endif /*PXMC_WITH_PT_ZIC*/
675 * pxmc_axis_mode - Sets axis mode.[extern API]
676 * @mcs: Motion controller state information
677 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
678 * 2 .. stepper motor with IRC feedback and PWM ,
679 * 3 .. stepper motor with PWM control
680 * 4 .. DC motor with IRC feedback and PWM
684 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
688 pxmc_set_const_out(mcs, 0);
689 pxmc_clear_flag(mcs, PXMS_ENI_b);
690 pxmc_clear_flag(mcs, PXMS_PHA_b);
691 pxmc_clear_flag(mcs, PXMS_PTI_b);
695 /*mode=pxmc_axis_rdmode(mcs);*/
697 mode = PXMC_AXIS_MODE_BLDC;
700 res = pxmc_axis_pt4mode(mcs, mode);
702 pxmc_set_flag(mcs, PXMS_ENI_b);
706 void pxmc_sfi_isr(void)
709 pxmc_sfi_controller_and_output();
710 pxmc_sfi_generator();
714 int pxmc_initialize(void)
718 pxmc_state_t *mcs = &mcs0;
719 lpc_qei_state_t *qst = &lpc_qei_state;
723 /* Initialize QEI module for IRC counting */
724 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
726 /* Initialize QEI events processing */
727 if (lpc_qei_setup_irq(qst) < 0)
732 res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
734 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
735 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
737 pxmc_rocon_pwm_init(mcs, 0);
739 pxmc_main_list.pxml_cnt = 0;
740 pxmc_dbg_hist = NULL;
742 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;