

#include "sct_mc.h"

#include "board.h"

#include "mlib.h"
#include "mlib_types.h"

#define LPC_SET(n) SCT0->OUT[n].SET
#define LPC_CLR(n) SCT0->OUT[n].CLR

extern uint32_t current_seqa_ctrl;
extern volatile int Uadc, Iadc;
extern volatile float Uv, Ia;

unsigned char GET_MPOS(void); 

extern frac16_t f16CaptureSpeed,f16SpeedCoef;

volatile unsigned char g_InitPosVal = 0;
volatile unsigned char g_CurPosition = 0;
volatile unsigned char g_LstPosition = 0;
volatile unsigned char g_Direction=0;
extern int16_t cap_cnt;
extern int16_t cap_cntFilt;

frac16_t f16CaptureFilterArr[16];
uint8_t ui8CaptureFilterIndex;

//rpm/period estimate related section
//===================================
volatile uint32_t direction_estimate;
volatile uint32_t speed_timer_rd_new;
volatile uint32_t step_buffer_direction;
volatile uint32_t hall_edges_delta, hall_edges_delta_valid;
volatile uint32_t speed_sp;

void invalidate_period_estimate(void);
void update_period_estimate(void);

/*************************************************************************
***************          Zeljko added        *****************************
*************************************************************************/

volatile uint16_t pwm_top_active = 1000;
volatile uint16_t pwm_xy_deadtime = 12;

enum SCT0_in	{app_in_hsensors = 0};

enum SCT0_out{
  app_out_pwm1 = 0, 
  app_out_pwm2 = 1, 
  app_out_pwm3 = 2, 
  app_out_pwm4 = 3,
  app_out_pwm5 = 5,
  app_out_pwm6 = 6, 
  app_out_adc_trigger = 4};

enum SCT0_pwm_match {
  app_pwm_m_update0 = 0,
  app_pwm_m_update1,
  app_pwm_m_edge0,
  app_pwm_m_edge1,
  app_pwm_m_edge2,
  app_pwm_m_edge3,
  app_pwm_m_adc_trigger};

enum SCT0_event {
  app_pwm_ev_hsensor_edge = 0, 
  app_pwm_ev_update0,
  app_pwm_ev_update1, 
  app_pwm_ev_edge0,
  app_pwm_ev_edge1,
  app_pwm_ev_edge2,
  app_pwm_ev_edge3,
  app_pwm_ev_adc_trigger};

enum SCT0_pwm_state {app_pwm_st_idle = 0, app_pwm_st_active, app_pwm_st_transient};

#define EVCTR_MATCH_EVENT(x)    (SCT_EVENT_CTRL_COMBMODE(1) | SCT_EVENT_CTRL_MATCHSEL(x) )
#define EVCTR_IN_HIGH_EVENT(x)  (SCT_EVENT_CTRL_COMBMODE(2) | SCT_EVENT_CTRL_OUTSEL(0) | SCT_EVENT_CTRL_IOSEL(x) | SCT_EVENT_CTRL_IOCOND(3) )
#define	EVCTR_STATE_SET(x)      (SCT_EVENT_CTRL_STATELD(1)  | SCT_EVENT_CTRL_STATEV(x))
#define	EVCTR_STATE_NO_CHANGE	(SCT_EVENT_CTRL_STATELD(0)  | SCT_EVENT_CTRL_STATEV(0))

#define SCT_ADC_TRIGG_PORT 1
#define SCT_ADC_TRIGG_PIN  19

//PWM control
#define PWM_TB_H_Lx(PT, PB, H, L2, L1, L0) (PT<<28 | PB<<24 | H<<12 | L2<<8 | L1<<4 | L0<<0)

