long pxmc_rocon_irc_offset[PXML_MAIN_CNT];
unsigned pxmc_rocon_mark_filt[PXML_MAIN_CNT];
+unsigned pxmc_rocon_lxpwr_chips = 0;
static inline
pxmc_rocon_state_t *pxmc_state2rocon_state(pxmc_state_t *mcs)
return mcsrc;
}
+uint32_t pxmc_rocon_vin_adc_last;
+int pxmc_rocon_vin_act;
+int pxmc_rocon_vin_ofs = 20978;
+int pxmc_rocon_vin_mul = 32905;
+int pxmc_rocon_vin_shr = 14;
+
+static inline
+void pxmc_rocon_vin_compute(void)
+{
+ volatile uint32_t *vin_adc_reg;
+ uint32_t vin_adc;
+ int vin_act;
+
+ vin_adc_reg = fpga_lx_master_receiver_base;
+ vin_adc_reg += LX_MASTER_DATA_OFFS + 1 + 8 * 2;
+
+ vin_adc = *vin_adc_reg;
+
+ vin_act = (int16_t)(vin_adc - pxmc_rocon_vin_adc_last);
+ pxmc_rocon_vin_adc_last = vin_adc;
+
+ vin_act = (pxmc_rocon_vin_ofs - vin_act) * pxmc_rocon_vin_mul;
+ vin_act >>= pxmc_rocon_vin_shr;
+
+ pxmc_rocon_vin_act = vin_act;
+}
+
+unsigned int pxmc_rocon_rx_done_sqn;
+unsigned int pxmc_rocon_rx_done_sqn_inc;
+unsigned int pxmc_rocon_rx_done_sqn_misscnt;
+unsigned int pxmc_rocon_rx_done_sqn_missoffs;
+
+static inline
+void pxmc_rocon_rx_done_sqn_compute(void)
+{
+ uint32_t sqn_act;
+ uint32_t sqn_offs;
+ unsigned int sqn_expect = pxmc_rocon_rx_done_sqn + pxmc_rocon_rx_done_sqn_inc;
+
+ sqn_act = *fpga_lx_master_receiver_done_div;
+ sqn_offs = (sqn_act - sqn_expect) & 0x1f;
+ if (sqn_offs) {
+ if (pxmc_rocon_rx_done_sqn_missoffs != sqn_offs) {
+ pxmc_rocon_rx_done_sqn_misscnt = 1;
+ } else {
+ pxmc_rocon_rx_done_sqn_misscnt++;
+ if (pxmc_rocon_rx_done_sqn_misscnt >= 10)
+ sqn_expect += 1 - ((sqn_offs >> 3) & 2);
+ }
+ } else {
+ pxmc_rocon_rx_done_sqn_misscnt = 0;
+ }
+ pxmc_rocon_rx_done_sqn = sqn_expect;
+ pxmc_rocon_rx_done_sqn_missoffs = sqn_offs;
+}
+
+uint32_t pxmc_rocon_rx_err_cnt_last;
+uint32_t pxmc_rocon_rx_err_level;
+uint32_t pxmc_rocon_mcc_rx_done_sqn_last;
+uint32_t pxmc_rocon_mcc_stuck;
+
+static inline
+void pxmc_rocon_rx_error_check(void)
+{
+ uint32_t cnt;
+ uint32_t mcc_sqn;
+ pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
+
+ cnt = mcc_data->common.rx_err_cnt;
+ pxmc_rocon_rx_err_level = cnt - pxmc_rocon_rx_err_cnt_last;
+ pxmc_rocon_rx_err_cnt_last = cnt;
+
+ mcc_sqn = mcc_data->common.rx_done_sqn;
+ pxmc_rocon_mcc_stuck = mcc_sqn == pxmc_rocon_mcc_rx_done_sqn_last? 1: 0;
+ pxmc_rocon_mcc_rx_done_sqn_last = mcc_sqn;
+}
+
const uint8_t onesin10bits[1024]={
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,
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,
return pwm_reg;
}
+int pxmc_rocon_pwm_direct_wr(unsigned chan, unsigned pwm, int en)
+{
+ volatile uint32_t *pwm_reg;
+ pwm_reg = pxmc_rocon_pwm_chan2reg(chan);
+
+ if (pwm_reg == &pxmc_rocon_pwm_dummy_reg)
+ return -1;
+
+ *pwm_reg = pwm | (en? 0x4000: 0x8000);
+
+ return 0;
+}
+
/**
* pxmc_rocon_pwm3ph_wr - Output of the 3-phase PWM to the hardware
* @mcs: Motion controller state information
pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
+
+ if (pxmc_rocon_rx_err_level >= 2)
+ pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
+ else if (pxmc_rocon_mcc_stuck)
+ pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
}
pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
+
+ if (pxmc_rocon_rx_err_level >= 2)
+ pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
+ else if (pxmc_rocon_mcc_stuck)
+ pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
}
pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
}
/**
- * pxmc_pxmcc_nofb_inp - Dummy input for direct stepper motor control
+ * pxmc_pxmcc_nofb2ph_inp - Dummy input for direct stepper motor control
* @mcs: Motion controller state information
*/
int
-pxmc_pxmcc_nofb_inp(pxmc_state_t *mcs)
+pxmc_pxmcc_nofb2ph_inp(pxmc_state_t *mcs)
{
+ volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
+ uint32_t steps_pos_act = mcc_axis->steps_pos;
+ mcs->pxms_as = (int32_t)(steps_pos_act - mcs->pxms_ap);
+ mcs->pxms_ap += mcs->pxms_as;
return 0;
}
pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
pxmcc_axis_pwm_dq_out(mcs, 0, 0);
mcc_axis->steps_inc = 0;
+ mcc_axis->steps_inc_next = 0;
mcsrc->cur_d_err_sum = 0;
mcsrc->cur_q_err_sum = 0;
} else {
int cur_q_req, cur_q_err;
int max_pwm = mcs->pxms_me;
int32_t stpinc;
+ int32_t stpdiv;
pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
pxmcc_axis_cur_dq_raw2filt(&cur_q, cur_q_raw);
pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
- mcs->pxms_ap=mcs->pxms_rp;
- mcs->pxms_as=mcs->pxms_rs;
- mcc_axis->steps_lim = mcc_axis->steps_cnt + 6;
+ stpinc = mcs->pxms_rp - mcsrc->steps_pos_prev;
- stpinc = mcs->pxms_rs;
- mcc_axis->steps_inc = stpinc;
+ stpdiv = pxmc_rocon_rx_done_sqn_inc;
+ mcc_axis->steps_inc_next = (stpinc + stpdiv / 2) / stpdiv;
+ mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
- /* stpinc /= (mcs->pxms_ptirc << PXMC_SUBDIV(mcs)); */
- /* pxms_ptscale_mult; pxms_ptscale_shift; */
+ mcsrc->steps_pos_prev = mcs->pxms_rp;
+
+ mcc_axis->steps_sqn_next = pxmc_rocon_rx_done_sqn +
+ pxmc_rocon_rx_done_sqn_inc - 1;
+
+ if (pxmc_rocon_rx_err_level >= 2)
+ pxmc_set_errno(mcs, PXMS_E_WINDCURADC);
+ else if (pxmc_rocon_mcc_stuck)
+ pxmc_set_errno(mcs, PXMS_E_MCC_FAULT);
}
return 0;
{
volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
+ pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
uint32_t ptirc;
uint32_t ptreci;
uint32_t inp_info;
mcc_data->common.pwm_cycle = PXMC_LXPWR_PWM_CYCLE;
ptirc = mcs->pxms_ptirc;
+ if (mode == PXMCC_MODE_STEPPER)
+ ptirc <<= PXMC_SUBDIV(mcs);
+
ull = (1ULL << 32) * mcs->pxms_ptper;
ptreci = (ull + ptirc / 2) / ptirc;
break;
case PXMCC_MODE_STEPPER:
phcnt = 4;
- mcc_axis->ptreci = 1;
inp_info = (char*)&mcc_axis->steps_pos - (char*)mcc_data;
break;
}
mcc_axis->ccflg = 0;
mcc_axis->pwm_dq = 0;
- mcc_axis->steps_lim = mcc_axis->steps_cnt;
- mcc_axis->steps_inc = 0;
- mcc_axis->steps_pos = 0;
- if (mode != PXMCC_MODE_STEPPER) {
+ if (mode == PXMCC_MODE_STEPPER) {
+ mcsrc->steps_pos_prev = mcs->pxms_rp = mcs->pxms_ap;
+ mcs->pxms_rs = mcs->pxms_as = 0;
+ mcc_axis->steps_inc_next = 0;
+ mcc_axis->steps_pos_next = mcsrc->steps_pos_prev;
+ mcc_axis->steps_inc = 0;
+ mcc_axis->steps_pos = mcsrc->steps_pos_prev;
+ mcc_axis->ptirc = mcs->pxms_ptirc << PXMC_SUBDIV(mcs);
+ } else {
pxmcc_pxmc_ptofs2mcc(mcs, 1);
}
return 0;
}
+int pxmcc_curadc_zero(int wait)
+{
+ int chan;
+ unsigned try = wait? 200: 0;
+ volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
+ volatile pxmcc_curadc_data_t *curadc;
+
+ for (chan = 0; chan < PXMCC_CURADC_CHANNELS; chan++)
+ pxmc_rocon_pwm_direct_wr(chan, 0, 0);
+
+ do {
+ if (mcc_data->common.fwversion == PXMCC_FWVERSION)
+ break;
+ if (!try--)
+ return -1;
+ } while(1);
+
+ if (wait) {
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+ }
+
+ for (chan = 0; chan < PXMCC_CURADC_CHANNELS; chan++) {
+ curadc = mcc_data->curadc + chan;
+ curadc->siroladc_offs += curadc->cur_val;
+ }
+
+ return 0;
+}
+
/*******************************************************************/
volatile void *pxmc_rocon_rx_data_hist_buff;
hal_gpio_set_value(T2MAT1_PIN, 0);
hal_gpio_set_value(T2MAT0_PIN, 0);
+ pxmc_rocon_rx_done_sqn_compute();
+ pxmc_rocon_vin_compute();
+ pxmc_rocon_rx_error_check();
+
if (pxmc_rocon_rx_data_hist_buff >= pxmc_rocon_rx_data_hist_buff_end)
pxmc_rocon_rx_data_hist_buff = NULL;
*(pbuf++) = *(ptumbl++);
pxmc_rocon_rx_data_hist_buff = pbuf;
+ } else if (!((pxmc_rocon_rx_data_hist_mode & 0xf8) ^ 0x10)) {
+ uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
+ volatile pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
+ volatile pxmcc_curadc_data_t *curadc;
+ pxmc_rocon_state_t *mcsrc = NULL;
+ int chan = pxmc_rocon_rx_data_hist_mode & 7;
+ if (chan < pxmc_main_list.pxml_cnt)
+ mcsrc = pxmc_state2rocon_state(pxmc_main_list.pxml_arr[chan]);
+ if (mcsrc) {
+ *(pbuf++) = pxmc_rocon_vin_act;
+ chan = mcsrc->base.pxms_inp_info;
+ *(pbuf++) = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];;
+ *(pbuf++) = mcsrc->base.pxms_rp >> PXMC_SUBDIV(&mcsrc->base);
+ *(pbuf++) = mcsrc->base.pxms_ene;
+ *(pbuf++) = mcsrc->base.pxms_foi;
+ chan = mcsrc->base.pxms_out_info;
+ curadc = mcc_data->curadc + chan;
+ *(pbuf++) = *pxmc_rocon_pwm_chan2reg(chan++);
+ *(pbuf++) = (curadc++)->cur_val;
+ *(pbuf++) = *pxmc_rocon_pwm_chan2reg(chan++);
+ *(pbuf++) = (curadc++)->cur_val;
+ *(pbuf++) = *pxmc_rocon_pwm_chan2reg(chan++);
+ *(pbuf++) = (curadc++)->cur_val;
+ *(pbuf++) = *pxmc_rocon_pwm_chan2reg(chan++);
+ *(pbuf++) = (curadc++)->cur_val;
+ pxmc_rocon_rx_data_hist_buff = pbuf;
+ }
}
}
}
int
-pxmc_rocon_pwm_master_init(void)
+pxmc_rocon_pwm_master_setup(unsigned lxpwr_chips)
{
int i;
int grp_in = 0;
int grp_out = 0;
unsigned word_slot;
unsigned receiver_done_div = 1;
+ unsigned lxpwr_chips_max = 2;
#ifdef LXPWR_WITH_SIROLADC
unsigned lxpwr_header = 1;
unsigned lxpwr_words = 1 + 8 * 2 + 2;
- unsigned lxpwr_chips = 2;
unsigned lxpwr_chip_pwm_cnt = 8;
#else /*LXPWR_WITH_SIROLADC*/
unsigned lxpwr_header = 0;
unsigned lxpwr_words = 8;
- unsigned lxpwr_chips = 2;
unsigned lxpwr_chip_pwm_cnt = 8;
#endif /*LXPWR_WITH_SIROLADC*/
*fpga_lx_master_transmitter_reg = 0;
*fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
*fpga_lx_master_receiver_done_div = receiver_done_div << 8;
+ pxmc_rocon_rx_done_sqn_inc = receiver_done_div;
- for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
+ if (lxpwr_chips > lxpwr_chips_max)
+ return -1;
+
+ for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips_max; i++)
fpga_lx_master_receiver_base[i] = 0;
+ if (lxpwr_chips >= 2) {
+ word_slot = LX_MASTER_DATA_OFFS + lxpwr_words;
+ fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
+ }
+
word_slot = LX_MASTER_DATA_OFFS;
fpga_lx_master_receiver_base[grp_in++] = (word_slot << 8) | lxpwr_words;
+
fpga_lx_master_receiver_base[grp_in++] = 0x0000;
- for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips; i++)
+ for (i = 0; i < LX_MASTER_DATA_OFFS + lxpwr_words * lxpwr_chips_max; i++)
fpga_lx_master_transmitter_base[i] = 0;
word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
return 0;
}
+int
+pxmc_rocon_wait_rx_done(void)
+{
+ uint32_t sqn_last;
+ uint32_t sqn_act;
+ uint32_t timeout = 10000;
+
+ sqn_last = *fpga_lx_master_receiver_done_div;
+ sqn_last = sqn_last & 0x1f;
+
+ do {
+ sqn_act = *fpga_lx_master_receiver_done_div;
+ sqn_act = sqn_act & 0x1f;
+ if (sqn_act != sqn_last)
+ return 0;
+ } while(timeout--);
+
+ return -1;
+}
+
+int
+pxmc_rocon_pwm_master_init(void)
+{
+ int res;
+ volatile uint32_t *lxpwr_header_ptr;
+ unsigned lxpwr_words = 1 + 8 * 2 + 2;
+
+ pxmc_rocon_lxpwr_chips = 0;
+
+ res = pxmc_rocon_pwm_master_setup(2);
+ if (res < 0)
+ return 0;
+
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+
+ lxpwr_header_ptr = fpga_lx_master_receiver_base;
+ lxpwr_header_ptr += LX_MASTER_DATA_OFFS;
+
+ if (lxpwr_header_ptr[0] == 0xb100 + lxpwr_words - 1) {
+ if (lxpwr_header_ptr[lxpwr_words] == 0xb100 + lxpwr_words - 1) {
+ pxmc_rocon_lxpwr_chips = 2;
+ return 2;
+ }
+ return -1;
+ }
+
+ if (lxpwr_header_ptr[lxpwr_words] != 0xb100 + lxpwr_words - 1) {
+ return -1;
+ }
+
+ res = pxmc_rocon_pwm_master_setup(1);
+ if (res < 0)
+ return 0;
+
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+ if (pxmc_rocon_wait_rx_done() < 0)
+ return -1;
+
+ if (lxpwr_header_ptr[0] != 0xb100 + lxpwr_words - 1)
+ return -1;
+
+ pxmc_rocon_lxpwr_chips = 1;
+
+ return 1;
+}
+
int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
unsigned long index_irc, int diff2err)
{
return res;
}
+int pxmc_axis_out_chans4mode(int mode)
+{
+ switch (mode) {
+ case PXMC_AXIS_MODE_DC:
+ return 2;
+ case PXMC_AXIS_MODE_BLDC:
+ case PXMC_AXIS_MODE_BLDC_PXMCC:
+ return 3;
+ case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
+ case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
+ case PXMC_AXIS_MODE_STEPPER_PXMCC:
+ return 4;
+ }
+ return -1;
+}
+
int pxmc_axis_rdmode(pxmc_state_t *mcs)
{
if (mcs->pxms_do_out == pxmc_rocon_pwm2ph_out)
return -1;
}
-
int
pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
{
int res;
int prev_mode;
- pxmc_set_const_out(mcs, 0);
+ pxmc_axis_release(mcs);
pxmc_clear_flag(mcs, PXMS_ENI_b);
pxmc_clear_flags(mcs,PXMS_ENO_m);
/* Clear possible stall index flags from hardware */
mode = PXMC_AXIS_MODE_DC;
if ((prev_mode == PXMC_AXIS_MODE_BLDC_PXMCC) ||
- (prev_mode == PXMCC_MODE_STEPPER_WITH_IRC))
+ (prev_mode == PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC) ||
+ (prev_mode == PXMC_AXIS_MODE_STEPPER_PXMCC))
pxmcc_axis_setup(mcs, PXMCC_MODE_IDLE);
res = pxmc_axis_pt4mode(mcs, mode);
if (res < 0)
return -1;
- if (mcs->pxms_do_inp == pxmc_pxmcc_nofb_inp)
+ if (mcs->pxms_do_inp == pxmc_pxmcc_nofb2ph_inp)
mcs->pxms_do_inp = pxmc_inp_rocon_inp;
if (mcs->pxms_do_con == pxmc_pxmcc_nofb_con)
mcs->pxms_do_con = pxmc_pid_con;
if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER) < 0)
return -1;
pxmcc_axis_enable(mcs, 1);
- mcs->pxms_do_inp = pxmc_pxmcc_nofb_inp;
+ mcs->pxms_do_inp = pxmc_pxmcc_nofb2ph_inp;
mcs->pxms_do_con = pxmc_pxmcc_nofb_con;
mcs->pxms_do_out = pxmc_pxmcc_nofb2ph_out;
break;
}
+pxmc_call_t *const pxmc_reg_type_table[] = {
+ pxmc_pid_con,
+ pxmc_pid_con,
+ pxmc_pidnl_con
+};
+
+
+int pxmc_get_reg_type(pxmc_state_t *mcs)
+{
+ int reg_type;
+ int max_type = sizeof(pxmc_reg_type_table) / sizeof(*pxmc_reg_type_table);
+
+ for (reg_type = 1; reg_type < max_type; reg_type++)
+ if (mcs->pxms_do_con == pxmc_reg_type_table[reg_type])
+ return reg_type;
+ return 0;
+}
+
+int pxmc_set_reg_type(pxmc_state_t *mcs, int reg_type)
+{
+ int max_type = sizeof(pxmc_reg_type_table) / sizeof(*pxmc_reg_type_table);
+
+ if ((reg_type < 0) || (reg_type >= max_type))
+ return -1;
+ if (mcs->pxms_flg & PXMS_ENR_m)
+ return -1;
+
+ mcs->pxms_do_con = pxmc_reg_type_table[reg_type];
+ return 0;
+}
+
int pxmc_clear_power_stop(void)
{
return 0;
if (pbusy_bits != NULL)
*pbusy_bits = busy_bits;
- if (error_bits != NULL)
+ if (perror_bits != NULL)
*perror_bits = error_bits;
return flg;
pxmc_for_each_mcs(var, mcs)
{
- pxmc_set_const_out(mcs,0);
+ pxmc_axis_release(mcs);
}
pxmc_main_list.pxml_cnt = 0;
int res;
int i;
+ pxmc_main_list.pxml_cnt = 0;
+ pxmc_dbg_hist = NULL;
+ #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
+ disable_irq(ROCON_RX_IRQn);
+ #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
+ __memory_barrier();
+
pxmc_state_t *mcs = &mcs0.base;
lpc_qei_state_t *qst = &lpc_qei_state;
/*pxmc_ctm4pwm3f_wr(mcs, 0, 0, 0);*/
//pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
- pxmc_rocon_pwm_master_init();
+ res = pxmc_rocon_pwm_master_init();
+ if (res < 0)
+ return -1;
+
#ifdef PXMC_ROCON_TIMED_BY_RX_DONE
pxmc_rocon_rx_done_isr_setup(pxmc_rocon_rx_done_isr);
#endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
- pxmc_main_list.pxml_cnt = 0;
- pxmc_dbg_hist = NULL;
__memory_barrier();
pxmc_main_list.pxml_cnt = PXML_MAIN_CNT;