]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - sw/app/rocon/appl_pxmc.c
RoCoN: log requested position and I component accumulator as well.
[fpga/lx-cpu1/lx-rocon.git] / sw / app / rocon / appl_pxmc.c
index 2731da34d8bfe746b9d59e9588a0f412f22842c8..1378b598870f5c43a87f73971b89240edfa13616 100644 (file)
@@ -1,8 +1,7 @@
 /*******************************************************************
   Motion and Robotic System (MARS) aplication components.
 
-  appl_pxmc.c - position controller subsystem core generic
-                and LP_MPW1 hardware specific support
+  appl_pxmc.c - position controller RoCoN hardware support
 
   Copyright (C) 2001-2013 by Pavel Pisa - originator
                           pisa@cmp.felk.cvut.cz
 #include <hal_gpio.h>
 #include <hal_machperiph.h>
 #include <stdlib.h>
+#include <string.h>
+#include <LPC17xx.h>
+#include <lpcTIM.h>
 
 #include "appl_defs.h"
 #include "appl_fpga.h"
+#include "appl_pxmc.h"
+#include "pxmcc_types.h"
+#include "pxmcc_interface.h"
+
+#define PXMC_AXIS_MODE_BLDC_PXMCC             (PXMC_AXIS_MODE_BLDC + 1)
+#define PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC (PXMC_AXIS_MODE_BLDC + 2)
+#define PXMC_AXIS_MODE_STEPPER_PXMCC          (PXMC_AXIS_MODE_BLDC + 3)
 
 int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
                            unsigned long index_irc, int diff2err);
@@ -47,10 +56,106 @@ int pxmc_ptofs_from_index(pxmc_state_t *mcs, unsigned long irc,
 #define HAL_ERR_SENSITIVITY 20
 #define HAL_ERR_MAX_COUNT    5
 
-unsigned pxmc_rocon_pwm_magnitude = 2500;
+#define LXPWR_WITH_SIROLADC  1
+
+#define LX_MASTER_DATA_OFFS  8
+
+#define PXMC_LXPWR_PWM_CYCLE 2500
+
+unsigned pxmc_rocon_pwm_magnitude = PXMC_LXPWR_PWM_CYCLE;
 
 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)
+{
+  pxmc_rocon_state_t *mcsrc;
+ #ifdef UL_CONTAINEROF
+  mcsrc = UL_CONTAINEROF(mcs, pxmc_rocon_state_t, base);
+ #else /*UL_CONTAINEROF*/
+  mcsrc = (pxmc_rocon_state_t*)((char*)mcs - __builtin_offsetof(pxmc_rocon_state_t, base));
+ #endif /*UL_CONTAINEROF*/
+  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,
@@ -118,7 +223,8 @@ pxmc_inp_rocon_is_mark(pxmc_state_t *mcs)
 
   irc_state = *fpga_irc_state[chan];
 
-  mark = (irc_state ^ (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
+  mark = ((irc_state >> (ffs(FPGA_IRC_STATE_MARK_MASK) - 1)) ^
+         (mcs->pxms_cfg >> PXMS_CFG_HPS_b)) & 1;
 
   filt = pxmc_rocon_mark_filt[chan];
   filt = (filt << 1) | mark;
@@ -135,9 +241,9 @@ pxmc_inp_rocon_is_index_edge(pxmc_state_t *mcs)
   int chan=mcs->pxms_inp_info;
 
   irc_state = *fpga_irc_state[chan];
-  *fpga_irc_state[chan] = 1 << 2;
+  *fpga_irc_state[chan] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
 
-  index = (irc_state >> 2) & 1;
+  index = (irc_state >> (ffs(FPGA_IRC_STATE_INDEX_EVENT_MASK) - 1)) & 1;
 
   return index;
 }
@@ -206,7 +312,7 @@ pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
   long irc;
   long index_irc;
 
-  if (!(*fpga_irc_state[chan] & (1 << 2)))
+  if (!(*fpga_irc_state[chan] & FPGA_IRC_STATE_INDEX_EVENT_MASK))
     return 0;
 
   irc = fpga_irc[chan]->count + pxmc_rocon_irc_offset[chan];
@@ -215,12 +321,49 @@ pxmc_inp_rocon_ptofs_from_index_poll(struct pxmc_state *mcs, int diff2err)
   return pxmc_ptofs_from_index(mcs, irc, index_irc, diff2err);
 }
 
+uint32_t pxmc_rocon_receiver_dummy_reg;
+
+static inline volatile uint32_t *
+pxmc_rocon_receiver_chan2reg(unsigned chan)
+{
+  volatile uint32_t *rec_reg;
+
+  if (chan >= 16)
+    return &pxmc_rocon_receiver_dummy_reg;
+
+  rec_reg = fpga_lx_master_receiver_base;
+
+ #ifdef LXPWR_WITH_SIROLADC
+  rec_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) * 3 + chan * 2;
+ #else /*LXPWR_WITH_SIROLADC*/
+  rec_reg += LX_MASTER_DATA_OFFS + chan;
+ #endif /*LXPWR_WITH_SIROLADC*/
+
+  return rec_reg;
+}
+
 inline unsigned