// this array specifies pwm output based on the hall reading and selected direction (0-cw, 1-ccw)
// hall sensor A is encoded as MSB, C as LSB; hall sensor readings are used as index
// sub-array 0: specifies clockwise steps
// sub-array 1: specifies couter clockwise steps
const unsigned long hall_to_pwm[2][8] = {
  { 0,                        //000
    PWM_TB_H_Lx(5,6,4,3,2,1), //001 
    PWM_TB_H_Lx(3,4,2,6,5,1), //010
    PWM_TB_H_Lx(5,6,2,4,3,1), //011
    PWM_TB_H_Lx(1,2,6,5,4,3), //100
    PWM_TB_H_Lx(1,2,4,6,5,3), //101
    PWM_TB_H_Lx(3,4,6,5,2,1), //110
    0                         //111
  }, 
  { 0,                        //000
    PWM_TB_H_Lx(3,4,6,5,2,1), //001 
    PWM_TB_H_Lx(1,2,4,6,5,3), //010
    PWM_TB_H_Lx(1,2,6,5,4,3), //011
    PWM_TB_H_Lx(5,6,2,4,3,1), //100
    PWM_TB_H_Lx(3,4,2,6,5,1), //101
    PWM_TB_H_Lx(5,6,4,3,2,1), //110
    0                         //111
  }
};

// free-running timer prescaler requirements: to be used with 1 Hz - 100 Hz (60 - 6000 rpm)
// @30 MHz - 30*10^6 / 1 /6 = 5*10^6 counts/Hall edge => prescaler of at least 77 so that the counter stays 16 bits
//           30*10^6 / 100 /6 = 50000 counts/Hall edge => prescaler not needed
#define SCT_SPEED_PRESC    (11)


uint8_t s_Mdirection = 0;
extern volatile uint32_t speed_limit_monitor;
volatile uint32_t speed_limit_monitor_old;
/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: SCT_IRQHandler
*
* @brief   The function is used to handle SCT interrupt for detect new position and current motor speed.
*        
* @param  none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
int SCT0_IRQHandler(void)
{
  speed_limit_monitor_old = speed_limit_monitor; //debug purpose 
  
  speed_limit_monitor =0; // check if motor running 
  
  //capture free running counter value
  speed_timer_rd_new  = (SCT0->COUNT & SCT_COUNT_CTR_H_MASK)>>SCT_COUNT_CTR_H_SHIFT;
  
  if (ui8CaptureFilterIndex >= 7)//ui8CaptureFilterSize)
  {
    ui8CaptureFilterIndex = 0;
  }
  f16CaptureFilterArr[ui8CaptureFilterIndex] = speed_timer_rd_new;
  ui8CaptureFilterIndex++;
  
  cap_cntFilt =  speed_timer_rd_new;/*   (  f16CaptureFilterArr[0] 
                       + f16CaptureFilterArr[1] 
                       + f16CaptureFilterArr[2] 
                       + f16CaptureFilterArr[3] 
                       + f16CaptureFilterArr[4] 
                       + f16CaptureFilterArr[5]
                       + f16CaptureFilterArr[6] 
                       + f16CaptureFilterArr[7])>>3;*/
  
  
  PINT->IST = 0x07<<0;
  PINT->RISE = 0x07<<0;
  PINT->FALL = 0x07<<0;
    
  PINT->PMCTRL = 0;
  PINT->PMCTRL = 3;
  
  SCT0->EVFLAG = 1<<app_pwm_ev_hsensor_edge;
  
  //GET MPOS?? 
  g_CurPosition = GET_MPOS();
  if (g_CurPosition!=g_LstPosition)
  {  
    update_sct_out(hall_to_pwm[s_Mdirection][g_CurPosition]);
  }
  g_LstPosition = g_CurPosition;

  //PWM reload register update begin
   GPIO->SET[SCT_ADC_TRIGG_PORT] = 1<<SCT_ADC_TRIGG_PIN;
    
   GPIO->CLR[SCT_ADC_TRIGG_PORT] = 1<<SCT_ADC_TRIGG_PIN;
  //PWM reload register update end
  
   
   SCT0->CTRL |= SCT_CTRL_HALT_H(1); // HALT upper part of SCT
   SCT0->CTRL |= SCT_CTRL_CLRCTR_H_MASK; //reset counter value 
     
   //RUN both timers
   SCT0->CTRL &= ~(SCT_CTRL_STOP_H(1) | SCT_CTRL_HALT_H(1) | SCT_CTRL_STOP_L(1) | SCT_CTRL_HALT_L(1));
  
  return true;
}

