2020from glasgow .abstract import AbstractAssembly , GlasgowPin , ClockDivisor
2121from glasgow .applet import GlasgowAppletV2 , GlasgowAppletError
2222
23+ MAX_BS = 1024
24+
2325
2426class AUDError (GlasgowAppletError ):
2527 pass
@@ -86,7 +88,7 @@ def elaborate(self, platform):
8688
8789 # Wait for clock period to pass, then set clock high
8890 with m .State ("OUT-CLOCK-0" ):
89- with m .If (timer == self .divisor ):
91+ with m .If (timer == self .divisor >> 1 ):
9092 m .d .sync += self .audck_o .eq (1 )
9193 m .d .sync += timer .eq (0 )
9294 m .next = "OUT-CLOCK-1"
@@ -95,7 +97,7 @@ def elaborate(self, platform):
9597
9698 # Wait for clock period to pass, then return to command reception
9799 with m .State ("OUT-CLOCK-1" ):
98- with m .If (timer == self .divisor ):
100+ with m .If (timer == self .divisor >> 1 ):
99101 m .d .sync += self .audck_o .eq (0 )
100102 m .d .comb += self .i_stream .ready .eq (1 ) # Indicate to AUDComponent we're ready to receive a new command
101103 m .next = "RECV-COMMAND"
@@ -110,7 +112,7 @@ def elaborate(self, platform):
110112
111113 # Wait for clock period to pass, then sample data and set clock high
112114 with m .State ("INP-CLOCK-0" ):
113- with m .If (timer == self .divisor ):
115+ with m .If (timer == self .divisor >> 1 ):
114116 m .d .sync += self .audck_o .eq (1 )
115117 m .d .sync += timer .eq (0 )
116118
@@ -123,7 +125,7 @@ def elaborate(self, platform):
123125
124126 # Wait for clock period to pass, then send data
125127 with m .State ("INP-CLOCK-1" ):
126- with m .If (timer == self .divisor ):
128+ with m .If (timer == self .divisor >> 1 ):
127129 m .d .sync += self .audck_o .eq (0 )
128130 m .next = "SEND-DATA"
129131 with m .Else ():
@@ -323,12 +325,10 @@ async def run(self):
323325 async def out (self , val ):
324326 await self ._cmd (AUDCommand .Out , val )
325327
326- async def inp (self , n ) -> bytes :
328+ async def inp (self , n ):
327329 await self ._cmd (AUDCommand .Inp , n )
328330
329- # This is the only place we need to flush, as we're going to wait for a response
330- await self ._pipe .flush ()
331-
331+ async def read (self , n ) -> bytes :
332332 data = await self ._pipe .recv (n )
333333 data = bytes (data )
334334 self ._logger .log (self ._level , "AUD: read <%s>" , data .hex ())
@@ -350,34 +350,47 @@ async def init(self):
350350 for i in range (10 ):
351351 await self .out (0 )
352352
353- async def read (self , addr : int , sz : Literal [1 ,2 ,4 ] = 4 , timeout : int = 100 ):
353+ async def bulk_read (self , addr : int , sz : int , bs : Literal [1 ,2 ,4 ] = 4 ):
354354 assert addr in range (0 , 1 << 32 ), "Address must be a 32-bit value"
355- assert sz in (1 , 2 , 4 ), "Size must be one of 1, 2, or 4 bytes"
355+ assert bs in (1 , 2 , 4 ), "Block size must be one of 1, 2, or 4 bytes"
356+
357+ # Queue up all the reads
358+ for block_addr in range (addr , addr + sz , bs ):
359+ await self .sync (0 )
360+ await self .out (0 )
361+
362+ # Send the Read command
363+ cmd = _AUDMonitorCommand .Read .value | \
364+ {
365+ 1 : _AUDMonitorSize .Byte ,
366+ 2 : _AUDMonitorSize .Word ,
367+ 4 : _AUDMonitorSize .LongWord ,
368+ }[bs ].value
369+ await self .out (cmd )
370+
371+ # Clock out Addr
372+ for i in range (8 ):
373+ await self .out ((block_addr >> (i * 4 )) & 0b1111 )
356374
357- await self .sync (0 )
358- await self .out (0 )
375+ await self .inp (1 + 2 * bs )
359376
360- # Send the Read command
361- cmd = _AUDMonitorCommand .Read .value | \
362- {
363- 1 : _AUDMonitorSize .Byte ,
364- 2 : _AUDMonitorSize .Word ,
365- 4 : _AUDMonitorSize .LongWord ,
366- }[sz ].value
367- await self .out (cmd )
377+ # This is the only place we need to flush, as we're going to wait for a response
378+ await self ._pipe .flush ()
368379
369- # Clock out Addr
370- for i in range (8 ):
371- await self .out ((addr >> (i * 4 )) & 0b1111 )
380+ # Get all the responses
381+ out = []
382+ for _ in range (addr , addr + sz , bs ):
383+ data = await self .read (1 + 2 * bs )
372384
373- out = await self . inp ( 1 + 2 * sz )
374- out = out [1 :] # Remove the status code nibble
385+ # Remove the status code nibble
386+ data = data [1 :]
375387
376- # Combine nibbles into bytes and reverse
377- out = bytes ([x << 4 | y for x , y in zip (out [0 ::2 ], out [1 ::2 ])])
378- out = out [::- 1 ]
388+ # Combine nibbles into bytes and reverse
389+ data = bytes ([y << 4 | x for x , y in zip (data [0 ::2 ], data [1 ::2 ])])
390+ data = data [::- 1 ]
391+ out .append (data )
379392
380- return out
393+ return b"" . join ( out )
381394
382395
383396class AUDApplet (GlasgowAppletV2 ):
@@ -467,11 +480,11 @@ async def run(self, args):
467480 await self .aud_iface .init ()
468481
469482 self .logger .trace ("Reading data" )
470- bs = 4
483+ bs = min ( MAX_BS , args . length )
471484
472485 for i in range (args .address , args .address + args .length , bs ):
473- data = await self .aud_iface .read (i , sz = bs )
486+ data = await self .aud_iface .bulk_read (i , bs )
474487 args .file .write (data )
475- self ._show_progress (i - args .address + bs , args .length , f"Read { data .hex ()} " )
488+ self ._show_progress (i - args .address + bs , args .length , f"Read { data [: 0x10 ] .hex ()} ... " )
476489
477490 self .logger .trace ("Done" )
0 commit comments