-pxmc_rocon_bdc_hal_rd(pxmc_state_t *mcs)
+pxmc_rocon_bldc_hal_rd(pxmc_state_t *mcs)
 {
   unsigned h = 0;
-  /* FIXME */
-  h = 1;
+  volatile uint32_t *rec_reg_a, *rec_reg_b, *rec_reg_c;
+  int chan = mcs->pxms_out_info;
+  int hal_offs;
+
+ #ifdef LXPWR_WITH_SIROLADC
+  hal_offs = 1;
+ #else /*LXPWR_WITH_SIROLADC*/
+  hal_offs = 0;
+ #endif /*LXPWR_WITH_SIROLADC*/
+
+  rec_reg_a = pxmc_rocon_receiver_chan2reg(chan + 0);
+  rec_reg_b = pxmc_rocon_receiver_chan2reg(chan + 1);
+  rec_reg_c = pxmc_rocon_receiver_chan2reg(chan + 2);
+
+  h  = (rec_reg_a[hal_offs] >> 14) & 1;
+  h |= (rec_reg_b[hal_offs] >> 13) & 2;
+  h |= (rec_reg_c[hal_offs] >> 12) & 4;
+
   /* return 3 bits corresponding to the HAL senzor input */
   return h;
 }
@@ -262,14 +405,29 @@ pxmc_rocon_pwm_chan2reg(unsigned chan)
     return &pxmc_rocon_pwm_dummy_reg;
 
   pwm_reg = fpga_lx_master_transmitter_base;
- #if 0 /* FPGA design version 2 */
-  pwm_reg += 1 + (chan >> 8) + chan;
- #else  /* FPGA design version 3 */
-  pwm_reg += chan + 8;
- #endif
+
+ #ifdef LXPWR_WITH_SIROLADC
+  pwm_reg += LX_MASTER_DATA_OFFS + 1 + (chan >> 3) + chan;
+ #else /*LXPWR_WITH_SIROLADC*/
+  pwm_reg += LX_MASTER_DATA_OFFS + chan;
+ #endif /*LXPWR_WITH_SIROLADC*/
+
   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
@@ -329,7 +487,7 @@ pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
    #if 0
     pxmc_irc_16bit_commindx(mcs, mcs->pxms_rp >> PXMC_SUBDIV(mcs));
     sync_mode = 1;
-   #elif 1
+   #elif 0
     {
       int res;
       res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
@@ -342,7 +500,7 @@ pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
     }
    #else
 
-    hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bdc_hal_rd(mcs)];
+    hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
 
     if (hal_pos == 0xff)
     {
@@ -381,19 +539,25 @@ pxmc_rocon_pwm3ph_out(pxmc_state_t *mcs)
 
           pxmc_set_flag(mcs, PXMS_PTI_b);
           pxmc_clear_flag(mcs, PXMS_PRA_b);
-
-          /* if phase table position to mask is know do fine phase table alignment */
-          if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
-            /*pxmc_inp_rocon_is_index_edge(mcs);*/
-          }
         }
         else
         {
           if (!(mcs->pxms_flg & PXMS_PTI_m))
             mcs->pxms_ptindx = ptindx;
         }
+      } else {
+        /* if phase table position to mask is know do fine phase table alignment */
+        if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
+          int res;
+          res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
+          if (res < 0) {
+            pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
+          } else if (res) {
+            pxmc_set_flag(mcs, PXMS_PTI_b);
+            pxmc_set_flag(mcs, PXMS_PHA_b);
+          }
+        }
       }
-
       mcs->pxms_hal = hal_pos;
     }
    #endif
@@ -488,10 +652,10 @@ pxmc_rocon_pwm2ph_wr(pxmc_state_t *mcs, short pwm1, short pwm2)
   volatile uint32_t *pwm_reg_ap, *pwm_reg_an, *pwm_reg_bp, *pwm_reg_bn;
   int chan = mcs->pxms_out_info;
 
-  pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 0);
-  pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 1);
-  pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 2);
-  pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 3);
+  pwm_reg_bn = pxmc_rocon_pwm_chan2reg(chan + 0);
+  pwm_reg_bp = pxmc_rocon_pwm_chan2reg(chan + 1);
+  pwm_reg_an = pxmc_rocon_pwm_chan2reg(chan + 2);
+  pwm_reg_ap = pxmc_rocon_pwm_chan2reg(chan + 3);
 
   if (pwm2 >= 0) {
     *pwm_reg_bp = pwm2 | 0x4000;
@@ -653,28 +817,793 @@ pxmc_rocon_pwm_dc_out(pxmc_state_t *mcs)
   return 0;
 }
 