/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: MC_INIT
*
* @brief   The function is used to initiate PME and after call SCT init for MotorControl
*        
* @param  none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void MC_INIT(void)
{
  
  // Write to SCT0_INMUX to select SCT_PIN function 
  INPUTMUX->SCT_INMUX[0] = INPUTMUX_SCT_INMUX_INP_N(7); /*  SCT_INMUX_GPIOINT_BMATCH = 7 */
  // Configure the SCT ...
  // Give the module a reset
  
  SYSCON->SYSAHBCLKCTRL0 |= SYSCON_SYSAHBCLKCTRL0_SCT(1);
  SYSCON->PRESETCTRL0 &= ~(SYSCON_PRESETCTRL0_SCT_RST_N(1));
  SYSCON->PRESETCTRL0 |=  (SYSCON_PRESETCTRL0_SCT_RST_N(1));
  
  // Peripheral reset to the GPIO and pin interrupt modules. '0' asserts, '1' deasserts reset.
  SYSCON->PRESETCTRL0 &=  ~(SYSCON_PRESETCTRL0_GPIO0_RST_N(1) | SYSCON_PRESETCTRL0_GPIO1_RST_N(1) | SYSCON_PRESETCTRL0_GPIOINT_RST_N(1));
  SYSCON->PRESETCTRL0 |=   (SYSCON_PRESETCTRL0_GPIO0_RST_N(1) | SYSCON_PRESETCTRL0_GPIO1_RST_N(1) | SYSCON_PRESETCTRL0_GPIOINT_RST_N(1));
  
  // Configure the PME ...
  // Configure p0.8 - p0.11 as pattern match inputs 0 - 3 by writing to PINTSEL0-3 in SYSCON
  SYSCON->PINTSEL[0] =  M_PHA; // IN0 
  SYSCON->PINTSEL[1] =  M_PHB; // IN1 
  SYSCON->PINTSEL[2] =  M_PHC; // IN2 
  
  // Setup the PMSRC register
  //                    B.S.0      B.S.1       B.S.2       B.S.3       B.S.4       B.S.5       B.S.6       B.S.7
  //                     IN0        IN1         IN1         IN2         IN3        unused      unused      unused
  PINT->PMSRC = (0 << 8) | (1 << 11) | (2 << 14) | (0 << 17) | (0 << 20) | (0 << 23) | (0 << 26) | (0 << 29);
  
  // Setup the PMCFG register to configure the bit slice conditions and the endpoints.
  // Users can easily create macros for the conditions and the shifters.
  PINT->PMCFG = (1 << 0)  |     // Slice 0 is endpoint of Term0
                (1 << 1)  |     // Slice 1 is endpoint of Term1
                (1 << 2)  |     // Slice 2 is endpoint of Term2
                (3 << 8)  |     // Slice 0 rising/falling edge
                (3 << 11) |     // Slice 1 rising/falling edge
                (3 << 14) |     // Slice 2 rising/falling edge
                (6 << 17) | (6 << 20) | (6 << 23) | (6 << 26) | (6UL << 29);   // Slice 3,4,5,6,7 unused
  
  PINT->PMCTRL |= PINT_PMCTRL_SEL_PMATCH(1) | PINT_PMCTRL_ENA_RXEV(1);
  
  // Configure GPIO...
  GPIO->DIR[0] &= ~(0x2010002);        // P0.1 16 25 to input
 
  GPIO->DIR[0] |= (0x11300000);      // P0.28 24 21 20 to output
  GPIO->DIR[1] |= (0x300000);      // P1.20 21 to output
 
  GPIO_PortClear( GPIO, 0, 0x11300000); // Clear P0.28 24 21 20
  GPIO_PortClear( GPIO, 1, 0x300000);	// Clear P1.20 21
  
     
  // Clear any pending or left-over edge-detect logic
  PINT->IST  = 0xFF;
  PINT->RISE = 0xFF;
  PINT->FALL = 0xFF;
  
  SCT_INIT();
}	




