Add Sonata PWM Driver Adds a simple PWM driver for the Sonata board. Right now there is only 1 PWM but as this may change in the future, the driver has been written in a generic way such that the number of PWM can be easily modified.
diff --git a/sdk/include/platform/sunburst/platform-pwm.hh b/sdk/include/platform/sunburst/platform-pwm.hh new file mode 100644 index 0000000..60f1704 --- /dev/null +++ b/sdk/include/platform/sunburst/platform-pwm.hh
@@ -0,0 +1,68 @@ +#pragma once +#include <debug.hh> +#include <stdint.h> + +/** + * A driver for Sonata's Pulse-Width Modulation (PWM). + * + * Documentation source can be found at: + * https://github.com/lowRISC/sonata-system/blob/97a525c48f7bf051b999d0178dba04859819bc5e/doc/ip/pwm.md + * + * Rendered documentation is served from: + * https://lowrisc.github.io/sonata-system/doc/ip/pwm.html + */ +struct SonataPulseWidthModulation +{ + /** + * Flag to set when debugging the driver for UART log messages. + */ + static constexpr bool DebugDriver = false; + + /** + * Helper for conditional debug logs and assertions. + */ + using Debug = ConditionalDebug<DebugDriver, "PWM">; + + /** + * The number of pulse-width modulated outputs that are available. + */ + static constexpr size_t OutputCount = 1; + + /** + * The pulse-width modulation outputs available on Sonata. + */ + struct OutputRegisters + { + /** + * The duty cycle of the wave, represented as a width counter. That + * is, the number of clock cycles for which the signal will be on. The + * duty cycle as a percentage is (duty cycle / period) * 100. + */ + uint32_t dutyCycle; + + /** + * The period (width) of the output block wave, set with the number of + * clock cycles that one period should last. The maximum period is 255 + * as only an 8 bit counter is being used. + */ + uint32_t period; + } outputs[OutputCount]; + + /* + * Sets the output of a specified pulse-width modulated output. + * + * The first argument is the index of the output. The second argument is + * the period (length) of the output wave represented as a counter of + * system clock cycles. The third argument is the number of clock cycles + * for which a high pulse is sent within that period. + * + * So for example `output_set(0, 200, 31)` should set a 15.5% output. + */ + void output_set(uint32_t index, uint8_t period, uint8_t dutyCycle) volatile + { + Debug::Assert(index < OutputCount, "Specified PWM is out of range"); + Debug::Assert(dutyCycle <= period, "Duty cycle cannot exceed 100%"); + outputs[index].period = period; + outputs[index].dutyCycle = dutyCycle; + } +};