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 typeof(mcs->pxms_ptvang) ptvang;
310 unsigned char hal_pos;
318 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
319 (mcs->pxms_flg & PXMS_PRA_m))
322 short ptirc = mcs->pxms_ptirc;
323 short divisor = mcs->pxms_ptper * 6;
326 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
331 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
333 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
335 pxmc_set_flag(mcs, PXMS_PTI_b);
336 pxmc_set_flag(mcs, PXMS_PHA_b);
341 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
346 pxmc_rocon_process_hal_error(mcs);
350 if (mcs->pxms_halerc)
353 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
355 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
357 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
359 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
361 if ((ptindx > ptindx_prev + ptirc / 2) ||
362 (ptindx_prev > ptindx + ptirc / 2))
364 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
371 ptindx = (ptindx_prev + ptindx) / 2;
374 mcs->pxms_ptindx = ptindx;
376 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
378 pxmc_set_flag(mcs, PXMS_PTI_b);
379 pxmc_clear_flag(mcs, PXMS_PRA_b);
381 /* if phase table position to mask is know do fine phase table alignment */
382 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
383 /*pxmc_inp_rocon_is_index_edge(mcs);*/
388 if (!(mcs->pxms_flg & PXMS_PTI_m))
389 mcs->pxms_ptindx = ptindx;
393 mcs->pxms_hal = hal_pos;
399 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
400 /* FIXME - check winding current against limit */
401 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
405 ptvang = mcs->pxms_ptvang;
409 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
413 indx = mcs->pxms_ptindx;
415 /* tuning of magnetic field/voltage advance angle */
416 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
421 /* Generating direction of stator mag. field for backward torque */
424 if ((indx -= ptvang) < 0)
425 indx += mcs->pxms_ptirc;
429 /* Generating direction of stator mag. field for forward torque */
430 if ((indx += ptvang) >= mcs->pxms_ptirc)
431 indx -= mcs->pxms_ptirc;
434 if (mcs->pxms_ptscale_mult)
435 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
437 pwm1 = mcs->pxms_ptptr1[indx];
438 pwm2 = mcs->pxms_ptptr2[indx];
439 pwm3 = mcs->pxms_ptptr3[indx];
441 #ifdef PXMC_WITH_PT_ZIC
442 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
444 pwm1 &= ~PXMC_PT_ZIC_MASK;
445 pwm2 &= ~PXMC_PT_ZIC_MASK;
446 pwm3 &= ~PXMC_PT_ZIC_MASK;
448 #endif /*PXMC_WITH_PT_ZIC*/
450 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
451 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
453 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
454 if (pwm1 & PXMC_PT_ZIC_MASK)
457 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
458 if (pwm2 & PXMC_PT_ZIC_MASK)
461 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
462 if (pwm3 & PXMC_PT_ZIC_MASK)
465 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
467 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
471 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
478 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
479 * @mcs: Motion controller state information
481 /*static*/ inline void
482 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
484 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
485 int chan = mcs->pxms_out_info;
487 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 0);
488 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 1);
489 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 2);
490 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 3);
493 *pwm_reg_bp = pwm2 | 0x4000;
497 *pwm_reg_bn = -pwm2 | 0x4000;
501 *pwm_reg_ap = pwm1 | 0x4000;
505 *pwm_reg_an = -pwm1 | 0x4000;
510 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
511 * @mcs: Motion controller state information
514 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
516 typeof(mcs->pxms_ptvang) ptvang;
524 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
525 (mcs->pxms_flg&PXMS_PRA_m)){
527 short ptirc=mcs->pxms_ptirc;
530 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
535 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
537 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
539 pxmc_set_flag(mcs, PXMS_PTI_b);
540 pxmc_set_flag(mcs, PXMS_PHA_b);
545 ptindx = mcs->pxms_ptindx;
547 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
549 mcs->pxms_ptindx = ptindx;
551 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
553 pxmc_set_flag(mcs, PXMS_PTI_b);
554 pxmc_clear_flag(mcs, PXMS_PRA_b);
556 /* if phase table position to mask is know do fine phase table alignment */
557 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
558 // lpc_qei_setup_index_catch(&lpc_qei_state);
561 if(!(mcs->pxms_flg&PXMS_PTI_m))
562 mcs->pxms_ptindx = ptindx;
568 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
569 /* FIXME - check winding current against limit */
570 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
574 ptvang = mcs->pxms_ptvang;
578 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
582 indx = mcs->pxms_ptindx;
584 /* tuning of magnetic field/voltage advance angle */
585 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
588 /* Generating direction of stator mag. field for backward torque */
590 if ((indx -= ptvang)<0)
591 indx += mcs->pxms_ptirc;
593 /* Generating direction of stator mag. field for forward torque */
594 if ((indx += ptvang) >= mcs->pxms_ptirc)
595 indx -= mcs->pxms_ptirc;
598 if (mcs->pxms_ptscale_mult)
599 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
601 pwm1 = mcs->pxms_ptptr1[indx];
602 pwm2 = mcs->pxms_ptptr2[indx];
604 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
605 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
607 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
608 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
609 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
611 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
613 /*pxmc_lpc_wind_current_over_cnt = 0;*/
614 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
621 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
622 * @mcs: Motion controller state information
625 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
627 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
628 int chan = mcs->pxms_out_info;
629 int ene = mcs->pxms_ene;
631 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
632 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
638 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
640 *pwm_reg_b = ene | 0x4000;
644 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
646 *pwm_reg_a = ene | 0x4000;
652 /* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
654 pxmc_rocon_pwm_master_init(void)
658 *fpga_lx_master_reset = 1;
659 *fpga_lx_master_transmitter_reg = 0;
661 for (i = 0; i < 8 + 16; i ++)
662 fpga_lx_master_transmitter_base[i] = 0;
664 fpga_lx_master_transmitter_base[0] = 0x0808;
665 fpga_lx_master_transmitter_base[1] = 0x0000;
667 *fpga_lx_master_reset = 0;
672 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
673 unsigned long index_irc, int diff2err)
678 ofs = ofsl = index_irc - mcs->pxms_ptmark;
682 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
683 if (diff >= mcs->pxms_ptirc / 2)
684 diff -= mcs->pxms_ptirc;
685 if (diff <= -mcs->pxms_ptirc / 2)
686 diff += mcs->pxms_ptirc;
689 if(diff >= mcs->pxms_ptirc / 6) {
694 diff = (unsigned long)ofsl - irc;
695 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
698 mcs->pxms_ptofs = ofs;
704 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
705 * @mcs: Motion controller state information
708 pxmc_dummy_con(pxmc_state_t *mcs)
713 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
714 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
715 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
716 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
717 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
718 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
720 /* initialize for hard home */
722 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
724 pxmc_set_flag(mcs,PXMS_BSY_b);
725 #if 0 /* config and speed already set in pxmc_hh */
727 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
729 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
731 mcs->pxms_gen_hsp = spd;
734 mcs->pxms_gen_htim = 16;
735 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
736 return pxmc_rocon_hh_gd10(mcs);
739 /* fill initial mark filter and then decide */
741 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
745 if(mcs->pxms_flg & PXMS_ERR_m)
746 return pxmc_spdnext_gend(mcs);
748 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
749 mcs->pxms_rp += mcs->pxms_rs;
751 mark = pxmc_inp_rocon_is_mark(mcs);
753 if (mcs->pxms_gen_htim) {
754 mcs->pxms_gen_htim--;
758 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
759 /* limit switch is not used */
760 pxmc_inp_rocon_is_index_edge(mcs);
761 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
766 /* go out from switch */
767 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
769 /* switch is off -> look for it */
770 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
775 /* go out from switch */
777 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
781 if(mcs->pxms_flg & PXMS_ERR_m)
782 return pxmc_spdnext_gend(mcs);
784 mark = pxmc_inp_rocon_is_mark(mcs);
787 /* switch is off -> look for it again */
788 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
791 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
792 mcs->pxms_rp += mcs->pxms_rs;
797 /* switch is off -> look for it */
799 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
804 if (mcs->pxms_flg & PXMS_ERR_m)
805 return pxmc_spdnext_gend(mcs);
807 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
808 mcs->pxms_rp += mcs->pxms_rs;
810 mark = pxmc_inp_rocon_is_mark(mcs);
813 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
816 mcs->pxms_gen_hsp = spd;
817 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
823 /* switch is on -> find edge */
825 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
829 if (mcs->pxms_flg & PXMS_ERR_m)
830 return pxmc_spdnext_gend(mcs);
832 mark = pxmc_inp_rocon_is_mark(mcs);
835 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
836 pxmc_inp_rocon_is_index_edge(mcs);
837 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
839 pxmc_inp_rocon_ap_zero(mcs);
840 mcs->pxms_do_gen = pxmc_stop_gi;
844 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
845 mcs->pxms_rp += mcs->pxms_rs;
850 /* calibrate on revolution index */
852 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
854 if (mcs->pxms_flg & PXMS_ERR_m)
855 return pxmc_spdnext_gend(mcs);
857 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
858 mcs->pxms_rp += mcs->pxms_rs;
860 if (pxmc_inp_rocon_is_index_edge(mcs)){
861 pxmc_inp_rocon_irc_offset_from_index(mcs);
862 mcs->pxms_do_gen = pxmc_stop_gi;
868 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
870 return pxmc_rocon_hh_gi;
880 pxmc_pid_con /*pxmc_dummy_con*/,
882 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
886 pxmc_inp_rocon_ap2hw,
887 pxms_ap: 0, pxms_as: 0,
888 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
889 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
892 pxms_ene: 0, pxms_erc: 0,
893 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
894 pxms_me: 0x7e00/*0x7fff*/,
896 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
902 /*pxms_ptamp: 0x7fff,*/
916 pxmc_rocon_pwm_dc_out,
920 pxmc_inp_rocon_ap2hw,
921 pxms_ap: 0, pxms_as: 0,
922 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
923 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
926 pxms_ene: 0, pxms_erc: 0,
927 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
928 pxms_me: 0x7e00/*0x7fff*/,
930 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
935 /*pxms_ptamp: 0x7fff,*/
949 pxmc_rocon_pwm_dc_out,
953 pxmc_inp_rocon_ap2hw,
954 pxms_ap: 0, pxms_as: 0,
955 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
956 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
959 pxms_ene: 0, pxms_erc: 0,
960 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
961 pxms_me: 0x7e00/*0x7fff*/,
963 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
968 /*pxms_ptamp: 0x7fff,*/
982 pxmc_rocon_pwm_dc_out,
986 pxmc_inp_rocon_ap2hw,
987 pxms_ap: 0, pxms_as: 0,
988 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
989 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
992 pxms_ene: 0, pxms_erc: 0,
993 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
994 pxms_me: 0x7e00/*0x7fff*/,
996 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1001 /*pxms_ptamp: 0x7fff,*/
1015 pxmc_rocon_pwm_dc_out,
1019 pxmc_inp_rocon_ap2hw,
1020 pxms_ap: 0, pxms_as: 0,
1021 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1022 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1025 pxms_ene: 0, pxms_erc: 0,
1026 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1027 pxms_me: 0x7e00/*0x7fff*/,
1029 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1034 /*pxms_ptamp: 0x7fff,*/
1048 pxmc_rocon_pwm_dc_out,
1052 pxmc_inp_rocon_ap2hw,
1053 pxms_ap: 0, pxms_as: 0,
1054 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1055 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1058 pxms_ene: 0, pxms_erc: 0,
1059 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1060 pxms_me: 0x7e00/*0x7fff*/,
1062 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1067 /*pxms_ptamp: 0x7fff,*/
1081 pxmc_rocon_pwm_dc_out,
1085 pxmc_inp_rocon_ap2hw,
1086 pxms_ap: 0, pxms_as: 0,
1087 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1088 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1091 pxms_ene: 0, pxms_erc: 0,
1092 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1093 pxms_me: 0x7e00/*0x7fff*/,
1095 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1100 /*pxms_ptamp: 0x7fff,*/
1114 pxmc_rocon_pwm_dc_out,
1118 pxmc_inp_rocon_ap2hw,
1119 pxms_ap: 0, pxms_as: 0,
1120 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1121 pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
1124 pxms_ene: 0, pxms_erc: 0,
1125 pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1126 pxms_me: 0x7e00/*0x7fff*/,
1128 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1133 /*pxms_ptamp: 0x7fff,*/
1139 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1140 {&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
1143 pxmc_state_list_t pxmc_main_list =
1150 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1152 pxmc_state_t *mcs = (pxmc_state_t *)context;
1155 irc = qst->index_pos;
1157 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1160 ofs = irc - mcs->pxms_ptmark;
1161 diff = ofs - mcs->pxms_ptofs;
1163 if (diff >= mcs->pxms_ptirc / 2)
1164 diff -= mcs->pxms_ptirc;
1166 if (diff <= -mcs->pxms_ptirc / 2)
1167 diff += mcs->pxms_ptirc;
1172 if (diff >= mcs->pxms_ptirc / 6)
1174 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1178 mcs->pxms_ptofs = ofs;
1179 pxmc_set_flag(mcs, PXMS_PHA_b);
1183 ofs=irc-mcs->pxms_ptofs;
1184 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1186 ofs-=mcs->pxms_ptirc;
1188 ofs+=mcs->pxms_ptirc;
1191 mcs->pxms_ptmark=ofs;
1194 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1197 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1201 lpc_qei_state_t *qst = &lpc_qei_state;
1202 int irc = lpc_qei_get_pos(qst);
1205 if (!qst->index_occ)
1208 idx_rel = qst->index_pos - irc;
1209 idx_rel %= mcs->pxms_ptirc;
1212 idx_rel += mcs->pxms_ptirc;
1214 ptofs = irc - mcs->pxms_ptofs;
1215 ptmark = ptofs + idx_rel;
1217 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1220 ptmark -= mcs->pxms_ptirc;
1222 ptmark += mcs->pxms_ptirc;
1225 if ((unsigned short)ptmark < mcs->pxms_ptirc)
1227 mcs->pxms_ptmark = ptmark;
1233 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
1238 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
1239 lpc_qei_state_t *qst = &lpc_qei_state;
1241 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
1242 lpc_qei_setup_index_catch(qst);
1244 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
1245 spd = 1 << PXMC_SUBDIV(mcs);
1247 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1252 int pxmc_lpc_pthalalign_run(void)
1254 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
1257 static inline void pxmc_sfi_input(void)
1261 pxmc_for_each_mcs(var, mcs)
1263 /* PXMS_ENI_m - check if input (IRC) update is enabled */
1264 if (mcs->pxms_flg & PXMS_ENI_m)
1266 pxmc_call(mcs, mcs->pxms_do_inp);
1271 static inline void pxmc_sfi_controller_and_output(void)
1275 pxmc_for_each_mcs(var, mcs)
1277 /* PXMS_ENR_m - check if controller is enabled */
1278 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
1281 /* If output only is enabled, we skip the controller */
1282 if (mcs->pxms_flg & PXMS_ENR_m)
1285 pxmc_call(mcs, mcs->pxms_do_con);
1287 /* PXMS_ERR_m - if axis in error state */
1288 if (mcs->pxms_flg & PXMS_ERR_m)
1292 /* for bushless motors, it is necessary to call do_out
1293 even if the controller is not enabled and PWM should be provided. */
1294 pxmc_call(mcs, mcs->pxms_do_out);
1299 static inline void pxmc_sfi_generator(void)
1303 pxmc_for_each_mcs(var, mcs)
1305 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
1306 if (mcs->pxms_flg & PXMS_ENG_m)
1308 pxmc_call(mcs, mcs->pxms_do_gen);
1313 static inline void pxmc_sfi_dbg(void)
1317 pxmc_for_each_mcs(var, mcs)
1319 if (mcs->pxms_flg & PXMS_DBG_m)
1321 pxmc_call(mcs, mcs->pxms_do_deb);
1326 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
1330 int inp_chan = mcs->pxms_inp_info;
1332 long irc = fpga_irc[inp_chan]->count;
1334 if (!pxmc_inp_rocon_is_index_edge(mcs))
1337 idx_rel = fpga_irc[inp_chan]->count_index - irc;
1338 idx_rel %= mcs->pxms_ptirc;
1340 idx_rel += mcs->pxms_ptirc;
1342 ptofs = irc-mcs->pxms_ptofs;
1343 ptmark = ptofs+idx_rel;
1345 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
1347 ptmark -= mcs->pxms_ptirc;
1349 ptmark += mcs->pxms_ptirc;
1352 if((unsigned short)ptmark < mcs->pxms_ptirc) {
1353 mcs->pxms_ptmark = ptmark;
1358 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
1363 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
1365 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
1367 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
1368 spd=1<<PXMC_SUBDIV(mcs);
1370 /* clear bit indicating previous index */
1371 pxmc_inp_rocon_is_index_edge(mcs);
1373 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
1378 int pxmc_axis_rdmode(pxmc_state_t *mcs)
1380 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
1381 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
1382 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
1383 return PXMC_AXIS_MODE_DC;
1384 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
1385 return PXMC_AXIS_MODE_BLDC;
1391 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
1393 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
1396 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1397 mode = pxmc_axis_rdmode(mcs);
1402 /*case PXMC_AXIS_MODE_STEPPER:*/
1403 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1404 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
1406 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1407 case PXMC_AXIS_MODE_DC:
1408 /*profive some sane dummy values*/
1409 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
1410 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
1411 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
1413 mcs->pxms_ptscale_mult=1;
1414 mcs->pxms_ptscale_shift=15;
1416 case PXMC_AXIS_MODE_BLDC:
1417 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
1418 #ifndef PXMC_WITH_PT_ZIC
1419 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
1420 #else /*PXMC_WITH_PT_ZIC*/
1421 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
1422 #endif /*PXMC_WITH_PT_ZIC*/
1428 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
1434 * pxmc_axis_mode - Sets axis mode.[extern API]
1435 * @mcs: Motion controller state information
1436 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
1437 * 2 .. stepper motor with IRC feedback and PWM ,
1438 * 3 .. stepper motor with PWM control
1439 * 4 .. DC motor with IRC feedback and PWM
1443 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
1447 pxmc_set_const_out(mcs, 0);
1448 pxmc_clear_flag(mcs, PXMS_ENI_b);
1449 pxmc_clear_flag(mcs, PXMS_PHA_b);
1450 pxmc_clear_flag(mcs, PXMS_PTI_b);
1452 if (mode == PXMC_AXIS_MODE_NOCHANGE)
1453 mode = pxmc_axis_rdmode(mcs);
1457 mode = PXMC_AXIS_MODE_DC;
1459 res = pxmc_axis_pt4mode(mcs, mode);
1464 /*case PXMC_AXIS_MODE_STEPPER:*/
1465 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
1466 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
1468 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
1469 case PXMC_AXIS_MODE_DC:
1470 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
1472 case PXMC_AXIS_MODE_BLDC:
1473 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
1479 pxmc_set_flag(mcs, PXMS_ENI_b);
1483 void pxmc_sfi_isr(void)
1486 pxmc_sfi_controller_and_output();
1487 pxmc_sfi_generator();
1489 /* Kick LX Master watchdog */
1490 if (pxmc_main_list.pxml_cnt != 0)
1491 *fpga_lx_master_transmitter_wdog = 1;
1494 int pxmc_clear_power_stop(void)
1504 if (!pxmc_main_list.pxml_cnt)
1507 pxmc_for_each_mcs(var, mcs)
1509 pxmc_set_const_out(mcs,0);
1512 pxmc_main_list.pxml_cnt = 0;
1518 int pxmc_initialize(void)
1523 pxmc_state_t *mcs = &mcs0;
1524 lpc_qei_state_t *qst = &lpc_qei_state;
1526 *fpga_irc_reset = 1;
1528 for (i = 0; i < 8; i++) {
1529 fpga_irc[i]->count = 0;
1530 *fpga_irc_state[i] = 1 << 2;
1533 /* Initialize QEI module for IRC counting */
1534 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
1536 /* Initialize QEI events processing */
1537 if (lpc_qei_setup_irq(qst) < 0)
1540 *fpga_irc_reset = 0;
1542 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
1544 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
1545 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1547 pxmc_rocon_pwm_master_init();
1549 pxmc_main_list.pxml_cnt = 0;
1550 pxmc_dbg_hist = NULL;
1552 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;