Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ws2812] resumable write and dma example #879

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
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
52 changes: 52 additions & 0 deletions examples/stm32f469_discovery/ws2812b/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2019, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/driver/pwm/ws2812b.hpp>
#include <modm/ui/led/tables.hpp>
#include <modm/processing/timer.hpp>

using namespace Board;

using Output = Board::D11;
modm::Ws2812b<SpiMaster2, Output, 8*8> leds;
modm::ShortPeriodicTimer tmr{33ms};

int
main()
{
Board::initialize();
LedD13::setOutput();
leds.initialize<Board::SystemClock>();

constexpr uint8_t max = 60;
uint8_t r=0, g=max/3, b=max/3*2;

while (true)
{
for (size_t ii=0; ii < leds.size; ii++)
{
leds.setColor(ii,
{modm::ui::table22_8_256[r*3/2],
modm::ui::table22_8_256[g*3/2],
modm::ui::table22_8_256[b*3/2]});
if (r++ >= max) r = 0;
if (g++ >= max) g = 0;
if (b++ >= max) b = 0;
}
leds.write();

while(not tmr.execute()) ;
LedD13::toggle();
}

return 0;
}
13 changes: 13 additions & 0 deletions examples/stm32f469_discovery/ws2812b/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<library>
<extends>modm:disco-f469ni</extends>
<options>
<option name=":build:build.path">../../../build/stm32f469_discovery/ws2812b</option>
</options>
<modules>
<module>modm:driver:ws2812</module>
<module>modm:platform:spi:2</module>
<module>modm:ui:led</module>
<module>modm:build:scons</module>
</modules>
</library>
62 changes: 62 additions & 0 deletions examples/stm32f469_discovery/ws2812b_dma/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2019, Niklas Hauser
* Copyright (c) 2023, Henrik Hose
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/driver/pwm/ws2812b.hpp>
#include <modm/ui/led/tables.hpp>
#include <modm/processing/timer.hpp>
#include <modm/processing.hpp>

using namespace Board;

using Output = Board::D11;
using DmaRx = Dma1::Channel3;
using DmaTx = Dma1::Channel4;
using SpiLed = SpiMaster2_Dma<DmaRx, DmaTx>;
// using SpiLed = SpiMaster2; // for non-dma version
modm::Ws2812b<SpiLed, Output, 8*8> leds;
modm::ShortPeriodicTimer tmr{33ms};

constexpr uint8_t max = 62;
uint8_t r=0, g=max/3, b=max/3*2;

int
main()
{
Board::initialize();
LedD13::setOutput();
Dma1::enable();
leds.initialize<Board::SystemClock>();

constexpr uint8_t max = 60;
uint8_t r=0, g=max/3, b=max/3*2;

while (true)
{
for (size_t ii=0; ii < leds.size; ii++)
{
leds.setColor(ii,
{modm::ui::table22_8_256[r*3/2],
modm::ui::table22_8_256[g*3/2],
modm::ui::table22_8_256[b*3/2]});
if (r++ >= max) r = 0;
if (g++ >= max) g = 0;
if (b++ >= max) b = 0;
}
leds.write();

while(not tmr.execute()) ;
// LedD13::toggle();
}

return 0;
}
15 changes: 15 additions & 0 deletions examples/stm32f469_discovery/ws2812b_dma/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8'?>
<library>
<extends>modm:disco-f469ni</extends>
<options>
<option name=":build:build.path">../../../build/stm32f469_discovery/ws2812b_dma</option>
</options>
<modules>
<module>modm:driver:ws2812</module>
<module>modm:platform:spi:2</module>
<module>modm:platform:dma</module>
<module>modm:ui:led</module>
<module>modm:build:scons</module>
<module>modm:processing:timer</module>
</modules>
</library>
1 change: 1 addition & 0 deletions src/modm/architecture/interface/spi_master.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class SpiMaster : public ::modm::PeripheralDriver, public Spi
*/
static modm::ResumableResult<void>
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);

#endif
};

Expand Down
1 change: 1 addition & 0 deletions src/modm/driver/pwm/ws2812.lb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def prepare(module, options):
":architecture:spi",
":architecture:unaligned",
":math:units",
":processing:resumable",
":ui:color")
return options[":target"].identifier.platform == "stm32"

Expand Down
17 changes: 15 additions & 2 deletions src/modm/driver/pwm/ws2812b.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#include <modm/architecture/interface/spi_master.hpp>
#include <modm/architecture/interface/unaligned.hpp>
#include <modm/ui/color.hpp>
#include <modm/processing/resumable.hpp>

namespace modm
{

/// @ingroup modm_driver_ws2812
template< class SpiMaster, class Output, size_t LEDs >
class Ws2812b
class Ws2812b : protected modm::NestedResumable<3>
{
protected: // 7654 3210 7654 3210 7654 3210
static constexpr uint32_t base_mask = 0b0010'0100'1001'0010'0100'1001;
Expand Down Expand Up @@ -100,14 +101,26 @@ class Ws2812b
return {color[1], color[0], color[2]};
}

void
modm::ResumableResult<void>
write()
requires (SpiMaster::usesDma())
{
RF_BEGIN();
RF_CALL(SpiMaster::transfer(data, nullptr, length+1));
RF_END_RETURN();
}

modm::ResumableResult<void>
write()
{
RF_BEGIN();
for (const auto value : data) {
while (not SpiMaster::Hal::isTransmitRegisterEmpty()) ;
SpiMaster::Hal::write(value);
}
RF_END_RETURN();
}

};

} // namespace modm
3 changes: 3 additions & 0 deletions src/modm/platform/spi/rp/spi_master_dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public:
waitCompleted([](){});
}

static constexpr bool
usesDma(){return true;};

private:
// needed for transfers where no RX or TX buffers are given
static inline uint8_t dmaDummy{0};
Expand Down
1 change: 1 addition & 0 deletions src/modm/platform/spi/stm32/spi_master.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ public:

static modm::ResumableResult<void>
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);

};

} // namespace platform
Expand Down
3 changes: 3 additions & 0 deletions src/modm/platform/spi/stm32/spi_master_dma.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public:
static modm::ResumableResult<void>
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);

static constexpr bool
usesDma(){return true;};

private:
static void
handleDmaTransferError();
Expand Down