-/* PWM outputs placed on (PWM1), PWM2, PWM4, PWM6 */
+/*******************************************************************/
+/* PXMCC - PXMC coprocessor support and communication */
+
+void pxmcc_pxmc_ptofs2mcc(pxmc_state_t *mcs, int enable_update)
+{
+  volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
+  int inp_chan=mcs->pxms_inp_info;
+  uint32_t ptofs;
+  uint32_t irc;
+
+  if (mcc_axis != NULL) {
+    if (enable_update >= 0)
+      mcc_axis->ptirc = 0xffffffff;
+    ptofs = mcs->pxms_ptofs - pxmc_rocon_irc_offset[inp_chan];
+    irc = fpga_irc[inp_chan]->count;
+    ptofs = (int16_t)(ptofs - irc) + irc;
+    mcc_axis->ptofs = ptofs;
+    if (enable_update > 0) {
+      mcc_axis->ptirc = mcs->pxms_ptirc;
+    }
+  }
+}
+
+static inline
+void pxmcc_axis_get_cur_dq_filt_raw(pxmc_state_t *mcs,
+                                    int32_t *p_cur_d_raw, int32_t *p_cur_q_raw)
+{
+  volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
+  pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
+  uint32_t cur_d_cum = mcc_axis->cur_d_cum;
+  uint32_t cur_q_cum = mcc_axis->cur_q_cum;
+  int32_t cur_d;
+  int32_t cur_q;
+
+  cur_d = cur_d_cum - mcsrc->cur_d_cum_prev;
+  mcsrc->cur_d_cum_prev = cur_d_cum;
+  cur_q = cur_q_cum - mcsrc->cur_q_cum_prev;
+  mcsrc->cur_q_cum_prev = cur_q_cum;
+
+  *p_cur_d_raw = cur_d;
+  *p_cur_q_raw = cur_q;
+}
+
+static inline
+void pxmcc_axis_cur_dq_raw2filt(int *p_cur, int32_t cur_raw)
+{
+  int cur_div;
+  int32_t cur;
+  cur_div = cur_raw & 0x1f;
+  cur = cur_raw / cur_div;
+  cur += (1 << 11) | 0x20;
+  *p_cur = cur >> 12;
+}
+
+
+void pxmcc_axis_get_cur_dq_filt(pxmc_state_t *mcs, int *p_cur_d, int *p_cur_q)
+{
+  int32_t cur_d_raw;
+  int32_t cur_q_raw;
+
+  pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
+
+  pxmcc_axis_cur_dq_raw2filt(p_cur_d, cur_d_raw);
+  pxmcc_axis_cur_dq_raw2filt(p_cur_q, cur_q_raw);
+}
+
+static inline
+void pxmcc_cur_ctrl_pi(int *p_pwm, int32_t *p_cur_err_sum,
+               int cur_err, short cur_ctrl_p, short cur_ctrl_i, int max_pwm)
+{
+  int pwm;
+  int32_t cur_err_sum = *p_cur_err_sum;
+
+  pwm = (cur_err * cur_ctrl_p) >> 8;
+
+  if (cur_ctrl_i)
+    cur_err_sum += cur_err * cur_ctrl_i;
+  else
+    cur_err_sum = 0;
+
+  pwm += cur_err_sum >> 16;
+
+  if (pwm > max_pwm) {
+    cur_err_sum -= (pwm - max_pwm) << 16;
+    pwm = max_pwm;
+  } else if (-pwm > max_pwm) {
+    cur_err_sum -= (pwm + max_pwm) << 16;
+    pwm = 0 - max_pwm;
+  }
+  *p_cur_err_sum = cur_err_sum;
+  *p_pwm = pwm;
+}
+
 int