/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: SCT_INIT
*
* @brief   The function is used to initiate SCT for motor control.
*        
* @param  none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SCT_INIT (void)
{
 
  SCT0->CONFIG &= ~(SCT_CONFIG_CLKMODE(1)| SCT_CONFIG_AUTOLIMIT_L(1)  | SCT_CONFIG_AUTOLIMIT_H(1)  | SCT_CONFIG_INSYNC(1)); 
  SCT0->CONFIG |= SCT_CONFIG_CLKMODE(0)| SCT_CONFIG_AUTOLIMIT_L(0)  | SCT_CONFIG_AUTOLIMIT_H(0)  | SCT_CONFIG_INSYNC(1) ; /* SPLIT, Synchronization for input 0 */
        
  //L: no prescaler, HALT; H: prescaler, HALT
  SCT0->CTRL = SCT_CTRL_PRE_L(1-1) | SCT_CTRL_HALT_L(1)|
               SCT_CTRL_PRE_H(SCT_SPEED_PRESC-1) | SCT_CTRL_HALT_H(1);
  SCT0->EVEN = 0;		 //disable all interrupts
  SCT0->EVFLAG = 0xFFFFFFFF;	 //clear all flags
  
  /* MATCH/CAPTURE registers */
  SCT0->REGMODE = SCT_REGMODE_REGMOD_L(0) | SCT_REGMODE_REGMOD_H(0);
  
  //match register setup
  //====================
  //update0...
  SCT0->SCTMATCH[0]    = SCT_SCTMATCH_MATCHn_L(49);
  SCT0->SCTMATCHREL[0] = SCT_SCTMATCH_MATCHn_L(49);
  //update1...
  SCT0->SCTMATCH[1]    = SCT_SCTMATCH_MATCHn_L(99);
  SCT0->SCTMATCHREL[1] = SCT_SCTMATCH_MATCHn_L(99);
  //app_pwm_m_edge0...
  SCT0->SCTMATCH[2] =  SCT_SCTMATCH_MATCHn_L( pwm_xy_deadtime-1 );   /* CONSTANT DEAD TIME!  */
  SCT0->SCTMATCHREL[2] = SCT_SCTMATCH_MATCHn_L( pwm_xy_deadtime-1 ); /* CONSTANT DEAD TIME!  */
  //app_pwm_m_edge1...
  SCT0->SCTMATCH[3] = SCT_SCTMATCH_MATCHn_L(0 );
  SCT0->SCTMATCHREL[3] = SCT_SCTMATCH_MATCHn_L( 0 );
  //app_pwm_m_edge2...
  SCT0->SCTMATCH[4] = SCT_SCTMATCH_MATCHn_L( 0);
  SCT0->SCTMATCHREL[4] = SCT_SCTMATCH_MATCHn_L( 0 );
  //app_pwm_m_edge3...
  SCT0->SCTMATCH[5] = SCT_SCTMATCH_MATCHn_L( 2048-1 );    /*Constant PWM frequency */
  SCT0->SCTMATCHREL[5] = SCT_SCTMATCH_MATCHn_L( 2048-1 ); /*Constatn PWM frequency */
  //app_pwm_m_adc_trigger...
 
  SCT0->SCTMATCH[6] = SCT_SCTMATCH_MATCHn_L( 1000 );
  SCT0->SCTMATCHREL[6] = SCT_SCTMATCH_MATCHn_L( 1000 );
  
//  pwm_xy_deadtime = MATCH_PWM_EDGE0;
//  pwm_x_active = MATCH_PWM_EDGE1 - MATCH_PWM_EDGE0;
//  pwm_x_active = MATCH_PWM_EDGE3 - MATCH_PWM_EDGE2;
//  pwm_xy_update_req = 0;
//  pwm_xy_update_counter = 0;
  
  //event setup
  //===========
  
  //    setup for event: 0
  //   enabled in state: app_pwm_st_active
  //       generated by: HIGH(app_in_hsensors)
  //      state machine: go to state app_pwm_st_transient
  //       misc control: limiting, stop, interrupt
  SCT0->EVENT[0].STATE = 1<<app_pwm_st_idle | 1<<app_pwm_st_active;
  SCT0->EVENT[0].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_IN_HIGH_EVENT(app_in_hsensors) | EVCTR_STATE_SET(app_pwm_st_transient);
  SCT0->LIMIT |= 1<<0;
  SCT0->STOP |= 1<<0;
  SCT0->EVEN |= 1<<0;
  
  //    setup for event: 1
  //   enabled in state: app_pwm_st_transient
  //       generated by: MATCH(app_pwm_m_update0)
  //      state machine: do not change state
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[1].STATE = 1<<app_pwm_st_transient;
  SCT0->EVENT[1].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_update0) | EVCTR_STATE_NO_CHANGE;
  
  //    setup for event: 2
  //   enabled in state: app_pwm_st_transient
  //       generated by: MATCH(app_pwm_m_update1)
  //      state machine: go to state app_pwm_st_active
  //       misc control: limiting
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[2].STATE = 1<<app_pwm_st_transient;
  SCT0->EVENT[2].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_update1) | EVCTR_STATE_SET(app_pwm_st_active);
  SCT0->LIMIT |= 1<<2;
  
  //    setup for event: 3
  //   enabled in state: app_pwm_st_active
  //       generated by: MATCH(app_pwm_m_edge0)
  //      state machine: do not change state
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[3].STATE = 1<<app_pwm_st_active;
  SCT0->EVENT[3].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_edge0) | EVCTR_STATE_NO_CHANGE;
  
  
  //    setup for event: app_pwm_ev_edge1
  //   enabled in state: app_pwm_st_active
  //       generated by: MATCH(app_pwm_m_edge1)
  //      state machine: do not change state
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[4].STATE = 1<<app_pwm_st_active;
  SCT0->EVENT[4].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_edge1) | EVCTR_STATE_NO_CHANGE;
  
  //    setup for event: app_pwm_ev_edge2
  //   enabled in state: app_pwm_st_active
  //       generated by: MATCH(app_pwm_m_edge2)
  //      state machine: do not change state
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[5].STATE = 1<<app_pwm_st_active;
  SCT0->EVENT[5].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_edge2) | EVCTR_STATE_NO_CHANGE;
  
  
  //    setup for event: app_pwm_ev_edge3
  //   enabled in state: app_pwm_st_active
  //       generated by: MATCH(app_pwm_m_edge3)
  //      state machine: do not change state
  //       misc control: limiting
  //     output control: updated from the isr based on the rotor position and direction
  SCT0->EVENT[6].STATE = 1<<app_pwm_st_active;
  SCT0->EVENT[6].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_edge3) | EVCTR_STATE_NO_CHANGE;
  SCT0->LIMIT |= 1<<6;
  
  //    setup for event: app_pwm_ev_adc_trigger
  //   enabled in state: app_pwm_st_active
  //       generated by: MATCH(app_pwm_m_adc_trigger)
  //      state machine: do not change state
  //     output control: toggle app_out_adc_trigger
  SCT0->EVENT[7].STATE = 1<<app_pwm_st_active;
  SCT0->EVENT[7].CTRL = SCT_EVENT_CTRL_HEVENT(0) | EVCTR_MATCH_EVENT(app_pwm_m_adc_trigger) | EVCTR_STATE_NO_CHANGE;
  SCT0->OUT[app_out_adc_trigger].SET |= 1<<7;
  SCT0->OUT[app_out_adc_trigger].CLR |= 1<<7;
  
  //make sure no PWM output activity is selected at this point
  SCT0->OUT[app_out_pwm1].CLR = 0;
  SCT0->OUT[app_out_pwm1].SET = 0;
  SCT0->OUT[app_out_pwm2].CLR = 0;
  SCT0->OUT[app_out_pwm2].SET = 0;
  SCT0->OUT[app_out_pwm3].CLR = 0;
  SCT0->OUT[app_out_pwm3].SET = 0;
  SCT0->OUT[app_out_pwm4].CLR = 0;
  SCT0->OUT[app_out_pwm4].SET = 0;
  SCT0->OUT[app_out_pwm5].CLR = 0;
  SCT0->OUT[app_out_pwm5].SET = 0;
  SCT0->OUT[app_out_pwm6].CLR = 0;
  SCT0->OUT[app_out_pwm6].SET = 0;
  
  SCT0->STATE = app_pwm_st_idle;
  SCT0->COUNT = 0xF00D;
  SCT0->EVFLAG = 0xFF;
  
  invalidate_period_estimate();
  
  //what to do when having SET/CLR at the same time
  SCT0->RES = 3<<(app_out_adc_trigger<<1);

  /* Enable at the NVIC */
  NVIC_SetPriority(SCT0_IRQn, 1);
  NVIC_EnableIRQ(SCT0_IRQn);
}

