Skip to content

Commit

Permalink
[rp] pio: make initialization code more close to pio program
Browse files Browse the repository at this point in the history
  • Loading branch information
andryblack committed Oct 26, 2024
1 parent aabdeb5 commit 2e37c2b
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 100 deletions.
71 changes: 3 additions & 68 deletions examples/rp_pico/pio_ws2812/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,9 @@
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include "ws2812.pio.hpp"
using namespace Board;

/* from https://github.com/raspberrypi/pico-examples/blob/master/pio/ws2812/ws2812.pio */

// constants WS2812
// static constexpr uint32_t T0H = 350; // ns
// static constexpr uint32_t T0L = 800;
// static constexpr uint32_t T1H = 700;
// static constexpr uint32_t T1L = 600;

// constants WS2812B
static constexpr uint32_t T0H = 400; // ns
static constexpr uint32_t T0L = 850;
static constexpr uint32_t T1H = 850;
static constexpr uint32_t T1L = 400;

static constexpr uint32_t TimeScale = 50;

static constexpr uint32_t TH_Common = T0H/TimeScale;
static constexpr uint32_t TH_Add = (T1H-T0H)/TimeScale;
static constexpr uint32_t TL_Common = T1L/TimeScale;
static constexpr uint32_t TL_Add = (T0L-T1L)/TimeScale;

static constexpr uint32_t T3 = 12;//

// labels
struct bitloop {};
struct do_one {};
struct do_zero {};


/*
.wrap_target
bitloop:
out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
do_one:
jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
do_zero:
nop side 0 [T2 - 1] ; Or drive low, for a short pulse
.wrap
*/
// PIO program
static constexpr auto pio_prog = PIOProgram::begin()
.sideset<1>
.wrapTarget<>
.label<bitloop>
.instr(pio::Out.x<1> .side<0>.delay<TL_Common-1>)
.instr(pio::Jmp.not_x.to<do_zero> .side<1>.delay<TH_Common-1>)
.label<do_one>
.instr(pio::Jmp.to<bitloop> .side<1>.delay<TH_Add-1>)
.label<do_zero>
.instr(pio::Nop .side<0>.delay<TL_Add-1>)
.wrap<>
.end();