-pxmc_rocon_pwm_master_init(void)
+pxmc_pxmcc_pwm3ph_out(pxmc_state_t *mcs)
+{
+  int32_t cur_d_raw;
+  int32_t cur_q_raw;
+  pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
+
+  if (!(mcs->pxms_flg & PXMS_PTI_m) || !(mcs->pxms_flg & PXMS_PHA_m) ||
+      (mcs->pxms_flg & PXMS_PRA_m)) {
+    short ptindx;
+    short ptirc = mcs->pxms_ptirc;
+    short divisor = mcs->pxms_ptper * 6;
+    unsigned char hal_pos;
+
+    hal_pos = pxmc_lpc_bdc_hal_pos_table[pxmc_rocon_bldc_hal_rd(mcs)];
+
+    if (hal_pos == 0xff) {
+      if (mcs->pxms_ene)
+        pxmc_rocon_process_hal_error(mcs);
+    } else {
+      if (mcs->pxms_halerc)
+        mcs->pxms_halerc--;
+
+      ptindx = (hal_pos * ptirc + divisor / 2) / divisor;
+
+      if (!(mcs->pxms_flg & PXMS_PTI_m) || (mcs->pxms_flg & PXMS_PRA_m)) {
+        int set_ptofs_fl = 0;
+        int ptofs_enable_update = 0;
+
+        if (((hal_pos != mcs->pxms_hal) && (mcs->pxms_hal != 0x40)) && 1) {
+          short ptindx_prev = (mcs->pxms_hal * ptirc + divisor / 2) / divisor;;
+
+          if ((ptindx > ptindx_prev + ptirc / 2) ||
+              (ptindx_prev > ptindx + ptirc / 2)) {
+            ptindx = (ptindx_prev + ptindx - ptirc) / 2;
+
+            if (ptindx < 0)
+              ptindx += ptirc;
+          } else {
+            ptindx = (ptindx_prev + ptindx) / 2;
+          }
+
+          set_ptofs_fl = 1;
+          ptofs_enable_update = 1;
+
+          pxmc_set_flag(mcs, PXMS_PTI_b);
+          pxmc_clear_flag(mcs, PXMS_PRA_b);
+        } else {
+          if (!(mcs->pxms_flg & PXMS_PTI_m))
+            set_ptofs_fl = 1;
+        }
+        if (set_ptofs_fl) {
+          mcs->pxms_ptindx = ptindx;
+          mcs->pxms_ptofs = (mcs->pxms_ap >> PXMC_SUBDIV(mcs)) + mcs->pxms_ptshift - ptindx;
+
+          pxmcc_pxmc_ptofs2mcc(mcs, ptofs_enable_update);
+        }
+      } else {
+        /* if phase table position to mask is know do fine phase table alignment */
+        if (mcs->pxms_cfg & PXMS_CFG_I2PT_m) {
+          int res;
+
+          res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
+          if (res < 0) {
+            pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
+          } else if (res) {
+            pxmcc_pxmc_ptofs2mcc(mcs, 1);
+            pxmc_set_flag(mcs, PXMS_PTI_b);
+            pxmc_set_flag(mcs, PXMS_PHA_b);
+          }
+        }
+      }
+      mcs->pxms_hal = hal_pos;
+    }
+  }
+
+  pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
+
+  {
+    /*wind_current[0]=(ADC->ADDR0 & 0xFFF0)>>4;*/
+    /* FIXME - check winding current against limit */
+    /* pxmc_set_errno(mcs, PXMS_E_WINDCURRENT); */
+  }
+
+  {
+    int ene, pwm_d, pwm_q;
+
+    ene = mcs->pxms_ene;
+    pwm_d = 0;
+    pwm_q = (pxmc_rocon_pwm_magnitude * ene) >> 15;
+
+    if (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m)) {
+      int cur_d;
+      int cur_d_req, cur_d_err;
+      int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
+
+      cur_d_req = 0;
+
+      pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
+
+      cur_d_err = cur_d_req - cur_d;
+
+      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);
+
+    if (mcs->pxms_flg & PXMS_ERR_m)
+      pxmc_rocon_pwm3ph_wr(mcs, 0, 0, 0);
+  }
+
+  return 0;
+}
+
+int
+pxmc_pxmcc_pwm2ph_out(pxmc_state_t *mcs)
+{
+  pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
+  int32_t cur_d_raw;
+  int32_t cur_q_raw;
+
+  pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
+
+  if(!(mcs->pxms_flg&PXMS_PTI_m) || !(mcs->pxms_flg&PXMS_PHA_m) ||
+     (mcs->pxms_flg&PXMS_PRA_m)) {
+
+    {
+      /* Wait for index mark to align phases */
+      int res;
+      res = pxmc_inp_rocon_ptofs_from_index_poll(mcs, 0);
+      if (res < 0) {
+        pxmc_set_errno(mcs, PXMS_E_I2PT_TOOBIG);
+      } else if (res) {
+        pxmcc_pxmc_ptofs2mcc(mcs, 1);
+        pxmc_set_flag(mcs, PXMS_PTI_b);
+        pxmc_set_flag(mcs, PXMS_PHA_b);
+      } else {
+        pxmcc_pxmc_ptofs2mcc(mcs, 0);
+      }
+    }
+  }
+
+  {
+    int ene, pwm_d, pwm_q;
+
+    ene = mcs->pxms_ene;
+    pwm_d = 0;
+
+    if (mcs->pxms_flg & PXMS_PHA_m &&
+        (mcs->pxms_flg & (PXMS_ENR_m | PXMS_ENO_m))) {
+      int cur_d;
+      int cur_d_req, cur_d_err;
+      int max_pwm = (pxmc_rocon_pwm_magnitude * mcs->pxms_me) >> 15;
+
+      cur_d_req = 0;
+
+      pxmcc_axis_cur_dq_raw2filt(&cur_d, cur_d_raw);
+
+      cur_d_err = cur_d_req - cur_d;
+
+      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;
+
+    pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
+
+    if (mcs->pxms_flg & PXMS_ERR_m)
+      pxmc_rocon_pwm2ph_wr(mcs, 0, 0);
+  }
+
+  return 0;
+}
+
+/**
+ * pxmc_pxmcc_nofb2ph_inp - Dummy input for direct stepper motor control
+ * @mcs:        Motion controller state information
+ */
+int
+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_pxmcc_nofb_con - Empty controller for direct stepper motor control
+ * @mcs:        Motion controller state information
+ */
+int
+pxmc_pxmcc_nofb_con(pxmc_state_t *mcs)
+{
+  mcs->pxms_ene=mcs->pxms_me;
+  return 0;
+}
+
+int
+pxmc_pxmcc_nofb2ph_out(pxmc_state_t *mcs)
+{
+  pxmc_rocon_state_t *mcsrc = pxmc_state2rocon_state(mcs);
+  volatile pxmcc_axis_data_t *mcc_axis = pxmc_rocon_mcs2pxmcc(mcs);
+  int32_t cur_d_raw;
+  int32_t cur_q_raw;
+
+  pxmcc_axis_get_cur_dq_filt_raw(mcs, &cur_d_raw, &cur_q_raw);
+
+  if ((mcs->pxms_flg & PXMS_ERR_m) ||
+      !(mcs->pxms_flg & (PXMS_ENO_m | PXMS_ENR_m))) {
+    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 pwm_d, pwm_q;
+    int cur_d, cur_q;
+    int cur_d_req, cur_d_err;
+    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);
+
+    if (!mcs->pxms_ene)
+      cur_d_req = 0;
+    else
+      cur_d_req = mcsrc->cur_hold;
+
+    cur_d_err = cur_d_req - cur_d;
+
+    pxmcc_cur_ctrl_pi(&pwm_d, &mcsrc->cur_d_err_sum, cur_d_err,
+                      mcsrc->cur_d_p, mcsrc->cur_d_i, max_pwm);
+
+    /* pwm_d = (pxmc_rocon_pwm_magnitude * ene) >> 15; */
+
+    cur_q_req = 0;
+
+    cur_q_err = cur_q_req - cur_q;
+
+    pxmcc_cur_ctrl_pi(&pwm_q, &mcsrc->cur_q_err_sum, cur_q_err,
+                      mcsrc->cur_q_p, mcsrc->cur_q_i, max_pwm);
+
+    pxmcc_axis_pwm_dq_out(mcs, pwm_d, pwm_q);
+
+    stpinc = mcs->pxms_rp - mcsrc->steps_pos_prev;
+
+    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;
+
+    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;
+}
+
+int pxmcc_axis_setup(pxmc_state_t *mcs, int mode)
+{
+  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;
+  uint32_t pwmtx_info;
+  uint32_t pwmtx_info_dummy = 27;
+  uint64_t ull;
+  int      i;
+  int      phcnt = 0;
+  int      pwm_chan;
+
+  if (mcc_axis == NULL)
+    return -1;
+
+  if (mcc_data->common.fwversion != PXMCC_FWVERSION)
+    return -1;
+
+  mcc_axis->ccflg = 0;
+  mcc_axis->mode = PXMCC_MODE_IDLE;
+
+  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;
+
+  mcc_axis->ptreci = ptreci;
+
+  pxmcc_pxmc_ptofs2mcc(mcs, 0);
+
+  inp_info = (char*)&fpga_irc[mcs->pxms_inp_info]->count - (char*)fpga_irc[0];
+  inp_info += mcc_data->common.irc_base;
+
+  switch (mode) {
+    case PXMCC_MODE_IDLE:
+      phcnt = 0;
+      break;
+    case PXMCC_MODE_BLDC:
+      phcnt = 3;
+      break;
+    case PXMCC_MODE_STEPPER_WITH_IRC:
+      phcnt = 4;
+      break;
+    case PXMCC_MODE_STEPPER:
+      phcnt = 4;
+      inp_info = (char*)&mcc_axis->steps_pos - (char*)mcc_data;
+      break;
+  }
+
+  mcc_axis->inp_info = inp_info;
+  mcc_axis->out_info = mcs->pxms_out_info;
+
+  pwm_chan = mcs->pxms_out_info;
+
+  pwmtx_info = (pwmtx_info_dummy << 0) | (pwmtx_info_dummy << 8) |
+               (pwmtx_info_dummy << 16) | (pwmtx_info_dummy << 24);
+
+  for (i = phcnt; --i >= 0; ) {
+    volatile uint32_t *pwm_reg;
+    volatile uint32_t *pwm_reg_base = fpga_lx_master_transmitter_base;
+
+    pwmtx_info <<= 8;
+
+    pwm_reg = pxmc_rocon_pwm_chan2reg(pwm_chan + i);
+    if (pwm_reg == &pxmc_rocon_pwm_dummy_reg) {
+      pwmtx_info |= pwmtx_info_dummy;
+    } else {
+      pwmtx_info |= pwm_reg - pwm_reg_base;
+    }
+  }
+
+  mcc_axis->pwmtx_info = pwmtx_info;
+
+  mcc_axis->mode = mode;
+
+  mcc_axis->ccflg = 0;
+  mcc_axis->pwm_dq = 0;
+
+  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;
+volatile void *pxmc_rocon_rx_data_hist_buff_end;
+int pxmc_rocon_rx_data_hist_mode;
+
+uint32_t pxmc_rocon_rx_last_irq;
+uint32_t pxmc_rocon_rx_cycle_time;
+uint32_t pxmc_rocon_rx_irq_latency;
+uint32_t pxmc_rocon_rx_irq_latency_max;
+
+IRQ_HANDLER_FNC(pxmc_rocon_rx_done_isr)
+{
+  uint32_t ir;
+
+  ir = ROCON_RX_TIM->IR & LPC_TIM_IR_ALL_m;
+  ROCON_RX_TIM->IR = ir;
+  if (ir & LPC_TIM_IR_CR1INT_m) {
+    uint32_t cr0, cr1;
+    cr0 = ROCON_RX_TIM->CR0;
+    cr1 = ROCON_RX_TIM->CR1;
+
+    pxmc_rocon_rx_cycle_time = cr1 - pxmc_rocon_rx_last_irq;
+    pxmc_rocon_rx_last_irq = cr1;
+
+    hal_gpio_set_value(T2MAT0_PIN, 1);
+    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;
+
+    if (pxmc_rocon_rx_data_hist_buff != NULL) {
+      if (pxmc_rocon_rx_data_hist_mode == 0) {
+        int i;
+        volatile uint32_t *pwm_reg = fpga_lx_master_transmitter_base + 8;
+        volatile uint32_t *rec_reg = fpga_lx_master_receiver_base + 8;
+        uint16_t *pbuf = (uint16_t *)pxmc_rocon_rx_data_hist_buff;
+        for (i = 0; i < 8; i++) {
+          *(pbuf++) = *(rec_reg++);
+        }
+        for (i = 0; i < 8; i++) {
+          *(pbuf++) = *(pwm_reg++);
+        }
+        pxmc_rocon_rx_data_hist_buff = pbuf;
+      } else if (pxmc_rocon_rx_data_hist_mode == 1) {
+        int i;
+        uint32_t *pbuf = (uint32_t *)pxmc_rocon_rx_data_hist_buff;
+        pxmcc_data_t *mcc_data = pxmc_rocon_mcc_data();
+        pxmcc_axis_data_t *mcc_axis = mcc_data->axis + 0;
+        uint32_t *ptumbl = (uint32_t *)mcc_axis;
+
+        for (i = 0; i < 16; i++)
+          *(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;
+        }
+      }
+    }
+
+    pxmc_rocon_rx_irq_latency = ROCON_RX_TIM->TC - cr1;
+    if (pxmc_rocon_rx_irq_latency > pxmc_rocon_rx_irq_latency_max)
+      pxmc_rocon_rx_irq_latency_max = pxmc_rocon_rx_irq_latency;
+
+   #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
+    pxmc_sfi_isr();
+    do_pxmc_coordmv();
+   #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
+  }
+
+  return IRQ_HANDLED;
+}
+
+int
+pxmc_rocon_rx_done_isr_setup(irq_handler_t rx_done_isr_handler)
+{
+
+  disable_irq(ROCON_RX_IRQn);
+
+  hal_pin_conf_set(T2MAT0_PIN, PORT_CONF_GPIO_OUT_LO);
+  hal_pin_conf_set(T2MAT1_PIN, PORT_CONF_GPIO_OUT_LO);
+  hal_pin_conf(T2CAP0_PIN);
+  hal_pin_conf(T2CAP1_PIN);
+
+  hal_gpio_direction_output(T2MAT0_PIN, 1);
+  hal_gpio_direction_output(T2MAT1_PIN, 0);
+  hal_gpio_set_value(T2MAT0_PIN, 0);
+
+  /* Enable CLKOUT pin function, source CCLK, divide by 1 */
+  LPC_SC->CLKOUTCFG = 0x0100;
+
+  request_irq(ROCON_RX_IRQn, rx_done_isr_handler, 0, NULL,NULL);
+
+  ROCON_RX_TIM->TCR = 0;
+  ROCON_RX_TIM->CTCR = 0;
+  ROCON_RX_TIM->PR = 0;        /* Divide by 1 */
+
+  ROCON_RX_TIM->CCR = LPC_TIM_CCR_CAP0RE_m | LPC_TIM_CCR_CAP1FE_m |
+                   LPC_TIM_CCR_CAP1I_m;
+
+  ROCON_RX_TIM->EMR = __val2mfld(LPC_TIM_EMR_EMC0_m, LPC_TIM_EMR_NOP) |
+                   __val2mfld(LPC_TIM_EMR_EMC1_m, LPC_TIM_EMR_NOP);
+
+  ROCON_RX_TIM->MCR = 0;                       /* No IRQ on MRx */
+  ROCON_RX_TIM->TCR = LPC_TIM_TCR_CEN_m;       /* Enable timer counting */
+  enable_irq(ROCON_RX_IRQn);           /* Enable interrupt */
+
+  return 0;
+
+}
+
+int
+pxmc_rocon_pwm_master_setup(unsigned lxpwr_chips)
 {
   int i;
-       int grp = 0;
+  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_chip_pwm_cnt = 8;
+ #else /*LXPWR_WITH_SIROLADC*/
+  unsigned lxpwr_header = 0;
+  unsigned lxpwr_words = 8;
+  unsigned lxpwr_chip_pwm_cnt = 8;
+ #endif /*LXPWR_WITH_SIROLADC*/
+
+ #ifdef PXMC_ROCON_TIMED_BY_RX_DONE
+  receiver_done_div = 5;
+ #endif /*PXMC_ROCON_TIMED_BY_RX_DONE*/
 
   *fpga_lx_master_reset = 1;
   *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;
+
+  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;
+  }
 
-  for (i = 0; i < 8 + 16; i ++)
+  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_max; i++)
     fpga_lx_master_transmitter_base[i] = 0;
 
-  fpga_lx_master_transmitter_base[grp++] = 0x0808;
-  /*fpga_lx_master_transmitter_base[grp++] = 0x1008;*/
-  fpga_lx_master_transmitter_base[grp++] = 0x0000;
+  word_slot = LX_MASTER_DATA_OFFS + lxpwr_header + lxpwr_chip_pwm_cnt;
+  fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
+ #ifdef LXPWR_WITH_SIROLADC
+  fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
+ #endif /*LXPWR_WITH_SIROLADC*/
+
+  word_slot = LX_MASTER_DATA_OFFS + 0;
+  fpga_lx_master_transmitter_base[grp_out++] = (word_slot << 8) | lxpwr_words;
+ #ifdef LXPWR_WITH_SIROLADC
+  fpga_lx_master_transmitter_base[word_slot] = 0xc100 | (lxpwr_words - 1);
+ #endif /*LXPWR_WITH_SIROLADC*/
+
+  fpga_lx_master_transmitter_base[grp_out++] = 0x0000;
 
   *fpga_lx_master_reset = 0;
+  *fpga_lx_master_transmitter_cycle = PXMC_LXPWR_PWM_CYCLE; /* 50 MHz -> 20 kHz */
+  *fpga_lx_master_receiver_done_div = receiver_done_div << 8;
 
   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)
 {
@@ -876,8 +1805,9 @@ pxmc_call_t *pxmc_get_hh_gi_4axis(pxmc_state_t *mcs)
   return pxmc_rocon_hh_gi;
 }
 