/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: SCT_FSM_STOP
*
* @brief   The function is used to stop SCT function.
*        
* @param  none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SCT_STOP (void)
{
  SCT0->CTRL |=  SCT_CTRL_HALT_H(1) | SCT_CTRL_HALT_L(1); /*Halt both  part of SCT */  
  SCT0->OUTPUT = 0x0;
  
  //invalidate_period_estimate();
}

/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: GET_MPOS
*
* @brief   The function gets the motor position, reading the hall-sensors. 
*          The function returns the motor position.
*        
* @param  none
*
* @return s_MotorPosition
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
unsigned char GET_MPOS(void) 
{
  unsigned char s_MotorPosition;  
  unsigned int s_i;
  
  for(s_i=0; s_i<10; s_i++){};
  s_MotorPosition = 0;
  
  uint32_t pha;
  uint32_t phb;
  uint32_t phc;
  
  pha = ((GPIO->PIN[0] & (1 << M_PHA)) >> M_PHA) << 2;
  phb = ((GPIO->PIN[0] & (1 << M_PHB)) >> M_PHB) << 1;
  phc = ((GPIO->PIN[0] & (1 << M_PHC)) >> M_PHC) << 0;
  s_MotorPosition = pha | phb | phc;
  
  return s_MotorPosition;
}

