Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/utility/M5IOE1_Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,24 @@ namespace m5
writeRegister(M5IOE1_REG_PWM_FREQ_L, data, sizeof(data));
}

void M5IOE1_Class::setPwmDuty(std::uint8_t channel, std::uint16_t duty12, bool enable, bool polarity)
bool M5IOE1_Class::setPwmDutyPercent(pwm_channel_t channel, std::uint32_t duty,
pwm_polarity_t polarity, bool enable)
{
if (channel > pwm_ch4) { return; }
duty12 &= 0x0FFF;
if (duty > 100) { return false; }
auto duty12 = duty * 0x0FFF / 100;
return setPwmDuty12bit(channel, duty12, polarity, enable);
}

bool M5IOE1_Class::setPwmDuty12bit(pwm_channel_t channel, std::uint32_t duty12,
pwm_polarity_t polarity, bool enable)
{
if (channel > pwm_ch4 || duty12 > 0x0FFF) { return false; }
std::uint8_t high = static_cast<std::uint8_t>(duty12 >> 8);
if (enable) { high |= M5IOE1_PWM_ENABLE; }
if (polarity) { high |= M5IOE1_PWM_POLARITY; }
if (polarity == pwm_polarity_t::inverted) { high |= M5IOE1_PWM_POLARITY; }
std::uint8_t data[2] = { static_cast<std::uint8_t>(duty12 & 0xFF), high };
writeRegister(static_cast<std::uint8_t>(M5IOE1_REG_PWM1_DUTY_L + channel * 2), data, sizeof(data));
auto reg = static_cast<std::uint8_t>(M5IOE1_REG_PWM1_DUTY_L + static_cast<std::uint8_t>(channel) * 2);
return writeRegister(reg, data, sizeof(data));
}

void M5IOE1_Class::resetIrq()
Expand Down
17 changes: 16 additions & 1 deletion src/utility/M5IOE1_Class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define __M5_M5IOE1_CLASS_H__

#include "IOExpander_Base.hpp"
#include "pwm_types.hpp"

namespace m5
{
Expand Down Expand Up @@ -61,7 +62,21 @@ namespace m5

void setPwmFrequency(std::uint16_t frequency);

void setPwmDuty(std::uint8_t channel, std::uint16_t duty12, bool enable = true, bool polarity = false);
/// set PWM duty in percent.
/// @param channel PWM channel (pwm_ch1 - pwm_ch4).
/// @param duty duty cycle in percent (0-100).
/// @param polarity PWM output polarity.
/// @param enable true=enable / false=disable.
bool setPwmDutyPercent(pwm_channel_t channel, std::uint32_t duty,
pwm_polarity_t polarity = pwm_polarity_t::normal, bool enable = true);

/// set PWM duty with 12-bit precision.
/// @param channel PWM channel (pwm_ch1 - pwm_ch4).
/// @param duty12 duty cycle (0-4095).
/// @param polarity PWM output polarity.
/// @param enable true=enable / false=disable.
bool setPwmDuty12bit(pwm_channel_t channel, std::uint32_t duty12,
pwm_polarity_t polarity = pwm_polarity_t::normal, bool enable = true);

void resetIrq() override;

Expand Down
8 changes: 4 additions & 4 deletions src/utility/Power_Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ namespace m5
/// cannot be confirmed, the pin is left as a plain output driving low,
/// which is silent whatever the retained PWM state is.
bool pwm_off = false;
for (int retry = 3; !(pwm_off = M5pm1.setPwmDuty12bit(M5PM1_Class::pwm_ch1, 0, false, false)) && --retry; )
for (int retry = 3; !(pwm_off = M5pm1.setPwmDuty12bit(M5PM1_Class::pwm_ch1, 0, pwm_polarity_t::normal, false)) && --retry; )
{
m5gfx::delay(10);
}
Expand Down Expand Up @@ -402,7 +402,7 @@ namespace m5
// IO9 (G9 motor / PWM1): push-pull output, duty off until setVibration
ioe1.setHighImpedance(M5IOE1_Class::gpio9, false);
ioe1.setDirection(M5IOE1_Class::gpio9, true);
ioe1.setPwmDuty(M5IOE1_Class::pwm_ch1, 0, false); // PWM off at boot
ioe1.setPwmDuty12bit(M5IOE1_Class::pwm_ch1, 0, pwm_polarity_t::normal, false); // PWM off at boot
}
break;

