Skip to content

Commit 86466c9

Browse files
committed
applet.video.ws2812_output: Add optional framerate limiter
1 parent f91a2fa commit 86466c9

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

software/glasgow/applet/video/ws2812_output/__init__.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from amaranth.lib import io, wiring, stream
55
from amaranth.lib.wiring import In
66

7-
from glasgow.abstract import AbstractAssembly, GlasgowPin, PortGroup
7+
from glasgow.abstract import AbstractAssembly, ClockDivisor, GlasgowPin, PortGroup
88
from glasgow.applet import GlasgowAppletV2
99
from glasgow.support.endpoint import *
1010
from glasgow.gateware.pll import *
@@ -26,6 +26,7 @@ def elaborate(self, platform):
2626

2727
class VideoWS2812OutputComponent(wiring.Component):
2828
i_stream: In(stream.Signature(8))
29+
framerate_divisor: In(24)
2930

3031
def __init__(
3132
self, ports: PortGroup, count: int, pix_in_size: int, pix_out_size: int, pix_format_func
@@ -66,10 +67,14 @@ def elaborate(self, platform):
6667
byt_ctr = Signal(range((pix_in_size) + 1))
6768
pix_ctr = Signal(range(self.count + 1))
6869
word_ctr = Signal(range(max(2, len(self.ports.out))))
70+
framerate_ctr = Signal(self.framerate_divisor.shape())
6971

7072
pix = Array([Signal(8) for i in range((pix_in_size) - 1)])
7173
word = Signal(pix_out_bpp * len(self.ports.out))
7274

75+
with m.If(framerate_ctr + 1 != 0):
76+
m.d.sync += framerate_ctr.eq(framerate_ctr + 1)
77+
7378
with m.FSM():
7479
with m.State("LOAD"):
7580
m.d.comb += [
@@ -130,14 +135,16 @@ def elaborate(self, platform):
130135

131136
with m.State("RESET"):
132137
m.d.comb += output.out.eq(0)
133-
m.d.sync += cyc_ctr.eq(cyc_ctr + 1)
134-
with m.If(cyc_ctr == t_reset):
138+
with m.If(cyc_ctr + 1 != 0):
139+
m.d.sync += cyc_ctr.eq(cyc_ctr + 1)
140+
with m.If((cyc_ctr >= t_reset) & (framerate_ctr >= self.framerate_divisor)):
135141
m.d.sync += [
136142
cyc_ctr.eq(0),
137143
pix_ctr.eq(0),
138144
bit_ctr.eq(0),
139145
byt_ctr.eq(0),
140146
word_ctr.eq(0),
147+
framerate_ctr.eq(0),
141148
]
142149
m.next = "LOAD"
143150

@@ -165,11 +172,18 @@ def __init__(
165172
self._pipe = assembly.add_out_pipe(
166173
component.i_stream, buffer_size=len(out) * count * pix_in_size * buffer
167174
)
175+
self._framerate = assembly.add_clock_divisor(
176+
component.framerate_divisor, ref_period=assembly.sys_clk_period, name="framerate"
177+
)
168178

169179
async def write(self, data):
170180
await self._pipe.send(data)
171181
await self._pipe.flush()
172182

183+
@property
184+
def framerate(self) -> ClockDivisor:
185+
return self._framerate
186+
173187

174188
class VideoWS2812OutputApplet(GlasgowAppletV2):
175189
logger = logging.getLogger(__name__)
@@ -216,6 +230,16 @@ def build(self, args):
216230
buffer=args.buffer,
217231
)
218232

233+
@classmethod
234+
def add_setup_arguments(cls, parser):
235+
parser.add_argument(
236+
"-r", "--framerate", type=float,
237+
help="configure a framerate limiter in Hz")
238+
239+
async def setup(self, args):
240+
if args.framerate is not None:
241+
await self.ws2812_iface.framerate.set_frequency(args.framerate)
242+
219243
@classmethod
220244
def add_run_arguments(cls, parser):
221245
ServerEndpoint.add_argument(parser, "endpoint")

0 commit comments

Comments
 (0)