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 uint32_t pxmc_rocon_rx_err_cnt_last;
139 uint32_t pxmc_rocon_rx_err_level;
140 uint32_t pxmc_rocon_mcc_rx_done_sqn_last;
141 uint32_t pxmc_rocon_mcc_stuck;
144 void pxmc_rocon_rx_error_check(void)
148 pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
150 cnt = mcc_data->common.rx_err_cnt;
151 pxmc_rocon_rx_err_level = cnt - pxmc_rocon_rx_err_cnt_last;
152 pxmc_rocon_rx_err_cnt_last = cnt;
154 mcc_sqn = mcc_data->common.rx_done_sqn;
155 pxmc_rocon_mcc_stuck = mcc_sqn == pxmc_rocon_mcc_rx_done_sqn_last? 1: 0;
156 pxmc_rocon_mcc_rx_done_sqn_last = mcc_sqn;
159 const uint8_t onesin10bits[1024]={
160 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,
161 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,
162 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,
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 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,
165 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,
166 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,
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 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,
169 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,
170 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,
171 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,
172 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,
173 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,
174 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,
175 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,
176 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,
177 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,
178 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,
179 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,
180 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,
181 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,
182 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,
183 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,
184 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,
185 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,
186 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,
187 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,
188 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,
189 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,
190 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,
191 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
195 pxmc_inp_rocon_inp(struct pxmc_state *mcs)
197 int chan=mcs->pxms_inp_info;
201 /* read position from hardware */
202 irc = fpga_irc[chan]->count;
203 irc += pxmc_rocon_irc_offset[chan];
204 pos = irc << PXMC_SUBDIV(mcs);
205 mcs->pxms_as = pos - mcs->pxms_ap;
208 /* Running of the motor commutator */
209 if (mcs->pxms_flg & PXMS_PTI_m)
210 pxmc_irc_16bit_commindx(mcs, irc);
216 pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
221 int chan=mcs->pxms_inp_info;
223 irc_state = *fpga_irc_state[chan];
225 mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
226 (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
228 filt = pxmc_rocon_mark_filt[chan];
229 filt = (filt << 1) | mark;
230 pxmc_rocon_mark_filt[chan] = filt;
232 return onesin10bits[filt & 0x03ff];
236 pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
240 int chan=mcs->pxms_inp_info;
242 irc_state = *fpga_irc_state[chan];
243 *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
245 index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
251 pxmc_inp_rocon_adjust_to_irc_change(struct pxmc_state *mcs, long irc_diff)
253 long pos_diff = irc_diff << PXMC_SUBDIV(mcs);
255 mcs->pxms_ptofs += irc_diff;
257 mcs->pxms_ap += pos_diff;
258 mcs->pxms_rp += pos_diff;
263 pxmc_inp_rocon_irc_offset_from_index(struct pxmc_state *mcs)
265 int chan=mcs->pxms_inp_info;
269 irc_offset = -fpga_irc[chan]->count_index;
270 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
271 pxmc_rocon_irc_offset[chan] = irc_offset;
272 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
276 pxmc_inp_rocon_ap_zero(struct pxmc_state *mcs)
278 int chan=mcs->pxms_inp_info;
282 irc_offset = -fpga_irc[chan]->count;
283 irc_diff = irc_offset - pxmc_rocon_irc_offset[chan];
284 pxmc_rocon_irc_offset[chan] = irc_offset;
285 return pxmc_inp_rocon_adjust_to_irc_change(mcs, irc_diff);
289 pxmc_inp_rocon_ap2hw(struct pxmc_state *mcs)
291 int chan=mcs->pxms_inp_info;
295 irc = fpga_irc[chan]->count;
296 pos_diff = mcs->pxms_ap - (irc << PXMC_SUBDIV(mcs));
298 irc = pos_diff >> PXMC_SUBDIV(mcs);
300 /* Adjust phase table alignemt to modified IRC readout */
301 mcs->pxms_ptofs += irc - pxmc_rocon_irc_offset[chan];
303 pxmc_rocon_irc_offset[chan] = irc;
308 pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
310 int chan=mcs->pxms_inp_info;
314 if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
317 irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
318 index_irc = fpga_irc[chan]->count_index + pxmc_rocon_irc_offset[chan];
320 return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
323 uint32_t pxmc_rocon_receiver_dummy_reg;
325 static inline volatile uint32_t *
326 pxmc_rocon_receiver_chan2reg(unsigned chan)
328 volatile uint32_t *rec_reg;
331 return &pxmc_rocon_receiver_dummy_reg;
333 rec_reg = fpga_lx_master_receiver_base;
335 #ifdef LXPWR_WITH_SIROLADC
336 rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) * 3 + chan * 2;
337 #else /*LXPWR_WITH_SIROLADC*/
338 rec_reg += LX_MASTER_DATA_OFFS + chan;
339 #endif /*LXPWR_WITH_SIROLADC*/
345 pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
348 volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
349 int chan = mcs->pxms_out_info;
352 #ifdef LXPWR_WITH_SIROLADC
354 #else /*LXPWR_WITH_SIROLADC*/
356 #endif /*LXPWR_WITH_SIROLADC*/
358 rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
359 rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
360 rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
362 h = (rec_reg_a[hal_offs] >> 14) & 1;
363 h |= (rec_reg_b[hal_offs] >> 13) & 2;
364 h |= (rec_reg_c[hal_offs] >> 12) & 4;
366 /* return 3 bits corresponding to the HAL senzor input */
371 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
383 const unsigned char pxmc_lpc_bdc_hal_pos_table[8] =
396 uint32_t pxmc_rocon_pwm_dummy_reg;
398 static inline volatile uint32_t *
399 pxmc_rocon_pwm_chan2reg(unsigned chan)
401 volatile uint32_t *pwm_reg;
404 return &pxmc_rocon_pwm_dummy_reg;
406 pwm_reg = fpga_lx_master_transmitter_base;
408 #ifdef LXPWR_WITH_SIROLADC
409 pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) + chan;
410 #else /*LXPWR_WITH_SIROLADC*/
411 pwm_reg += LX_MASTER_DATA_OFFS + chan;
412 #endif /*LXPWR_WITH_SIROLADC*/
417 int pxmc_rocon_pwm_direct_wr(unsigned chan, unsigned pwm, int en)
419 volatile uint32_t *pwm_reg;
420 pwm_reg = pxmc_rocon_pwm_chan2reg(chan);
422 if (pwm_reg == &pxmc_rocon_pwm_dummy_reg)
425 *pwm_reg = pwm | (en? 0x4000: 0x8000);
431 * pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
432 * @mcs: Motion controller state information
434 /*static*/ inline void
435 pxmc_rocon_pwm3ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2, short pwm3)
437 volatile uint32_t *pwm_reg_a, *pwm_reg_b, *pwm_reg_c;
438 int chan = mcs->pxms_out_info;
440 pwm_reg_c = pxmc_rocon_pwm_chan2reg(chan + 0);
441 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
442 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 2);
450 pxmc_rocon_process_hal_error(struct pxmc_state *mcs)
452 if (mcs->pxms_halerc >= HAL_ERR_SENSITIVITY * HAL_ERR_MAX_COUNT)
454 pxmc_set_errno(mcs, PXMS_E_HAL);
459 mcs->pxms_halerc += HAL_ERR_SENSITIVITY;
463 * pxmc_rocon_pwm3ph_out - Phase output for brush-less 3-phase motor
464 * @mcs: Motion controller state information
467 pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
469 typeof(mcs->pxms_ptvang) ptvang;
471 unsigned char hal_pos;
479 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
480 (mcs->pxms_flg & PXMS_PRA_m))
483 short ptirc = mcs->pxms_ptirc;
484 short divisor = mcs->pxms_ptper * 6;
487 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
492 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
494 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
496 pxmc_set_flag(mcs, PXMS_PTI_b);
497 pxmc_set_flag(mcs, PXMS_PHA_b);
502 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
507 pxmc_rocon_process_hal_error(mcs);
511 if (mcs->pxms_halerc)
514 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
516 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m))
518 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1)
520 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
522 if ((ptindx > ptindx_prev + ptirc / 2) ||
523 (ptindx_prev > ptindx + ptirc / 2))
525 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
532 ptindx = (ptindx_prev + ptindx) / 2;
535 mcs->pxms_ptindx = ptindx;
537 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
539 pxmc_set_flag(mcs, PXMS_PTI_b);
540 pxmc_clear_flag(mcs, PXMS_PRA_b);
544 if (!(mcs->pxms_flg & PXMS_PTI_m))
545 mcs->pxms_ptindx = ptindx;
548 /* if phase table position to mask is know do fine phase table alignment */
549 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
551 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
553 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
555 pxmc_set_flag(mcs, PXMS_PTI_b);
556 pxmc_set_flag(mcs, PXMS_PHA_b);
560 mcs->pxms_hal = hal_pos;
566 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
567 /* FIXME - check winding current against limit */
568 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
572 ptvang = mcs->pxms_ptvang;
576 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
580 indx = mcs->pxms_ptindx;
582 /* tuning of magnetic field/voltage advance angle */
583 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
588 /* Generating direction of stator mag. field for backward torque */
591 if ((indx -= ptvang) < 0)
592 indx += mcs->pxms_ptirc;
596 /* Generating direction of stator mag. field for forward torque */
597 if ((indx += ptvang) >= mcs->pxms_ptirc)
598 indx -= mcs->pxms_ptirc;
601 if (mcs->pxms_ptscale_mult)
602 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
604 pwm1 = mcs->pxms_ptptr1[indx];
605 pwm2 = mcs->pxms_ptptr2[indx];
606 pwm3 = mcs->pxms_ptptr3[indx];
608 #ifdef PXMC_WITH_PT_ZIC
609 if (labs(mcs->pxms_as) < (10 << PXMC_SUBDIV(mcs)))
611 pwm1 &= ~PXMC_PT_ZIC_MASK;
612 pwm2 &= ~PXMC_PT_ZIC_MASK;
613 pwm3 &= ~PXMC_PT_ZIC_MASK;
615 #endif /*PXMC_WITH_PT_ZIC*/
617 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
618 /* Initialized CTM4 PWM period is 0x200 => divide by value about 2097024 */
620 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
621 if (pwm1 & PXMC_PT_ZIC_MASK)
624 pwm1 = (((unsigned long long)pwm1 * pwm_dc) >> (15 + 15)) | 0x4000;
625 if (pwm2 & PXMC_PT_ZIC_MASK)
628 pwm2 = (((unsigned long long)pwm2 * pwm_dc) >> (15 + 15)) | 0x4000;
629 if (pwm3 & PXMC_PT_ZIC_MASK)
632 pwm3 = (((unsigned long long)pwm3 * pwm_dc) >> (15 + 15)) | 0x4000;
634 pxmc_rocon_pwm3ph_wr(mcs, pwm1, pwm2, pwm3);
638 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
645 * pxmc_rocon_pwm2ph_wr - Output of the 2-phase stepper motor PWM to the hardware
646 * @mcs: Motion controller state information
648 /*static*/ inline void
649 pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
651 volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
652 int chan = mcs->pxms_out_info;
654 pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
655 pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
656 pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
657 pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
660 *pwm_reg_bp = pwm2 | 0x4000;
664 *pwm_reg_bn = -pwm2 | 0x4000;
668 *pwm_reg_ap = pwm1 | 0x4000;
672 *pwm_reg_an = -pwm1 | 0x4000;
677 * pxmc_rocon_pwm2ph_out - Phase output of the 2-phase stepper motor PWM
678 * @mcs: Motion controller state information
681 pxmc_rocon_pwm2ph_out(pxmc_state_t *mcs)
683 typeof(mcs->pxms_ptvang) ptvang;
691 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
692 (mcs->pxms_flg&PXMS_PRA_m)){
694 short ptirc=mcs->pxms_ptirc;
697 pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
702 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
704 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
706 pxmc_set_flag(mcs, PXMS_PTI_b);
707 pxmc_set_flag(mcs, PXMS_PHA_b);
712 ptindx = mcs->pxms_ptindx;
714 if(0 && (!(mcs->pxms_flg&PXMS_PTI_m) || (mcs->pxms_flg&PXMS_PRA_m))) {
716 mcs->pxms_ptindx = ptindx;
718 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
720 pxmc_set_flag(mcs, PXMS_PTI_b);
721 pxmc_clear_flag(mcs, PXMS_PRA_b);
723 /* if phase table position to mask is know do fine phase table alignment */
724 //if(mcs->pxms_cfg & PXMS_CFG_I2PT_m)
725 // lpc_qei_setup_index_catch(&lpc_qei_state);
728 if(!(mcs->pxms_flg&PXMS_PTI_m))
729 mcs->pxms_ptindx = ptindx;
735 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
736 /* FIXME - check winding current against limit */
737 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
741 ptvang = mcs->pxms_ptvang;
745 ene = mcs->pxms_flg & PXMS_BSY_m? mcs->pxms_me: 0;
749 indx = mcs->pxms_ptindx;
751 /* tuning of magnetic field/voltage advance angle */
752 indx += (mcs->pxms_s1 * mcs->pxms_as) >> (PXMC_SUBDIV(mcs) + 8);
755 /* Generating direction of stator mag. field for backward torque */
757 if ((indx -= ptvang)<0)
758 indx += mcs->pxms_ptirc;
760 /* Generating direction of stator mag. field for forward torque */
761 if ((indx += ptvang) >= mcs->pxms_ptirc)
762 indx -= mcs->pxms_ptirc;
765 if (mcs->pxms_ptscale_mult)
766 indx = ((unsigned long)indx * mcs->pxms_ptscale_mult) >> mcs->pxms_ptscale_shift;
768 pwm1 = mcs->pxms_ptptr1[indx];
769 pwm2 = mcs->pxms_ptptr2[indx];
771 /* Default phase-table amplitude is 0x7fff, ene max is 0x7fff */
772 /* Initialized PWM period is 0x200 => divide by value about 2097024 */
774 unsigned long pwm_dc = pxmc_rocon_pwm_magnitude * (unsigned long)ene;
775 pwm1 = ((unsigned long long)pwm1 * pwm_dc) >> (15+15);
776 pwm2 = ((unsigned long long)pwm2 * pwm_dc) >> (15+15);
778 pxmc_rocon_pwm2ph_wr(mcs, pwm1, pwm2);
780 /*pxmc_lpc_wind_current_over_cnt = 0;*/
781 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
788 * pxmc_rocon_pwm_dc_out - DC motor CW and CCW PWM output
789 * @mcs: Motion controller state information
792 pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
794 volatile uint32_t *pwm_reg_a, *pwm_reg_b;
795 int chan = mcs->pxms_out_info;
796 int ene = mcs->pxms_ene;
798 pwm_reg_a = pxmc_rocon_pwm_chan2reg(chan + 0);
799 pwm_reg_b = pxmc_rocon_pwm_chan2reg(chan + 1);
805 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
807 *pwm_reg_b = ene | 0x4000;
811 ene = (ene * (pxmc_rocon_pwm_magnitude + 5)) >> 15;
813 *pwm_reg_a = ene | 0x4000;
819 /*******************************************************************/
820 /* PXMCC - PXMC coprocessor support and communication */
822 void pxmcc_pxmc_ptofs2mcc(pxmc_state_t *mcs, int enable_update)
824 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
825 int inp_chan=mcs->pxms_inp_info;
829 if (mcc_axis != NULL) {
830 if (enable_update >= 0)
831 mcc_axis->ptirc = 0xffffffff;
832 ptofs = mcs->pxms_ptofs - pxmc_rocon_irc_offset[inp_chan];
833 irc = fpga_irc[inp_chan]->count;
834 ptofs = (int16_t)(ptofs - irc) + irc;
835 mcc_axis->ptofs = ptofs;
836 if (enable_update > 0) {
837 mcc_axis->ptirc = mcs->pxms_ptirc;
843 void pxmcc_axis_get_cur_dq_filt_raw(pxmc_state_t *mcs,
844 int32_t *p_cur_d_raw, int32_t *p_cur_q_raw)
846 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
847 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
848 uint32_t cur_d_cum = mcc_axis->cur_d_cum;
849 uint32_t cur_q_cum = mcc_axis->cur_q_cum;
853 cur_d = cur_d_cum - mcsrc->cur_d_cum_prev;
854 mcsrc->cur_d_cum_prev = cur_d_cum;
855 cur_q = cur_q_cum - mcsrc->cur_q_cum_prev;
856 mcsrc->cur_q_cum_prev = cur_q_cum;
858 *p_cur_d_raw = cur_d;
859 *p_cur_q_raw = cur_q;
863 void pxmcc_axis_cur_dq_raw2filt(int *p_cur, int32_t cur_raw)
867 cur_div = cur_raw & 0x1f;
868 cur = cur_raw / cur_div;
869 cur += (1 << 11) | 0x20;
874 void pxmcc_axis_get_cur_dq_filt(pxmc_state_t *mcs, int *p_cur_d, int *p_cur_q)
879 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
881 pxmcc_axis_cur_dq_raw2filt(p_cur_d, cur_d_raw);
882 pxmcc_axis_cur_dq_raw2filt(p_cur_q, cur_q_raw);
886 void pxmcc_cur_ctrl_pi(int *p_pwm, int32_t *p_cur_err_sum,
887 int cur_err, short cur_ctrl_p, short cur_ctrl_i, int max_pwm)
890 int32_t cur_err_sum = *p_cur_err_sum;
892 pwm = (cur_err * cur_ctrl_p) >> 8;
895 cur_err_sum += cur_err * cur_ctrl_i;
899 pwm += cur_err_sum >> 16;
902 cur_err_sum -= (pwm - max_pwm) << 16;
904 } else if (-pwm > max_pwm) {
905 cur_err_sum -= (pwm + max_pwm) << 16;
908 *p_cur_err_sum = cur_err_sum;
913 pxmc_pxmcc_pwm3ph_out(pxmc_state_t *mcs)
917 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
919 if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
920 (mcs->pxms_flg & PXMS_PRA_m)) {
922 short ptirc = mcs->pxms_ptirc;
923 short divisor = mcs->pxms_ptper * 6;
924 unsigned char hal_pos;
926 hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
928 if (hal_pos == 0xff) {
930 pxmc_rocon_process_hal_error(mcs);
932 if (mcs->pxms_halerc)
935 ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
937 if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m)) {
938 int set_ptofs_fl = 0;
939 int ptofs_enable_update = 0;
941 if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1) {
942 short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
944 if ((ptindx > ptindx_prev + ptirc / 2) ||
945 (ptindx_prev > ptindx + ptirc / 2)) {
946 ptindx = (ptindx_prev + ptindx - ptirc) / 2;
951 ptindx = (ptindx_prev + ptindx) / 2;
955 ptofs_enable_update = 1;
957 pxmc_set_flag(mcs, PXMS_PTI_b);
958 pxmc_clear_flag(mcs, PXMS_PRA_b);
960 if (!(mcs->pxms_flg & PXMS_PTI_m))
964 mcs->pxms_ptindx = ptindx;
965 mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
967 pxmcc_pxmc_ptofs2mcc(mcs, ptofs_enable_update);
970 /* if phase table position to mask is know do fine phase table alignment */
971 if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
974 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
976 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
978 pxmcc_pxmc_ptofs2mcc(mcs, 1);
979 pxmc_set_flag(mcs, PXMS_PTI_b);
980 pxmc_set_flag(mcs, PXMS_PHA_b);
984 mcs->pxms_hal = hal_pos;
988 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
991 /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
992 /* FIXME - check winding current against limit */
993 /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
997 int ene, pwm_d, pwm_q;
1001 pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
1003 if (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m)) {
1005 int cur_d_req, cur_d_err;
1006 int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
1010 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
1012 cur_d_err = cur_d_req - cur_d;
1014 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
1015 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
1017 if (pxmc_rocon_rx_err_level >= 2)
1018 pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
1019 else if (pxmc_rocon_mcc_stuck)
1020 pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
1023 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
1025 if (mcs->pxms_flg & PXMS_ERR_m)
1026 pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
1033 pxmc_pxmcc_pwm2ph_out(pxmc_state_t *mcs)
1035 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1039 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
1041 if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
1042 (mcs->pxms_flg&PXMS_PRA_m)) {
1045 /* Wait for index mark to align phases */
1047 res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
1049 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1051 pxmcc_pxmc_ptofs2mcc(mcs, 1);
1052 pxmc_set_flag(mcs, PXMS_PTI_b);
1053 pxmc_set_flag(mcs, PXMS_PHA_b);
1055 pxmcc_pxmc_ptofs2mcc(mcs, 0);
1061 int ene, pwm_d, pwm_q;
1063 ene = mcs->pxms_ene;
1066 if (mcs->pxms_flg & PXMS_PHA_m &&
1067 (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m))) {
1069 int cur_d_req, cur_d_err;
1070 int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
1074 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
1076 cur_d_err = cur_d_req - cur_d;
1078 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
1079 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
1081 if (pxmc_rocon_rx_err_level >= 2)
1082 pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
1083 else if (pxmc_rocon_mcc_stuck)
1084 pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
1087 pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
1089 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
1091 if (mcs->pxms_flg & PXMS_ERR_m)
1092 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
1099 * pxmc_pxmcc_nofb2ph_inp - Dummy input for direct stepper motor control
1100 * @mcs: Motion controller state information
1103 pxmc_pxmcc_nofb2ph_inp(pxmc_state_t *mcs)
1105 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1106 uint32_t steps_pos_act = mcc_axis->steps_pos;
1107 mcs->pxms_as = (int32_t)(steps_pos_act - mcs->pxms_ap);
1108 mcs->pxms_ap += mcs->pxms_as;
1113 * pxmc_pxmcc_nofb_con - Empty controller for direct stepper motor control
1114 * @mcs: Motion controller state information
1117 pxmc_pxmcc_nofb_con(pxmc_state_t *mcs)
1119 mcs->pxms_ene=mcs->pxms_me;
1124 pxmc_pxmcc_nofb2ph_out(pxmc_state_t *mcs)
1126 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1127 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1131 pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
1133 if ((mcs->pxms_flg & PXMS_ERR_m) ||
1134 !(mcs->pxms_flg & (PXMS_ENO_m | PXMS_ENR_m))) {
1135 pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
1136 pxmcc_axis_pwm_dq_out(mcs, 0, 0);
1137 mcc_axis->steps_inc = 0;
1138 mcc_axis->steps_inc_next = 0;
1139 mcsrc->cur_d_err_sum = 0;
1140 mcsrc->cur_q_err_sum = 0;
1144 int cur_d_req, cur_d_err;
1145 int cur_q_req, cur_q_err;
1146 int max_pwm = mcs->pxms_me;
1150 pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
1151 pxmcc_axis_cur_dq_raw2filt(&cur_q, cur_q_raw);
1156 cur_d_req = mcsrc->cur_hold;
1158 cur_d_err = cur_d_req - cur_d;
1160 pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
1161 mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
1163 /* pwm_d = (pxmc_rocon_pwm_magnitude * ene) >> 15; */
1167 cur_q_err = cur_q_req - cur_q;
1169 pxmcc_cur_ctrl_pi(&pwm_q, &mcsrc->cur_q_err_sum, cur_q_err,
1170 mcsrc->cur_q_p, mcsrc->cur_q_i, max_pwm);
1172 pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
1174 stpinc = mcs->pxms_rp - mcsrc->steps_pos_prev;
1176 stpdiv = pxmc_rocon_rx_done_sqn_inc;
1177 mcc_axis->steps_inc_next = (stpinc + stpdiv / 2) / stpdiv;
1178 mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
1180 mcsrc->steps_pos_prev = mcs->pxms_rp;
1182 mcc_axis->steps_sqn_next = pxmc_rocon_rx_done_sqn +
1183 pxmc_rocon_rx_done_sqn_inc - 1;
1185 if (pxmc_rocon_rx_err_level >= 2)
1186 pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
1187 else if (pxmc_rocon_mcc_stuck)
1188 pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
1194 int pxmcc_axis_setup(pxmc_state_t *mcs, int mode)
1196 volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
1197 volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
1198 pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
1202 uint32_t pwmtx_info;
1203 uint32_t pwmtx_info_dummy = 27;
1209 if (mcc_axis == NULL)
1212 if (mcc_data->common.fwversion != PXMCC_FWVERSION)
1215 mcc_axis->ccflg = 0;
1216 mcc_axis->mode = PXMCC_MODE_IDLE;
1218 mcc_data->common.pwm_cycle = PXMC_LXPWR_PWM_CYCLE;
1220 ptirc = mcs->pxms_ptirc;
1221 if (mode == PXMCC_MODE_STEPPER)
1222 ptirc <<= PXMC_SUBDIV(mcs);
1224 ull = (1ULL << 32) * mcs->pxms_ptper;
1225 ptreci = (ull + ptirc / 2) / ptirc;
1227 mcc_axis->ptreci = ptreci;
1229 pxmcc_pxmc_ptofs2mcc(mcs, 0);
1231 inp_info = (char*)&fpga_irc[mcs->pxms_inp_info]->count - (char*)fpga_irc[0];
1232 inp_info += mcc_data->common.irc_base;
1235 case PXMCC_MODE_IDLE:
1238 case PXMCC_MODE_BLDC:
1241 case PXMCC_MODE_STEPPER_WITH_IRC:
1244 case PXMCC_MODE_STEPPER:
1246 inp_info = (char*)&mcc_axis->steps_pos - (char*)mcc_data;
1250 mcc_axis->inp_info = inp_info;
1251 mcc_axis->out_info = mcs->pxms_out_info;
1253 pwm_chan = mcs->pxms_out_info;
1255 pwmtx_info = (pwmtx_info_dummy << 0) | (pwmtx_info_dummy << 8) |
1256 (pwmtx_info_dummy << 16) | (pwmtx_info_dummy << 24);
1258 for (i = phcnt; --i >= 0; ) {
1259 volatile uint32_t *pwm_reg;
1260 volatile uint32_t *pwm_reg_base = fpga_lx_master_transmitter_base;
1264 pwm_reg = pxmc_rocon_pwm_chan2reg(pwm_chan + i);
1265 if (pwm_reg == &pxmc_rocon_pwm_dummy_reg) {
1266 pwmtx_info |= pwmtx_info_dummy;
1268 pwmtx_info |= pwm_reg - pwm_reg_base;
1272 mcc_axis->pwmtx_info = pwmtx_info;
1274 mcc_axis->mode = mode;
1276 mcc_axis->ccflg = 0;
1277 mcc_axis->pwm_dq = 0;
1279 if (mode == PXMCC_MODE_STEPPER) {
1280 mcsrc->steps_pos_prev = mcs->pxms_rp = mcs->pxms_ap;
1281 mcs->pxms_rs = mcs->pxms_as = 0;
1282 mcc_axis->steps_inc_next = 0;
1283 mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
1284 mcc_axis->steps_inc = 0;
1285 mcc_axis->steps_pos = mcsrc->steps_pos_prev;
1286 mcc_axis->ptirc = mcs->pxms_ptirc << PXMC_SUBDIV(mcs);
1288 pxmcc_pxmc_ptofs2mcc(mcs, 1);
1293 /*******************************************************************/
1295 volatile void *pxmc_rocon_rx_data_hist_buff;
1296 volatile void *pxmc_rocon_rx_data_hist_buff_end;
1297 int pxmc_rocon_rx_data_hist_mode;
1299 uint32_t pxmc_rocon_rx_last_irq;
1300 uint32_t pxmc_rocon_rx_cycle_time;
1301 uint32_t pxmc_rocon_rx_irq_latency;
1302 uint32_t pxmc_rocon_rx_irq_latency_max;
1304 IRQ_HANDLER_FNC(pxmc_rocon_rx_done_isr)
1308 ir = ROCON_RX_TIM->IR & LPC_TIM_IR_ALL_m;
1309 ROCON_RX_TIM->IR = ir;
1310 if (ir & LPC_TIM_IR_CR1INT_m) {
1312 cr0 = ROCON_RX_TIM->CR0;
1313 cr1 = ROCON_RX_TIM->CR1;
1315 pxmc_rocon_rx_cycle_time = cr1 - pxmc_rocon_rx_last_irq;
1316 pxmc_rocon_rx_last_irq = cr1;
1318 hal_gpio_set_value(T2MAT0_PIN, 1);
1319 hal_gpio_set_value(T2MAT1_PIN, 0);
1320 hal_gpio_set_value(T2MAT0_PIN, 0);
1322 pxmc_rocon_rx_done_sqn_compute();
1323 pxmc_rocon_vin_compute();
1324 pxmc_rocon_rx_error_check();
1326 if (pxmc_rocon_rx_data_hist_buff >= pxmc_rocon_rx_data_hist_buff_end)
1327 pxmc_rocon_rx_data_hist_buff = NULL;
1329 if (pxmc_rocon_rx_data_hist_buff != NULL) {
1330 if (pxmc_rocon_rx_data_hist_mode == 0) {
1332 volatile uint32_t *pwm_reg = fpga_lx_master_transmitter_base + 8;
1333 volatile uint32_t *rec_reg = fpga_lx_master_receiver_base + 8;
1334 uint16_t *pbuf = (uint16_t *)pxmc_rocon_rx_data_hist_buff;
1335 for (i = 0; i < 8; i++) {
1336 *(pbuf++) = *(rec_reg++);
1338 for (i = 0; i < 8; i++) {
1339 *(pbuf++) = *(pwm_reg++);
1341 pxmc_rocon_rx_data_hist_buff = pbuf;
1342 } else if (pxmc_rocon_rx_data_hist_mode == 1) {
1344 uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
1345 pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
1346 pxmcc_axis_data_t *mcc_axis = mcc_data->axis + 0;
1347 uint32_t *ptumbl = (uint32_t *)mcc_axis;
1349 for (i = 0; i < 16; i++)
1350 *(pbuf++) = *(ptumbl++);
1352 pxmc_rocon_rx_data_hist_buff = pbuf;
1356 pxmc_rocon_rx_irq_latency = ROCON_RX_TIM->TC - cr1;
1357 if (pxmc_rocon_rx_irq_latency > pxmc_rocon_rx_irq_latency_max)
1358 pxmc_rocon_rx_irq_latency_max = pxmc_rocon_rx_irq_latency;
1360 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1363 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1370 pxmc_rocon_rx_done_isr_setup(irq_handler_t rx_done_isr_handler)
1373 disable_irq(ROCON_RX_IRQn);
1375 hal_pin_conf_set(T2MAT0_PIN, PORT_CONF_GPIO_OUT_LO);
1376 hal_pin_conf_set(T2MAT1_PIN, PORT_CONF_GPIO_OUT_LO);
1377 hal_pin_conf(T2CAP0_PIN);
1378 hal_pin_conf(T2CAP1_PIN);
1380 hal_gpio_direction_output(T2MAT0_PIN, 1);
1381 hal_gpio_direction_output(T2MAT1_PIN, 0);
1382 hal_gpio_set_value(T2MAT0_PIN, 0);
1384 /* Enable CLKOUT pin function, source CCLK, divide by 1 */
1385 LPC_SC->CLKOUTCFG = 0x0100;
1387 request_irq(ROCON_RX_IRQn, rx_done_isr_handler, 0, NULL,NULL);
1389 ROCON_RX_TIM->TCR = 0;
1390 ROCON_RX_TIM->CTCR = 0;
1391 ROCON_RX_TIM->PR = 0; /* Divide by 1 */
1393 ROCON_RX_TIM->CCR = LPC_TIM_CCR_CAP0RE_m | LPC_TIM_CCR_CAP1FE_m |
1394 LPC_TIM_CCR_CAP1I_m;
1396 ROCON_RX_TIM->EMR = __val2mfld(LPC_TIM_EMR_EMC0_m, LPC_TIM_EMR_NOP) |
1397 __val2mfld(LPC_TIM_EMR_EMC1_m, LPC_TIM_EMR_NOP);
1399 ROCON_RX_TIM->MCR = 0; /* No IRQ on MRx */
1400 ROCON_RX_TIM->TCR = LPC_TIM_TCR_CEN_m; /* Enable timer counting */
1401 enable_irq(ROCON_RX_IRQn); /* Enable interrupt */
1408 pxmc_rocon_pwm_master_init(void)
1414 unsigned receiver_done_div = 1;
1415 #ifdef LXPWR_WITH_SIROLADC
1416 unsigned lxpwr_header = 1;
1417 unsigned lxpwr_words = 1 + 8 * 2 + 2;
1418 unsigned lxpwr_chips = 2;
1419 unsigned lxpwr_chip_pwm_cnt = 8;
1420 #else /*LXPWR_WITH_SIROLADC*/
1421 unsigned lxpwr_header = 0;
1422 unsigned lxpwr_words = 8;
1423 unsigned lxpwr_chips = 2;
1424 unsigned lxpwr_chip_pwm_cnt = 8;
1425 #endif /*LXPWR_WITH_SIROLADC*/
1427 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
1428 receiver_done_div = 5;
1429 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
1431 *fpga_lx_master_reset = 1;
1432 *fpga_lx_master_transmitter_reg = 0;
1433 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1434 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1435 pxmc_rocon_rx_done_sqn_inc = receiver_done_div;
1437 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1438 fpga_lx_master_receiver_base[i] = 0;
1440 word_slot = LX_MASTER_DATA_OFFS;
1441 fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
1442 fpga_lx_master_receiver_base[grp_in++] = 0x0000;
1444 for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
1445 fpga_lx_master_transmitter_base[i] = 0;
1447 word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
1448 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1449 #ifdef LXPWR_WITH_SIROLADC
1450 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1451 #endif /*LXPWR_WITH_SIROLADC*/
1453 word_slot = LX_MASTER_DATA_OFFS + 0;
1454 fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
1455 #ifdef LXPWR_WITH_SIROLADC
1456 fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
1457 #endif /*LXPWR_WITH_SIROLADC*/
1459 fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
1461 *fpga_lx_master_reset = 0;
1462 *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
1463 *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
1468 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
1469 unsigned long index_irc, int diff2err)
1474 ofs = ofsl = index_irc - mcs->pxms_ptmark;
1478 diff = (unsigned short)ofs - (unsigned short)mcs->pxms_ptofs;
1479 if (diff >= mcs->pxms_ptirc / 2)
1480 diff -= mcs->pxms_ptirc;
1481 if (diff <= -mcs->pxms_ptirc / 2)
1482 diff += mcs->pxms_ptirc;
1485 if(diff >= mcs->pxms_ptirc / 6) {
1490 diff = (unsigned long)ofsl - irc;
1491 ofs = ofsl - (diff / mcs->pxms_ptirc) * mcs->pxms_ptirc;
1494 mcs->pxms_ptofs = ofs;
1500 * pxmc_dummy_con - Dummy controller for synchronous BLDC/PMSM/steper drive
1501 * @mcs: Motion controller state information
1504 pxmc_dummy_con(pxmc_state_t *mcs)
1509 int pxmc_rocon_hh_gd10(pxmc_state_t *mcs);
1510 int pxmc_rocon_hh_gd20(pxmc_state_t *mcs);
1511 int pxmc_rocon_hh_gd30(pxmc_state_t *mcs);
1512 int pxmc_rocon_hh_gd40(pxmc_state_t *mcs);
1513 int pxmc_rocon_hh_gd50(pxmc_state_t *mcs);
1514 int pxmc_rocon_hh_gd90(pxmc_state_t *mcs);
1516 /* initialize for hard home */
1518 pxmc_rocon_hh_gi(pxmc_state_t *mcs)
1520 pxmc_set_flag(mcs,PXMS_BSY_b);
1521 #if 0 /* config and speed already set in pxmc_hh */
1523 spd >>= mcs->pxms_cfg & PXMS_CFG_HSPD_m;
1525 if(mcs->pxms_cfg & PXMS_CFG_HDIR_m)
1527 mcs->pxms_gen_hsp = spd;
1530 mcs->pxms_gen_htim = 16;
1531 mcs->pxms_do_gen = pxmc_rocon_hh_gd10;
1532 return pxmc_rocon_hh_gd10(mcs);
1535 /* fill initial mark filter and then decide */
1537 pxmc_rocon_hh_gd10(pxmc_state_t *mcs)
1541 if(mcs->pxms_flg & PXMS_ERR_m)
1542 return pxmc_spdnext_gend(mcs);
1544 pxmc_spd_gacc(&(mcs->pxms_rs), 0, mcs->pxms_ma);
1545 mcs->pxms_rp += mcs->pxms_rs;
1547 mark = pxmc_inp_rocon_is_mark(mcs);
1549 if (mcs->pxms_gen_htim) {
1550 mcs->pxms_gen_htim--;
1554 if (!(mcs->pxms_cfg & PXMS_CFG_HLS_m)) {
1555 /* limit switch is not used */
1556 pxmc_inp_rocon_is_index_edge(mcs);
1557 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1562 /* go out from switch */
1563 mcs->pxms_do_gen = pxmc_rocon_hh_gd20;
1565 /* switch is off -> look for it */
1566 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1571 /* go out from switch */
1573 pxmc_rocon_hh_gd20(pxmc_state_t *mcs)
1577 if(mcs->pxms_flg & PXMS_ERR_m)
1578 return pxmc_spdnext_gend(mcs);
1580 mark = pxmc_inp_rocon_is_mark(mcs);
1583 /* switch is off -> look for it again */
1584 mcs->pxms_do_gen = pxmc_rocon_hh_gd30;
1587 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1588 mcs->pxms_rp += mcs->pxms_rs;
1593 /* switch is off -> look for it */
1595 pxmc_rocon_hh_gd30(pxmc_state_t *mcs)
1600 if (mcs->pxms_flg & PXMS_ERR_m)
1601 return pxmc_spdnext_gend(mcs);
1603 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1604 mcs->pxms_rp += mcs->pxms_rs;
1606 mark = pxmc_inp_rocon_is_mark(mcs);
1609 spd = mcs->pxms_gen_hsp >> 2; /* slow down */
1612 mcs->pxms_gen_hsp = spd;
1613 mcs->pxms_do_gen = pxmc_rocon_hh_gd40;
1619 /* switch is on -> find edge */
1621 pxmc_rocon_hh_gd40(pxmc_state_t *mcs)
1625 if (mcs->pxms_flg & PXMS_ERR_m)
1626 return pxmc_spdnext_gend(mcs);
1628 mark = pxmc_inp_rocon_is_mark(mcs);
1631 if (mcs->pxms_cfg & PXMS_CFG_HRI_m) {
1632 pxmc_inp_rocon_is_index_edge(mcs);
1633 mcs->pxms_do_gen = pxmc_rocon_hh_gd50;
1635 pxmc_inp_rocon_ap_zero(mcs);
1636 mcs->pxms_do_gen = pxmc_stop_gi;
1640 pxmc_spd_gacc(&(mcs->pxms_rs), -mcs->pxms_gen_hsp, mcs->pxms_ma);
1641 mcs->pxms_rp += mcs->pxms_rs;
1646 /* calibrate on revolution index */
1648 pxmc_rocon_hh_gd50(pxmc_state_t *mcs)
1650 if (mcs->pxms_flg & PXMS_ERR_m)
1651 return pxmc_spdnext_gend(mcs);
1653 pxmc_spd_gacc(&(mcs->pxms_rs), mcs->pxms_gen_hsp, mcs->pxms_ma);
1654 mcs->pxms_rp += mcs->pxms_rs;
1656 if (pxmc_inp_rocon_is_index_edge(mcs)){
1657 pxmc_inp_rocon_irc_offset_from_index(mcs);
1658 mcs->pxms_do_gen = pxmc_stop_gi;
1664 pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
1666 return pxmc_rocon_hh_gi;
1669 pxmc_rocon_state_t mcs0 =
1677 pxmc_pid_con /*pxmc_dummy_con*/,
1679 pxmc_rocon_pwm_dc_out /*pxmc_rocon_pwm3ph_out*/,
1683 pxmc_inp_rocon_ap2hw,
1684 pxms_ap: 0, pxms_as: 0,
1685 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1686 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1689 pxms_ene: 0, pxms_erc: 0,
1690 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1691 pxms_me: 0x7e00/*0x7fff*/,
1693 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1694 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1695 PXMS_CFG_I2PT_m * 0 | 0x2,
1700 /*pxms_ptamp: 0x7fff,*/
1711 pxmc_rocon_state_t mcs1 =
1721 pxmc_rocon_pwm_dc_out,
1725 pxmc_inp_rocon_ap2hw,
1726 pxms_ap: 0, pxms_as: 0,
1727 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1728 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1731 pxms_ene: 0, pxms_erc: 0,
1732 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1733 pxms_me: 0x7e00/*0x7fff*/,
1735 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1736 PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
1737 PXMS_CFG_I2PT_m * 0 | 0x2,
1741 /*pxms_ptamp: 0x7fff,*/
1746 pxmc_rocon_state_t mcs2 =
1756 pxmc_rocon_pwm_dc_out,
1760 pxmc_inp_rocon_ap2hw,
1761 pxms_ap: 0, pxms_as: 0,
1762 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1763 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1766 pxms_ene: 0, pxms_erc: 0,
1767 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1768 pxms_me: 0x7e00/*0x7fff*/,
1770 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1771 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1772 PXMS_CFG_HDIR_m | 0x2,
1776 /*pxms_ptamp: 0x7fff,*/
1781 pxmc_rocon_state_t mcs3 =
1791 pxmc_rocon_pwm_dc_out,
1795 pxmc_inp_rocon_ap2hw,
1796 pxms_ap: 0, pxms_as: 0,
1797 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1798 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1801 pxms_ene: 0, pxms_erc: 0,
1802 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1803 pxms_me: 0x7e00/*0x7fff*/,
1805 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1806 PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
1807 PXMS_CFG_HDIR_m * 0 | 0x2,
1811 /*pxms_ptamp: 0x7fff,*/
1816 pxmc_rocon_state_t mcs4 =
1826 pxmc_rocon_pwm_dc_out,
1830 pxmc_inp_rocon_ap2hw,
1831 pxms_ap: 0, pxms_as: 0,
1832 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1833 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1836 pxms_ene: 0, pxms_erc: 0,
1837 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1838 pxms_me: 0x7e00/*0x7fff*/,
1840 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
1841 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1842 PXMS_CFG_HDIR_m | 0x2,
1846 /*pxms_ptamp: 0x7fff,*/
1851 pxmc_rocon_state_t mcs5 =
1861 pxmc_rocon_pwm_dc_out,
1865 pxmc_inp_rocon_ap2hw,
1866 pxms_ap: 0, pxms_as: 0,
1867 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1868 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1871 pxms_ene: 0, pxms_erc: 0,
1872 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1873 pxms_me: 0x7e00/*0x7fff*/,
1875 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
1876 PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
1877 PXMS_CFG_HDIR_m | 0x2,
1881 /*pxms_ptamp: 0x7fff,*/
1886 pxmc_rocon_state_t mcs6 =
1896 pxmc_rocon_pwm_dc_out,
1900 pxmc_inp_rocon_ap2hw,
1901 pxms_ap: 0, pxms_as: 0,
1902 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1903 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1906 pxms_ene: 0, pxms_erc: 0,
1907 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1908 pxms_me: 0x7e00/*0x7fff*/,
1910 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1915 /*pxms_ptamp: 0x7fff,*/
1920 pxmc_rocon_state_t mcs7 =
1930 pxmc_rocon_pwm_dc_out,
1934 pxmc_inp_rocon_ap2hw,
1935 pxms_ap: 0, pxms_as: 0,
1936 pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
1937 pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
1940 pxms_ene: 0, pxms_erc: 0,
1941 pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
1942 pxms_me: 0x7e00/*0x7fff*/,
1944 PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
1949 /*pxms_ptamp: 0x7fff,*/
1954 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
1955 {&mcs0.base, &mcs1.base, &mcs2.base, &mcs3.base,
1956 &mcs4.base, &mcs5.base, &mcs6.base, &mcs7.base};
1959 pxmc_state_list_t pxmc_main_list =
1966 void pxmc_lpc_qei_callback_index(struct lpc_qei_state_t *qst, void *context)
1968 pxmc_state_t *mcs = (pxmc_state_t *)context;
1971 irc = qst->index_pos;
1973 if ((mcs->pxms_cfg & PXMS_CFG_I2PT_m) && (mcs->pxms_flg & PXMS_PTI_m))
1976 ofs = irc - mcs->pxms_ptmark;
1977 diff = ofs - mcs->pxms_ptofs;
1979 if (diff >= mcs->pxms_ptirc / 2)
1980 diff -= mcs->pxms_ptirc;
1982 if (diff <= -mcs->pxms_ptirc / 2)
1983 diff += mcs->pxms_ptirc;
1988 if (diff >= mcs->pxms_ptirc / 6)
1990 pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
1994 mcs->pxms_ptofs = ofs;
1995 pxmc_set_flag(mcs, PXMS_PHA_b);
1999 ofs=irc-mcs->pxms_ptofs;
2000 if((unsigned short)ofs>=(unsigned short)mcs->pxms_ptirc) {
2002 ofs-=mcs->pxms_ptirc;
2004 ofs+=mcs->pxms_ptirc;
2007 mcs->pxms_ptmark=ofs;
2010 /*lpc_qei_set_cmpos(qst, 0, qst->index_pos-4000);*/
2013 int pxmc_lpc_pthalalign_callback(pxmc_state_t *mcs)
2017 lpc_qei_state_t *qst = &lpc_qei_state;
2018 int irc = lpc_qei_get_pos(qst);
2021 if (!qst->index_occ)
2024 idx_rel = qst->index_pos - irc;
2025 idx_rel %= mcs->pxms_ptirc;
2028 idx_rel += mcs->pxms_ptirc;
2030 ptofs = irc - mcs->pxms_ptofs;
2031 ptmark = ptofs + idx_rel;
2033 if ((unsigned short)ptmark >= mcs->pxms_ptirc)
2036 ptmark -= mcs->pxms_ptirc;
2038 ptmark += mcs->pxms_ptirc;
2041 if ((unsigned short)ptmark < mcs->pxms_ptirc)
2043 mcs->pxms_ptmark = ptmark;
2049 int pxmc_lpc_pthalalign(pxmc_state_t *mcs, int periods)
2054 pxmc_call_t *fin_fnc = pxmc_lpc_pthalalign_callback;
2055 lpc_qei_state_t *qst = &lpc_qei_state;
2057 mcs->pxms_cfg &= ~PXMS_CFG_I2PT_m;
2058 lpc_qei_setup_index_catch(qst);
2060 r2acq = ((long)mcs->pxms_ptirc << PXMC_SUBDIV(mcs)) * periods;
2061 spd = 1 << PXMC_SUBDIV(mcs);
2063 res = pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
2068 int pxmc_lpc_pthalalign_run(void)
2070 return pxmc_lpc_pthalalign(pxmc_main_list.pxml_arr[0], 20);
2073 static inline void pxmc_sfi_input(void)
2077 pxmc_for_each_mcs(var, mcs)
2079 /* PXMS_ENI_m - check if input (IRC) update is enabled */
2080 if (mcs->pxms_flg & PXMS_ENI_m)
2082 pxmc_call(mcs, mcs->pxms_do_inp);
2087 static inline void pxmc_sfi_controller_and_output(void)
2091 pxmc_for_each_mcs(var, mcs)
2093 /* PXMS_ENR_m - check if controller is enabled */
2094 if (mcs->pxms_flg & PXMS_ENR_m || mcs->pxms_flg & PXMS_ENO_m)
2097 /* If output only is enabled, we skip the controller */
2098 if (mcs->pxms_flg & PXMS_ENR_m)
2101 pxmc_call(mcs, mcs->pxms_do_con);
2103 /* PXMS_ERR_m - if axis in error state */
2104 if (mcs->pxms_flg & PXMS_ERR_m)
2108 /* for bushless motors, it is necessary to call do_out
2109 even if the controller is not enabled and PWM should be provided. */
2110 pxmc_call(mcs, mcs->pxms_do_out);
2115 static inline void pxmc_sfi_generator(void)
2119 pxmc_for_each_mcs(var, mcs)
2121 /* PXMS_ENG_m - check if requested value (position) generator is enabled */
2122 if (mcs->pxms_flg & PXMS_ENG_m)
2124 pxmc_call(mcs, mcs->pxms_do_gen);
2129 static inline void pxmc_sfi_dbg(void)
2133 pxmc_for_each_mcs(var, mcs)
2135 if (mcs->pxms_flg & PXMS_DBG_m)
2137 pxmc_call(mcs, mcs->pxms_do_deb);
2142 int pxmc_rocon_pthalalign_callback(pxmc_state_t *mcs)
2146 int inp_chan = mcs->pxms_inp_info;
2148 long irc = fpga_irc[inp_chan]->count;
2150 if (!pxmc_inp_rocon_is_index_edge(mcs))
2153 idx_rel = fpga_irc[inp_chan]->count_index - irc;
2154 idx_rel %= mcs->pxms_ptirc;
2156 idx_rel += mcs->pxms_ptirc;
2158 ptofs = irc-mcs->pxms_ptofs;
2159 ptmark = ptofs+idx_rel;
2161 if((unsigned short)ptmark >= mcs->pxms_ptirc) {
2163 ptmark -= mcs->pxms_ptirc;
2165 ptmark += mcs->pxms_ptirc;
2168 if((unsigned short)ptmark < mcs->pxms_ptirc) {
2169 mcs->pxms_ptmark = ptmark;
2174 int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
2179 pxmc_call_t *fin_fnc = pxmc_rocon_pthalalign_callback;
2181 mcs->pxms_cfg&=~PXMS_CFG_I2PT_m;
2183 r2acq=((long)mcs->pxms_ptirc<<PXMC_SUBDIV(mcs))*periods;
2184 spd=1<<PXMC_SUBDIV(mcs);
2186 /* clear bit indicating previous index */
2187 pxmc_inp_rocon_is_index_edge(mcs);
2189 res=pxmc_pthalalign(mcs, r2acq, spd, fin_fnc);
2194 int pxmc_axis_out_chans4mode(int mode)
2197 case PXMC_AXIS_MODE_DC:
2199 case PXMC_AXIS_MODE_BLDC:
2200 case PXMC_AXIS_MODE_BLDC_PXMCC:
2202 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
2203 case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
2204 case PXMC_AXIS_MODE_STEPPER_PXMCC:
2210 int pxmc_axis_rdmode(pxmc_state_t *mcs)
2212 if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
2213 return PXMC_AXIS_MODE_STEPPER_WITH_IRC;
2214 if (mcs->pxms_do_out == pxmc_rocon_pwm_dc_out)
2215 return PXMC_AXIS_MODE_DC;
2216 if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
2217 return PXMC_AXIS_MODE_BLDC;
2218 if (mcs->pxms_do_out == pxmc_pxmcc_pwm3ph_out)
2219 return PXMC_AXIS_MODE_BLDC_PXMCC;
2220 if (mcs->pxms_do_out == pxmc_pxmcc_pwm2ph_out)
2221 return PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC;
2222 if (mcs->pxms_do_out == pxmc_pxmcc_nofb2ph_out)
2223 return PXMC_AXIS_MODE_STEPPER_PXMCC;
2228 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
2230 static const typeof(*mcs->pxms_ptptr1) dummy0 = 0;
2233 if (mode == PXMC_AXIS_MODE_NOCHANGE)
2234 mode = pxmc_axis_rdmode(mcs);
2239 /* case PXMC_AXIS_MODE_STEPPER: */
2240 case PXMC_AXIS_MODE_STEPPER_PXMCC:
2241 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
2242 case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
2243 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
2245 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
2246 case PXMC_AXIS_MODE_DC:
2247 /*profive some sane dummy values*/
2248 mcs->pxms_ptptr1 = (typeof(mcs->pxms_ptptr1))&dummy0;
2249 mcs->pxms_ptptr2 = (typeof(mcs->pxms_ptptr1))&dummy0;
2250 mcs->pxms_ptptr3 = (typeof(mcs->pxms_ptptr1))&dummy0;
2252 mcs->pxms_ptscale_mult=1;
2253 mcs->pxms_ptscale_shift=15;
2255 case PXMC_AXIS_MODE_BLDC:
2256 case PXMC_AXIS_MODE_BLDC_PXMCC:
2257 /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
2258 #ifndef PXMC_WITH_PT_ZIC
2259 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
2260 #else /*PXMC_WITH_PT_ZIC*/
2261 res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup_zic, 0, 0);
2262 #endif /*PXMC_WITH_PT_ZIC*/
2268 mcs->pxms_ptvang = pxmc_ptvang_deg2irc(mcs, 90);
2274 * pxmc_axis_mode - Sets axis mode.[extern API]
2275 * @mcs: Motion controller state information
2276 * @mode: 0 .. previous mode, 1 .. stepper motor mode,
2277 * 2 .. stepper motor with IRC feedback and PWM ,
2278 * 3 .. stepper motor with PWM control
2279 * 4 .. DC motor with IRC feedback and PWM
2283 pxmc_axis_mode(pxmc_state_t *mcs, int mode)
2288 pxmc_set_const_out(mcs, 0);
2289 pxmc_clear_flag(mcs, PXMS_ENI_b);
2290 pxmc_clear_flags(mcs,PXMS_ENO_m);
2291 /* Clear possible stall index flags from hardware */
2292 pxmc_inp_rocon_is_index_edge(mcs);
2293 pxmc_clear_flag(mcs, PXMS_PHA_b);
2294 pxmc_clear_flag(mcs, PXMS_PTI_b);
2297 prev_mode = pxmc_axis_rdmode(mcs);
2299 if (mode == PXMC_AXIS_MODE_NOCHANGE)
2304 mode = PXMC_AXIS_MODE_DC;
2306 if ((prev_mode == PXMC_AXIS_MODE_BLDC_PXMCC) ||
2307 (prev_mode == PXMCC_MODE_STEPPER_WITH_IRC))
2308 pxmcc_axis_setup(mcs, PXMCC_MODE_IDLE);
2310 res = pxmc_axis_pt4mode(mcs, mode);
2314 if (mcs->pxms_do_inp == pxmc_pxmcc_nofb2ph_inp)
2315 mcs->pxms_do_inp = pxmc_inp_rocon_inp;
2316 if (mcs->pxms_do_con == pxmc_pxmcc_nofb_con)
2317 mcs->pxms_do_con = pxmc_pid_con;
2320 /*case PXMC_AXIS_MODE_STEPPER:*/
2321 case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
2322 mcs->pxms_do_out = pxmc_rocon_pwm2ph_out;
2324 /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
2325 case PXMC_AXIS_MODE_DC:
2326 mcs->pxms_do_out = pxmc_rocon_pwm_dc_out;
2328 case PXMC_AXIS_MODE_BLDC:
2329 mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
2331 case PXMC_AXIS_MODE_BLDC_PXMCC:
2332 if (pxmcc_axis_setup(mcs, PXMCC_MODE_BLDC) < 0)
2334 pxmcc_axis_enable(mcs, 1);
2335 mcs->pxms_do_out = pxmc_pxmcc_pwm3ph_out;
2337 case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
2338 if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER_WITH_IRC) < 0)
2340 pxmcc_axis_enable(mcs, 1);
2341 mcs->pxms_do_out = pxmc_pxmcc_pwm2ph_out;
2343 case PXMC_AXIS_MODE_STEPPER_PXMCC:
2344 if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER) < 0)
2346 pxmcc_axis_enable(mcs, 1);
2347 mcs->pxms_do_inp = pxmc_pxmcc_nofb2ph_inp;
2348 mcs->pxms_do_con = pxmc_pxmcc_nofb_con;
2349 mcs->pxms_do_out = pxmc_pxmcc_nofb2ph_out;
2355 /* Clear possible stall index flags from hardware */
2356 pxmc_inp_rocon_is_index_edge(mcs);
2357 /* Request new phases alignment for changed parameters */
2358 pxmc_clear_flag(mcs, PXMS_PHA_b);
2359 pxmc_clear_flag(mcs, PXMS_PTI_b);
2360 pxmc_set_flag(mcs, PXMS_ENI_b);
2364 void pxmc_sfi_isr(void)
2366 unsigned long spent = pxmc_fast_tick_time();
2369 pxmc_sfi_controller_and_output();
2370 pxmc_sfi_generator();
2372 /* Kick LX Master watchdog */
2373 if (pxmc_main_list.pxml_cnt != 0)
2374 *fpga_lx_master_transmitter_wdog = 1;
2376 spent = pxmc_fast_tick_time() - spent;
2378 if(spent > pxmc_sfi_spent_time_max)
2379 pxmc_sfi_spent_time_max = spent;
2383 int pxmc_clear_power_stop(void)
2388 int pxmc_process_state_check(unsigned long *pbusy_bits,
2389 unsigned long *perror_bits)
2392 unsigned short chan;
2393 unsigned long busy_bits = 0;
2394 unsigned long error_bits = 0;
2397 pxmc_for_each_mcs(chan, mcs) {
2399 flg |= mcs->pxms_flg;
2400 if (mcs->pxms_flg & PXMS_BSY_m)
2401 busy_bits |= 1 << chan;
2402 if (mcs->pxms_flg & PXMS_ERR_m)
2403 error_bits |= 1 << chan;
2406 if (appl_errstop_mode) {
2407 if((flg & PXMS_ENG_m) && (flg & PXMS_ERR_m)) {
2408 pxmc_for_each_mcs(chan, mcs) {
2409 if(mcs&&(mcs->pxms_flg & PXMS_ENG_m)) {
2416 if (pbusy_bits != NULL)
2417 *pbusy_bits = busy_bits;
2418 if (error_bits != NULL)
2419 *perror_bits = error_bits;
2429 if (!pxmc_main_list.pxml_cnt)
2432 pxmc_for_each_mcs(var, mcs)
2434 pxmc_set_const_out(mcs,0);
2437 pxmc_main_list.pxml_cnt = 0;
2443 int pxmc_initialize(void)
2448 pxmc_state_t *mcs = &mcs0.base;
2449 lpc_qei_state_t *qst = &lpc_qei_state;
2451 *fpga_irc_reset = 1;
2453 for (i = 0; i < 8; i++) {
2454 fpga_irc[i]->count = 0;
2455 fpga_irc[i]->count_index = 0;
2456 *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
2459 /* Initialize QEI module for IRC counting */
2460 pxmc_inp_lpc_qei_init(mcs->pxms_inp_info);
2462 /* Initialize QEI events processing */
2463 if (lpc_qei_setup_irq(qst) < 0)
2466 *fpga_irc_reset = 0;
2468 //res = pxmc_axis_pt4mode(mcs, PXMC_AXIS_MODE_BLDC);
2470 /*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
2471 //pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
2473 pxmc_rocon_pwm_master_init();
2474 #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
2475 pxmc_rocon_rx_done_isr_setup(pxmc_rocon_rx_done_isr);
2476 #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
2478 pxmc_main_list.pxml_cnt = 0;
2479 pxmc_dbg_hist = NULL;
2481 pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;