From 86e5ca98685497ae729996066bdafd5ce87b0ee7 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Thu, 28 Nov 2019 06:53:44 -0800 Subject: [PATCH] Fix and cleanup L1/lpc40xx/Pwm Reduced the amount of redundant code in the driver as well as the tests. Made the tests easier to follow and understand. Removed tests that did actually test anything. The problem with the PWM driver is stated in #963 and has been applied to this patch. Resolves #963 --- library/L1_Peripheral/lpc17xx/pwm.hpp | 53 +++--- library/L1_Peripheral/lpc40xx/pwm.hpp | 168 +++++++++++------- .../L1_Peripheral/lpc40xx/test/pwm_test.cpp | 126 +++++++------ library/L1_Peripheral/pwm.hpp | 6 +- library/L2_HAL/actuators/servo/servo.hpp | 9 +- library/utility/log.hpp | 10 ++ 6 files changed, 206 insertions(+), 166 deletions(-) diff --git a/library/L1_Peripheral/lpc17xx/pwm.hpp b/library/L1_Peripheral/lpc17xx/pwm.hpp index f0bfad4c26..c4e53a269d 100644 --- a/library/L1_Peripheral/lpc17xx/pwm.hpp +++ b/library/L1_Peripheral/lpc17xx/pwm.hpp @@ -20,53 +20,54 @@ struct PwmChannel // NOLINT inline static const Pin kPwmPin3 = Pin::CreatePin<2, 3>(); inline static const Pin kPwmPin4 = Pin::CreatePin<2, 4>(); inline static const Pin kPwmPin5 = Pin::CreatePin<2, 5>(); + public: /// Definition of the PWM 1 peripheral. inline static const lpc40xx::Pwm::Peripheral_t kPwm1Peripheral = { - .registers = reinterpret_cast(LPC_PWM1), - .power_on_id = SystemController::Peripherals::kPwm1, + .registers = reinterpret_cast(LPC_PWM1), + .id = SystemController::Peripherals::kPwm1, }; /// Definition for channel 0 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm0 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin0, - .channel = 1, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin0, + .channel = 1, + .pin_function_code = 0b01, }; /// Definition for channel 1 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm1 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin1, - .channel = 2, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin1, + .channel = 2, + .pin_function_code = 0b01, }; /// Definition for channel 2 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm2 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin2, - .channel = 3, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin2, + .channel = 3, + .pin_function_code = 0b01, }; /// Definition for channel 3 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm3 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin3, - .channel = 4, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin3, + .channel = 4, + .pin_function_code = 0b01, }; /// Definition for channel 4 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm4 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin4, - .channel = 5, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin4, + .channel = 5, + .pin_function_code = 0b01, }; /// Definition for channel 5 of PWM peripheral 1. inline static const lpc40xx::Pwm::Channel_t kPwm5 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin5, - .channel = 6, - .pin_function_id = 0b01, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin5, + .channel = 6, + .pin_function_code = 0b01, }; }; } // namespace lpc17xx diff --git a/library/L1_Peripheral/lpc40xx/pwm.hpp b/library/L1_Peripheral/lpc40xx/pwm.hpp index 9ae153ef43..13d15f6235 100644 --- a/library/L1_Peripheral/lpc40xx/pwm.hpp +++ b/library/L1_Peripheral/lpc40xx/pwm.hpp @@ -82,7 +82,7 @@ class Pwm final : public sjsu::Pwm /// Holds the address to the LPC PWM peripheral. LPC_PWM_TypeDef * registers; /// The power on id for the above LPC PWM peripheral. - sjsu::SystemController::PeripheralID power_on_id; + sjsu::SystemController::PeripheralID id; }; /// Defines all information necessary to control a specific PWM channel. struct Channel_t @@ -94,7 +94,7 @@ class Pwm final : public sjsu::Pwm /// Reference to the PWM channel number. uint8_t channel : 3; /// Contains the pin function id, used to select PWM output for the pin. - uint8_t pin_function_id : 3; + uint8_t pin_function_code : 3; }; /// Structure used as a namespace for predefined Channel definitions struct Channel // NOLINT @@ -116,55 +116,55 @@ class Pwm final : public sjsu::Pwm public: /// Definition of the PWM 0 peripheral. inline static const Peripheral_t kPwm0Peripheral = { - .registers = LPC_PWM0, - .power_on_id = sjsu::lpc40xx::SystemController::Peripherals::kPwm1, + .registers = LPC_PWM0, + .id = sjsu::lpc40xx::SystemController::Peripherals::kPwm1, }; /// Definition of the PWM 1 peripheral. inline static const Peripheral_t kPwm1Peripheral = { - .registers = LPC_PWM1, - .power_on_id = sjsu::lpc40xx::SystemController::Peripherals::kPwm1, + .registers = LPC_PWM1, + .id = sjsu::lpc40xx::SystemController::Peripherals::kPwm1, }; /// Definition for channel 0 of PWM peripheral 1. inline static const Channel_t kPwm0 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin0, - .channel = 1, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin0, + .channel = 1, + .pin_function_code = 0b001, }; /// Definition for channel 1 of PWM peripheral 1. inline static const Channel_t kPwm1 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin1, - .channel = 2, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin1, + .channel = 2, + .pin_function_code = 0b001, }; /// Definition for channel 2 of PWM peripheral 1. inline static const Channel_t kPwm2 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin2, - .channel = 3, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin2, + .channel = 3, + .pin_function_code = 0b001, }; /// Definition for channel 3 of PWM peripheral 1. inline static const Channel_t kPwm3 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin3, - .channel = 4, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin3, + .channel = 4, + .pin_function_code = 0b001, }; /// Definition for channel 4 of PWM peripheral 1. inline static const Channel_t kPwm4 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin4, - .channel = 5, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin4, + .channel = 5, + .pin_function_code = 0b001, }; /// Definition for channel 5 of PWM peripheral 1. inline static const Channel_t kPwm5 = { - .peripheral = kPwm1Peripheral, - .pin = kPwmPin5, - .channel = 6, - .pin_function_id = 0b001, + .peripheral = kPwm1Peripheral, + .pin = kPwmPin5, + .channel = 6, + .pin_function_code = 0b001, }; }; /// Constructor for a LPC40xx PWM channel. @@ -186,41 +186,46 @@ class Pwm final : public sjsu::Pwm SJ2_ASSERT_FATAL(1 <= channel_.channel && channel_.channel <= 6, "Channel must be between 1 and 6 on LPC40xx platforms."); - system_controller_.PowerUpPeripheral(channel_.peripheral.power_on_id); + system_controller_.PowerUpPeripheral(channel_.peripheral.id); + + auto * pwm = channel_.peripheral.registers; // Set prescalar to 1 so the input frequency to the PWM peripheral is equal // to the peripheral clock frequency. // // PR = Prescale register = defines the maximum value for the prescaler - channel_.peripheral.registers->PR = 0; + pwm->PR = 0; + // PC = Prescale counter. Set to 0 to cause the timer counter to increment // after each peripheral clock tick. - channel_.peripheral.registers->PC = 0; + pwm->PC = 0; + // Mode 0x0 means increment time counter (TC) after the peripheral clock // has cycled the amount inside of the prescale. - channel_.peripheral.registers->CTCR = bit::Insert( - channel_.peripheral.registers->CTCR, 0, CountControl::kMode); + pwm->CTCR = bit::Insert(pwm->CTCR, 0, CountControl::kMode); + // 0x0 for this register says to use the TC for input counts. - channel_.peripheral.registers->CTCR = bit::Insert( - channel_.peripheral.registers->CTCR, 0, CountControl::kCountInput); + pwm->CTCR = bit::Insert(pwm->CTCR, 0, CountControl::kCountInput); + // Match register 0 is used to generate the desired frequency. If the time // counter TC is equal to MR0 const units::frequency::hertz_t kPeripheralFrequency = - system_controller_.GetPeripheralFrequency( - channel_.peripheral.power_on_id); - channel_.peripheral.registers->MR0 = - (kPeripheralFrequency / frequency_hz).to(); + system_controller_.GetPeripheralFrequency(channel_.peripheral.id); + + pwm->MR0 = (kPeripheralFrequency / frequency_hz).to(); + // Sets match register 0 to reset when TC and Match 0 match each other, // meaning that the PWM pulse will cycle continuously. - channel_.peripheral.registers->MCR = - bit::Set(channel_.peripheral.registers->MCR, MatchControl::kPwm0Reset); + pwm->MCR = bit::Set(pwm->MCR, MatchControl::kPwm0Reset); + // Enables PWM TC and PC for counting and enables PWM mode EnablePwm(); + // Enables PWM[channel] output - channel_.peripheral.registers->PCR = - bit::Set(channel_.peripheral.registers->PCR, - OutputControl::kEnableOutput.position + channel_.channel); + uint32_t channel_bit_position = + OutputControl::kEnableOutput.position + channel_.channel; + pwm->PCR = bit::Set(pwm->PCR, channel_bit_position); - channel_.pin.SetPinFunction(channel_.pin_function_id); + channel_.pin.SetPinFunction(channel_.pin_function_code); return Status::kSuccess; } @@ -229,30 +234,42 @@ class Pwm final : public sjsu::Pwm { SJ2_ASSERT_FATAL(0.0f <= duty_cycle && duty_cycle <= 1.0f, "duty_cycle of Duty Cycle provided is out of bounds."); - GetMatchRegisters()[channel_.channel] = CalculateDutyCycle(duty_cycle); + *GetMatchRegisters(channel_.channel) = CalculateDutyCycle(duty_cycle); + // LER (Load Enable Register) sets the hardware up to load the new duty + // cycle period in the next reset cycle after MR0 match. Hardware requires + // this as a means ot prevent itself from glitching and changing pwm + // instantaniously. channel_.peripheral.registers->LER |= (1 << channel_.channel); } float GetDutyCycle() const override { - return (static_cast(GetMatchRegisters()[channel_.channel]) / - static_cast(GetMatchRegisters()[0])); + auto period = static_cast(*GetMatchRegisters(channel_.channel)); + auto max_period = static_cast(*GetMatchRegisters(0)); + return period / max_period; } void SetFrequency(units::frequency::hertz_t frequency_hz) const override { - SJ2_ASSERT_FATAL(frequency_hz != 0_Hz, "Pwm Frequency cannot be zero Hz."); - // Disables PWM mode; this will reset all counters to 0 - // And allow us to update MR0 + SJ2_RETURN_IF( + frequency_hz == 0_Hz, + "Cannot set frequency to 0Hz! This call will have no effect!"); + + auto peripheral_frequency = + system_controller_.GetPeripheralFrequency(channel_.peripheral.id); + // Get the current duty cycle so we can match it to the updated frequency. float previous_duty_cycle = GetDutyCycle(); + + // In order to avoid PWM glitches, the PWM must be disabled while updating + // the MR0 register. Doing this will reset all counters to 0 and allow us to + // update MR0. EnablePwm(false); - const units::frequency::hertz_t kPeripheralFrequency = - system_controller_.GetPeripheralFrequency( - channel_.peripheral.power_on_id); - channel_.peripheral.registers->MR0 = - (kPeripheralFrequency / frequency_hz).to(); - SetDutyCycle(previous_duty_cycle); - EnablePwm(); + { + auto new_frequency = (peripheral_frequency / frequency_hz).to(); + *GetMatchRegisters(0) = new_frequency; + SetDutyCycle(previous_duty_cycle); + } + EnablePwm(true); } /// Helper method for converting the match register 0 to a frequency in Hz. @@ -260,18 +277,21 @@ class Pwm final : public sjsu::Pwm /// @return the current frequency of the PWM channel units::frequency::hertz_t GetFrequency() const { - uint32_t match_register0 = GetMatchRegisters()[0]; + uint32_t match_register0 = *GetMatchRegisters(0); units::frequency::hertz_t result = 0_Hz; if (match_register0 != 0) { - const units::frequency::hertz_t kPeripheralFrequency = - system_controller_.GetPeripheralFrequency( - channel_.peripheral.power_on_id); - result = kPeripheralFrequency / match_register0; + auto pwm_frequency = + system_controller_.GetPeripheralFrequency(channel_.peripheral.id); + + result = pwm_frequency / match_register0; } return result; } + + private: /// Helper method for enabling and disabling this PWM channel. + /// /// @param enable - default to true, if set to false, will disable this PWM /// channel. void EnablePwm(bool enable = true) const @@ -294,13 +314,24 @@ class Pwm final : public sjsu::Pwm *pwm_timer = bit::Clear(*pwm_timer, Timer::kPwmEnable); } } + /// Helper method to make getting a pointer to the Match Register 0 more /// readable in the code. /// /// @return a pointer to the match 0 register. - volatile uint32_t * GetMatchRegisters() const + volatile uint32_t * GetMatchRegisters(uint8_t match) const { - return &channel_.peripheral.registers->MR0; + switch (match) + { + case 0: return &channel_.peripheral.registers->MR0; + case 1: return &channel_.peripheral.registers->MR1; + case 2: return &channel_.peripheral.registers->MR2; + case 3: return &channel_.peripheral.registers->MR3; + case 4: return &channel_.peripheral.registers->MR4; + case 5: return &channel_.peripheral.registers->MR5; + case 6: return &channel_.peripheral.registers->MR6; + default: return &channel_.peripheral.registers->MR0; + } } /// Converts a percent value from 0.0f to 1.0f to the closest approximate /// match register value and returns that value. @@ -311,10 +342,9 @@ class Pwm final : public sjsu::Pwm /// supplied duty cycle. uint32_t CalculateDutyCycle(float duty_cycle_percent) const { - float pwm_period = static_cast(GetMatchRegisters()[0]); + float pwm_period = static_cast(*GetMatchRegisters(0)); return static_cast(duty_cycle_percent * pwm_period); } - private: /// Reference to a const channel description for this instance of the PWM /// driver. const Channel_t & channel_; diff --git a/library/L1_Peripheral/lpc40xx/test/pwm_test.cpp b/library/L1_Peripheral/lpc40xx/test/pwm_test.cpp index a4e74765d0..388e2c3167 100644 --- a/library/L1_Peripheral/lpc40xx/test/pwm_test.cpp +++ b/library/L1_Peripheral/lpc40xx/test/pwm_test.cpp @@ -1,3 +1,5 @@ +#include + #include "config.hpp" #include "L0_Platform/lpc40xx/LPC40xx.h" #include "L1_Peripheral/lpc40xx/pin.hpp" @@ -16,12 +18,11 @@ TEST_CASE("Testing lpc40xx PWM instantiation", "[lpc40xx-pwm]") memset(&local_pwm, 0, sizeof(local_pwm)); // Set mock for sjsu::SystemController - constexpr units::frequency::hertz_t kDummySystemControllerClockFrequency = - 12_MHz; + constexpr units::frequency::hertz_t kPeriperhalClockFrequency = 12_MHz; Mock mock_system_controller; Fake(Method(mock_system_controller, PowerUpPeripheral)); When(Method(mock_system_controller, GetSystemFrequency)) - .AlwaysReturn(kDummySystemControllerClockFrequency); + .AlwaysReturn(kPeriperhalClockFrequency); When(Method(mock_system_controller, GetPeripheralClockDivider)) .AlwaysReturn(1); @@ -32,96 +33,93 @@ TEST_CASE("Testing lpc40xx PWM instantiation", "[lpc40xx-pwm]") // Creating mock peripheral configuration Pwm::Peripheral_t mock_peripheral = { - .registers = &local_pwm, - .power_on_id = sjsu::lpc40xx::SystemController::Peripherals::kPwm0, + .registers = &local_pwm, + .id = sjsu::lpc40xx::SystemController::Peripherals::kPwm0, }; // Creating mock channel configuration Pwm::Channel_t mock_channel = { .peripheral = mock_peripheral, .pin = mock_pwm_pin.get(), - .channel = 1, - .pin_function_id = 0b101, + .channel = 5, + .pin_function_code = 0b101, }; Pwm test_pwm(mock_channel, mock_system_controller.get()); SECTION("Initialization values") { - test_pwm.Initialize(1_kHz); + // Setup + constexpr uint32_t kCounterEnable = 0; + constexpr uint8_t kCounterReset = 1; + constexpr uint8_t kPwmEnable = 3; + + // Exercise + test_pwm.Initialize(2_kHz); + + // Verify Verify(Method(mock_system_controller, PowerUpPeripheral) .Matching([](sjsu::SystemController::PeripheralID id) { return sjsu::lpc40xx::SystemController::Peripherals::kPwm0 .device_id == id.device_id; })); - // PWM Count Control Register should be all zeros + // Verify: PWM Count Control Register should be all zeros CHECK(0 == local_pwm.CTCR); - // Check that Match Control Register reset for PWM0 has been set - CHECK(0b1 == bit::Read(local_pwm.MCR, 1)); - // Timer Control Register - constexpr uint32_t kCounterEnable = 0; - constexpr uint8_t kCounterReset = 1; - constexpr uint8_t kPwmEnable = 3; - CHECK(0b1 == bit::Read(local_pwm.TCR, kCounterEnable)); - CHECK(0b0 == bit::Read(local_pwm.TCR, kCounterReset)); - CHECK(0b1 == bit::Read(local_pwm.TCR, kPwmEnable)); - - CHECK(0b1 == bit::Extract(local_pwm.PCR, mock_channel.channel + 8)); - + // Verify: Check that Match Control Register reset for PWM0 has been set + CHECK(1 == bit::Read(local_pwm.MCR, 1)); + // Verify: that the appropriate flags in the timer register have been set + CHECK(1 == bit::Read(local_pwm.TCR, kCounterEnable)); + CHECK(0 == bit::Read(local_pwm.TCR, kCounterReset)); + CHECK(1 == bit::Read(local_pwm.TCR, kPwmEnable)); + // Verify: verify that the pwm control enable has been set + CHECK(1 == bit::Extract(local_pwm.PCR, mock_channel.channel + 8)); Verify(Method(mock_pwm_pin, SetPinFunction) - .Using(mock_channel.pin_function_id)) + .Using(mock_channel.pin_function_code)) .Once(); - - test_pwm.Initialize(5_kHz); - CHECK(5000_Hz == test_pwm.GetFrequency()); + // Verify: that the default frequency was set. + CHECK(2000_Hz == test_pwm.GetFrequency()); } - SECTION("Match Register 0") + SECTION("Set & Get Duty Cycle") { - CHECK(test_pwm.GetMatchRegisters()[0] == local_pwm.MR0); - } - - SECTION("Calculate the Duty Cycle") - { - test_pwm.SetDutyCycle(.27f); - float calculated_duty_cycle_precent = - static_cast(test_pwm.CalculateDutyCycle(.27f)); - float match_register_0 = - static_cast(test_pwm.GetMatchRegisters()[0]); - float error = calculated_duty_cycle_precent - (.27f * match_register_0); - CHECK((-.1f <= error && error <= .1f) == true); + // Setup + local_pwm.MR0 = 100; + local_pwm.MR5 = 0; + const auto kDutyCycle = 0.27f; + const auto kExpectedMR5 = static_cast(local_pwm.MR0 * kDutyCycle); + + // Exercise + test_pwm.SetDutyCycle(kDutyCycle); + + // Verify + CHECK(kExpectedMR5 == local_pwm.MR5); + CHECK(fabs(kDutyCycle - test_pwm.GetDutyCycle()) < 0.001f); + CHECK(bit::Read(local_pwm.LER, mock_channel.channel)); } SECTION("Setting and Getting Frequency") { - test_pwm.SetDutyCycle(0.5f); - test_pwm.SetFrequency(2000_Hz); - CHECK(kDummySystemControllerClockFrequency / local_pwm.MR0 == 2000_Hz); + // Setup + const auto kFrequency = 2000_Hz; + const float kDutyCycle = 0.5f; + // Setup: Expected values + const auto kExpectedDivider = kPeriperhalClockFrequency / kFrequency; + const auto kExpectedMR0 = kExpectedDivider.to(); + const auto kExpectedMR5 = static_cast(kExpectedMR0 * kDutyCycle); + // Setup: Old condition of the PWM peripheral to be changed in the + // "Exercise" phase of the test. + local_pwm.MR0 = 100; + local_pwm.MR5 = static_cast(local_pwm.MR0 * kDutyCycle); + + // Exercise + test_pwm.SetDutyCycle(kDutyCycle); + test_pwm.SetFrequency(kFrequency); + + // Verify + CHECK(kExpectedMR0 == local_pwm.MR0); + CHECK(kExpectedMR5 == local_pwm.MR5); CHECK(test_pwm.GetFrequency() == 2000_Hz); } - - SECTION("Set Duty Cycle") - { - test_pwm.SetFrequency(1000_Hz); - test_pwm.SetDutyCycle(.50f); - float mr0 = static_cast(local_pwm.MR0); - float mr1 = static_cast(local_pwm.MR1); - float error = (mr1 / mr0) - 0.5f; - CHECK(local_pwm.MR0 == test_pwm.GetMatchRegisters()[0]); - CHECK(local_pwm.MR1 == test_pwm.CalculateDutyCycle(.50f)); - CHECK((-0.1f <= error && error <= 0.1f) == true); - CHECK(local_pwm.LER == 0b10); - } - - SECTION("Get Duty Cycle") - { - float duty_cycle = 0.10f; - test_pwm.SetFrequency(1000_Hz); - test_pwm.SetDutyCycle(duty_cycle); - float error = duty_cycle - test_pwm.GetDutyCycle(); - CHECK((-0.01f <= error && error <= 0.01f) == true); - } - sjsu::lpc40xx::SystemController::system_controller = LPC_SC; } } // namespace sjsu::lpc40xx diff --git a/library/L1_Peripheral/pwm.hpp b/library/L1_Peripheral/pwm.hpp index 32cba5dab5..56c7c1ef14 100644 --- a/library/L1_Peripheral/pwm.hpp +++ b/library/L1_Peripheral/pwm.hpp @@ -21,9 +21,11 @@ class Pwm /// /// @param frequency - starting frequency of PWM waveform virtual Status Initialize(units::frequency::hertz_t frequency) const = 0; - /// Set output pwm pin to the following duty cycle. + /// Set output pulse width to following duty cycle. /// - /// @param duty_cycle - duty cycle precent from 0 to 1 + /// @param duty_cycle - duty cycle precent from 0 to 1. Where 0.5 would be a + /// 50% duty cycle meaning that the pulse will be on for 50% of the + /// time and off for the other 50%. virtual void SetDutyCycle(float duty_cycle) const = 0; /// @return current duty cycle from hardware virtual float GetDutyCycle() const = 0; diff --git a/library/L2_HAL/actuators/servo/servo.hpp b/library/L2_HAL/actuators/servo/servo.hpp index 190a77483d..1a7efe2d88 100644 --- a/library/L2_HAL/actuators/servo/servo.hpp +++ b/library/L2_HAL/actuators/servo/servo.hpp @@ -31,7 +31,6 @@ class Servo units::frequency::hertz_t frequency = kDefaultFrequency) { servo_pwm_.Initialize(frequency); - SetFrequency(frequency); } virtual void SetFrequency( @@ -42,8 +41,8 @@ class Servo std::chrono::microseconds((1_MHz / frequency).to()); } - // Sets the minimum and maximum pulse width lengths that the class will - // use to clamp its pulse width output when using SetAngle. + // Sets the minimum and maximum pulse width lengths that the class will use + // to clamp its pulse width output when using SetAngle. virtual void SetPulseBounds(std::chrono::microseconds lower, std::chrono::microseconds upper) { @@ -51,8 +50,8 @@ class Servo pulse_upper_bound_ = upper; } - // Sets your angle bounds that maps angles to microseconds when - // using SetAngle + // Sets your angle bounds that maps angles to microseconds when using + // SetAngle. virtual void SetAngleBounds(units::angle::degree_t min_angle, units::angle::degree_t max_angle) { diff --git a/library/utility/log.hpp b/library/utility/log.hpp index d2a8ce2b93..c279b0ee9f 100644 --- a/library/utility/log.hpp +++ b/library/utility/log.hpp @@ -79,6 +79,16 @@ } \ } while (0) +/// Returns and prints statement if condition returns true +#define SJ2_RETURN_IF(condition, warning_message, ...) \ + do \ + { \ + if ((condition)) \ + { \ + LOG_WARNING(warning_message SJ2_COLOR_RESET, ##__VA_ARGS__); \ + } \ + } while (0) + /// When the condition is false, issue a critical level message to the user and /// halt the processor. #define SJ2_ASSERT_FATAL_WITH_DUMP(with_dump, condition, fatal_message, ...) \