-pxmc_state_t mcs0 =
+pxmc_rocon_state_t mcs0 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -892,15 +1822,16 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 0,
   pxms_out_info: 0,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m | PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
-  PXMS_CFG_HDIR_m | 0x2,
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
+  PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
+  PXMS_CFG_I2PT_m * 0 | 0x2,
 
   pxms_ptper: 1,
   pxms_ptirc: 1000,
@@ -908,10 +1839,17 @@ pxms_cfg:
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
+},
+  .cur_d_p = 150,
+  .cur_d_i = 6000,
+  .cur_q_p = 150,
+  .cur_q_i = 6000,
+  .cur_hold = 200,
 };
 
-pxmc_state_t mcs1 =
+pxmc_rocon_state_t mcs1 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -926,25 +1864,27 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 1,
   pxms_out_info: 2,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 | PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
-  PXMS_CFG_HDIR_m | 0x2,
-               
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
+  PXMS_CFG_HRI_m * 0 | PXMS_CFG_HDIR_m * 0 |
+  PXMS_CFG_I2PT_m * 0 | 0x2,
+
   pxms_ptper: 1,
   pxms_ptirc: 1000,
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs2 =
+pxmc_rocon_state_t mcs2 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -959,25 +1899,27 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 2,
   pxms_out_info: 4,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 | PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
