Add all basic functions, never reset, dynamic pulse changes

This commit is contained in:
Hierophect 2019-10-27 19:17:01 -04:00
parent cb491e855c
commit 0cd8c3d5a8
5 changed files with 99 additions and 33 deletions

View File

@ -31,13 +31,17 @@
#include "common-hal/pulseio/PWMOut.h" #include "common-hal/pulseio/PWMOut.h"
#include "shared-bindings/pulseio/PWMOut.h" #include "shared-bindings/pulseio/PWMOut.h"
#include "supervisor/shared/translate.h" #include "supervisor/shared/translate.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
#include "common-hal/microcontroller/Pin.h"
#define PWM_MAX_FREQ 6000000 #define PWM_MAX_FREQ 6000000
#define ALL_CLOCKS 0xFFFF #define ALL_CLOCKS 0xFFFF
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
STATIC void tim_clock_enable(uint16_t mask); STATIC void tim_clock_enable(uint16_t mask);
STATIC void tim_clock_disable(uint16_t mask); STATIC void tim_clock_disable(uint16_t mask);
@ -62,13 +66,37 @@ static uint32_t timer_get_source_freq(uint32_t tim_id) {
} }
void pwmout_reset(void) { void pwmout_reset(void) {
tim_clock_disable(ALL_CLOCKS); uint16_t never_reset_mask = 0x00;
for(int i=0;i<TIM_BANK_ARRAY_LEN;i++) {
if(!never_reset_tim[i]) {
reserved_tim[i] = 0x00;
tim_frequencies[i] = 0x00;
} else {
never_reset_mask |= 1<<i;
}
}
tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
} }
void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) { void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
for(size_t i = 0 ; i < TIM_BANK_ARRAY_LEN; i++) {
if (mcu_tim_banks[i] == self->handle.Instance) {
never_reset_tim[i] = true;
never_reset_pin_number(self->tim->pin->port, self->tim->pin->number);
break;
}
}
} }
void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) { void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) {
//TODO: doesn't this need an equivalent release pin in microcontroller.c?
//I don't see that implemented in any port.
for(size_t i = 0 ; i < TIM_BANK_ARRAY_LEN; i++) {
if (mcu_tim_banks[i] == self->handle.Instance) {
never_reset_tim[i] = false;
break;
}
}
} }
pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
@ -77,7 +105,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
uint32_t frequency, uint32_t frequency,
bool variable_frequency) { bool variable_frequency) {
if (frequency == 0 || frequency > 6000000) { if (frequency == 0 || frequency > 6000000) {
return PWMOUT_INVALID_FREQUENCY; mp_raise_ValueError(translate("Invalid frequency supplied"));
//return PWMOUT_INVALID_FREQUENCY;
} }
TIM_TypeDef * TIMx; TIM_TypeDef * TIMx;
@ -92,9 +121,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
for(uint i = 0; i < tim_num; i++) { for(uint i = 0; i < tim_num; i++) {
//if pin is same //if pin is same
if(mcu_tim_pin_list[i].pin = pin) { if(mcu_tim_pin_list[i].pin == pin) {
//check if the timer has a channel active //check if the timer has a channel active
if (reserved_tim[mcu_tim_pin_list[i].tim_index] != 0) { if (reserved_tim[mcu_tim_pin_list[i].tim_index-1] != 0) {
//is it the same channel? (or all channels reserved by a var-freq) //is it the same channel? (or all channels reserved by a var-freq)
if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) { if(reserved_tim[mcu_tim_pin_list[i].tim_index-1] & 1<<(mcu_tim_pin_list[i].channel_index-1)) {
tim_chan_taken = true; tim_chan_taken = true;
@ -128,8 +157,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
if (variable_frequency) { if (variable_frequency) {
reserved_tim[self->tim->tim_index-1] = 0x0F; reserved_tim[self->tim->tim_index-1] = 0x0F;
} else { } else {
reserved_tim[self->tim->tim_index-1] |= 1<<self->tim->channel_index-1; reserved_tim[self->tim->tim_index-1] |= 1<<(self->tim->channel_index-1);
} }
tim_frequencies[self->tim->tim_index-1] = frequency;
} else { //no match found } else { //no match found
if (tim_chan_taken) { if (tim_chan_taken) {
mp_raise_ValueError(translate("Timer hardware is reserved")); mp_raise_ValueError(translate("Timer hardware is reserved"));
@ -167,11 +197,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
uint32_t source_freq = timer_get_source_freq(self->tim->tim_index); uint32_t source_freq = timer_get_source_freq(self->tim->tim_index);
uint32_t period = PWM_MAX_FREQ/frequency; uint32_t period = PWM_MAX_FREQ/frequency;
mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock); //TODO: remove before merging.
mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq); // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock);
mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ)); // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq);
mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period); // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ));
mp_printf(&mp_plat_print, "Period: %d\n", (PWM_MAX_FREQ/frequency)); // mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period);
// mp_printf(&mp_plat_print, "Duty: %d\n", duty);
// mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index);
//Timer init //Timer init
self->handle.Instance = TIMx; self->handle.Instance = TIMx;
@ -222,7 +254,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
if(self->variable_frequency) { if(self->variable_frequency) {
reserved_tim[self->tim->tim_index-1] = 0x00; reserved_tim[self->tim->tim_index-1] = 0x00;
} else { } else {
reserved_tim[self->tim->tim_index-1] &= !(1<<self->tim->channel_index); reserved_tim[self->tim->tim_index-1] &= ~(1<<self->tim->channel_index);
HAL_TIM_PWM_Stop(&self->handle, self->channel); HAL_TIM_PWM_Stop(&self->handle, self->channel);
} }
reset_pin_number(self->tim->pin->port,self->tim->pin->number); reset_pin_number(self->tim->pin->port,self->tim->pin->number);
@ -236,15 +268,14 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
} }
void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) {
HAL_TIM_PWM_Stop(&self->handle, self->channel); uint16_t duty = duty_cycle/655;
uint32_t period = PWM_MAX_FREQ/self->frequency;
uint32_t input = (period*duty)/100;
//TODO: remove before merging
//mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input);
__HAL_TIM_SET_COMPARE(&self->handle, self->channel, input);
self->chan_handle.Pulse = ((PWM_MAX_FREQ/self->frequency)*duty_cycle)/100 - 1; self->duty_cycle = duty;
if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) {
mp_raise_ValueError(translate("Channel Re-Init Error"));
}
if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) {
mp_raise_ValueError(translate("Error restarting PWM"));
}
} }
uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
@ -252,10 +283,39 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
} }
void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) {
if (frequency == 0 || frequency > 6000000) {
mp_raise_ValueError(translate("Invalid PWM frequency"));
}
if (frequency == self->frequency) return;
uint32_t source_freq = timer_get_source_freq(self->tim->tim_index);
uint32_t period = PWM_MAX_FREQ/frequency;
//shut down
HAL_TIM_PWM_Stop(&self->handle, self->channel);
tim_clock_disable(1<<(self->tim->tim_index-1));
//Only change altered values
self->handle.Init.Period = period - 1;
self->handle.Init.Prescaler = (source_freq / PWM_MAX_FREQ) - 1; // TIM runs at ~6MHz
//restart everything
if(HAL_TIM_PWM_Init(&self->handle) != HAL_OK) {
mp_raise_ValueError(translate("Timer Re-Init Error"));
}
if(HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) {
mp_raise_ValueError(translate("Channel Re-Init Error"));
}
if(HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) {
mp_raise_ValueError(translate("Error restarting PWM"));
}
tim_frequencies[self->tim->tim_index-1] = frequency;
self->frequency = frequency;
} }
uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
return 0; return self->frequency;
} }
bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {

View File

@ -27,6 +27,11 @@
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H #ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H #define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "stm32f4xx_hal.h"
#include "stm32f4/periph.h"
#include "py/obj.h" #include "py/obj.h"
typedef struct { typedef struct {

View File

@ -148,15 +148,15 @@ const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = {
TIM(11,3,1,&pin_PF07), TIM(11,3,1,&pin_PF07),
TIM(13,9,1,&pin_PF08), TIM(13,9,1,&pin_PF08),
TIM(14,9,1,&pin_PF09), TIM(14,9,1,&pin_PF09),
TIM(12,9,1,&pin_PH06), // TIM(12,9,1,&pin_PH06),
TIM(12,9,2,&pin_PH09), // TIM(12,9,2,&pin_PH09),
TIM(5,2,1,&pin_PH10), // TIM(5,2,1,&pin_PH10),
TIM(5,2,2,&pin_PH11), // TIM(5,2,2,&pin_PH11),
TIM(5,2,3,&pin_PH12), // TIM(5,2,3,&pin_PH12),
TIM(5,2,4,&pin_PI00), // TIM(5,2,4,&pin_PI00),
TIM(8,3,4,&pin_PI02), // TIM(8,3,4,&pin_PI02),
TIM(8,3,1,&pin_PI05), // TIM(8,3,1,&pin_PI05),
TIM(8,3,2,&pin_PI06), // TIM(8,3,2,&pin_PI06),
TIM(8,3,3,&pin_PI07), // TIM(8,3,3,&pin_PI07),
}; };

View File

@ -42,10 +42,9 @@ extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6];
extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6];
#define TIM_BANK_ARRAY_LEN 14 #define TIM_BANK_ARRAY_LEN 14
TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, TIM_TypeDef * mcu_tim_banks[14];
TIM11, TIM12, TIM13, TIM14};
#define TIM_PIN_ARRAY_LEN 66 #define TIM_PIN_ARRAY_LEN 66
const mcu_tim_pin_obj_t mcu_tim_pin_list[66] = { const mcu_tim_pin_obj_t mcu_tim_pin_list[66];
#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H

View File

@ -33,6 +33,7 @@
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
#include "common-hal/busio/I2C.h" #include "common-hal/busio/I2C.h"
#include "common-hal/busio/SPI.h" #include "common-hal/busio/SPI.h"
#include "common-hal/pulseio/PWMOut.h"
#include "stm32f4/clocks.h" #include "stm32f4/clocks.h"
#include "stm32f4/gpio.h" #include "stm32f4/gpio.h"
@ -57,6 +58,7 @@ void reset_port(void) {
reset_all_pins(); reset_all_pins();
i2c_reset(); i2c_reset();
spi_reset(); spi_reset();
pwmout_reset();
} }
void reset_to_bootloader(void) { void reset_to_bootloader(void) {