From 9da18f0ecc68d4422390fb629b255d34373ccf3d Mon Sep 17 00:00:00 2001 From: kris Date: Sun, 24 Feb 2019 00:03:36 +0000 Subject: [PATCH] Initial working version of video player. The basic strategy is that we remove as much conditional evaluation as possible from the inner decode loop. e.g. rather than doing opcode dispatch by some kind of table lookup (etc), this is precomputed on the server side. The next opcode in the stream is encoded as a branch offset to that opcode's first instruction, and we modify the BRA instruction in place to dispatch there. TCP buffer management is also offloaded to the server side; we rely on the server to explicitly schedule an ACK opcode every 2048 bytes to drop us into a slow path where we move the W5100 read pointer, send the TCP ACK, and block until the read socket has enough data to continue with. This outer loop is overly conservative (e.g. since we're performing exactly known read sizes we can omit a lot of duplicate bookkeeping), i.e. there is a lot of room for optimizing this. Experimental (i.e. not working yet) support for audio delay loop; we should be able to leverage the way we do offset-based dispatch to implement variable-delay loops with some level of cycle resolution. --- ethernet/ethernet/main.s | 234 ++++++++++++++++++++++++++++----------- 1 file changed, 167 insertions(+), 67 deletions(-) diff --git a/ethernet/ethernet/main.s b/ethernet/ethernet/main.s index db5154a..8797ca2 100644 --- a/ethernet/ethernet/main.s +++ b/ethernet/ethernet/main.s @@ -1,6 +1,6 @@ ; ; main.s -; ethernet +; ethernet video decoder ; ; Created by Kris Kennaway on 03/01/2019. ; Copyright © 2019 Kris Kennaway. All rights reserved. @@ -89,6 +89,12 @@ GETSIZE = $08 ; 2 BYTES FOR RX_RSR GETOFFSET = $0A ; 2 BYTES FOR OFFSET ADDR GETSTARTADR = $0C ; 2 BYTES FOR PHYSICAL ADDR +hgr = $f3e2 +gr = $c050 +text = $c051 +fullscr = $c052 +tick = $c030 + ; RESET AND CONFIGURE W5100 LDA #6 ; 5 RETRIES TO GET CONNECTION STA PTR ; NUMBER OF RETRIES @@ -143,7 +149,7 @@ RESET: STA WADRH LDA #RXMASK - STA GETOFFSET+1 - LDA WDATA ; LOW BYTE - AND #=1 page + CMP #$10 ; expect at least 4k + bcc CHECKRECV ; not yet + STA GETSIZE+1 + LDA WDATA + STA GETSIZE ; low byte XXX should be 0 + ;jsr DEBUG - LDA WDATA ; XXX: do I have to read it? DOn't think so - -; We know there is at least a page in the buffer, so read it +; reset address pointer to socket buffer +; CALCULATE OFFSET ADDRESS USING READ POINTER AND RX MASK + LDA #RXMASK + STA GETOFFSET+1 + LDA WDATA ; LOW BYTE + ; why is this not 0? + ;BEQ @L ; XXX assert 0 + ;BRK +@L: + AND #RXBASE STA GETSTARTADR+1 -; SET BUFFER ADDRESS ON W5100 - JSR DEBUG ; UNCOMMENT FOR W5100 DEBUG INFO + ; SET BUFFER ADDRESS ON W5100 + ;JSR DEBUG ; UNCOMMENT FOR W5100 DEBUG INFO LDA GETSTARTADR+1 ; HIGH BYTE FIRST STA WADRH LDA GETSTARTADR STA WADRL -; SET BUFFER ADDRESS ON APPLE -; XXX can hoist this out of the loop and let the low byte wrap - LDA #0 ; LOW BYTE OF BUFFER - STA PTR - LDA #$50 ; HIGH BYTE - STA PTR+1 + ; restore content + PLA + ; fall through -; BEGIN COPY - LDY #$00 -@L: - LDA WDATA - STA (PTR),Y - JSR CLEANOUT ; DEBUG PRINT - INY - BNE @L +; MAIN VIDEO LOOP +op_nop: ; 11 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 - LDA #$8D ; - JSR COUT ; DEBUG PRINT +op_store: ; 20 + LDY WDATA ; 4 +store1: + STA $2000,y ; 5 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 + +op_set_content: ; 15 + LDA WDATA ; 4 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 + +op_set_page: ; 27 + LDY WDATA ; 4 + STY store1+2 ; 4 + STY rle2+2 ; 4 + ;STY batch_store1+2 ; 4 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 + +op_rle: ; 12 + N (2 + 5 + 3) + (-1 + 4 + 4 + 3) = 22 + 10N + LDY WDATA ; 4 start offset + STY rle2+1 ; 4 + LDY WDATA ; 4 repeat count +rle1: + DEY ; 2 +rle2: + STA $2000,y ; 5 + BNE rle1 ; 2/3 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 + +;op_batch_store: ; 4 + N(4 + 5 + 2 + 3) + -1 + 4 + 4 + 3 = 14 + 14 N +; LDX WDATA ; 4 number of stores +;@1: +; LDY WDATA ; 4 offset +;batch_store1: +; STA $2000,y ; 5 +; DEY ; 2 +; BNE @1 ; 2/3 +; LDY WDATA ; 4 +; STY @D+1 ; 4 +;@D: +; BRA op_done ; 3 + +; tick with cycle padding, 15 .. 35 duty cycle in increments of 2 cycles + ; 20 cycles of NOP + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 + NOP ; 2 +op_tick: + STY tick ; 4 + LDY WDATA ; 4 + STY @D+1 ; 4 +@D: + BRA op_done ; 3 + +op_done: + RTS + +op_ack: +; MOVE ADDRESS POINTER 1 page further in socket buffer +; LDX WADRH ; socket pointer +; INX ; UPDATE REXRD TO REFLECT DATA WE JUST READ -UPDATERXRD: +; TODO: be careful about which registers we stomp here + +; UPDATERXRD: + PHA ; XXX + CLC LDA #>S0RXRD ; NEED HIGH BYTE HERE - STA WADRH ; XXX needed? I think this is already set + STA WADRH LDA #