-  0x2,
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
+  PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
+  PXMS_CFG_HDIR_m | 0x2,
 
   pxms_ptper: 1,
   pxms_ptirc: 1000,
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs3 =
+pxmc_rocon_state_t mcs3 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -992,25 +1934,27 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 3,
   pxms_out_info: 6,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 | PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
-  PXMS_CFG_HDIR_m | 0x2,
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
+  PXMS_CFG_I2PT_m * 0 | PXMS_CFG_HRI_m |
+  PXMS_CFG_HDIR_m * 0 | 0x2,
 
   pxms_ptper: 1,
   pxms_ptirc: 1000,
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs4 =
+pxmc_rocon_state_t mcs4 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -1025,25 +1969,27 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 4,
   pxms_out_info: 8,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
-  0x1,
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m * 0 |
+  PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
+  PXMS_CFG_HDIR_m | 0x2,
 
   pxms_ptper: 1,
   pxms_ptirc: 1000,
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs5 =
+pxmc_rocon_state_t mcs5 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -1058,25 +2004,27 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 5,
   pxms_out_info: 10,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
-  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
-  0x1,
+  PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_HPS_m |
+  PXMS_CFG_HRI_m | PXMS_CFG_I2PT_m * 0 |
+  PXMS_CFG_HDIR_m | 0x2,
 
   pxms_ptper: 1,
   pxms_ptirc: 1000,
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs6 =
+pxmc_rocon_state_t mcs6 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -1091,11 +2039,11 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 6,
   pxms_out_info: 12,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
   PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
