35 #if defined(PIOS_INCLUDE_PWM)
38 static int32_t PIOS_PWM_Get(uintptr_t rcvr_id, uint8_t channel);
46 const static uint32_t PWM_SUPERVISOR_TIMEOUT = 100000;
47 const static uint32_t PWM_CAPTURE_MAX = 3000;
49 enum pios_pwm_dev_magic {
50 PIOS_PWM_DEV_MAGIC = 0xab30293c,
53 enum pios_pwm_capture_state {
54 PIOS_PWM_CAPTURE_RISING,
55 PIOS_PWM_CAPTURE_FALLING,
59 enum pios_pwm_dev_magic
magic;
68 static bool PIOS_PWM_validate(
struct pios_pwm_dev * pwm_dev)
70 return (pwm_dev->magic == PIOS_PWM_DEV_MAGIC);
73 static struct pios_pwm_dev * PIOS_PWM_alloc(
void)
75 struct pios_pwm_dev * pwm_dev;
77 pwm_dev = (
struct pios_pwm_dev *)
PIOS_malloc(
sizeof(*pwm_dev));
78 if (!pwm_dev)
return(NULL);
80 memset(pwm_dev, 0,
sizeof(*pwm_dev));
82 pwm_dev->magic = PIOS_PWM_DEV_MAGIC;
86 static void PIOS_PWM_tim_overflow_cb (uintptr_t
id, uintptr_t context, uint8_t channel, uint16_t
count);
87 static void PIOS_PWM_tim_edge_cb (uintptr_t
id, uintptr_t context, uint8_t channel, uint16_t
count);
89 .
overflow = PIOS_PWM_tim_overflow_cb,
90 .edge = PIOS_PWM_tim_edge_cb,
101 struct pios_pwm_dev * pwm_dev;
103 pwm_dev = (
struct pios_pwm_dev *) PIOS_PWM_alloc();
104 if (!pwm_dev)
goto out_fail;
123 TIM_ICInitTypeDef TIM_ICInitStructure = cfg->
tim_ic_init;
124 TIM_ICInitStructure.TIM_Channel = chan->
timer_chan;
125 TIM_ICInit(chan->
timer, &TIM_ICInitStructure);
130 TIM_ITConfig(chan->
timer, TIM_IT_CC1, ENABLE);
133 TIM_ITConfig(chan->
timer, TIM_IT_CC2, ENABLE);
136 TIM_ITConfig(chan->
timer, TIM_IT_CC3, ENABLE);
139 TIM_ITConfig(chan->
timer, TIM_IT_CC4, ENABLE);
144 TIM_ITConfig(chan->
timer, TIM_IT_Update, ENABLE);
148 *pwm_id = (uintptr_t) pwm_dev;
163 static int32_t PIOS_PWM_Get(uintptr_t rcvr_id, uint8_t channel)
165 struct pios_pwm_dev * pwm_dev = (
struct pios_pwm_dev *)rcvr_id;
167 if (!PIOS_PWM_validate(pwm_dev)) {
172 if (channel >= PIOS_PWM_NUM_INPUTS) {
176 return pwm_dev->CaptureValue[channel];
179 static void PIOS_PWM_tim_overflow_cb (uintptr_t tim_id, uintptr_t context, uint8_t channel, uint16_t
count)
181 struct pios_pwm_dev * pwm_dev = (
struct pios_pwm_dev *)context;
183 if (!PIOS_PWM_validate(pwm_dev)) {
188 if (channel >= pwm_dev->cfg->num_channels) {
193 pwm_dev->overflow_count[channel]++;
195 if (pwm_dev->overflow_count[channel] * count >= PWM_SUPERVISOR_TIMEOUT) {
196 pwm_dev->CaptureState[channel] = PIOS_PWM_CAPTURE_RISING;
197 pwm_dev->RiseValue[channel] = 0;
199 pwm_dev->overflow_count[channel] = 0;
203 static void PIOS_PWM_tim_edge_cb (uintptr_t tim_id, uintptr_t context, uint8_t chan_idx, uint16_t count)
206 struct pios_pwm_dev * pwm_dev = (
struct pios_pwm_dev *)context;
208 if (!PIOS_PWM_validate(pwm_dev)) {
213 if (chan_idx >= pwm_dev->cfg->num_channels) {
222 TIM_ICInitTypeDef TIM_ICInitStructure = pwm_dev->cfg->tim_ic_init;
223 if (pwm_dev->CaptureState[chan_idx] == PIOS_PWM_CAPTURE_RISING) {
224 pwm_dev->RiseValue[chan_idx] =
count;
225 pwm_dev->overflow_count[chan_idx] = 0;
228 pwm_dev->CaptureState[chan_idx] = PIOS_PWM_CAPTURE_FALLING;
231 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
232 TIM_ICInitStructure.TIM_Channel = chan->
timer_chan;
233 TIM_ICInit(chan->
timer, &TIM_ICInitStructure);
235 uint16_t fall_value =
count;
237 uint32_t
value = fall_value - pwm_dev->RiseValue[chan_idx];
239 if (pwm_dev->overflow_count[chan_idx] > 1 || fall_value > pwm_dev->RiseValue[chan_idx])
240 value += pwm_dev->overflow_count[chan_idx] * chan->
timer->ARR;
242 if (value <= PWM_CAPTURE_MAX) {
243 pwm_dev->CaptureValue[chan_idx] =
value;
244 pwm_dev->overflow_count[chan_idx] = 0;
248 pwm_dev->CaptureState[chan_idx] = PIOS_PWM_CAPTURE_RISING;
251 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
252 TIM_ICInitStructure.TIM_Channel = chan->
timer_chan;
253 TIM_ICInit(chan->
timer, &TIM_ICInitStructure);
int32_t PIOS_PWM_Init(uintptr_t *pwm_id, const struct pios_pwm_cfg *cfg)
const struct pios_rcvr_driver pios_pwm_rcvr_driver
int32_t(* read)(uintptr_t id, uint8_t channel)
Main PiOS header to include all the compiled in PiOS options.
TIM_ICInitTypeDef tim_ic_init
#define PIOS_DEBUG_Assert(test)
void * PIOS_malloc(size_t size)
void(* overflow)(uintptr_t tim_id, uintptr_t context, uint8_t chan_idx, uint16_t count)
static struct flyingpicmd_cfg_fa cfg
const struct pios_tim_channel * channels
int32_t PIOS_TIM_InitChannels(uintptr_t *tim_id, const struct pios_tim_channel *channels, uint8_t num_channels, const struct pios_tim_callbacks *callbacks, uintptr_t context)
#define PIOS_PWM_NUM_INPUTS