44from amaranth .lib import io , wiring , stream
55from amaranth .lib .wiring import In
66
7- from glasgow .abstract import AbstractAssembly , GlasgowPin , PortGroup
7+ from glasgow .abstract import AbstractAssembly , ClockDivisor , GlasgowPin , PortGroup
88from glasgow .applet import GlasgowAppletV2
99from glasgow .support .endpoint import *
1010from glasgow .gateware .pll import *
@@ -26,6 +26,7 @@ def elaborate(self, platform):
2626
2727class 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
174188class 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