@@ -1106,10 +2054,11 @@ pxms_cfg:
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
+}};
 
-pxmc_state_t mcs7 =
+pxmc_rocon_state_t mcs7 =
 {
+.base = {
 pxms_flg:
   PXMS_ENI_m,
 pxms_do_inp:
@@ -1124,11 +2073,11 @@ pxms_do_ap2hw:
   pxmc_inp_rocon_ap2hw,
   pxms_ap: 0, pxms_as: 0,
   pxms_rp: 55 * 256, pxms_rs: 0, pxms_subdiv: 8,
-  pxms_md: 800 << 8, pxms_ms: 1000, pxms_ma: 10,
+  pxms_md: 800 << 8, pxms_ms: 500, pxms_ma: 10,
   pxms_inp_info: 7,
   pxms_out_info: 14,
   pxms_ene: 0, pxms_erc: 0,
-  pxms_p: 80, pxms_i: 30, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
+  pxms_p: 80, pxms_i: 10, pxms_d: 200, pxms_s1: 200, pxms_s2: 0,
   pxms_me: 0x7e00/*0x7fff*/,
 pxms_cfg:
   PXMS_CFG_SMTH_m | PXMS_CFG_MD2E_m | PXMS_CFG_HLS_m | PXMS_CFG_I2PT_m * 0 |
@@ -1139,11 +2088,11 @@ pxms_cfg:
   /*pxms_ptamp: 0x7fff,*/
 
   pxms_hal: 0x40,
-};
-
+}};
 
 pxmc_state_t *pxmc_main_arr[PXML_MAIN_CNT] =
-{&mcs0, &mcs1, &mcs2, &mcs3, &mcs4, &mcs5, &mcs6, &mcs7};
+{&mcs0.base, &mcs1.base, &mcs2.base, &mcs3.base,
+ &mcs4.base, &mcs5.base, &mcs6.base, &mcs7.base};
 
 
 pxmc_state_list_t  pxmc_main_list =
@@ -1381,6 +2330,22 @@ int pxmc_rocon_pthalalign(pxmc_state_t *mcs, int periods)
   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)
