Servo/Motor/PWM: Avoid runtime memory alloc.

This commit is contained in:
Phil Howard 2023-03-13 14:44:42 +00:00
parent a45eeb1623
commit af2b74d65d
8 changed files with 22 additions and 41 deletions

View File

@ -29,8 +29,6 @@ namespace motor {
}
MotorCluster::~MotorCluster() {
delete[] states;
delete[] configs;
}
bool MotorCluster::init() {
@ -713,10 +711,8 @@ namespace motor {
float deadzone, DecayMode mode, bool auto_phase) {
uint8_t motor_count = pwms.get_chan_pair_count();
if(motor_count > 0) {
states = new MotorState[motor_count];
configs = new motor_config[motor_count];
for(uint motor = 0; motor < motor_count; motor++) {
configs[motor] = motor_config();
states[motor] = MotorState(direction, speed_scale, zeropoint, deadzone);
configs[motor].phase = (auto_phase) ? (float)motor / (float)motor_count : 0.0f;
configs[motor].mode = mode;

View File

@ -22,12 +22,15 @@ namespace motor {
//--------------------------------------------------
// Variables
//--------------------------------------------------
public:
static const uint MAX_MOTOR_CHANNELS = 16;
private:
PWMCluster pwms;
uint32_t pwm_period;
float pwm_frequency;
MotorState* states;
motor_config* configs;
MotorState states[MAX_MOTOR_CHANNELS];
motor_config configs[MAX_MOTOR_CHANNELS];
//--------------------------------------------------

View File

@ -27,7 +27,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, uint pin_mask, bool loading_zone)
, sm(sm)
, pin_mask(pin_mask & ((1u << NUM_BANK0_GPIOS) - 1))
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -48,7 +47,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, uint pin_base, uint pin_count, bool loa
, sm(sm)
, pin_mask(0x00000000)
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -68,7 +66,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, const uint8_t *pins, uint32_t length, b
, sm(sm)
, pin_mask(0x00000000)
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -90,7 +87,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<uint8_t> pins, bo
, sm(sm)
, pin_mask(0x00000000)
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -111,7 +107,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, const pin_pair *pin_pairs, uint32_t len
, sm(sm)
, pin_mask(0x00000000)
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -137,7 +132,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<pin_pair> pin_pai
, sm(sm)
, pin_mask(0x00000000)
, channel_count(0)
, channels(nullptr)
, wrap_level(0)
, loading_zone(loading_zone) {
@ -159,8 +153,8 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<pin_pair> pin_pai
void PWMCluster::constructor_common() {
// Initialise all the channels this PWM will control
if(channel_count > 0) {
channels = new ChannelState[channel_count];
for(uint i = 0; i < channel_count; i++) {
channels[i] = ChannelState();
}
// Set up the transition buffers
@ -216,8 +210,6 @@ PWMCluster::~PWMCluster() {
gpio_set_function(channel_to_pin_map[channel], GPIO_FUNC_NULL);
}
}
delete[] channels;
}
void PWMCluster::dma_interrupt_handler() {

View File

@ -24,6 +24,7 @@ namespace pimoroni {
public:
static const uint BUFFER_SIZE = 64; // Set to 64, the maximum number of single rises and falls for 32 channels within a looping time period
static const uint NUM_BUFFERS = 3;
static const uint MAX_PWM_CHANNELS = 32;
//--------------------------------------------------
@ -104,7 +105,7 @@ namespace pimoroni {
int dma_channel;
uint pin_mask;
uint8_t channel_count;
ChannelState* channels;
ChannelState channels[NUM_BANK0_GPIOS];
uint8_t channel_to_pin_map[NUM_BANK0_GPIOS];
uint wrap_level;

View File

@ -10,7 +10,7 @@ namespace servo {
}
Calibration::Calibration()
: calibration(nullptr), calibration_size(0), limit_lower(true), limit_upper(true) {
: calibration_size(0), limit_lower(true), limit_upper(true) {
}
Calibration::Calibration(CalibrationType default_type)
@ -19,7 +19,7 @@ namespace servo {
}
Calibration::Calibration(const Calibration &other)
: calibration(nullptr), calibration_size(0), limit_lower(other.limit_lower), limit_upper(other.limit_upper) {
: calibration_size(0), limit_lower(other.limit_lower), limit_upper(other.limit_upper) {
uint size = other.size();
apply_blank_pairs(size);
for(uint i = 0; i < size; i++) {
@ -28,10 +28,6 @@ namespace servo {
}
Calibration::~Calibration() {
if(calibration != nullptr) {
delete[] calibration;
calibration = nullptr;
}
}
Calibration &Calibration::operator=(const Calibration &other) {
@ -57,16 +53,13 @@ namespace servo {
}
void Calibration::apply_blank_pairs(uint size) {
if(calibration != nullptr) {
delete[] calibration;
}
if(size > 0) {
calibration = new Pair[size];
for(auto i = 0u; i < size; i++) {
calibration[i] = Pair();
}
calibration_size = size;
}
else {
calibration = nullptr;
calibration_size = 0;
}
}

View File

@ -19,6 +19,8 @@ namespace servo {
static constexpr float DEFAULT_MID_PULSE = 1500.0f; // in microseconds
static constexpr float DEFAULT_MAX_PULSE = 2500.0f; // in microseconds
static const uint MAX_CALIBRATION_PAIRS = 32;
private:
static constexpr float LOWER_HARD_LIMIT = 400.0f; // The minimum microsecond pulse to send
static constexpr float UPPER_HARD_LIMIT = 2600.0f; // The maximum microsecond pulse to send
@ -110,7 +112,7 @@ namespace servo {
// Variables
//--------------------------------------------------
private:
Pair* calibration;
Pair calibration[MAX_CALIBRATION_PAIRS];
uint calibration_size;
bool limit_lower;
bool limit_upper;

View File

@ -44,8 +44,6 @@ namespace servo {
}
ServoCluster::~ServoCluster() {
delete[] states;
delete[] servo_phases;
}
bool ServoCluster::init() {
@ -502,9 +500,6 @@ namespace servo {
void ServoCluster::create_servo_states(CalibrationType default_type, bool auto_phase) {
uint8_t servo_count = pwms.get_chan_count();
if(servo_count > 0) {
states = new ServoState[servo_count];
servo_phases = new float[servo_count];
for(uint servo = 0; servo < servo_count; servo++) {
states[servo] = ServoState(default_type);
servo_phases[servo] = (auto_phase) ? (float)servo / (float)servo_count : 0.0f;
@ -515,9 +510,6 @@ namespace servo {
void ServoCluster::create_servo_states(const Calibration& calibration, bool auto_phase) {
uint8_t servo_count = pwms.get_chan_count();
if(servo_count > 0) {
states = new ServoState[servo_count];
servo_phases = new float[servo_count];
for(uint servo = 0; servo < servo_count; servo++) {
states[servo] = ServoState(calibration);
servo_phases[servo] = (auto_phase) ? (float)servo / (float)servo_count : 0.0f;

View File

@ -12,12 +12,14 @@ namespace servo {
//--------------------------------------------------
// Variables
//--------------------------------------------------
public:
static const uint MAX_SERVO_CHANNELS = 32;
private:
PWMCluster pwms;
uint32_t pwm_period;
float pwm_frequency;
ServoState* states;
float* servo_phases;
ServoState states[MAX_SERVO_CHANNELS];
float servo_phases[MAX_SERVO_CHANNELS];
//--------------------------------------------------