1 /*******************************************************************
2 Motion and Robotic System (MARS) aplication components.
4 appl_pxmc.c - position controller RoCoN hardware support
6 Copyright (C) 2001-2013 by Pavel Pisa - originator
8 (C) 2001-2013 by PiKRON Ltd. - originator
11 This file can be used and copied according to next
13 - GPL - GNU Public License
14 - other license provided by project originators
16 *******************************************************************/
19 #include <system_def.h>
21 #include <pxmc_lpc_qei.h>
22 #include <pxmc_internal.h>
23 #include <pxmc_inp_common.h>
24 #include <pxmc_gen_info.h>
26 #include <hal_machperiph.h>
32 #include "appl_defs.h"
33 #include "appl_fpga.h"
34 #include "appl_pxmc.h"
35 #include "pxmcc_types.h"
36 #include "pxmcc_interface.h"
38 #define PXMC_AXIS_MODE_BLDC_PXMCC (PXMC_AXIS_MODE_BLDC + 1)
39 #define PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC (PXMC_AXIS_MODE_BLDC + 2)
40 #define PXMC_AXIS_MODE_STEPPER_PXMCC (PXMC_AXIS_MODE_BLDC + 3)
42 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
43 unsigned long index_irc, int diff2err);
45 #ifndef pxmc_fast_tick_time
46 #define pxmc_fast_tick_time() (LPC_TIM0->TC)
49 #define PXML_MAIN_CNT 8
51 #define PXMC_WITH_PT_ZIC 1
52 #define PXMC_PT_ZIC_MASK 0x8000
54 #define LPCPWM1_FREQ 20000
56 #define HAL_ERR_SENSITIVITY 20
57 #define HAL_ERR_MAX_COUNT 5
59 #define LXPWR_WITH_SIROLADC 1
61 #define LX_MASTER_DATA_OFFS 8
63 #define PXMC_LXPWR_PWM_CYCLE 2500
65 unsigned pxmc_rocon_pwm_magnitude = PXMC_LXPWR_PWM_CYCLE;
67 long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
68 unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
71 pxmc_rocon_state_t *pxmc_state2rocon_state(pxmc_state_t *mcs)
73 pxmc_rocon_state_t *mcsrc;
75 mcsrc = UL_CONTAINEROF(mcs, pxmc_rocon_state_t, base);
76 #else /*UL_CONTAINEROF*/
77 mcsrc = (pxmc_rocon_state_t*)((char*)mcs - __builtin_offsetof(pxmc_rocon_state_t, base));
78 #endif /*UL_CONTAINEROF*/
82 uint32_t pxmc_rocon_vin_adc_last;
83 int pxmc_rocon_vin_act;
84 int pxmc_rocon_vin_ofs = 20978;
85 int pxmc_rocon_vin_mul = 32905;
86 int pxmc_rocon_vin_shr = 14;
89 void pxmc_rocon_vin_compute(void)
91 volatile uint32_t *vin_adc_reg;
95 vin_adc_reg = fpga_lx_master_receiver_base;
96 vin_adc_reg += LX_MASTER_DATA_OFFS + 1 + 8 * 2;
98 vin_adc = *vin_adc_reg;
100 vin_act = (int16_t)(vin_adc - pxmc_rocon_vin_adc_last);
101 pxmc_rocon_vin_adc_last = vin_adc;
103 vin_act = (pxmc_rocon_vin_ofs - vin_act) * pxmc_rocon_vin_mul;
104 vin_act >>= pxmc_rocon_vin_shr;
106 pxmc_rocon_vin_act = vin_act;
109 unsigned int pxmc_rocon_rx_done_sqn;
110 unsigned int pxmc_rocon_rx_done_sqn_inc;
111 unsigned int pxmc_rocon_rx_done_sqn_misscnt;
112 unsigned int pxmc_rocon_rx_done_sqn_missoffs;
115 void pxmc_rocon_rx_done_sqn_compute(void)
119 unsigned int sqn_expect = pxmc_rocon_rx_done_sqn + pxmc_rocon_rx_done_sqn_inc;
121 sqn_act = *fpga_lx_master_receiver_done_div;
122 sqn_offs = (sqn_act - sqn_expect) & 0x1f;
124 if (pxmc_rocon_rx_done_sqn_missoffs != sqn_offs) {
125 pxmc_rocon_rx_done_sqn_misscnt = 1;
127 pxmc_rocon_rx_done_sqn_misscnt++;
128 if (pxmc_rocon_rx_done_sqn_misscnt >= 10)
129 sqn_expect += 1 - ((sqn_offs >> 3) & 2);
132 pxmc_rocon_rx_done_sqn_misscnt = 0;
134 pxmc_rocon_rx_done_sqn = sqn_expect;
135 pxmc_rocon_rx_done_sqn_missoffs = sqn_offs;
138 const uint8_t onesin10bits[1024]={
139 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,
140 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,
141 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,
142 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,
143 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,
144 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,
145 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,
146 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,
147 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,
148 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,
149 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,
150 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,
151 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,
152 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,
153 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,
154 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,
155 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,
156 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,
157 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,
158 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,
159 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,
160 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,
161 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,
162 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,
163 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,
164 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,
165 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,
166 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,
167 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,
168 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,
169 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,
170 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
174 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
176 int chan=mcs->pxms_inp_info;
180 /* read position from hardware */
181 irc = fpga_irc[chan]->count;
182 irc += pxmc_rocon_irc_offset[chan];
183 pos = irc << PXMC_SUBDIV(mcs);
184 mcs->pxms_as = pos - mcs->pxms_ap;
187 /* Running of the motor commutator */
188 if (mcs->pxms_flg & PXMS_PTI_m)
189 pxmc_irc_16bit_commindx(mcs, irc);
195 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
200 int chan=mcs->pxms_inp_info;
202 irc_state = *fpga_irc_state[chan];
204 mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
205 (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
207 filt = pxmc_rocon_mark_filt[chan];
208 filt = (filt << 1) | mark;
209 pxmc_rocon_mark_filt[chan] = filt;
211 return onesin10bits[filt & 0x03ff];
215 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
219 int chan=mcs->pxms_inp_info;
221 irc_state = *fpga_irc_state[chan];
222 *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
224 index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
230 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
232 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
234 mcs->pxms_ptofs += irc_diff;
236 mcs->pxms_ap += pos_diff;
237 mcs->pxms_rp += pos_diff;
242 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
244 int chan=mcs->pxms_inp_info;
248 irc_offset = -fpga_irc[chan]->count_index;
249 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
250 pxmc_rocon_irc_offset[chan] = irc_offset;
251 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
255 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
257 int chan=mcs->pxms_inp_info;
261 irc_offset = -fpga_irc[chan]->count;
262 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
263 pxmc_rocon_irc_offset[chan] = irc_offset;
264 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
268 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
270 int chan=mcs->pxms_inp_info;
274 irc = fpga_irc[chan]->count;
275 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
277 irc = pos_diff >> PXMC_SUBDIV(mcs);
279 /* Adjust phase table alignemt to modified IRC readout */
280 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
282 pxmc_rocon_irc_offset[chan] = irc;
287 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
289 int chan=mcs->pxms_inp_info;
293 if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
296 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
297 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
299 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
302 uint32_t pxmc_rocon_receiver_dummy_reg;
304 static inline volatile uint32_t *
305 pxmc_rocon_receiver_chan2reg(unsigned chan)
307 volatile uint32_t *rec_reg;
310 return &pxmc_rocon_receiver_dummy_reg;
312 rec_reg = fpga_lx_master_receiver_base;
314 #ifdef LXPWR_WITH_SIROLADC
315 rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) * 3 + chan * 2;
316 #else /*LXPWR_WITH_SIROLADC*/
317 rec_reg += LX_MASTER_DATA_OFFS + chan;
318 #endif /*LXPWR_WITH_SIROLADC*/
324 pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
327 volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
328 int chan = mcs->pxms_out_info;
331 #ifdef LXPWR_WITH_SIROLADC
333 #else /*LXPWR_WITH_SIROLADC*/
335 #endif /*LXPWR_WITH_SIROLADC*/
337 rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
338 rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
339 rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
341 h = (rec_reg_a[hal_offs] >> 14) & 1;
342 h |= (rec_reg_b[hal_offs] >> 13) & 2;
343 h |= (rec_reg_c[hal_offs] >> 12) & 4;
345 /* return 3 bits corresponding to the HAL senzor input */
350 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
362 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
375 uint32_t pxmc_rocon_pwm_dummy_reg;
377 static inline volatile uint32_t *
378 pxmc_rocon_pwm_chan2reg(unsigned chan)
380 volatile uint32_t *pwm_reg;
383 return &pxmc_rocon_pwm_dummy_reg;
385 pwm_reg = fpga_lx_master_transmitter_base;
387 #ifdef LXPWR_WITH_SIROLADC
388 pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) + chan;
389 #else /*LXPWR_WITH_SIROLADC*/
390 pwm_reg += LX_MASTER_DATA_OFFS + chan;
391 #endif /*LXPWR_WITH_SIROLADC*/
396 int pxmc_rocon_pwm_direct_wr(unsigned chan, unsigned pwm, int en)
398 volatile uint32_t *pwm_reg;
399 pwm_reg = pxmc_rocon_pwm_chan2reg(chan);
401 if (pwm_reg == &pxmc_rocon_pwm_dummy_reg)
404 *pwm_reg = pwm | (en? 0x4000: 0x8000);
410 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
411 * @mcs: Motion controller state information
413 /*static*/ inline void
414 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
416 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
417 int chan = mcs->pxms_out_info;
419 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
420 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
421 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
429 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
431 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
433 pxmc_set_errno(mcs, PXMS_E_HAL);
438 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
442 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
443 * @mcs: Motion controller state information
446 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
448 typeof(mcs->pxms_ptvang) ptvang;
450 unsigned char hal_pos;
458 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
459 (mcs->pxms_flg & PXMS_PRA_m))
462 short ptirc = mcs->pxms_ptirc;
463 short divisor = mcs->pxms_ptper * 6;
466 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
471 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
473 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
475 pxmc_set_flag(mcs, PXMS_PTI_b);
476 pxmc_set_flag(mcs, PXMS_PHA_b);
481 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
486 pxmc_rocon_process_hal_error(mcs);
490 if (mcs->pxms_halerc)
493 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
495 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
497 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
499 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
501 if ((ptindx > ptindx_prev + ptirc / 2) ||
502 (ptindx_prev > ptindx + ptirc / 2))
504 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
511 ptindx = (ptindx_prev + ptindx) / 2;
514 mcs->pxms_ptindx = ptindx;
516 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
518 pxmc_set_flag(mcs, PXMS_PTI_b);
519 pxmc_clear_flag(mcs, PXMS_PRA_b);
523 if (!(mcs->pxms_flg & PXMS_PTI_m))
524 mcs->pxms_ptindx = ptindx;
527 /* if phase table position to mask is know do fine phase table alignment */
528 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
530 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
532 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
534 pxmc_set_flag(mcs, PXMS_PTI_b);
535 pxmc_set_flag(mcs, PXMS_PHA_b);
539 mcs->pxms_hal = hal_pos;
545 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
546 /* FIXME - check winding current against limit */
547 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
551 ptvang = mcs->pxms_ptvang;
555 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
559 indx = mcs->pxms_ptindx;
561 /* tuning of magnetic field/voltage advance angle */
562 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
567 /* Generating direction of stator mag. field for backward torque */
570 if ((indx -= ptvang) < 0)
571 indx += mcs->pxms_ptirc;
575 /* Generating direction of stator mag. field for forward torque */
576 if ((indx += ptvang) >= mcs->pxms_ptirc)
577 indx -= mcs->pxms_ptirc;
580 if (mcs->pxms_ptscale_mult)
581 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
583 pwm1 = mcs->pxms_ptptr1[indx];
584 pwm2 = mcs->pxms_ptptr2[indx];
585 pwm3 = mcs->pxms_ptptr3[indx];
587 #ifdef PXMC_WITH_PT_ZIC
588 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
590 pwm1 &= ~PXMC_PT_ZIC_MASK;
591 pwm2 &= ~PXMC_PT_ZIC_MASK;
592 pwm3 &= ~PXMC_PT_ZIC_MASK;
594 #endif /*PXMC_WITH_PT_ZIC*/
596 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
597 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
599 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
600 if (pwm1 & PXMC_PT_ZIC_MASK)
603 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
604 if (pwm2 & PXMC_PT_ZIC_MASK)
607 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
608 if (pwm3 & PXMC_PT_ZIC_MASK)
611 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
613 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
617 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
624 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
625 * @mcs: Motion controller state information
627 /*static*/ inline void
628 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
630 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
631 int chan = mcs->pxms_out_info;
633 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
634 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
635 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
636 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
639 *pwm_reg_bp = pwm2 | 0x4000;
643 *pwm_reg_bn = -pwm2 | 0x4000;
647 *pwm_reg_ap = pwm1 | 0x4000;
651 *pwm_reg_an = -pwm1 | 0x4000;
656 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
657 * @mcs: Motion controller state information
660 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
662 typeof(mcs->pxms_ptvang) ptvang;
670 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
671 (mcs->pxms_flg&PXMS_PRA_m)){
673 short ptirc=mcs->pxms_ptirc;
676 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
681 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
683 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
685 pxmc_set_flag(mcs, PXMS_PTI_b);
686 pxmc_set_flag(mcs, PXMS_PHA_b);
691 ptindx = mcs->pxms_ptindx;
693 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
695 mcs->pxms_ptindx = ptindx;
697 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
699 pxmc_set_flag(mcs, PXMS_PTI_b);
700 pxmc_clear_flag(mcs, PXMS_PRA_b);
702 /* if phase table position to mask is know do fine phase table alignment */
703 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
704 // lpc_qei_setup_index_catch(&lpc_qei_state);
707 if(!(mcs->pxms_flg&PXMS_PTI_m))
708 mcs->pxms_ptindx = ptindx;
714 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
715 /* FIXME - check winding current against limit */
716 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
720 ptvang = mcs->pxms_ptvang;
724 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
728 indx = mcs->pxms_ptindx;
730 /* tuning of magnetic field/voltage advance angle */
731 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
734 /* Generating direction of stator mag. field for backward torque */
736 if ((indx -= ptvang)<0)
737 indx += mcs->pxms_ptirc;
739 /* Generating direction of stator mag. field for forward torque */
740 if ((indx += ptvang) >= mcs->pxms_ptirc)
741 indx -= mcs->pxms_ptirc;
744 if (mcs->pxms_ptscale_mult)
745 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
747 pwm1 = mcs->pxms_ptptr1[indx];
748 pwm2 = mcs->pxms_ptptr2[indx];
750 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
751 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
753 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
754 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
755 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
757 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
759 /*pxmc_lpc_wind_current_over_cnt = 0;*/
760 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
767 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
768 * @mcs: Motion controller state information
771 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
773 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
774 int chan = mcs->pxms_out_info;
775 int ene = mcs->pxms_ene;
777 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
778 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
784 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
786 *pwm_reg_b = ene | 0x4000;
790 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
792 *pwm_reg_a = ene | 0x4000;
798 /*******************************************************************/
799 /* PXMCC - PXMC coprocessor support and communication */
801 void pxmcc_pxmc_ptofs2mcc(pxmc_state_t *mcs, int enable_update)
803 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
804 int inp_chan=mcs->pxms_inp_info;
808 if (mcc_axis != NULL) {
809 if (enable_update >= 0)
810 mcc_axis->ptirc = 0xffffffff;
811 ptofs = mcs->pxms_ptofs - pxmc_rocon_irc_offset[inp_chan];
812 irc = fpga_irc[inp_chan]->count;
813 ptofs = (int16_t)(ptofs - irc) + irc;
814 mcc_axis->ptofs = ptofs;
815 if (enable_update > 0) {
816 mcc_axis->ptirc = mcs->pxms_ptirc;
822 void pxmcc_axis_get_cur_dq_filt_raw(pxmc_state_t *mcs,
823 int32_t *p_cur_d_raw, int32_t *p_cur_q_raw)
825 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
826 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
827 uint32_t cur_d_cum = mcc_axis->cur_d_cum;
828 uint32_t cur_q_cum = mcc_axis->cur_q_cum;
832 cur_d = cur_d_cum - mcsrc->cur_d_cum_prev;
833 mcsrc->cur_d_cum_prev = cur_d_cum;
834 cur_q = cur_q_cum - mcsrc->cur_q_cum_prev;
835 mcsrc->cur_q_cum_prev = cur_q_cum;
837 *p_cur_d_raw = cur_d;
838 *p_cur_q_raw = cur_q;
842 void pxmcc_axis_cur_dq_raw2filt(int *p_cur, int32_t cur_raw)
846 cur_div = cur_raw & 0x1f;
847 cur = cur_raw / cur_div;
848 cur += (1 << 11) | 0x20;
853 void pxmcc_axis_get_cur_dq_filt(pxmc_state_t *mcs, int *p_cur_d, int *p_cur_q)
858 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
860 pxmcc_axis_cur_dq_raw2filt(p_cur_d, cur_d_raw);
861 pxmcc_axis_cur_dq_raw2filt(p_cur_q, cur_q_raw);
865 void pxmcc_cur_ctrl_pi(int *p_pwm, int32_t *p_cur_err_sum,
866 int cur_err, short cur_ctrl_p, short cur_ctrl_i, int max_pwm)
869 int32_t cur_err_sum = *p_cur_err_sum;
871 pwm = (cur_err * cur_ctrl_p) >> 8;
874 cur_err_sum += cur_err * cur_ctrl_i;
878 pwm += cur_err_sum >> 16;
881 cur_err_sum -= (pwm - max_pwm) << 16;
883 } else if (-pwm > max_pwm) {
884 cur_err_sum -= (pwm + max_pwm) << 16;
887 *p_cur_err_sum = cur_err_sum;
892 pxmc_pxmcc_pwm3ph_out(pxmc_state_t *mcs)
896 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
898 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
899 (mcs->pxms_flg & PXMS_PRA_m)) {
901 short ptirc = mcs->pxms_ptirc;
902 short divisor = mcs->pxms_ptper * 6;
903 unsigned char hal_pos;
905 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
907 if (hal_pos == 0xff) {
909 pxmc_rocon_process_hal_error(mcs);
911 if (mcs->pxms_halerc)
914 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
916 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m)) {
917 int set_ptofs_fl = 0;
918 int ptofs_enable_update = 0;
920 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1) {
921 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
923 if ((ptindx > ptindx_prev + ptirc / 2) ||
924 (ptindx_prev > ptindx + ptirc / 2)) {
925 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
930 ptindx = (ptindx_prev + ptindx) / 2;
934 ptofs_enable_update = 1;
936 pxmc_set_flag(mcs, PXMS_PTI_b);
937 pxmc_clear_flag(mcs, PXMS_PRA_b);
939 if (!(mcs->pxms_flg & PXMS_PTI_m))
943 mcs->pxms_ptindx = ptindx;
944 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
946 pxmcc_pxmc_ptofs2mcc(mcs, ptofs_enable_update);
949 /* if phase table position to mask is know do fine phase table alignment */
950 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
953 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
955 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
957 pxmcc_pxmc_ptofs2mcc(mcs, 1);
958 pxmc_set_flag(mcs, PXMS_PTI_b);
959 pxmc_set_flag(mcs, PXMS_PHA_b);
963 mcs->pxms_hal = hal_pos;
967 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
970 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
971 /* FIXME - check winding current against limit */
972 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
976 int ene, pwm_d, pwm_q;
980 pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
982 if (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m)) {
984 int cur_d_req, cur_d_err;
985 int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
989 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
991 cur_d_err = cur_d_req - cur_d;
993 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
994 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
997 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
999 if (mcs->pxms_flg & PXMS_ERR_m)
1000 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1007 pxmc_pxmcc_pwm2ph_out(pxmc_state_t *mcs)
1009 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1013 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
1015 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
1016 (mcs->pxms_flg&PXMS_PRA_m)) {
1019 /* Wait for index mark to align phases */
1021 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
1023 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1025 pxmcc_pxmc_ptofs2mcc(mcs, 1);
1026 pxmc_set_flag(mcs, PXMS_PTI_b);
1027 pxmc_set_flag(mcs, PXMS_PHA_b);
1029 pxmcc_pxmc_ptofs2mcc(mcs, 0);
1035 int ene, pwm_d, pwm_q;
1037 ene = mcs->pxms_ene;
1040 if (mcs->pxms_flg & PXMS_PHA_m &&
1041 (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m))) {
1043 int cur_d_req, cur_d_err;
1044 int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
1048 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
1050 cur_d_err = cur_d_req - cur_d;
1052 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
1053 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
1056 pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
1058 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
1060 if (mcs->pxms_flg & PXMS_ERR_m)
1061 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
1068 * pxmc_pxmcc_nofb2ph_inp - Dummy input for direct stepper motor control
1069 * @mcs: Motion controller state information
1072 pxmc_pxmcc_nofb2ph_inp(pxmc_state_t *mcs)
1074 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1075 uint32_t steps_pos_act = mcc_axis->steps_pos;
1076 mcs->pxms_as = (int32_t)(steps_pos_act - mcs->pxms_ap);
1077 mcs->pxms_ap += mcs->pxms_as;
1082 * pxmc_pxmcc_nofb_con - Empty controller for direct stepper motor control
1083 * @mcs: Motion controller state information
1086 pxmc_pxmcc_nofb_con(pxmc_state_t *mcs)
1088 mcs->pxms_ene=mcs->pxms_me;
1093 pxmc_pxmcc_nofb2ph_out(pxmc_state_t *mcs)
1095 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1096 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1100 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
1102 if ((mcs->pxms_flg & PXMS_ERR_m) ||
1103 !(mcs->pxms_flg & (PXMS_ENO_m | PXMS_ENR_m))) {
1104 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
1105 pxmcc_axis_pwm_dq_out(mcs, 0, 0);
1106 mcc_axis->steps_inc = 0;
1107 mcc_axis->steps_inc_next = 0;
1108 mcsrc->cur_d_err_sum = 0;
1109 mcsrc->cur_q_err_sum = 0;
1113 int cur_d_req, cur_d_err;
1114 int cur_q_req, cur_q_err;
1115 int max_pwm = mcs->pxms_me;
1119 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
1120 pxmcc_axis_cur_dq_raw2filt(&cur_q, cur_q_raw);
1125 cur_d_req = mcsrc->cur_hold;
1127 cur_d_err = cur_d_req - cur_d;
1129 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
1130 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
1132 /* pwm_d = (pxmc_rocon_pwm_magnitude * ene) >> 15; */
1136 cur_q_err = cur_q_req - cur_q;
1138 pxmcc_cur_ctrl_pi(&pwm_q, &mcsrc->cur_q_err_sum, cur_q_err,
1139 mcsrc->cur_q_p, mcsrc->cur_q_i, max_pwm);
1141 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
1143 stpinc = mcs->pxms_rp - mcsrc->steps_pos_prev;
1145 stpdiv = pxmc_rocon_rx_done_sqn_inc;
1146 mcc_axis->steps_inc_next = (stpinc + stpdiv / 2) / stpdiv;
1147 mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
1149 mcsrc->steps_pos_prev = mcs->pxms_rp;
1151 mcc_axis->steps_sqn_next = pxmc_rocon_rx_done_sqn +
1152 pxmc_rocon_rx_done_sqn_inc - 1;
1158 int pxmcc_axis_setup(pxmc_state_t *mcs, int mode)
1160 volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
1161 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1162 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1166 uint32_t pwmtx_info;
1167 uint32_t pwmtx_info_dummy = 27;
1173 if (mcc_axis == NULL)
1176 if (mcc_data->common.fwversion != PXMCC_FWVERSION)
1179 mcc_axis->ccflg = 0;
1180 mcc_axis->mode = PXMCC_MODE_IDLE;
1182 mcc_data->common.pwm_cycle = PXMC_LXPWR_PWM_CYCLE;
1184 ptirc = mcs->pxms_ptirc;
1185 if (mode == PXMCC_MODE_STEPPER)
1186 ptirc <<= PXMC_SUBDIV(mcs);
1188 ull = (1ULL << 32) * mcs->pxms_ptper;
1189 ptreci = (ull + ptirc / 2) / ptirc;
1191 mcc_axis->ptreci = ptreci;
1193 pxmcc_pxmc_ptofs2mcc(mcs, 0);
1195 inp_info = (char*)&fpga_irc[mcs->pxms_inp_info]->count - (char*)fpga_irc[0];
1196 inp_info += mcc_data->common.irc_base;
1199 case PXMCC_MODE_IDLE:
1202 case PXMCC_MODE_BLDC:
1205 case PXMCC_MODE_STEPPER_WITH_IRC:
1208 case PXMCC_MODE_STEPPER:
1210 inp_info = (char*)&mcc_axis->steps_pos - (char*)mcc_data;
1214 mcc_axis->inp_info = inp_info;
1215 mcc_axis->out_info = mcs->pxms_out_info;
1217 pwm_chan = mcs->pxms_out_info;
1219 pwmtx_info = (pwmtx_info_dummy << 0) | (pwmtx_info_dummy << 8) |
1220 (pwmtx_info_dummy << 16) | (pwmtx_info_dummy << 24);
1222 for (i = phcnt; --i >= 0; ) {
1223 volatile uint32_t *pwm_reg;
1224 volatile uint32_t *pwm_reg_base = fpga_lx_master_transmitter_base;
1228 pwm_reg = pxmc_rocon_pwm_chan2reg(pwm_chan + i);
1229 if (pwm_reg == &pxmc_rocon_pwm_dummy_reg) {
1230 pwmtx_info |= pwmtx_info_dummy;
1232 pwmtx_info |= pwm_reg - pwm_reg_base;
1236 mcc_axis->pwmtx_info = pwmtx_info;
1238 mcc_axis->mode = mode;
1240 mcc_axis->ccflg = 0;
1241 mcc_axis->pwm_dq = 0;
1243 if (mode == PXMCC_MODE_STEPPER) {
1244 mcsrc->steps_pos_prev = mcs->pxms_rp = mcs->pxms_ap;
1245 mcs->pxms_rs = mcs->pxms_as = 0;
1246 mcc_axis->steps_inc_next = 0;
1247 mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
1248 mcc_axis->steps_inc = 0;
1249 mcc_axis->steps_pos = mcsrc->steps_pos_prev;
1250 mcc_axis->ptirc = mcs->pxms_ptirc << PXMC_SUBDIV(mcs);
1252 pxmcc_pxmc_ptofs2mcc(mcs, 1);
1257 /*******************************************************************/
1259 volatile void *pxmc_rocon_rx_data_hist_buff;
1260 volatile void *pxmc_rocon_rx_data_hist_buff_end;
1261 int pxmc_rocon_rx_data_hist_mode;
1263 uint32_t pxmc_rocon_rx_last_irq;
1264 uint32_t pxmc_rocon_rx_cycle_time;
1265 uint32_t pxmc_rocon_rx_irq_latency;
1266 uint32_t pxmc_rocon_rx_irq_latency_max;
1268 IRQ_HANDLER_FNC(pxmc_rocon_rx_done_isr)
1272 ir = ROCON_RX_TIM->IR & LPC_TIM_IR_ALL_m;
1273 ROCON_RX_TIM->IR = ir;
1274 if (ir & LPC_TIM_IR_CR1INT_m) {
1276 cr0 = ROCON_RX_TIM->CR0;
1277 cr1 = ROCON_RX_TIM->CR1;
1279 pxmc_rocon_rx_cycle_time = cr1 - pxmc_rocon_rx_last_irq;
1280 pxmc_rocon_rx_last_irq = cr1;
1282 hal_gpio_set_value(T2MAT0_PIN, 1);
1283 hal_gpio_set_value(T2MAT1_PIN, 0);
1284 hal_gpio_set_value(T2MAT0_PIN, 0);
1286 pxmc_rocon_rx_done_sqn_compute();
1287 pxmc_rocon_vin_compute();
1289 if (pxmc_rocon_rx_data_hist_buff >= pxmc_rocon_rx_data_hist_buff_end)
1290 pxmc_rocon_rx_data_hist_buff = NULL;
1292 if (pxmc_rocon_rx_data_hist_buff != NULL) {
1293 if (pxmc_rocon_rx_data_hist_mode == 0) {
1295 volatile uint32_t *pwm_reg = fpga_lx_master_transmitter_base + 8;
1296 volatile uint32_t *rec_reg = fpga_lx_master_receiver_base + 8;
1297 uint16_t *pbuf = (uint16_t *)pxmc_rocon_rx_data_hist_buff;
1298 for (i = 0; i < 8; i++) {
1299 *(pbuf++) = *(rec_reg++);
1301 for (i = 0; i < 8; i++) {
1302 *(pbuf++) = *(pwm_reg++);
1304 pxmc_rocon_rx_data_hist_buff = pbuf;
1305 } else if (pxmc_rocon_rx_data_hist_mode == 1) {
1307 uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
1308 pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
1309 pxmcc_axis_data_t *mcc_axis = mcc_data->axis + 0;
1310 uint32_t *ptumbl = (uint32_t *)mcc_axis;
1312 for (i = 0; i < 16; i++)
1313 *(pbuf++) = *(ptumbl++);
1315 pxmc_rocon_rx_data_hist_buff = pbuf;
1319 pxmc_rocon_rx_irq_latency = ROCON_RX_TIM->TC - cr1;
1320 if (pxmc_rocon_rx_irq_latency > pxmc_rocon_rx_irq_latency_max)
1321 pxmc_rocon_rx_irq_latency_max = pxmc_rocon_rx_irq_latency;
1323 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1326 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1333 pxmc_rocon_rx_done_isr_setup(irq_handler_t rx_done_isr_handler)
1336 disable_irq(ROCON_RX_IRQn);
1338 hal_pin_conf_set(T2MAT0_PIN, PORT_CONF_GPIO_OUT_LO);
1339 hal_pin_conf_set(T2MAT1_PIN, PORT_CONF_GPIO_OUT_LO);
1340 hal_pin_conf(T2CAP0_PIN);
1341 hal_pin_conf(T2CAP1_PIN);
1343 hal_gpio_direction_output(T2MAT0_PIN, 1);
1344 hal_gpio_direction_output(T2MAT1_PIN, 0);
1345 hal_gpio_set_value(T2MAT0_PIN, 0);
1347 /* Enable CLKOUT pin function, source CCLK, divide by 1 */
1348 LPC_SC->CLKOUTCFG = 0x0100;
1350 request_irq(ROCON_RX_IRQn, rx_done_isr_handler, 0, NULL,NULL);
1352 ROCON_RX_TIM->TCR = 0;
1353 ROCON_RX_TIM->CTCR = 0;
1354 ROCON_RX_TIM->PR = 0; /* Divide by 1 */
1356 ROCON_RX_TIM->CCR = LPC_TIM_CCR_CAP0RE_m | LPC_TIM_CCR_CAP1FE_m |
1357 LPC_TIM_CCR_CAP1I_m;
1359 ROCON_RX_TIM->EMR = __val2mfld(LPC_TIM_EMR_EMC0_m, LPC_TIM_EMR_NOP) |
1360 __val2mfld(LPC_TIM_EMR_EMC1_m, LPC_TIM_EMR_NOP);
1362 ROCON_RX_TIM->MCR = 0; /* No IRQ on MRx */
1363 ROCON_RX_TIM->TCR = LPC_TIM_TCR_CEN_m; /* Enable timer counting */
1364 enable_irq(ROCON_RX_IRQn); /* Enable interrupt */
1371 pxmc_rocon_pwm_master_init(void)
1377 unsigned receiver_done_div = 1;
1378 #ifdef LXPWR_WITH_SIROLADC
1379 unsigned lxpwr_header = 1;
1380 unsigned lxpwr_words = 1 + 8 * 2 + 2;
1381 unsigned lxpwr_chips = 2;
1382 unsigned lxpwr_chip_pwm_cnt = 8;
1383 #else /*LXPWR_WITH_SIROLADC*/
1384 unsigned lxpwr_header = 0;
1385 unsigned lxpwr_words = 8;
1386 unsigned lxpwr_chips = 2;
1387 unsigned lxpwr_chip_pwm_cnt = 8;
1388 #endif /*LXPWR_WITH_SIROLADC*/
1390 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1391 receiver_done_div = 5;
1392 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1394 *fpga_lx_master_reset = 1;
1395 *fpga_lx_master_transmitter_reg = 0;
1396 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1397 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1398 pxmc_rocon_rx_done_sqn_inc = receiver_done_div;
1400 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1401 fpga_lx_master_receiver_base[i] = 0;
1403 word_slot = LX_MASTER_DATA_OFFS;
1404 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
1405 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
1407 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1408 fpga_lx_master_transmitter_base[i] = 0;
1410 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
1411 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1412 #ifdef LXPWR_WITH_SIROLADC
1413 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1414 #endif /*LXPWR_WITH_SIROLADC*/
1416 word_slot = LX_MASTER_DATA_OFFS + 0;
1417 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1418 #ifdef LXPWR_WITH_SIROLADC
1419 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1420 #endif /*LXPWR_WITH_SIROLADC*/
1422 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
1424 *fpga_lx_master_reset = 0;
1425 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1426 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1431 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
1432 unsigned long index_irc, int diff2err)
1437 ofs = ofsl = index_irc - mcs->pxms_ptmark;
1441 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
1442 if (diff >= mcs->pxms_ptirc / 2)
1443 diff -= mcs->pxms_ptirc;
1444 if (diff <= -mcs->pxms_ptirc / 2)
1445 diff += mcs->pxms_ptirc;
1448 if(diff >= mcs->pxms_ptirc / 6) {
1453 diff = (unsigned long)ofsl - irc;
1454 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
1457 mcs->pxms_ptofs = ofs;
1463 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
1464 * @mcs: Motion controller state information
1467 pxmc_dummy_con(pxmc_state_t *mcs)
1472 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
1473 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
1474 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
1475 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
1476 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
1477 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
1479 /* initialize for hard home */
1481 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
1483 pxmc_set_flag(mcs,PXMS_BSY_b);
1484 #if 0 /* config and speed already set in pxmc_hh */
1486 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
1488 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
1490 mcs->pxms_gen_hsp = spd;
1493 mcs->pxms_gen_htim = 16;
1494 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
1495 return pxmc_rocon_hh_gd10(mcs);
1498 /* fill initial mark filter and then decide */
1500 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
1504 if(mcs->pxms_flg & PXMS_ERR_m)
1505 return pxmc_spdnext_gend(mcs);
1507 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
1508 mcs->pxms_rp += mcs->pxms_rs;
1510 mark = pxmc_inp_rocon_is_mark(mcs);
1512 if (mcs->pxms_gen_htim) {
1513 mcs->pxms_gen_htim--;
1517 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
1518 /* limit switch is not used */
1519 pxmc_inp_rocon_is_index_edge(mcs);
1520 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1525 /* go out from switch */
1526 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
1528 /* switch is off -> look for it */
1529 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1534 /* go out from switch */
1536 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
1540 if(mcs->pxms_flg & PXMS_ERR_m)
1541 return pxmc_spdnext_gend(mcs);
1543 mark = pxmc_inp_rocon_is_mark(mcs);
1546 /* switch is off -> look for it again */
1547 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1550 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1551 mcs->pxms_rp += mcs->pxms_rs;
1556 /* switch is off -> look for it */
1558 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
1563 if (mcs->pxms_flg & PXMS_ERR_m)
1564 return pxmc_spdnext_gend(mcs);
1566 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1567 mcs->pxms_rp += mcs->pxms_rs;
1569 mark = pxmc_inp_rocon_is_mark(mcs);
1572 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
1575 mcs->pxms_gen_hsp = spd;
1576 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
1582 /* switch is on -> find edge */
1584 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
1588 if (mcs->pxms_flg & PXMS_ERR_m)
1589 return pxmc_spdnext_gend(mcs);
1591 mark = pxmc_inp_rocon_is_mark(mcs);
1594 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
1595 pxmc_inp_rocon_is_index_edge(mcs);
1596 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1598 pxmc_inp_rocon_ap_zero(mcs);
1599 mcs->pxms_do_gen = pxmc_stop_gi;
1603 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1604 mcs->pxms_rp += mcs->pxms_rs;
1609 /* calibrate on revolution index */
1611 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
1613 if (mcs->pxms_flg & PXMS_ERR_m)
1614 return pxmc_spdnext_gend(mcs);
1616 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1617 mcs->pxms_rp += mcs->pxms_rs;
1619 if (pxmc_inp_rocon_is_index_edge(mcs)){
1620 pxmc_inp_rocon_irc_offset_from_index(mcs);
1621 mcs->pxms_do_gen = pxmc_stop_gi;
1627 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
1629 return pxmc_rocon_hh_gi;
1632 pxmc_rocon_state_t mcs0 =
1640 pxmc_pid_con /*pxmc_dummy_con*/,
1642 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
1646 pxmc_inp_rocon_ap2hw,
1647 pxms_ap: 0, pxms_as: 0,
1648 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1649 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1652 pxms_ene: 0, pxms_erc: 0,
1653 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1654 pxms_me: 0x7e00/*0x7fff*/,
1656 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1657 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1658 PXMS_CFG_I2PT_m * 0 | 0x2,
1663 /*pxms_ptamp: 0x7fff,*/
1674 pxmc_rocon_state_t mcs1 =
1684 pxmc_rocon_pwm_dc_out,
1688 pxmc_inp_rocon_ap2hw,
1689 pxms_ap: 0, pxms_as: 0,
1690 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1691 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1694 pxms_ene: 0, pxms_erc: 0,
1695 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1696 pxms_me: 0x7e00/*0x7fff*/,
1698 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1699 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1700 PXMS_CFG_I2PT_m * 0 | 0x2,
1704 /*pxms_ptamp: 0x7fff,*/
1709 pxmc_rocon_state_t mcs2 =
1719 pxmc_rocon_pwm_dc_out,
1723 pxmc_inp_rocon_ap2hw,
1724 pxms_ap: 0, pxms_as: 0,
1725 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1726 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1729 pxms_ene: 0, pxms_erc: 0,
1730 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1731 pxms_me: 0x7e00/*0x7fff*/,
1733 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1734 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1735 PXMS_CFG_HDIR_m | 0x2,
1739 /*pxms_ptamp: 0x7fff,*/
1744 pxmc_rocon_state_t mcs3 =
1754 pxmc_rocon_pwm_dc_out,
1758 pxmc_inp_rocon_ap2hw,
1759 pxms_ap: 0, pxms_as: 0,
1760 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1761 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1764 pxms_ene: 0, pxms_erc: 0,
1765 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1766 pxms_me: 0x7e00/*0x7fff*/,
1768 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1769 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1770 PXMS_CFG_HDIR_m * 0 | 0x2,
1774 /*pxms_ptamp: 0x7fff,*/
1779 pxmc_rocon_state_t mcs4 =
1789 pxmc_rocon_pwm_dc_out,
1793 pxmc_inp_rocon_ap2hw,
1794 pxms_ap: 0, pxms_as: 0,
1795 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1796 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1799 pxms_ene: 0, pxms_erc: 0,
1800 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1801 pxms_me: 0x7e00/*0x7fff*/,
1803 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1804 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1805 PXMS_CFG_HDIR_m | 0x2,
1809 /*pxms_ptamp: 0x7fff,*/
1814 pxmc_rocon_state_t mcs5 =
1824 pxmc_rocon_pwm_dc_out,
1828 pxmc_inp_rocon_ap2hw,
1829 pxms_ap: 0, pxms_as: 0,
1830 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1831 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1834 pxms_ene: 0, pxms_erc: 0,
1835 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1836 pxms_me: 0x7e00/*0x7fff*/,
1838 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1839 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1840 PXMS_CFG_HDIR_m | 0x2,
1844 /*pxms_ptamp: 0x7fff,*/
1849 pxmc_rocon_state_t mcs6 =
1859 pxmc_rocon_pwm_dc_out,
1863 pxmc_inp_rocon_ap2hw,
1864 pxms_ap: 0, pxms_as: 0,
1865 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1866 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1869 pxms_ene: 0, pxms_erc: 0,
1870 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1871 pxms_me: 0x7e00/*0x7fff*/,
1873 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1878 /*pxms_ptamp: 0x7fff,*/
1883 pxmc_rocon_state_t mcs7 =
1893 pxmc_rocon_pwm_dc_out,
1897 pxmc_inp_rocon_ap2hw,
1898 pxms_ap: 0, pxms_as: 0,
1899 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1900 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1903 pxms_ene: 0, pxms_erc: 0,
1904 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1905 pxms_me: 0x7e00/*0x7fff*/,
1907 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1912 /*pxms_ptamp: 0x7fff,*/
1917 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1918 {&mcs0.base, &mcs1.base, &mcs2.base, &mcs3.base,
1919 &mcs4.base, &mcs5.base, &mcs6.base, &mcs7.base};
1922 pxmc_state_list_t pxmc_main_list =
1929 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1931 pxmc_state_t *mcs = (pxmc_state_t *)context;
1934 irc = qst->index_pos;
1936 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1939 ofs = irc - mcs->pxms_ptmark;
1940 diff = ofs - mcs->pxms_ptofs;
1942 if (diff >= mcs->pxms_ptirc / 2)
1943 diff -= mcs->pxms_ptirc;
1945 if (diff <= -mcs->pxms_ptirc / 2)
1946 diff += mcs->pxms_ptirc;
1951 if (diff >= mcs->pxms_ptirc / 6)
1953 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1957 mcs->pxms_ptofs = ofs;
1958 pxmc_set_flag(mcs, PXMS_PHA_b);
1962 ofs=irc-mcs->pxms_ptofs;
1963 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
1965 ofs-=mcs->pxms_ptirc;
1967 ofs+=mcs->pxms_ptirc;
1970 mcs->pxms_ptmark=ofs;
1973 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
1976 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
1980 lpc_qei_state_t *qst = &lpc_qei_state;
1981 int irc = lpc_qei_get_pos(qst);
1984 if (!qst->index_occ)
1987 idx_rel = qst->index_pos - irc;
1988 idx_rel %= mcs->pxms_ptirc;
1991 idx_rel += mcs->pxms_ptirc;
1993 ptofs = irc - mcs->pxms_ptofs;
1994 ptmark = ptofs + idx_rel;
1996 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
1999 ptmark -= mcs->pxms_ptirc;
2001 ptmark += mcs->pxms_ptirc;
2004 if ((unsigned short)ptmark < mcs->pxms_ptirc)
2006 mcs->pxms_ptmark = ptmark;
2012 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
2017 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
2018 lpc_qei_state_t *qst = &lpc_qei_state;
2020 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
2021 lpc_qei_setup_index_catch(qst);
2023 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
2024 spd = 1 << PXMC_SUBDIV(mcs);
2026 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
2031 int pxmc_lpc_pthalalign_run(void)
2033 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
2036 static inline void pxmc_sfi_input(void)
2040 pxmc_for_each_mcs(var, mcs)
2042 /* PXMS_ENI_m - check if input (IRC) update is enabled */
2043 if (mcs->pxms_flg & PXMS_ENI_m)
2045 pxmc_call(mcs, mcs->pxms_do_inp);
2050 static inline void pxmc_sfi_controller_and_output(void)
2054 pxmc_for_each_mcs(var, mcs)
2056 /* PXMS_ENR_m - check if controller is enabled */
2057 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
2060 /* If output only is enabled, we skip the controller */
2061 if (mcs->pxms_flg & PXMS_ENR_m)
2064 pxmc_call(mcs, mcs->pxms_do_con);
2066 /* PXMS_ERR_m - if axis in error state */
2067 if (mcs->pxms_flg & PXMS_ERR_m)
2071 /* for bushless motors, it is necessary to call do_out
2072 even if the controller is not enabled and PWM should be provided. */
2073 pxmc_call(mcs, mcs->pxms_do_out);
2078 static inline void pxmc_sfi_generator(void)
2082 pxmc_for_each_mcs(var, mcs)
2084 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
2085 if (mcs->pxms_flg & PXMS_ENG_m)
2087 pxmc_call(mcs, mcs->pxms_do_gen);
2092 static inline void pxmc_sfi_dbg(void)
2096 pxmc_for_each_mcs(var, mcs)
2098 if (mcs->pxms_flg & PXMS_DBG_m)
2100 pxmc_call(mcs, mcs->pxms_do_deb);
2105 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
2109 int inp_chan = mcs->pxms_inp_info;
2111 long irc = fpga_irc[inp_chan]->count;
2113 if (!pxmc_inp_rocon_is_index_edge(mcs))
2116 idx_rel = fpga_irc[inp_chan]->count_index - irc;
2117 idx_rel %= mcs->pxms_ptirc;
2119 idx_rel += mcs->pxms_ptirc;
2121 ptofs = irc-mcs->pxms_ptofs;
2122 ptmark = ptofs+idx_rel;
2124 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
2126 ptmark -= mcs->pxms_ptirc;
2128 ptmark += mcs->pxms_ptirc;
2131 if((unsigned short)ptmark < mcs->pxms_ptirc) {
2132 mcs->pxms_ptmark = ptmark;
2137 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
2142 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
2144 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
2146 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
2147 spd=1<<PXMC_SUBDIV(mcs);
2149 /* clear bit indicating previous index */
2150 pxmc_inp_rocon_is_index_edge(mcs);
2152 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
2157 int pxmc_axis_rdmode(pxmc_state_t *mcs)
2159 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
2160 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
2161 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
2162 return PXMC_AXIS_MODE_DC;
2163 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
2164 return PXMC_AXIS_MODE_BLDC;
2165 if (mcs->pxms_do_out == pxmc_pxmcc_pwm3ph_out)
2166 return PXMC_AXIS_MODE_BLDC_PXMCC;
2167 if (mcs->pxms_do_out == pxmc_pxmcc_pwm2ph_out)
2168 return PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC;
2169 if (mcs->pxms_do_out == pxmc_pxmcc_nofb2ph_out)
2170 return PXMC_AXIS_MODE_STEPPER_PXMCC;
2176 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
2178 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
2181 if (mode == PXMC_AXIS_MODE_NOCHANGE)
2182 mode = pxmc_axis_rdmode(mcs);
2187 /* case PXMC_AXIS_MODE_STEPPER: */
2188 case PXMC_AXIS_MODE_STEPPER_PXMCC:
2189 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
2190 case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
2191 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
2193 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
2194 case PXMC_AXIS_MODE_DC:
2195 /*profive some sane dummy values*/
2196 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
2197 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
2198 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
2200 mcs->pxms_ptscale_mult=1;
2201 mcs->pxms_ptscale_shift=15;
2203 case PXMC_AXIS_MODE_BLDC:
2204 case PXMC_AXIS_MODE_BLDC_PXMCC:
2205 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
2206 #ifndef PXMC_WITH_PT_ZIC
2207 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
2208 #else /*PXMC_WITH_PT_ZIC*/
2209 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
2210 #endif /*PXMC_WITH_PT_ZIC*/
2216 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
2222 * pxmc_axis_mode - Sets axis mode.[extern API]
2223 * @mcs: Motion controller state information
2224 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
2225 * 2 .. stepper motor with IRC feedback and PWM ,
2226 * 3 .. stepper motor with PWM control
2227 * 4 .. DC motor with IRC feedback and PWM
2231 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
2236 pxmc_set_const_out(mcs, 0);
2237 pxmc_clear_flag(mcs, PXMS_ENI_b);
2238 pxmc_clear_flags(mcs,PXMS_ENO_m);
2239 /* Clear possible stall index flags from hardware */
2240 pxmc_inp_rocon_is_index_edge(mcs);
2241 pxmc_clear_flag(mcs, PXMS_PHA_b);
2242 pxmc_clear_flag(mcs, PXMS_PTI_b);
2245 prev_mode = pxmc_axis_rdmode(mcs);
2247 if (mode == PXMC_AXIS_MODE_NOCHANGE)
2252 mode = PXMC_AXIS_MODE_DC;
2254 if ((prev_mode == PXMC_AXIS_MODE_BLDC_PXMCC) ||
2255 (prev_mode == PXMCC_MODE_STEPPER_WITH_IRC))
2256 pxmcc_axis_setup(mcs, PXMCC_MODE_IDLE);
2258 res = pxmc_axis_pt4mode(mcs, mode);
2262 if (mcs->pxms_do_inp == pxmc_pxmcc_nofb2ph_inp)
2263 mcs->pxms_do_inp = pxmc_inp_rocon_inp;
2264 if (mcs->pxms_do_con == pxmc_pxmcc_nofb_con)
2265 mcs->pxms_do_con = pxmc_pid_con;
2268 /*case PXMC_AXIS_MODE_STEPPER:*/
2269 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
2270 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
2272 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
2273 case PXMC_AXIS_MODE_DC:
2274 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
2276 case PXMC_AXIS_MODE_BLDC:
2277 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
2279 case PXMC_AXIS_MODE_BLDC_PXMCC:
2280 if (pxmcc_axis_setup(mcs, PXMCC_MODE_BLDC) < 0)
2282 pxmcc_axis_enable(mcs, 1);
2283 mcs->pxms_do_out = pxmc_pxmcc_pwm3ph_out;
2285 case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
2286 if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER_WITH_IRC) < 0)
2288 pxmcc_axis_enable(mcs, 1);
2289 mcs->pxms_do_out = pxmc_pxmcc_pwm2ph_out;
2291 case PXMC_AXIS_MODE_STEPPER_PXMCC:
2292 if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER) < 0)
2294 pxmcc_axis_enable(mcs, 1);
2295 mcs->pxms_do_inp = pxmc_pxmcc_nofb2ph_inp;
2296 mcs->pxms_do_con = pxmc_pxmcc_nofb_con;
2297 mcs->pxms_do_out = pxmc_pxmcc_nofb2ph_out;
2303 /* Clear possible stall index flags from hardware */
2304 pxmc_inp_rocon_is_index_edge(mcs);
2305 /* Request new phases alignment for changed parameters */
2306 pxmc_clear_flag(mcs, PXMS_PHA_b);
2307 pxmc_clear_flag(mcs, PXMS_PTI_b);
2308 pxmc_set_flag(mcs, PXMS_ENI_b);
2312 void pxmc_sfi_isr(void)
2314 unsigned long spent = pxmc_fast_tick_time();
2317 pxmc_sfi_controller_and_output();
2318 pxmc_sfi_generator();
2320 /* Kick LX Master watchdog */
2321 if (pxmc_main_list.pxml_cnt != 0)
2322 *fpga_lx_master_transmitter_wdog = 1;
2324 spent = pxmc_fast_tick_time() - spent;
2326 if(spent > pxmc_sfi_spent_time_max)
2327 pxmc_sfi_spent_time_max = spent;
2331 int pxmc_clear_power_stop(void)
2336 int pxmc_process_state_check(unsigned long *pbusy_bits,
2337 unsigned long *perror_bits)
2340 unsigned short chan;
2341 unsigned long busy_bits = 0;
2342 unsigned long error_bits = 0;
2345 pxmc_for_each_mcs(chan, mcs) {
2347 flg |= mcs->pxms_flg;
2348 if (mcs->pxms_flg & PXMS_BSY_m)
2349 busy_bits |= 1 << chan;
2350 if (mcs->pxms_flg & PXMS_ERR_m)
2351 error_bits |= 1 << chan;
2354 if (appl_errstop_mode) {
2355 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
2356 pxmc_for_each_mcs(chan, mcs) {
2357 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
2364 if (pbusy_bits != NULL)
2365 *pbusy_bits = busy_bits;
2366 if (error_bits != NULL)
2367 *perror_bits = error_bits;
2377 if (!pxmc_main_list.pxml_cnt)
2380 pxmc_for_each_mcs(var, mcs)
2382 pxmc_set_const_out(mcs,0);
2385 pxmc_main_list.pxml_cnt = 0;
2391 int pxmc_initialize(void)
2396 pxmc_state_t *mcs = &mcs0.base;
2397 lpc_qei_state_t *qst = &lpc_qei_state;
2399 *fpga_irc_reset = 1;
2401 for (i = 0; i < 8; i++) {
2402 fpga_irc[i]->count = 0;
2403 fpga_irc[i]->count_index = 0;
2404 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
2407 /* Initialize QEI module for IRC counting */
2408 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
2410 /* Initialize QEI events processing */
2411 if (lpc_qei_setup_irq(qst) < 0)
2414 *fpga_irc_reset = 0;
2416 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
2418 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
2419 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
2421 pxmc_rocon_pwm_master_init();
2422 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
2423 pxmc_rocon_rx_done_isr_setup(pxmc_rocon_rx_done_isr);
2424 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
2426 pxmc_main_list.pxml_cnt = 0;
2427 pxmc_dbg_hist = NULL;
2429 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;