//                                                1  2  3  4  5  6
const unsigned long out_pwm1_6_2_sct_out[7] = {0, 0, 1, 2, 3, 5, 6};
/*****************************************************************************
+FUNCTION----------------------------------------------------------------
* @function name: update_sct_out
*
* @brief   The function is used to configure the SCT PWM output while motor commutate between six state .
*        
* @param  index
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
// This is a redesigned routine based on the corect cw/ccw sequence !!!
void update_sct_out(unsigned long pwm_control)
{
  unsigned long pwm_out_t, pwm_out_b, pwm_out_h, pwm_out_l2, pwm_out_l1, pwm_out_l0;
  
  pwm_out_t  = out_pwm1_6_2_sct_out[(pwm_control>>28) & 0x0F];
  pwm_out_b  = out_pwm1_6_2_sct_out[(pwm_control>>24) & 0x0F];
  pwm_out_h  = out_pwm1_6_2_sct_out[(pwm_control>>12) & 0x0F];
  pwm_out_l2 = out_pwm1_6_2_sct_out[(pwm_control>>8 ) & 0x0F];
  pwm_out_l1 = out_pwm1_6_2_sct_out[(pwm_control>>4 ) & 0x0F];
  pwm_out_l0 = out_pwm1_6_2_sct_out[(pwm_control>>0 ) & 0x0F];
	
  //update pwm out control based on the routine call specification
  //==============================================================
  SCT0->OUT[pwm_out_t].SET = 1<<app_pwm_ev_edge0;
  SCT0->OUT[pwm_out_t].CLR = 1<<app_pwm_ev_edge1 | 1<<app_pwm_ev_update0;
	
  SCT0->OUT[pwm_out_b].SET = 1<<app_pwm_ev_edge2;
  SCT0->OUT[pwm_out_b].CLR = 1<<app_pwm_ev_edge3 | 1<<app_pwm_ev_update0;
	
  SCT0->OUT[pwm_out_h].SET = 1<<app_pwm_ev_update1;
  SCT0->OUT[pwm_out_h].CLR = 0;
	
  SCT0->OUT[pwm_out_l2].SET = 0;
  SCT0->OUT[pwm_out_l2].CLR = 1<<app_pwm_ev_update0;

  SCT0->OUT[pwm_out_l1].SET = 0;
  SCT0->OUT[pwm_out_l1].CLR = 1<<app_pwm_ev_update0;

  SCT0->OUT[pwm_out_l0].SET = 0;
  SCT0->OUT[pwm_out_l0].CLR = 1<<app_pwm_ev_update0;
	
  return;
}

void invalidate_period_estimate(void)
{
  step_buffer_direction = 2;
  hall_edges_delta_valid = 0;

  return;
}

/* EOF. */