Expand Down Expand Up @@ -2780,13 +2780,13 @@ namespace m5
// M5IOE1 PWM1 (0x1B/0x1C) -> pin IO9 / G9 motor; duty 12-bit in [11:0], EN=bit7 of high byte.
auto& ioe1 = static_cast<M5IOE1_Class&>(M5.getIOExpander(0));
if (level == 0) {
ioe1.setPwmDuty(M5IOE1_Class::pwm_ch1, 0, false);
ioe1.setPwmDuty12bit(M5IOE1_Class::pwm_ch1, 0, pwm_polarity_t::normal, false);
} else {
// PWM needs IO9 in output mode (M5IOE1 pin index 8 -> GPIO_MODE_H bit0).
ioe1.setHighImpedance(M5IOE1_Class::gpio9, false);
ioe1.setDirection(M5IOE1_Class::gpio9, true);
uint16_t duty12 = static_cast<uint16_t>((static_cast<uint32_t>(level) * 0x0FFFu) / 255u);
ioe1.setPwmDuty(M5IOE1_Class::pwm_ch1, duty12);
ioe1.setPwmDuty12bit(M5IOE1_Class::pwm_ch1, duty12);
}
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/utility/led/LED_PaperMono_Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace m5
ioe1.digitalWrite(ioe1_led_b_pin, b >= 2048);

if (g > 4095) { g = 4095; }
ioe1.setPwmDuty(M5IOE1_Class::pwm_ch2, g, g > 0);
ioe1.setPwmDuty12bit(M5IOE1_Class::pwm_ch2, g, pwm_polarity_t::normal, g > 0);
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/utility/power/M5PM1_Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,21 @@ namespace m5
return writeRegister(M5PM1_REG_PWM_FREQ_L, data, sizeof(data));
}

bool M5PM1_Class::setPwmDuty(pwm_channel_t channel, std::uint8_t duty, bool polarity, bool enable)
bool M5PM1_Class::setPwmDutyPercent(pwm_channel_t channel, std::uint32_t duty,
pwm_polarity_t polarity, bool enable)
{
if (duty > 100) { return false; }
auto duty12 = static_cast<std::uint16_t>(static_cast<std::uint32_t>(duty) * 0x0FFF / 100);
auto duty12 = duty * 0x0FFF / 100;
return setPwmDuty12bit(channel, duty12, polarity, enable);
}

bool M5PM1_Class::setPwmDuty12bit(pwm_channel_t channel, std::uint16_t duty12, bool polarity, bool enable)
bool M5PM1_Class::setPwmDuty12bit(pwm_channel_t channel, std::uint32_t duty12,
pwm_polarity_t polarity, bool enable)
{
if (!is_valid_pwm_channel(channel) || duty12 > 0x0FFF) { return false; }
std::uint8_t high = static_cast<std::uint8_t>(duty12 >> 8);
if (enable) { high |= M5PM1_PWM_ENABLE; }
if (polarity) { high |= M5PM1_PWM_POLARITY; }
if (polarity == pwm_polarity_t::inverted) { high |= M5PM1_PWM_POLARITY; }
std::uint8_t data[2] = { static_cast<std::uint8_t>(duty12 & 0xFF), high };
auto reg = static_cast<std::uint8_t>(M5PM1_REG_PWM0_L + static_cast<std::uint8_t>(channel) * 2);
return writeRegister(reg, data, sizeof(data));
Expand Down
11 changes: 7 additions & 4 deletions src/utility/power/M5PM1_Class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define __M5_M5PM1_CLASS_H__

#include "../I2C_Class.hpp"
#include "../pwm_types.hpp"

namespace m5
{
Expand Down Expand Up @@ -129,16 +130,18 @@ namespace m5
/// set PWM duty in percent.
/// @param channel PWM channel (pwm_ch0 / pwm_ch1).
/// @param duty duty cycle in percent (0-100).
/// @param polarity false=normal / true=inverted.
/// @param polarity PWM output polarity.
/// @param enable true=enable / false=disable.
bool setPwmDuty(pwm_channel_t channel, std::uint8_t duty, bool polarity = false, bool enable = true);
bool setPwmDutyPercent(pwm_channel_t channel, std::uint32_t duty,
pwm_polarity_t polarity = pwm_polarity_t::normal, bool enable = true);

/// set PWM duty with 12-bit precision.
/// @param channel PWM channel (pwm_ch0 / pwm_ch1).
/// @param duty12 duty cycle (0-4095).
/// @param polarity false=normal / true=inverted.
/// @param polarity PWM output polarity.
/// @param enable true=enable / false=disable.
bool setPwmDuty12bit(pwm_channel_t channel, std::uint16_t duty12, bool polarity = false, bool enable = true);
bool setPwmDuty12bit(pwm_channel_t channel, std::uint32_t duty12,
pwm_polarity_t polarity = pwm_polarity_t::normal, bool enable = true);

/// clear PM1 wake source bits selected by mask.
bool clearWakeSource(std::uint8_t mask = 0x7F);
Expand Down
21 changes: 21 additions & 0 deletions src/utility/pwm_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) M5Stack. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef __M5_PWM_TYPES_H__
#define __M5_PWM_TYPES_H__

#include <cstdint>

namespace m5
{
/// PWM output polarity.
/// normal : the duty is the high time. The output idles low (POL = 0).
/// inverted : the duty is the low time. The output idles high (POL = 1),
/// which the datasheet calls active low.
enum class pwm_polarity_t : std::uint8_t
{ normal = 0
, inverted = 1
};
}

#endif
Loading