diff --git a/examples/rp_pico/pio_ws2812/main.cpp b/examples/rp_pico/pio_ws2812/main.cpp index a5e1699570..b03920beff 100644 --- a/examples/rp_pico/pio_ws2812/main.cpp +++ b/examples/rp_pico/pio_ws2812/main.cpp @@ -54,17 +54,17 @@ struct do_zero {}; .wrap */ // PIO program -static constexpr auto pio_prog = modm::platform::PIOProgram::begin() - .sideset<1>() - .wrapTarget() - .label() - .instr(pio::Out().x<1>() .side<0>().delay()) - .instr(pio::Jmp().not_x().to() .side<1>().delay()) - .label() - .instr(pio::Jmp().to() .side<1>().delay()) - .label() - .instr(pio::Nop() .side<0>().delay()) - .wrap() +static constexpr auto pio_prog = PIOProgram::begin() + .sideset<1> + .wrapTarget<> + .label + .instr(pio::Out.x<1> .side<0>.delay) + .instr(pio::Jmp.not_x.to .side<1>.delay) + .label + .instr(pio::Jmp.to .side<1>.delay) + .label + .instr(pio::Nop .side<0>.delay) + .wrap<> .end(); diff --git a/src/modm/platform/pio/rp/pio.hpp.in b/src/modm/platform/pio/rp/pio.hpp.in index 6cbf7852fe..fe688d8366 100644 --- a/src/modm/platform/pio/rp/pio.hpp.in +++ b/src/modm/platform/pio/rp/pio.hpp.in @@ -60,12 +60,12 @@ namespace modm::platform } template - friend class pio::StateMachine; + friend class pio::implementation::StateMachine; public: static constexpr Peripheral peripherial = Peripheral::Pio{{ id }}; template - class StateMachine : public modm::platform::pio::StateMachine {}; + class StateMachine : public modm::platform::pio::implementation::StateMachine {}; template< class... Signals > static void diff --git a/src/modm/platform/pio/rp/pio_asm.hpp b/src/modm/platform/pio/rp/pio_asm.hpp index ddf9bd29f7..983f55e0e3 100644 --- a/src/modm/platform/pio/rp/pio_asm.hpp +++ b/src/modm/platform/pio/rp/pio_asm.hpp @@ -17,359 +17,425 @@ namespace modm::platform::pio { + namespace implementation + { + struct Instruction { + uint16_t value; + constexpr Instruction(uint16_t val) : value(val) {} + constexpr uint16_t store(size_t offset) const { + return ((value & 0xe000) == 0x0000) ? (value + offset) : value; + } + constexpr Instruction operator | (uint16_t params) const { + return Instruction(value | params); + } + constexpr bool operator == (uint16_t val) const { + return value == val; + } + }; - struct Instruction { - uint16_t value; - constexpr Instruction(uint16_t val) : value(val) {} - constexpr uint16_t store(size_t offset) const { - return ((value & 0xe000) == 0x0000) ? (value + offset) : value; - } - constexpr Instruction operator | (uint16_t params) const { - return Instruction(value | params); - } - constexpr bool operator == (uint16_t val) const { - return value == val; - } - }; - - enum class Opcode : uint16_t { - JMP = 0x0000 << 13, - WAIT = 0x0001 << 13, - IN = 0x0002 << 13, - OUT = 0x0003 << 13, - PUSH = 0x0004 << 13, - PULL = (0x0004 << 13) | (0x0001 << 7), - MOV = 0x0005 << 13, - IRQ = 0x0006 << 13, - SET = 0x0007 << 13, - }; - - struct OptionalValue { - uint16_t value{0}; - bool is_set{false}; - }; - - static constexpr uint16_t NO_SIDE_VALUE = 0xffff; - - template - struct SideDelay { - static constexpr const uint16_t side_value = (side == NO_SIDE_VALUE) ? 0 : side; - static constexpr const bool side_value_present = side != NO_SIDE_VALUE; - static constexpr const uint16_t delay_value = delay; - }; - - template - struct InstructionEncoding { - static constexpr const Opcode opcode = Res::opcode; - static constexpr const uint16_t DELAY_SIDESET_SHIFT = 8; - static constexpr const uint16_t DELAY_SIDESET_MASK = 0x1f << DELAY_SIDESET_SHIFT; - static constexpr const uint16_t ARG1_SHIFT = 5; - - using SideDelayConfig = SideDelay<>; - - template - struct SideValue : Res { - using SideDelayConfig = SideDelay; - constexpr SideValue() {} + enum class Opcode : uint16_t { + JMP = 0x0000 << 13, + WAIT = 0x0001 << 13, + IN = 0x0002 << 13, + OUT = 0x0003 << 13, + PUSH = 0x0004 << 13, + PULL = (0x0004 << 13) | (0x0001 << 7), + MOV = 0x0005 << 13, + IRQ = 0x0006 << 13, + SET = 0x0007 << 13, + }; + + struct OptionalValue { + uint16_t value{0}; + bool is_set{false}; + }; + + static constexpr uint16_t NO_SIDE_VALUE = 0xffff; + + template + struct SideDelay { + static constexpr const uint16_t side_value = (side == NO_SIDE_VALUE) ? 0 : side; + static constexpr const bool side_value_present = side != NO_SIDE_VALUE; + static constexpr const uint16_t delay_value = delay; + }; + + template + struct InstructionEncoding { + static constexpr const Opcode opcode = Res::opcode; + static constexpr const uint16_t DELAY_SIDESET_SHIFT = 8; + static constexpr const uint16_t DELAY_SIDESET_MASK = 0x1f << DELAY_SIDESET_SHIFT; + static constexpr const uint16_t ARG1_SHIFT = 5; + + using SideDelayConfig = SideDelay<>; + + template + struct SideValue : Res { + using SideDelayConfig = SideDelay; + constexpr SideValue() {} + template + struct DelayValue : Res { + constexpr DelayValue() {} + using SideDelayConfig = SideDelay; + template + static constexpr Instruction encode(const Encoder& coder) { + return Res::encode(coder) | (coder.template encodeSideDelay() << DELAY_SIDESET_SHIFT); + } + }; + template + static constexpr auto delay = DelayValue(); + + template + static constexpr Instruction encode(const Encoder& coder) { + return Res::encode(coder) | (coder.template encodeSideDelay() << DELAY_SIDESET_SHIFT); + } + }; template struct DelayValue : Res { constexpr DelayValue() {} - using SideDelayConfig = SideDelay; + using SideDelayConfig = SideDelay; template - constexpr Instruction encode(const Encoder& coder) const { + static constexpr Instruction encode(const Encoder& coder) { return Res::encode(coder) | (coder.template encodeSideDelay() << DELAY_SIDESET_SHIFT); } }; + + constexpr InstructionEncoding() {} template - constexpr auto delay() { - return DelayValue(); - } - template - constexpr Instruction encode(const Encoder& coder) const { - return Res::encode(coder) | (coder.template encodeSideDelay() << DELAY_SIDESET_SHIFT); - } - }; - template - struct DelayValue : Res { - constexpr DelayValue() {} - using SideDelayConfig = SideDelay; + static constexpr auto side = SideValue(); + template + static constexpr auto delay = DelayValue(); + template - constexpr Instruction encode(const Encoder& coder) const { - return Res::encode(coder) | (coder.template encodeSideDelay() << DELAY_SIDESET_SHIFT); + static constexpr Instruction encode(const Encoder& ) { + return Instruction(uint16_t(opcode)); } }; - constexpr InstructionEncoding() {} - template - constexpr auto side() const { - return SideValue(); - } - template - constexpr auto delay() { - return DelayValue(); - } - template - constexpr Instruction encode(const Encoder& ) const { - return Instruction(uint16_t(opcode)); + template + static constexpr bool check(const T& t,uint16_t value) { + struct Encoder { + constexpr uint16_t encodeSideDelay(const OptionalValue& /*side*/,uint16_t /*delay*/) const { + return 0; + } + }; + return t.encode(Encoder()) == value; } - }; - - enum class JmpCondition : uint16_t { - ALWAYS = 0x00, - NOT_X = 0x01, - X_DEC = 0x02, - NOT_Y = 0x03, - Y_DEC = 0x04, - X_NE_Y = 0x05, - PIN = 0x06, - NOT_ORSE = 0x07, - }; - template - struct Jmp : InstructionEncoding> { - static constexpr const Opcode opcode = Opcode::JMP; - static constexpr const JmpCondition condition_value = condition; - static constexpr const uint16_t addr_value = addr; - static_assert(addr_value < 0x0f, "Invalid addr"); - - using LabelName = Label; - using Base = InstructionEncoding>; - - explicit constexpr Jmp() {} - static constexpr auto not_x() { return Jmp(); } - static constexpr auto x_dec() { return Jmp(); } - static constexpr auto not_y() { return Jmp(); } - static constexpr auto y_dec() { return Jmp(); } - static constexpr auto x_ne_y() { return Jmp(); } - static constexpr auto pin() { return Jmp(); } - static constexpr auto not_osre() { return Jmp(); } - - template - static constexpr auto to() { return Jmp(); } - - template - static constexpr uint16_t getAddr(const Encoder& coder) { + + enum class JmpCondition : uint16_t { + ALWAYS = 0x00, + NOT_X = 0x01, + X_DEC = 0x02, + NOT_Y = 0x03, + Y_DEC = 0x04, + X_NE_Y = 0x05, + PIN = 0x06, + NOT_ORSE = 0x07, + }; + template + static constexpr uint16_t getJmpAddr(const Encoder& coder,uint16_t addr_value) { if constexpr (std::is_same_v) { return addr_value; } else { return coder.template getOffset