uint8_t OneTinyPpmGen::begin(uint8_t PpmModu, uint8_t ChNb, uint16_t PpmPeriod_us /*= DEFAULT_PPM_PERIOD*/)
{
  boolean Ok = false;
  uint8_t Ch;

  _ChMaxNb = (ChNb > CHANNEL_MAX_NB)?CHANNEL_MAX_NB:ChNb; /* Max is 12 Channels */
  _Next    = (OneChSt_t *)malloc(sizeof(OneChSt_t) * (_ChMaxNb + 1)); /* + 1 for Synchro Channel */
  Ok = (_Next != NULL);
  if (Ok)
  {
    _Idx = _ChMaxNb; /* To reload values at startup */
    _PpmPeriod_us = PpmPeriod_us;
    if(_PpmPeriod_us < PPM_FRAME_MIN_PERIOD_US)                                  _PpmPeriod_us = PPM_FRAME_MIN_PERIOD_US;
    if(_PpmPeriod_us < ((_ChMaxNb * (uint16_t)CHANNEL_MAX_US) + SYNCHRO_MIN_US)) _PpmPeriod_us = (_ChMaxNb * (uint16_t)CHANNEL_MAX_US) + SYNCHRO_MIN_US;
    if(_PpmPeriod_us > PPM_FRAME_MAX_PERIOD_US)                                  _PpmPeriod_us = PPM_FRAME_MAX_PERIOD_US;
    for(Ch = 1; Ch <= _ChMaxNb; Ch++) /* Init all the channels to Neutral */
    {
      setChWidth_us(Ch, PPM_NEUTRAL_US);
    }
#if 1
#warning TO DO: fix issue with positive modulation ! (bad signal randomly generated)
    /* Set Pin as Output according to the PPM modulation level */
    PPM_OC_DDR |= PPM_OC_PIN_MSK; /* Set pin as output */
    if(PpmModu == TINY_PPM_GEN_NEG_MOD)
    {
      PPM_OC_PIN |= PPM_OC_PIN_MSK; /* Set pin to high */
    }
    else
    {
      PPM_OC_PIN &= ~PPM_OC_PIN_MSK; /* Set pin to low */
    }
    TIM_MODE_NORMAL();
    if(PpmModu == TINY_PPM_GEN_POS_MOD)
    {
      PPM_OC_FORCE(); /* Force Output Compare to initialize properly the output */
    }
    else delay(1);
#else
    //test
    PPM_OC_DDR |= PPM_OC_PIN_MSK; /* Set pin as output */
    TIM_MODE_NORMAL();
    INIT_PPM_PIN(PpmModu);
#endif
    TOGGLE_PPM_PIN_ENABLE();
    PPM_OC_INT_ENABLE();
  }
  return(Ok);
}
void OneTinyPpmGen::setChWidth_us(uint8_t Ch, uint16_t Width_us)
{
    uint16_t ChTickNb, SumTick = 0, SynchTick;
    uint8_t  Ch_Next_Ovf, Ch_Next_Rem, Ch0_Next_Ovf, Ch0_Next_Rem;

    if((Ch >= 1) && (Ch <= _ChMaxNb))
    {
        ChTickNb = PPM_US_TO_TICK(Width_us - PPM_HEADER_US + (MS_TIMER_TICK_DURATION_US / 2)); /* Convert in rounded Timer Ticks */
        Ch_Next_Ovf = (ChTickNb & 0xFF00) >> 8;
        Ch_Next_Rem = (ChTickNb & 0x00FF);
        if(Ch_Next_Rem < PPM_GUARD_TICK)
        {
            Ch_Next_Ovf |= HALF_OVF_MASK;
            Ch_Next_Rem += HALF_OVF_VAL;
        }
        /* Update Synchro Time */
        for(uint8_t Idx = 1; Idx <= _ChMaxNb; Idx++)
        {
            SumTick += PPM_US_TO_TICK(PPM_HEADER_US);
            if(Idx != Ch)
            {
                SumTick += ((_Ch[Idx].Cur.Ovf & FULL_OVF_MASK) << 8) + _Ch[Idx].Next.Rem;
                if(_Ch[Idx].Cur.Ovf & HALF_OVF_MASK) SumTick -= HALF_OVF_VAL;
            }
            else
            {
                SumTick += ((Ch_Next_Ovf & FULL_OVF_MASK) << 8) + Ch_Next_Rem;
                if(Ch_Next_Ovf & HALF_OVF_MASK) SumTick -= HALF_OVF_VAL;
            }
        }
        SynchTick = PPM_US_TO_TICK(_PpmPeriod_us) - SumTick - PPM_US_TO_TICK(PPM_HEADER_US);
        Ch0_Next_Ovf = (SynchTick & 0xFF00) >> 8;
        Ch0_Next_Rem = (SynchTick & 0x00FF);
        if(Ch0_Next_Rem < PPM_GUARD_TICK)
        {
            Ch0_Next_Ovf |= HALF_OVF_MASK;
            Ch0_Next_Rem += HALF_OVF_VAL;
        }
        /* Update requested Channel AND Synchro to keep constant the period (20ms) */
        PPM_OC_INT_DISABLE();
        _Ch[0].Next.Ovf = Ch0_Next_Ovf;
        _Ch[0].Next.Rem = Ch0_Next_Rem;
        _Ch[Ch].Next.Ovf = Ch_Next_Ovf;
        _Ch[Ch].Next.Rem = Ch_Next_Rem;
        PPM_OC_INT_ENABLE();
    }
uint8_t OneTinyPpmGen::begin(uint8_t PpmModu, uint8_t ChNb, uint16_t PpmPeriod_us /*= DEFAULT_PPM_PERIOD*/)
{
    boolean Ok = false;
    uint8_t Ch;

    _ChMaxNb = (ChNb > 8)?8:ChNb; /* Max is 8 Channels */
    _Ch = (ChSt_t *)malloc(sizeof(ChSt_t) * (_ChMaxNb + 1)); /* + 1 for Synchro Channel */
    Ok = (_Ch != NULL);
    if (Ok)
    {
        _Idx = _ChMaxNb; /* To reload values at startup */
        _PpmPeriod_us = PpmPeriod_us;
        if(_PpmPeriod_us < PPM_FRAME_MIN_PERIOD_US) _PpmPeriod_us = PPM_FRAME_MIN_PERIOD_US;
        if(_PpmPeriod_us > PPM_FRAME_MAX_PERIOD_US) _PpmPeriod_us = PPM_FRAME_MAX_PERIOD_US;
        for(Ch = 1; Ch <= _ChMaxNb; Ch++)
        {
            setChWidth_us(Ch, PPM_NEUTRAL_US);
        }
        /* Set Pin as Output according to the PPM modulation level */
        PPM_OC_DDR |= PPM_OC_PIN_MSK; /* Set pin as output */
        if(PpmModu == TINY_PPM_GEN_NEG_MOD)
        {
            PPM_OC_PIN |= PPM_OC_PIN_MSK; /* Set pin to high */
        }
        else
        {
            PPM_OC_PIN &= ~PPM_OC_PIN_MSK; /* Set pin to low */
        }
        TIM_MODE_NORMAL();
        if(PpmModu == TINY_PPM_GEN_POS_MOD)
        {
            PPM_OC_FORCE(); /* Force Output Compare to initialize properly the output */
        }
        else delay(1);
        TOGGLE_PPM_PIN_ENABLE();
        PPM_OC_INT_ENABLE();
    }
    return(Ok);
}