2022-02-11 11:40:04 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "pico/stdlib.h"
|
|
|
|
#include "hardware/pio.h"
|
|
|
|
#include "hardware/dma.h"
|
|
|
|
#include "hardware/irq.h"
|
2022-02-21 00:04:36 +00:00
|
|
|
#include <initializer_list>
|
2022-02-11 11:40:04 +00:00
|
|
|
|
2022-02-20 11:00:36 +00:00
|
|
|
namespace pimoroni {
|
2022-02-11 11:40:04 +00:00
|
|
|
|
2022-02-17 22:38:59 +00:00
|
|
|
struct TransitionData {
|
2022-02-20 11:00:36 +00:00
|
|
|
uint8_t channel;
|
2022-02-17 22:38:59 +00:00
|
|
|
uint32_t level;
|
|
|
|
bool state;
|
2022-03-06 13:12:34 +00:00
|
|
|
bool dummy;
|
2022-02-17 22:38:59 +00:00
|
|
|
|
2022-03-06 13:12:34 +00:00
|
|
|
TransitionData() : channel(0), level(0), state(false), dummy(false) {};
|
|
|
|
TransitionData(uint8_t channel, uint32_t level, bool new_state) : channel(channel), level(level), state(new_state), dummy(false) {};
|
|
|
|
TransitionData(uint32_t level) : channel(0), level(level), state(false), dummy(true) {};
|
2022-02-17 22:38:59 +00:00
|
|
|
|
|
|
|
bool compare(const TransitionData& other) const {
|
|
|
|
return level <= other.level;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-02-20 11:00:36 +00:00
|
|
|
class PWMCluster {
|
2022-02-17 22:38:59 +00:00
|
|
|
public:
|
2022-02-21 00:04:36 +00:00
|
|
|
PWMCluster(PIO pio, uint sm, uint pin_mask);
|
|
|
|
PWMCluster(PIO pio, uint sm, uint pin_base, uint pin_count);
|
|
|
|
PWMCluster(PIO pio, uint sm, std::initializer_list<uint8_t> pins);
|
2022-02-20 11:00:36 +00:00
|
|
|
~PWMCluster();
|
2022-02-21 00:04:36 +00:00
|
|
|
|
|
|
|
bool init();
|
|
|
|
|
|
|
|
uint get_pin_mask() const;
|
2022-03-07 16:26:20 +00:00
|
|
|
uint8_t get_chan_count() const;
|
|
|
|
|
|
|
|
uint32_t get_wrap() const;
|
|
|
|
uint32_t get_chan_level(uint8_t channel) const;
|
|
|
|
uint32_t get_chan_offset(uint8_t channel) const;
|
|
|
|
bool get_chan_polarity(uint8_t channel) const;
|
|
|
|
|
2022-02-17 22:38:59 +00:00
|
|
|
void set_wrap(uint32_t wrap, bool load = true);
|
|
|
|
void set_chan_level(uint8_t channel, uint32_t level, bool load = true);
|
|
|
|
void set_chan_offset(uint8_t channel, uint32_t offset, bool load = true);
|
|
|
|
void set_chan_polarity(uint8_t channel, bool polarity, bool load = true);
|
|
|
|
void set_clkdiv(float divider);
|
|
|
|
void set_clkdiv_int_frac(uint16_t integer, uint8_t fract);
|
|
|
|
//void set_phase_correct(bool phase_correct);
|
|
|
|
//void set_enabled(bool enabled);
|
|
|
|
void load_pwm();
|
|
|
|
static bool bit_in_mask(uint bit, uint mask);
|
2022-02-21 00:04:36 +00:00
|
|
|
private:
|
2022-02-17 22:38:59 +00:00
|
|
|
static void sorted_insert(TransitionData array[], uint &size, const TransitionData &data);
|
|
|
|
private:
|
|
|
|
PIO pio;
|
|
|
|
uint sm;
|
|
|
|
uint pio_program_offset;
|
2022-02-21 00:04:36 +00:00
|
|
|
uint pin_mask;
|
2022-03-07 16:26:20 +00:00
|
|
|
uint8_t channel_count;
|
2022-02-17 22:38:59 +00:00
|
|
|
uint channel_levels[NUM_BANK0_GPIOS];
|
|
|
|
uint channel_offsets[NUM_BANK0_GPIOS];
|
|
|
|
uint channel_polarities;
|
|
|
|
uint wrap_level;
|
2022-02-20 15:12:02 +00:00
|
|
|
|
2022-03-06 22:48:13 +00:00
|
|
|
uint channel_overruns[NUM_BANK0_GPIOS];
|
2022-03-06 23:34:54 +00:00
|
|
|
uint next_channel_overruns[NUM_BANK0_GPIOS];
|
2022-03-06 22:48:13 +00:00
|
|
|
|
2022-02-20 15:12:02 +00:00
|
|
|
public:
|
|
|
|
static bool calculate_pwm_factors(float freq, uint32_t& top_out, uint16_t& div16_out);
|
|
|
|
private:
|
|
|
|
static const uint64_t MAX_PWM_CLUSTER_WRAP = UINT16_MAX; // UINT32_MAX works too, but seems to produce less accurate counters
|
2022-02-17 22:38:59 +00:00
|
|
|
};
|
2022-02-11 11:40:04 +00:00
|
|
|
}
|