.feature c_comments /****************************************************************************** Copyright (c) 2014, Oliver Schmidt All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OLIVER SCHMIDT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ ptr := $06 ; 2 byte pointer value tmp := $08 ; 1 byte temporary value bas := $09 ; 1 byte socket 1 Base Address (hibyte) sha := $19 ; 2 byte physical addr shadow ($F000-$FFFF) len := $1B ; 2 byte frame length adv := $1D ; 2 byte pointer register advancement mode := $C0C4 addr := $C0C5 data := $C0C7 .export init .export recv_init, recv_byte, recv_done .export send_init, send_byte, send_done ;------------------------------------------------------------------------------ init: ; Set ip_parms pointer sta ptr stx ptr+1 ; S/W Reset lda #$80 sta mode : lda mode bmi :- ; Indirect Bus I/F mode, Address Auto-Increment lda #$03 sta mode ; Gateway IP Address Register: IP address of router on local network ldx #$00 ; Hibyte ldy #$01 ; Lobyte jsr set_addr ldy #3*4 ; ip_parms::cfg_gateway jsr set_ipv4value ; Subnet Mask Register: Netmask of local network ; -> addr is already set ldy #2*4 ; ip_parms::cfg_netmask jsr set_ipv4value ; Source Hardware Address Register: MAC Address ; -> addr is already set ldx #$00 : lda mac,x sta data inx cpx #$06 bcc :- ; Source IP Address Register: IP address of local machine ; -> addr is already set ldy #1*4 ; ip_parms::cfg_ip jsr set_ipv4value ; RX Memory Size Register: Assign 4KB each to sockets 0 and 1 ldx #$00 ; Hibyte ldy #$1A ; Lobyte jsr set_addr lda #$0A sta data ; TX Memory Size Register: Assign 4KB each to sockets 0 and 1 ; -> addr is already set ; -> A is still $0A sta data ; Socket 1 Destination IP Address Register: Destination IP address ; This has to be the last call to set_ipv4value because it writes ; as a side effect to 'hdr' and it is the destination IP address ; that has to be present in 'hdr' after initialization ldy #$0C jsr set_addrsocket1 ldy #0*4 ; ip_parms::serverip jsr set_ipv4value ; Socket 1 Destination Port Register: 6502 ; -> addr is already set jsr set_data6502 ; Socket 1 Source Port Register: 6502 ldy #$04 jsr set_addrsocket1 jsr set_data6502 ; Socket 1 Mode Register: UDP ldy #$00 jsr set_addrsocket1 lda #$02 sta data ; Socket 1 Command Register: OPEN ; addr is already set lda #$01 sta data rts ;------------------------------------------------------------------------------ set_ipv4value: ldx #$03 : lda (ptr),y iny sta data sta hdr+2,x dex bpl :- rts ;------------------------------------------------------------------------------ set_data6502: lda #<6502 ldx #>6502 stx data ; Hibyte sta data ; Lobyte rts ;------------------------------------------------------------------------------ recv_init: ; Socket 1 RX Received Size Register: 0 or volatile ? lda #$26 ; Socket RX Received Size Register jsr prolog bcs :+++ ; Socket 0 RX Read Pointer Register ; -> addr already set ; Calculate and set pyhsical address ldx #>$7000 ; Socket 1 RX Base Address jsr set_addrphysical ; Compare peer IP addr and peer port with expected values ; in 'hdr' and set C(arry flag) if there's a mismatch clc ldx #$05 stx tmp : jsr recv_byte ; Doesn't trash C ldx tmp eor hdr,x ; Doesn't trash C beq :+ sec : dec tmp bpl :-- php ; Save C ; Read data length jsr recv_byte ; Hibyte sta len+1 jsr recv_byte ; Lobyte sta len ; Add 8 byte header to set pointer advancement clc adc #<$0008 sta adv lda len+1 adc #>$0008 sta adv+1 ; Skip frame if it doesn't originate from our ; expected communicaion peer plp ; Restore C bcs recv_done ; Return success with data length lda len ldx len+1 clc : rts ;------------------------------------------------------------------------------ send_init: ; Set pointer advancement sta adv stx adv+1 ; Socket 1 TX Free Size Register: 0 or volatile ? lda #$20 ; Socket TX Free Size Register jsr prolog bcs :+ ; Socket 1 TX Free Size Register: < advancement ? cpx adv ; Lobyte sbc adv+1 ; Hibyte bcc rts_cs ; Socket 1 TX Write Pointer Register ldy #$24 jsr set_addrsocket1 ; Calculate and set pyhsical address ldx #>$5000 ; Socket 1 TX Base Address jsr set_addrphysical ; Return success clc : rts ;------------------------------------------------------------------------------ prolog: ; Check for completion of previous command ; Socket 1 Command Register: 0 ? jsr set_addrcmdreg1 ldx data bne rts_cs ; Not completed -> error ; Socket Size Register: not 0 ? tay ; Select Size Register jsr get_wordsocket1 stx ptr ; Lobyte sta ptr+1 ; Hibyte ora ptr bne :+ rts_cs: sec ; Error (size == 0) rts ; Socket Size Register: volatile ? : jsr get_wordsocket1 cpx ptr ; Lobyte bne rts_cs ; Volatile size -> error cmp ptr+1 ; Hibyte bne rts_cs ; Volatile size -> error clc ; Sucess (size != 0) rts ;------------------------------------------------------------------------------ recv_byte: ; Read byte lda data ; Increment physical addr shadow lobyte inc sha beq incsha rts ;------------------------------------------------------------------------------ send_byte: ; Write byte sta data ; Increment physical addr shadow lobyte inc sha beq incsha rts ; Increment physical addr shadow hibyte incsha: inc sha+1 beq set_addrbase rts ;------------------------------------------------------------------------------ recv_done: ; Set parameters for commit code lda #$40 ; RECV ldy #$28 ; Socket RX Read Pointer Register bne epilog ; Always ;------------------------------------------------------------------------------ send_done: ; Set parameters for commit code lda #$20 ; SEND ldy #$24 ; Socket TX Write Pointer Register ; Advance pointer register epilog: jsr set_addrsocket1 tay ; Save command clc lda ptr adc adv tax lda ptr+1 adc adv+1 sta data ; Hibyte stx data ; Lobyte ; Set command register tya ; Restore command jsr set_addrcmdreg1 sta data sec ; When coming from _recv_init -> error rts ;------------------------------------------------------------------------------ set_addrphysical: lda data ; Hibyte ldy data ; Lobyte sty ptr sta ptr+1 and #>$0FFF ; Socket Mask Address (hibyte) stx bas ; Socket Base Address (hibyte) ora bas tax ora #>$F000 ; Move sha/sha+1 to $F000-$FFFF sty sha sta sha+1 set_addr: stx addr ; Hibyte sty addr+1 ; Lobyte rts ;------------------------------------------------------------------------------ set_addrcmdreg1: ldy #$01 ; Socket Command Register set_addrsocket1: ldx #>$0500 ; Socket 1 register base address bne set_addr ; Always ;------------------------------------------------------------------------------ set_addrbase: ldx bas ; Socket Base Address (hibyte) ldy #<$0000 ; Socket Base Address (lobyte) beq set_addr ; Always ;------------------------------------------------------------------------------ get_wordsocket1: jsr set_addrsocket1 lda data ; Hibyte ldx data ; Lobyte rts ;------------------------------------------------------------------------------ .rodata mac: .byte $00, $08, $DC ; OUI of WIZnet .byte $11, $11, $11 ;------------------------------------------------------------------------------ .data hdr: .word 6502 ; Destination Port .res 4 ; Destination IP Address