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); }