static void reset_hsync_timers() { // Stop both timers TIM_Cmd(dev_cfg->pixel_timer.timer, DISABLE); uint32_t tim_id; const struct pios_tim_channel *channels = &dev_cfg->hsync_capture; // BUG: This is nuts this line is needed. It simply results in allocating // all the memory but somehow leaving it out breaks the timer functionality. // I do not see how these can be related if (failcount == 0) { if (PIOS_TIM_InitChannels(&tim_id, channels, 1, &px_callback, 0) < 0) { failcount++; } } dev_cfg->pixel_timer.timer->CNT = 0xFFFF - 100; // dc; // Listen to Channel1 (HSYNC) switch (dev_cfg->hsync_capture.timer_chan) { case TIM_Channel_1: TIM_SelectInputTrigger(dev_cfg->pixel_timer.timer, TIM_TS_TI1FP1); break; case TIM_Channel_2: TIM_SelectInputTrigger(dev_cfg->pixel_timer.timer, TIM_TS_TI2FP2); break; default: PIOS_Assert(0); } TIM_SelectSlaveMode(dev_cfg->pixel_timer.timer, TIM_SlaveMode_Trigger); }
/** * Initialise Servos */ int32_t PIOS_Brushless_Init(const struct pios_brushless_cfg * cfg) { uintptr_t tim_id; if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, NULL, 0)) { return -1; } /* Store away the requested configuration */ brushless_cfg = cfg; /* Configure the channels to be in output compare mode */ for (uint8_t i = 0; i < cfg->num_channels; i++) { const struct pios_tim_channel * chan = &cfg->channels[i]; /* Set up for output compare function */ switch(chan->timer_chan) { case TIM_Channel_1: TIM_OC1Init(chan->timer, (TIM_OCInitTypeDef*)&cfg->tim_oc_init); TIM_OC1PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_2: TIM_OC2Init(chan->timer, (TIM_OCInitTypeDef*)&cfg->tim_oc_init); TIM_OC2PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_3: TIM_OC3Init(chan->timer, (TIM_OCInitTypeDef*)&cfg->tim_oc_init); TIM_OC3PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; case TIM_Channel_4: TIM_OC4Init(chan->timer, (TIM_OCInitTypeDef*)&cfg->tim_oc_init); TIM_OC4PreloadConfig(chan->timer, TIM_OCPreload_Enable); break; } TIM_ARRPreloadConfig(chan->timer, ENABLE); TIM_CtrlPWMOutputs(chan->timer, ENABLE); TIM_Cmd(chan->timer, ENABLE); } for (uint8_t i = 0 ; i < NUM_BGC_CHANNELS; i++) { // Enable the available enable lines if (cfg->enables[i].gpio) { GPIO_Init(cfg->enables[i].gpio, (GPIO_InitTypeDef *) &cfg->enables[i].init); GPIO_SetBits(cfg->enables[i].gpio, cfg->enables[i].init.GPIO_Pin); } } // Start main task taskHandle = PIOS_Thread_Create( PIOS_BRUSHLESS_Task, "pios_brushless", STACK_SIZE_BYTES, NULL, TASK_PRIORITY); return 0; }
static void configure_hsync_timers() { // Stop both timers TIM_Cmd(dev_cfg->pixel_timer.timer, DISABLE); // This is overkill but used for consistency. No interrupts used for pixel clock // but this function calls the GPIO_Remap uint32_t tim_id; const struct pios_tim_channel *channels; // Init the channel to output the pixel clock channels = &dev_cfg->pixel_timer; PIOS_TIM_InitChannels(&tim_id, channels, 1, &px_callback, 0); // Init the channel to capture the pulse channels = &dev_cfg->hsync_capture; PIOS_TIM_InitChannels(&tim_id, channels, 1, &px_callback, 0); // Configure the input capture channel TIM_ICInitTypeDef TIM_ICInitStructure; switch (dev_cfg->hsync_capture.timer_chan) { case TIM_Channel_1: TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; break; case TIM_Channel_2: TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; break; default: PIOS_Assert(0); } TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(dev_cfg->pixel_timer.timer, &TIM_ICInitStructure); // Set up the channel to output the pixel clock switch (dev_cfg->pixel_timer.timer_chan) { case TIM_Channel_1: TIM_OC1Init(dev_cfg->pixel_timer.timer, &dev_cfg->tim_oc_init); TIM_OC1PreloadConfig(dev_cfg->pixel_timer.timer, TIM_OCPreload_Enable); TIM_SetCompare1(dev_cfg->pixel_timer.timer, dc); break; case TIM_Channel_2: TIM_OC2Init(dev_cfg->pixel_timer.timer, &dev_cfg->tim_oc_init); TIM_OC2PreloadConfig(dev_cfg->pixel_timer.timer, TIM_OCPreload_Enable); TIM_SetCompare2(dev_cfg->pixel_timer.timer, dc); break; case TIM_Channel_3: TIM_OC3Init(dev_cfg->pixel_timer.timer, &dev_cfg->tim_oc_init); TIM_OC3PreloadConfig(dev_cfg->pixel_timer.timer, TIM_OCPreload_Enable); TIM_SetCompare3(dev_cfg->pixel_timer.timer, dc); break; case TIM_Channel_4: TIM_OC4Init(dev_cfg->pixel_timer.timer, &dev_cfg->tim_oc_init); TIM_OC4PreloadConfig(dev_cfg->pixel_timer.timer, TIM_OCPreload_Enable); TIM_SetCompare4(dev_cfg->pixel_timer.timer, dc); break; } TIM_ARRPreloadConfig(dev_cfg->pixel_timer.timer, ENABLE); TIM_CtrlPWMOutputs(dev_cfg->pixel_timer.timer, ENABLE); // This shouldn't be needed as it should come from the config struture. Something // is clobbering that TIM_PrescalerConfig(dev_cfg->pixel_timer.timer, 0, TIM_PSCReloadMode_Immediate); TIM_SetAutoreload(dev_cfg->pixel_timer.timer, period); }
extern int32_t PIOS_PPM_Init(uint32_t * ppm_id, const struct pios_ppm_cfg * cfg) { PIOS_DEBUG_Assert(ppm_id); PIOS_DEBUG_Assert(cfg); struct pios_ppm_dev * ppm_dev; ppm_dev = (struct pios_ppm_dev *) PIOS_PPM_alloc(); if (!ppm_dev) goto out_fail; /* Bind the configuration to the device instance */ ppm_dev->cfg = cfg; /* Set up the state variables */ ppm_dev->PulseIndex = 0; ppm_dev->PreviousTime = 0; ppm_dev->CurrentTime = 0; ppm_dev->DeltaTime = 0; ppm_dev->LargeCounter = 0; ppm_dev->NumChannels = -1; ppm_dev->NumChannelsPrevFrame = -1; ppm_dev->NumChannelCounter = 0; ppm_dev->Tracking = FALSE; ppm_dev->Fresh = FALSE; for (uint8_t i = 0; i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) { /* Flush counter variables */ ppm_dev->CaptureValue[i] = 0; ppm_dev->CaptureValueNewFrame[i] = 0; } uint32_t tim_id; if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, &tim_callbacks, (uint32_t)ppm_dev)) { return -1; } /* Configure the channels to be in capture/compare mode */ for (uint8_t i = 0; i < cfg->num_channels; i++) { const struct pios_tim_channel * chan = &cfg->channels[i]; /* Configure timer for input capture */ TIM_ICInitTypeDef TIM_ICInitStructure = cfg->tim_ic_init; TIM_ICInitStructure.TIM_Channel = chan->timer_chan; TIM_ICInit(chan->timer, &TIM_ICInitStructure); /* Enable the Capture Compare Interrupt Request */ switch (chan->timer_chan) { case TIM_Channel_1: TIM_ITConfig(chan->timer, TIM_IT_CC1 | TIM_IT_Update, ENABLE); break; case TIM_Channel_2: TIM_ITConfig(chan->timer, TIM_IT_CC2 | TIM_IT_Update, ENABLE); break; case TIM_Channel_3: TIM_ITConfig(chan->timer, TIM_IT_CC3 | TIM_IT_Update, ENABLE); break; case TIM_Channel_4: TIM_ITConfig(chan->timer, TIM_IT_CC4 | TIM_IT_Update, ENABLE); break; } } /* Setup local variable which stays in this scope */ /* Doing this here and using a local variable saves doing it in the ISR */ TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; if (!PIOS_RTC_RegisterTickCallback(PIOS_PPM_Supervisor, (uint32_t)ppm_dev)) { PIOS_DEBUG_Assert(0); } *ppm_id = (uint32_t)ppm_dev; return(0); out_fail: return(-1); }
/** * Initialises all the pins */ int32_t PIOS_PWM_Init(uint32_t * pwm_id, const struct pios_pwm_cfg * cfg) { PIOS_DEBUG_Assert(pwm_id); PIOS_DEBUG_Assert(cfg); struct pios_pwm_dev * pwm_dev; pwm_dev = (struct pios_pwm_dev *) PIOS_PWM_alloc(); if (!pwm_dev) goto out_fail; /* Bind the configuration to the device instance */ pwm_dev->cfg = cfg; for (uint8_t i = 0; i < PIOS_PWM_NUM_INPUTS; i++) { /* Flush counter variables */ pwm_dev->CaptureState[i] = 0; pwm_dev->RiseValue[i] = 0; pwm_dev->FallValue[i] = 0; pwm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT; } uint32_t tim_id; if (PIOS_TIM_InitChannels(&tim_id, cfg->channels, cfg->num_channels, &tim_callbacks, (uint32_t)pwm_dev)) { return -1; } /* Configure the channels to be in capture/compare mode */ for (uint8_t i = 0; i < cfg->num_channels; i++) { const struct pios_tim_channel * chan = &cfg->channels[i]; /* Configure timer for input capture */ TIM_ICInitTypeDef TIM_ICInitStructure = cfg->tim_ic_init; TIM_ICInitStructure.TIM_Channel = chan->timer_chan; TIM_ICInit(chan->timer, &TIM_ICInitStructure); /* Enable the Capture Compare Interrupt Request */ switch (chan->timer_chan) { case TIM_Channel_1: TIM_ITConfig(chan->timer, TIM_IT_CC1, ENABLE); break; case TIM_Channel_2: TIM_ITConfig(chan->timer, TIM_IT_CC2, ENABLE); break; case TIM_Channel_3: TIM_ITConfig(chan->timer, TIM_IT_CC3, ENABLE); break; case TIM_Channel_4: TIM_ITConfig(chan->timer, TIM_IT_CC4, ENABLE); break; } // Need the update event for that timer to detect timeouts TIM_ITConfig(chan->timer, TIM_IT_Update, ENABLE); } *pwm_id = (uint32_t) pwm_dev; return (0); out_fail: return (-1); }