struct HW
{
Expand All @@ -86,21 +33,9 @@ main()
HW::DataGpio::setOutput(Gpio::OutputType::PushPull, Gpio::SlewRate::Fast);
HW::DataGpio::setDriveStrength(Gpio::DriveStrength::mA_12);

auto pio_prog_offset = HW::PIO::addProgram(pio_prog);

HW::PIO::connect<HW::DataGpio::Pad>();

HW::PIO_SM::addOutput<HW::DataGpio>();

HW::PIO_SM::config()
.setup(pio_prog_offset,pio_prog)
.setSidesetPins<HW::DataGpio,1,false,false>()
.setFifoJoinTx()
.setOutShift<false,true,24>()
.setFrequency<Board::SystemClock,1000000000/TimeScale>()
.init(pio_prog_offset+pio_prog.getOffset<bitloop>());
auto pio_program_offset = HW::PIO::addProgram(ws2812::program);

HW::PIO_SM::setEnabled(true);
ws2812::init<Board::SystemClock,HW::PIO,HW::PIO_SM,HW::DataGpio>(pio_program_offset);

constexpr auto delay_val = 5ms;

Expand Down
96 changes: 96 additions & 0 deletions examples/rp_pico/pio_ws2812/ws2812.pio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include <modm/board.hpp>

/* from https://github.com/raspberrypi/pico-examples/blob/master/pio/ws2812/ws2812.pio */

/* .program ws2812 */
namespace ws2812
{
using namespace modm::platform::pio;

// constants WS2812
// static constexpr uint32_t T0H = 350; // ns
// static constexpr uint32_t T0L = 800;
// static constexpr uint32_t T1H = 700;
// static constexpr uint32_t T1L = 600;

// constants WS2812B
static constexpr uint32_t T0H = 400; // ns
static constexpr uint32_t T0L = 850;
static constexpr uint32_t T1H = 850;
static constexpr uint32_t T1L = 400;

static constexpr uint32_t TimeScale = 50;

static constexpr uint32_t TH_Common = T0H/TimeScale;
static constexpr uint32_t TH_Add = (T1H-T0H)/TimeScale;
static constexpr uint32_t TL_Common = T1L/TimeScale;
static constexpr uint32_t TL_Add = (T0L-T1L)/TimeScale;

// labels
struct bitloop {};
struct do_one {};
struct do_zero {};

/*
.side_set 1
.wrap_target
bitloop:
out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
do_one:
jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
do_zero:
nop side 0 [T2 - 1] ; Or drive low, for a short pulse
.wrap
*/

// PIO program
static constexpr auto program = PIOProgram::begin()
.sideset<1>
.wrapTarget<>
.label<bitloop>
.instr(pio::Out.x<1> .side<0>.delay<TL_Common-1>)
.instr(pio::Jmp.not_x.to<do_zero> .side<1>.delay<TH_Common-1>)
.label<do_one>
.instr(pio::Jmp.to<bitloop> .side<1>.delay<TH_Add-1>)
.label<do_zero>
.instr(pio::Nop .side<0>.delay<TL_Add-1>)
.wrap<>
.end();

static_assert(program.code[0]==0x6721,"invalid program code[0]");
static_assert(program.code[1]==0x1723,"invalid program code[1]");
/*
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
pio_sm_config c = ws2812_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, pin);
sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
*/
// initialization code
template <typename SystemClock,typename PIO,typename SM,typename DataGpio>
static constexpr void init(uint16_t offset) {
PIO::template connect<typename DataGpio::Pad>();
SM::template addOutput<DataGpio>();

SM::config(offset,program)
.template setSidesetPins<DataGpio>()
.template setOutShift<false,true,24>()
.setFifoJoinTx()
.template setFrequency<SystemClock,1000000000/TimeScale>()
.init(offset+program.getOffset<bitloop>());
SM::setEnabled(true);
}

}
28 changes: 16 additions & 12 deletions src/modm/platform/pio/rp/pio_asm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ namespace modm::platform::pio
using Base = InstructionEncoding<Jmp<Label,addr>>;

template <JmpCondition condition,typename LabelImpl = Label>
struct JmpImpl : InstructionEncoding<JmpImpl<condition>>{
struct JmpImpl : InstructionEncoding<JmpImpl<condition,LabelImpl>>{
static constexpr const Opcode opcode = Opcode::JMP;
static constexpr const JmpCondition condition_value = condition;
static constexpr const uint16_t addr_value = addr;
using LabelName = LabelImpl;
using Base = InstructionEncoding<JmpImpl<condition>>;
using Base = InstructionEncoding<JmpImpl<condition,LabelImpl>>;
constexpr JmpImpl() {}
template <typename Encoder>
static constexpr Instruction encode(const Encoder& coder) {
Expand Down Expand Up @@ -605,12 +605,13 @@ namespace modm::platform::pio
};


template <size_t Length,typename Labels>
template <size_t Length,typename Labels,typename ProgramSettings,uint16_t wrap_target_t,uint16_t wrap_t>
struct ProgramCode {
using settings = ProgramSettings;
static constexpr const size_t length = Length;
const uint16_t wrap_target;
const uint16_t wrap;
constexpr ProgramCode( std::array<Instruction,Length>&& code,uint16_t wrap_target,uint16_t wrap) : wrap_target(wrap_target),wrap(wrap),code(std::move(code)) {
static constexpr const uint16_t wrap_target = wrap_target_t;
static constexpr const uint16_t wrap = wrap_t;
explicit constexpr ProgramCode( std::array<Instruction,Length>&& code) : code(std::move(code)) {

}
const std::array<Instruction,Length> code;
Expand All @@ -621,12 +622,14 @@ namespace modm::platform::pio
};


template <uint32_t sideset_count_t = 0,bool sideset_is_opt_t = true, uint16_t delay_max_t = 31, uint16_t sideset_max_t = 0>
template <uint32_t count_t = 0,bool sideset_is_opt_t = true, uint16_t delay_max_t = 31, uint16_t sideset_max_t = 0>
struct ProgramSettings {
static constexpr uint32_t sideset_count = sideset_count_t;
static constexpr uint32_t count = count_t;
static constexpr uint32_t sideset_count = sideset_is_opt_t ? (count_t+1) : count_t;
static constexpr bool sideset_is_opt = sideset_is_opt_t;
static constexpr uint16_t delay_max = delay_max_t;
static constexpr uint16_t sideset_max = sideset_max_t;
static constexpr bool sideset_pindirs = false;
};
template <size_t count>
struct ProgramSettingsSideset {
Expand All @@ -636,7 +639,7 @@ namespace modm::platform::pio
template <size_t count>
struct ProgramSettingsOptSideset {
static_assert(count <= 4,"maximum number of side set bits is 4");
using result = ProgramSettings<count+1,true,(1u << (5 - (count+1))) - 1,(1u << count) - 1>;
using result = ProgramSettings<count,true,(1u << (5 - (count+1))) - 1,(1u << count) - 1>;
};

template <OptionalValue target = OptionalValue{},OptionalValue instr = OptionalValue{}>
Expand Down Expand Up @@ -696,11 +699,12 @@ namespace modm::platform::pio
using AddedInstructions = typename instructions::add<Instr>;
return ProgramBuilder<settings,labels,AddedInstructions,wrap_settings>();
}
static constexpr ProgramCode<Instructions::length,Labels> end() {
static constexpr auto end() {
ProgramBuilder pb;
return ProgramCode<instructions::length,Labels>(instructions::build(pb),
return ProgramCode<instructions::length,Labels,settings,
wrap_settings::wrap_target.is_set?wrap_settings::wrap_target.value:0,
wrap_settings::wrap_instr.is_set?wrap_settings::wrap_instr.value:(Instructions::length-1));
wrap_settings::wrap_instr.is_set?wrap_settings::wrap_instr.value:(Instructions::length-1)
>(instructions::build(pb));
}
};

Expand Down
51 changes: 31 additions & 20 deletions src/modm/platform/pio/rp/pio_sm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,15 @@ namespace modm::platform::pio::implementation
(addPin<Pins,false>(),...);
sm().pinctrl = pinctrlSaved;
}
template <typename Setting >
struct Config {
using settings = Setting;
uint32_t clkdiv{0};
uint32_t execctrl{0};
uint32_t shiftctrl{0};
uint32_t pinctrl{0};
template < uint16_t div_int, uint8_t div_frac >
uint32_t execctrl{0};
uint32_t shiftctrl{0};
uint32_t pinctrl{0};

template < uint16_t div_int, uint8_t div_frac >
constexpr Config& setClkDiv() {
clkdiv = (uint32_t(div_frac) << PIO_SM0_CLKDIV_FRAC_LSB) |
(uint32_t(div_int) << PIO_SM0_CLKDIV_INT_LSB);
Expand Down Expand Up @@ -98,16 +101,26 @@ namespace modm::platform::pio::implementation
((pullThreshold & 0x1fu) << PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB);
return *this;
}
template < class StartPin , size_t count, bool optional, bool pindirs>
constexpr Config& setSidesetPins() {
static_assert((count+(optional?1:0)) <= 5,"too many sideset pins");
pinctrl = (pinctrl & ~(PIO_SM0_PINCTRL_SIDESET_COUNT_BITS | PIO_SM0_PINCTRL_SIDESET_BASE_BITS)) |
((count+(optional?1:0)) << PIO_SM0_PINCTRL_SIDESET_COUNT_LSB) |
(uint32_t(StartPin::pin) << PIO_SM0_PINCTRL_SIDESET_BASE_LSB);
execctrl = (execctrl & ~(PIO_SM0_EXECCTRL_SIDE_EN_BITS | PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS)) |
constexpr Config& setSideset() {
constexpr auto bit_count = settings::sideset_count;
constexpr auto optional = settings::sideset_is_opt;
constexpr auto pindirs = settings::sideset_pindirs;
static_assert(bit_count <= 5,"too many sideset pins");
static_assert(!optional || bit_count >= 1,"invalid config");

pinctrl = (pinctrl & ~PIO_SM0_PINCTRL_SIDESET_COUNT_BITS) |
(bit_count << PIO_SM0_PINCTRL_SIDESET_COUNT_LSB);
execctrl = (execctrl & ~(PIO_SM0_EXECCTRL_SIDE_EN_BITS | PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS)) |
((optional?1:0) << PIO_SM0_EXECCTRL_SIDE_EN_LSB) |
((pindirs?1:0) << PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
return *this;
return *this;
}
template < class StartPin>
constexpr Config& setSidesetPins() {

pinctrl = (pinctrl & ~(PIO_SM0_PINCTRL_SIDESET_BASE_BITS)) |
(uint32_t(StartPin::pin) << PIO_SM0_PINCTRL_SIDESET_BASE_LSB);
return *this;
}
template < class StartPin , size_t count>
constexpr Config& setOutPins() {
Expand Down Expand Up @@ -143,11 +156,7 @@ namespace modm::platform::pio::implementation
shiftctrl = (shiftctrl & ~(PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS | PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS));
return *this;
}
template <typename Program>
constexpr Config& setup(size_t offset,const Program& prg) {
setWrap(prg.wrap_target+offset,prg.wrap+offset);
return *this;
}

void init(uint16_t startPC) {
StateMachine::setEnabled(false);

Expand Down Expand Up @@ -192,10 +201,12 @@ namespace modm::platform::pio::implementation
return *this;
}
};
static constexpr Config config() {
return Config()
template <typename Program>
static constexpr auto config(size_t offset,const Program& ) {
return Config<typename Program::settings>()
.setSideset()
.template setClkDiv<1,0>()
.setWrap(0,31)
.setWrap(Program::wrap_target+offset,Program::wrap+offset)
.template setInShift<true,false,32>()
.template setOutShift<true,false,32>();
}
Expand Down

0 comments on commit 2e37c2b

Please sign in to comment.