2022-02-16 22:06:07 +00:00
|
|
|
#include "servo_cluster.hpp"
|
2022-02-20 15:12:02 +00:00
|
|
|
#include "pwm.hpp"
|
|
|
|
#include <cstdio>
|
2022-02-16 22:06:07 +00:00
|
|
|
|
|
|
|
namespace servo {
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, uint pin_mask, CalibrationType default_type, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pin_mask), pwm_frequency(freq) {
|
2022-03-07 22:27:43 +00:00
|
|
|
create_servo_states(default_type, auto_phase);
|
2022-02-21 00:04:36 +00:00
|
|
|
}
|
2022-02-20 15:12:02 +00:00
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, uint pin_base, uint pin_count, CalibrationType default_type, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pin_base, pin_count), pwm_frequency(freq) {
|
2022-03-08 14:26:57 +00:00
|
|
|
create_servo_states(default_type, auto_phase);
|
|
|
|
}
|
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, const uint8_t *pins, uint32_t length, CalibrationType default_type, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pins, length), pwm_frequency(freq) {
|
2022-03-07 22:27:43 +00:00
|
|
|
create_servo_states(default_type, auto_phase);
|
2022-02-21 00:04:36 +00:00
|
|
|
}
|
2022-02-20 15:12:02 +00:00
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, std::initializer_list<uint8_t> pins, CalibrationType default_type, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pins), pwm_frequency(freq) {
|
2022-03-07 22:27:43 +00:00
|
|
|
create_servo_states(default_type, auto_phase);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, uint pin_mask, const Calibration& calibration, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pin_mask), pwm_frequency(freq) {
|
2022-03-21 23:51:15 +00:00
|
|
|
create_servo_states(calibration, auto_phase);
|
|
|
|
}
|
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, uint pin_base, uint pin_count, const Calibration& calibration, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pin_base, pin_count), pwm_frequency(freq) {
|
2022-03-21 23:51:15 +00:00
|
|
|
create_servo_states(calibration, auto_phase);
|
|
|
|
}
|
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, const uint8_t *pins, uint32_t length, const Calibration& calibration, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pins, length), pwm_frequency(freq) {
|
2022-03-21 23:51:15 +00:00
|
|
|
create_servo_states(calibration, auto_phase);
|
|
|
|
}
|
|
|
|
|
2022-05-20 15:45:25 +01:00
|
|
|
ServoCluster::ServoCluster(PIO pio, uint sm, std::initializer_list<uint8_t> pins, const Calibration& calibration, float freq, bool auto_phase)
|
|
|
|
: pwms(pio, sm, pins), pwm_frequency(freq) {
|
2022-03-21 23:51:15 +00:00
|
|
|
create_servo_states(calibration, auto_phase);
|
|
|
|
}
|
|
|
|
|
2022-02-16 22:06:07 +00:00
|
|
|
ServoCluster::~ServoCluster() {
|
2022-03-10 17:09:06 +00:00
|
|
|
delete[] states;
|
2022-03-07 22:27:43 +00:00
|
|
|
delete[] servo_phases;
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ServoCluster::init() {
|
2022-02-21 00:04:36 +00:00
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
if(pwms.init()) {
|
|
|
|
// Calculate a suitable pwm wrap period for this frequency
|
2022-03-10 06:58:26 +00:00
|
|
|
uint32_t period; uint32_t div256;
|
|
|
|
if(pimoroni::PWMCluster::calculate_pwm_factors(pwm_frequency, period, div256)) {
|
2022-02-21 00:04:36 +00:00
|
|
|
pwm_period = period;
|
|
|
|
|
|
|
|
// Update the pwm before setting the new wrap
|
2022-03-07 22:27:43 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
2022-03-27 14:35:37 +01:00
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
2022-02-21 00:04:36 +00:00
|
|
|
pwms.set_chan_level(servo, 0, false);
|
2022-03-07 16:26:20 +00:00
|
|
|
pwms.set_chan_offset(servo, (uint32_t)(servo_phases[servo] * (float)pwm_period), false);
|
2022-02-21 00:04:36 +00:00
|
|
|
}
|
2022-02-16 22:06:07 +00:00
|
|
|
|
2022-02-21 00:04:36 +00:00
|
|
|
// Set the new wrap (should be 1 less than the period to get full 0 to 100%)
|
2022-03-07 16:26:20 +00:00
|
|
|
pwms.set_wrap(pwm_period, true); // NOTE Minus 1 not needed here. Maybe should change Wrap behaviour so it is needed, for consistency with hardware pwm?
|
2022-02-16 22:06:07 +00:00
|
|
|
|
2022-02-21 00:04:36 +00:00
|
|
|
// Apply the new divider
|
|
|
|
// This is done after loading new PWM values to avoid a lockup condition
|
2022-03-10 06:58:26 +00:00
|
|
|
uint8_t div = div256 >> 8;
|
|
|
|
uint8_t mod = div256 % 256;
|
2022-02-21 00:04:36 +00:00
|
|
|
pwms.set_clkdiv_int_frac(div, mod);
|
2022-02-16 22:06:07 +00:00
|
|
|
|
2022-02-21 00:04:36 +00:00
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
}
|
2022-02-16 22:06:07 +00:00
|
|
|
|
2022-02-21 00:04:36 +00:00
|
|
|
return success;
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
uint8_t ServoCluster::count() const {
|
2022-03-07 22:27:43 +00:00
|
|
|
return pwms.get_chan_count();
|
2022-02-17 22:38:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
uint8_t ServoCluster::pin(uint8_t servo) const {
|
2022-03-07 22:27:43 +00:00
|
|
|
return pwms.get_chan_pin(servo);
|
2022-03-02 17:36:00 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::enable(uint8_t servo, bool load) {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-30 11:49:47 +01:00
|
|
|
float new_pulse = states[servo].enable_with_return();
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 17:09:06 +00:00
|
|
|
void ServoCluster::enable(const uint8_t *servos, uint8_t length, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
enable(servos[i], false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::enable(std::initializer_list<uint8_t> servos, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
enable(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::enable_all(bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
enable(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::disable(uint8_t servo, bool load) {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-30 11:49:47 +01:00
|
|
|
float new_pulse = states[servo].disable_with_return();
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 17:09:06 +00:00
|
|
|
void ServoCluster::disable(const uint8_t *servos, uint8_t length, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
disable(servos[i], false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::disable(std::initializer_list<uint8_t> servos, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
disable(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::disable_all(bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
disable(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
bool ServoCluster::is_enabled(uint8_t servo) const {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].is_enabled();
|
2022-02-17 17:59:09 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::pulse(uint8_t servo) const {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].get_pulse();
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::pulse(uint8_t servo, float pulse, bool load) {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].set_pulse_with_return(pulse);
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::pulse(const uint8_t *servos, uint8_t length, float pulse, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->pulse(servos[i], pulse, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::pulse(std::initializer_list<uint8_t> servos, float pulse, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
for(auto servo : servos) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->pulse(servo, pulse, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::all_to_pulse(float pulse, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->pulse(servo, pulse, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::value(uint8_t servo) const {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].get_value();
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::value(uint8_t servo, float value, bool load) {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].set_value_with_return(value);
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-20 15:12:02 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::value(const uint8_t *servos, uint8_t length, float value, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->value(servos[i], value, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::value(std::initializer_list<uint8_t> servos, float value, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
for(auto servo : servos) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->value(servo, value, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::all_to_value(float value, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->value(servo, value, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::phase(uint8_t servo) const {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-07 16:26:20 +00:00
|
|
|
return servo_phases[servo];
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::phase(uint8_t servo, float phase, bool load) {
|
2022-03-07 22:27:43 +00:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-07 16:26:20 +00:00
|
|
|
servo_phases[servo] = MIN(MAX(phase, 0.0f), 1.0f);
|
|
|
|
pwms.set_chan_offset(servo, (uint32_t)(servo_phases[servo] * (float)pwms.get_wrap()), load);
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::phase(const uint8_t *servos, uint8_t length, float phase, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->phase(servos[i], phase, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::phase(std::initializer_list<uint8_t> servos, float phase, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
for(auto servo : servos) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->phase(servo, phase, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
void ServoCluster::all_to_phase(float phase, bool load) {
|
2022-03-10 20:34:59 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
2022-03-27 13:53:10 +01:00
|
|
|
this->phase(servo, phase, false);
|
2022-03-10 20:34:59 +00:00
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
float ServoCluster::frequency() const {
|
2022-02-20 15:12:02 +00:00
|
|
|
return pwm_frequency;
|
|
|
|
}
|
|
|
|
|
2022-03-27 13:53:10 +01:00
|
|
|
bool ServoCluster::frequency(float freq) {
|
2022-02-20 15:12:02 +00:00
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
if((freq >= ServoState::MIN_FREQUENCY) && (freq <= ServoState::MAX_FREQUENCY)) {
|
|
|
|
// Calculate a suitable pwm wrap period for this frequency
|
2022-03-10 06:58:26 +00:00
|
|
|
uint32_t period; uint32_t div256;
|
|
|
|
if(pimoroni::PWMCluster::calculate_pwm_factors(freq, period, div256)) {
|
2022-02-20 15:12:02 +00:00
|
|
|
|
|
|
|
pwm_period = period;
|
|
|
|
pwm_frequency = freq;
|
|
|
|
|
|
|
|
// Update the pwm before setting the new wrap
|
2022-03-07 22:27:43 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint servo = 0; servo < servo_count; servo++) {
|
2022-03-10 17:09:06 +00:00
|
|
|
if(states[servo].is_enabled()) {
|
|
|
|
apply_pulse(servo, states[servo].get_pulse(), false);
|
2022-03-10 03:22:01 +00:00
|
|
|
}
|
2022-03-07 22:27:43 +00:00
|
|
|
pwms.set_chan_offset(servo, (uint32_t)(servo_phases[servo] * (float)pwm_period), false);
|
2022-02-20 15:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set the new wrap (should be 1 less than the period to get full 0 to 100%)
|
|
|
|
pwms.set_wrap(pwm_period, true);
|
|
|
|
|
|
|
|
// Apply the new divider
|
2022-03-10 06:58:26 +00:00
|
|
|
uint16_t div = div256 >> 8;
|
|
|
|
uint8_t mod = div256 % 256;
|
2022-02-20 15:12:02 +00:00
|
|
|
pwms.set_clkdiv_int_frac(div, mod);
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
}
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
2022-02-20 15:12:02 +00:00
|
|
|
return success;
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::min_value(uint8_t servo) const {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].get_min_value();
|
2022-02-17 22:38:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::mid_value(uint8_t servo) const {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].get_mid_value();
|
2022-02-17 22:38:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
float ServoCluster::max_value(uint8_t servo) const {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].get_max_value();
|
2022-02-17 22:38:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::to_min(uint8_t servo, bool load) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].to_min_with_return();
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 20:34:59 +00:00
|
|
|
void ServoCluster::to_min(const uint8_t *servos, uint8_t length, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
to_min(servos[i], false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::to_min(std::initializer_list<uint8_t> servos, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
to_min(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::all_to_min(bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
to_min(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::to_mid(uint8_t servo, bool load) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].to_mid_with_return();
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 20:34:59 +00:00
|
|
|
void ServoCluster::to_mid(const uint8_t *servos, uint8_t length, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
to_mid(servos[i], false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::to_mid(std::initializer_list<uint8_t> servos, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
to_mid(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::all_to_mid(bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
to_mid(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::to_max(uint8_t servo, bool load) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].to_max_with_return();
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 20:34:59 +00:00
|
|
|
void ServoCluster::to_max(const uint8_t *servos, uint8_t length, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
to_max(servos[i], false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::to_max(std::initializer_list<uint8_t> servos, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
to_max(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::all_to_max(bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
to_max(servo, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::to_percent(uint8_t servo, float in, float in_min, float in_max, bool load) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].to_percent_with_return(in, in_min, in_max);
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 20:34:59 +00:00
|
|
|
void ServoCluster::to_percent(const uint8_t *servos, uint8_t length, float in, float in_min, float in_max, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
to_percent(servos[i], in, in_min, in_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::to_percent(std::initializer_list<uint8_t> servos, float in, float in_min, float in_max, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
to_percent(servo, in, in_min, in_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::all_to_percent(float in, float in_min, float in_max, bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
to_percent(servo, in, in_min, in_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::to_percent(uint8_t servo, float in, float in_min, float in_max, float value_min, float value_max, bool load) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-27 13:53:10 +01:00
|
|
|
float new_pulse = states[servo].to_percent_with_return(in, in_min, in_max, value_min, value_max);
|
2022-03-02 17:36:00 +00:00
|
|
|
apply_pulse(servo, new_pulse, load);
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
|
|
|
|
2022-03-10 20:34:59 +00:00
|
|
|
void ServoCluster::to_percent(const uint8_t *servos, uint8_t length, float in, float in_min, float in_max, float value_min, float value_max, bool load) {
|
|
|
|
assert(servos != nullptr);
|
|
|
|
for(uint8_t i = 0; i < length; i++) {
|
|
|
|
to_percent(servos[i], in, in_min, in_max, value_min, value_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::to_percent(std::initializer_list<uint8_t> servos, float in, float in_min, float in_max, float value_min, float value_max, bool load) {
|
|
|
|
for(auto servo : servos) {
|
|
|
|
to_percent(servo, in, in_min, in_max, value_min, value_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ServoCluster::all_to_percent(float in, float in_min, float in_max, float value_min, float value_max, bool load) {
|
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
|
|
|
for(uint8_t servo = 0; servo < servo_count; servo++) {
|
|
|
|
to_percent(servo, in, in_min, in_max, value_min, value_max, false);
|
|
|
|
}
|
|
|
|
if(load)
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
Calibration& ServoCluster::calibration(uint8_t servo) {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].calibration();
|
2022-02-16 22:06:07 +00:00
|
|
|
}
|
2022-02-17 22:38:59 +00:00
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
const Calibration& ServoCluster::calibration(uint8_t servo) const {
|
2022-05-18 12:41:39 +01:00
|
|
|
assert(servo < pwms.get_chan_count());
|
2022-03-10 17:09:06 +00:00
|
|
|
return states[servo].calibration();
|
2022-02-17 22:38:59 +00:00
|
|
|
}
|
2022-02-20 15:12:02 +00:00
|
|
|
|
2022-03-08 18:15:59 +00:00
|
|
|
void ServoCluster::load() {
|
|
|
|
pwms.load_pwm();
|
|
|
|
}
|
|
|
|
|
2022-03-27 14:35:37 +01:00
|
|
|
void ServoCluster::apply_pulse(uint8_t servo, float pulse, bool load) {
|
2022-02-20 15:12:02 +00:00
|
|
|
pwms.set_chan_level(servo, ServoState::pulse_to_level(pulse, pwm_period, pwm_frequency), load);
|
|
|
|
}
|
2022-03-07 16:26:20 +00:00
|
|
|
|
2022-03-07 22:27:43 +00:00
|
|
|
void ServoCluster::create_servo_states(CalibrationType default_type, bool auto_phase) {
|
2022-03-07 16:26:20 +00:00
|
|
|
uint8_t servo_count = pwms.get_chan_count();
|
2022-03-07 22:27:43 +00:00
|
|
|
if(servo_count > 0) {
|
2022-03-10 17:09:06 +00:00
|
|
|
states = new ServoState[servo_count];
|
2022-03-07 22:27:43 +00:00
|
|
|
servo_phases = new float[servo_count];
|
|
|
|
|
|
|
|
for(uint servo = 0; servo < servo_count; servo++) {
|
2022-03-10 17:09:06 +00:00
|
|
|
states[servo] = ServoState(default_type);
|
2022-03-07 22:27:43 +00:00
|
|
|
servo_phases[servo] = (auto_phase) ? (float)servo / (float)servo_count : 0.0f;
|
2022-03-07 16:26:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 23:51:15 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-16 22:06:07 +00:00
|
|
|
};
|