@@ -1389,10 +2354,15 @@ int pxmc_axis_rdmode(pxmc_state_t *mcs)
     return PXMC_AXIS_MODE_DC;
   if (mcs->pxms_do_out == pxmc_rocon_pwm3ph_out)
     return PXMC_AXIS_MODE_BLDC;
+  if (mcs->pxms_do_out == pxmc_pxmcc_pwm3ph_out)
+    return PXMC_AXIS_MODE_BLDC_PXMCC;
+  if (mcs->pxms_do_out == pxmc_pxmcc_pwm2ph_out)
+    return PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC;
+  if (mcs->pxms_do_out == pxmc_pxmcc_nofb2ph_out)
+    return PXMC_AXIS_MODE_STEPPER_PXMCC;
   return -1;
 }
 
-
 int
 pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
 {
@@ -1405,8 +2375,10 @@ pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
     return -1;
 
   switch (mode) {
-    /*case PXMC_AXIS_MODE_STEPPER:*/
+    /* case PXMC_AXIS_MODE_STEPPER: */
+    case PXMC_AXIS_MODE_STEPPER_PXMCC:
     case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
+    case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
       res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin, 0, 0);
       break;
     /*case PXMC_AXIS_MODE_STEPPER_WITH_PWM:*/
@@ -1420,6 +2392,7 @@ pxmc_axis_pt4mode(pxmc_state_t *mcs, int mode)
       mcs->pxms_ptscale_shift=15;
       break;
     case PXMC_AXIS_MODE_BLDC:
+    case PXMC_AXIS_MODE_BLDC_PXMCC:
       /* res = pxmc_init_ptable(mcs, PXMC_PTPROF_SIN3FUP); */
      #ifndef PXMC_WITH_PT_ZIC
       res = pxmc_ptable_set_profile(mcs, &pxmc_ptprofile_sin3phup, 0, 0);
@@ -1449,8 +2422,9 @@ int
 pxmc_axis_mode(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 */
@@ -1459,17 +2433,29 @@ pxmc_axis_mode(pxmc_state_t *mcs, int mode)
   pxmc_clear_flag(mcs, PXMS_PTI_b);
 
 
+  prev_mode = pxmc_axis_rdmode(mcs);
+
   if (mode == PXMC_AXIS_MODE_NOCHANGE)
-    mode = pxmc_axis_rdmode(mcs);
+    mode = prev_mode;
   if (mode < 0)
     return -1;
   if (!mode)
     mode = PXMC_AXIS_MODE_DC;
 
+  if ((prev_mode == PXMC_AXIS_MODE_BLDC_PXMCC) ||
+      (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_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;
+
   switch (mode) {
     /*case PXMC_AXIS_MODE_STEPPER:*/
     case PXMC_AXIS_MODE_STEPPER_WITH_IRC:
@@ -1482,6 +2468,26 @@ pxmc_axis_mode(pxmc_state_t *mcs, int mode)
     case PXMC_AXIS_MODE_BLDC:
       mcs->pxms_do_out = pxmc_rocon_pwm3ph_out;
       break;
+    case PXMC_AXIS_MODE_BLDC_PXMCC:
+      if (pxmcc_axis_setup(mcs, PXMCC_MODE_BLDC) < 0)
+        return -1;
+      pxmcc_axis_enable(mcs, 1);
+      mcs->pxms_do_out = pxmc_pxmcc_pwm3ph_out;
+      break;
+    case PXMC_AXIS_MODE_STEPPER_WITH_IRC_PXMCC:
+      if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER_WITH_IRC) < 0)
+        return -1;
+      pxmcc_axis_enable(mcs, 1);
+      mcs->pxms_do_out = pxmc_pxmcc_pwm2ph_out;
+      break;
+    case PXMC_AXIS_MODE_STEPPER_PXMCC:
+      if (pxmcc_axis_setup(mcs, PXMCC_MODE_STEPPER) < 0)
+        return -1;
+      pxmcc_axis_enable(mcs, 1);
+      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;
     default:
       return -1;
   }
@@ -1514,6 +2520,37 @@ void pxmc_sfi_isr(void)
 
 }
 
+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;
@@ -1549,7 +2586,7 @@ int pxmc_process_state_check(unsigned long *pbusy_bits,
 
   if (pbusy_bits != NULL)
     *pbusy_bits = busy_bits;
-  if (error_bits != NULL)
+  if (perror_bits != NULL)
     *perror_bits = error_bits;
 
   return flg;
@@ -1565,7 +2602,7 @@ int pxmc_done(void)
 
   pxmc_for_each_mcs(var, mcs)
   {
-    pxmc_set_const_out(mcs,0);
+    pxmc_axis_release(mcs);
   }
 
   pxmc_main_list.pxml_cnt = 0;
@@ -1579,14 +2616,22 @@ int pxmc_initialize(void)
   int res;
   int i;
 
-  pxmc_state_t *mcs = &mcs0;
+  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;
 
   *fpga_irc_reset = 1;
 
   for (i = 0; i < 8; i++) {
     fpga_irc[i]->count = 0;
-    *fpga_irc_state[i] = 1 << 2;
+    fpga_irc[i]->count_index = 0;
+    *fpga_irc_state[i] = FPGA_IRC_STATE_INDEX_EVENT_MASK;
   }
 
   /* Initialize QEI module for IRC counting */
@@ -1603,10 +2648,14 @@ int pxmc_initialize(void)
   /*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;