; (c)opyright 2014-2018 ; Sven Oliver ("SvOlli") Moll ; and Individual Computers .include "rrnetmk3.inc" .segment "CODE" cs8900a_check_hw: ; from cs8900a data sheet: ; Reset value is: ; 0000 1110 0110 0011 0000 0000 000X XXXX ; 0 E 6 3 0 0 X X ; The X XXXX codes for the CS8900A are: ; Rev B: 0 0111 (07) ; Rev C: 0 1000 (08) ; Rev D: 0 1001 (09) ; Rev F: 0 1010 (0a) .if USE_MACROS cs8900a_read_page CS_PP_PRODINF .else lda #$00 jsr cs8900a_get_packet_page .endif cpx #$0E bne @fail cpy #$63 bne @fail .if USE_MACROS cs8900a_read_page CS_PP_PRODINF+2 .else lda #$01 jsr cs8900a_get_packet_page .endif txa bne @fail cpy #$0B bcs @fail tya sec sbc #$07 bcc @fail sta CS8900A_REVISION rts @fail: lda #$FF rts cs8900a_init: .if USE_MACROS ; SelfCTL: ; HCB1 HCB0 HC1E HC0E - HWStandbyE HWSleepE SW Suspend RESET 1 5 ; 0 0 0 0 |0 0 0 0 | 0 1 1 ; 0|0 | 5 5 cs8900a_write_page CS_PP_SELFCTL, #$0055 .else lda #$14 sta PP_POINTER+0 lda #$01 sta PP_POINTER+1 lda #$55 sta PP_DATA0+0 lda #$00 sta PP_DATA0+1 .endif .if 0 ; wait ~13ms ldy #$0A ldx #$00 : inx bne :- dey bne :- .else ; according to documentation this should work ; in real life it doesn't : cs8900a_read_page CS_PP_SELFCTL txa and #$40 bne :- .endif .if USE_MACROS ; SelfCTL: ; HCB1 HCB0 HC1E HC0E - HWStandbyE HWSleepE SW Suspend RESET 1 5 ; 0 0 0 0 |0 0 0 0 | 0 1 1 ; 0|0 | 5 5 ; cs8900a_write_page CS_PP_SELFCTL, #$0055 ; RxCTL: ; - ExtraDataA RuntA CRCerrorA|BroadcastA IndividualA MulticastA RxOKA|PromiscuousA IAHashA 5 ; 0 0 0 0 | 1 1 0 1 | 0 0 ; 0|D | 0 5 cs8900a_write_page CS_PP_RXCTL, #$0D05 .else lda #$04 sta PP_POINTER+0 lda #$01 sta PP_POINTER+1 lda #$05 sta PP_DATA0+0 lda #$0D sta PP_DATA0+1 .endif ldx #$58 ldy #$00 : stx PP_POINTER+0 lda #$01 sta PP_POINTER+1 lda ROM_MAC_ADDR,y sta PP_DATA0+0 inx iny lda ROM_MAC_ADDR,y sta PP_DATA0+1 inx iny cpy #$06 bne :- .if USE_MACROS ; LineCTL: ; - LoRxSquelch 2-partDefDis PolarityDis ModBackoffE - AutoAUI/10BT AUIonly SerTxON SerRxON 1 3 ; 0 0 0 0 0 0 0 0 1 1 ; 0 0 D 3 cs8900a_write_page CS_PP_LINECTL, #$00D3 .else lda #$12 sta PP_POINTER+0 lda #$01 sta PP_POINTER+1 lda #$D3 sta PP_DATA0+0 lda #$00 sta PP_DATA0+1 .endif rts ; X/Y contains lo/hi of package size cs8900a_send_ip_frame_16: .if USE_SPEED_CODE_WRITE stx TEMP_A_16+0 sty TEMP_A_16+1 .endif jsr area_set_start jsr area_set_end lda #$C9 sta TXCMD+0 lda #$00 sta TXCMD+1 stx TXLENGTH+0 sty TXLENGTH+1 @readcue: jsr print_status .if USE_MACROS ; RxEvent: Y | X ; - ExtraData Runt CRCerror|Broadcast IndividualAdr Hashed RxOK|DribbleBits IAHash ; 8 4 2 1 | 8 4 2 1 | 8 4 cs8900a_read_page CS_PP_RXEVENT ; $0124 .else lda #$92 jsr cs8900a_get_packet_page .endif tya and #$73 beq :+ lda RXTX_DATA0+1 lda RXTX_DATA0+0 ldy RXTX_DATA0+1 ldx RXTX_DATA0+0 jsr cs8900a_drop_package jmp @readcue : .if USE_MACROS ; BusST: Y | X ; - - - -|- - - Rdy4TxNOW|TxBidErr - ; 8 4 2 1|8 4 2 1 | 8 4 cs8900a_read_page CS_PP_BUSST ; $0138 .else lda #$9C jsr cs8900a_get_packet_page .endif tya and #$01 beq @readcue .if USE_SPEED_CODE_WRITE ; load size from temporary memory lda TEMP_A_16+0 ldy TEMP_A_16+1 ; convert to number of 16-bit words to be copied lsr adc #$00 bne :+ lda #$80 ; whoops: $00 means $100 dey : tax ; now lets take a look how many pages need copying tya ; cpy #$00 would work also beq @write1page ; hibyte $00 -> only one page dey beq @write2pages ; hibyte $01 -> two pages ; none of the above -> three pages @write3pages: ldy #$00 : lda ETHER_FRAME_START+$000,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START+$000,y sta RXTX_DATA0+1 iny bne :- : lda ETHER_FRAME_START+$100,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START+$100,y sta RXTX_DATA0+1 iny bne :- : lda ETHER_FRAME_START+$200,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START+$200,y sta RXTX_DATA0+1 iny cpy TEMP_A_16+0 bne :- beq @done @write2pages: ; y=$00 from dey:beq lda ETHER_FRAME_START+$000,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START+$000,y sta RXTX_DATA0+1 iny bne @write2pages : lda ETHER_FRAME_START+$100,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START+$100,y sta RXTX_DATA0+1 iny cpy TEMP_A_16+0 bne :- beq @done @write1page: ; y=$00 from tya:beq lda ETHER_FRAME_START,y sta RXTX_DATA0+0 iny lda ETHER_FRAME_START,y sta RXTX_DATA0+1 iny cpy TEMP_A_16+0 bne @write1page @done: .else ldy #$00 @writeloop: lda AREA_START .if 1 lsr ; odd: C=1 lda (AREA_START),y bcs @odd sta RXTX_DATA0+0 bcc @done @odd: sta RXTX_DATA0+1 @done: .else ; this code will hang in native mode of the rr-net mk3 and #$01 tax lda (AREA_START),y sta RXTX_DATA0,x .endif .if USE_COMPACT_CODE jsr advance_area_start jsr area_check_end_16 .else inc AREA_START+0 bne :+ inc AREA_START+1 : lda AREA_START+0 cmp AREA_END+0 bne @writeloop lda AREA_START+1 cmp AREA_END+1 .endif bne @writeloop .endif inc TX_COUNTER cs8900a_print_tx: ldx #$13 ldy #$0A clc jsr PLOT lda TX_COUNTER jmp hexbyte_out ; empty buffer by reading data ; taking a shortcut here: there's a bug in original code ; that reads more bytes than available when size > 255 ; using it to our advantage by read-clearing data pagewise cs8900a_drop_package: iny : ldx #$80 : lda RXTX_DATA0+0 lda RXTX_DATA0+1 dex bne :- dey bne :-- inc DROP_COUNTER cs8900a_print_dropped: ldx #$13 ldy #$16 clc jsr PLOT lda DROP_COUNTER jmp hexbyte_out cs8900a_receive_ip_frame_16: .if USE_DEBUG inc $d020 .endif .if USE_MACROS ; RxEvent: Y | X ; - ExtraData Runt CRCerror|Broadcast IndividualAdr Hashed RxOK|DribbleBits IAHash ; 8 4 2 1 | 8 4 2 1 | 8 4 cs8900a_read_page CS_PP_RXEVENT ; $0124 .else lda #$92 jsr cs8900a_get_packet_page .endif tya and #$7F bne :+ .if USE_DEBUG dec $d020 .endif lda #$FF rts : lda RXTX_DATA0+1 lda RXTX_DATA0+0 ldy RXTX_DATA0+1 ldx RXTX_DATA0+0 ; maximum package size increased from 199 to 640 bytes cpy #$03 ; $300 or over? bcs cs8900a_drop_package ; drop it cpy #$02 ; less than $200 bcc :+ ; keep it cpx #$81 ; over $280 bcs cs8900a_drop_package ; drop it : ; X/Y now contain lo/hi of package size jsr area_set_start jsr area_set_end .if USE_SPEED_CODE_READ ; the following side effects are made: ; - package size is always even, will be padded if not ; - a low byte of $00 means +$100 in every case ; X contains lobyte of page ; convert to number of 16-bit words to be copied txa lsr adc #$00 bne :+ lda #$80 ; whoops: $00 means $100 dey : tax ; now lets take a look how many pages need copying tya ; cpy #$00 would work also beq @read1page ; hibyte $00 -> only one page dey beq @read2pages ; hibyte $01 -> two pages ; none of the above -> three pages @read3pages: ldy #$00 : lda RXTX_DATA0+0 sta ETHER_FRAME_START+$000,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START+$000,y iny bne :- : lda RXTX_DATA0+0 sta ETHER_FRAME_START+$100,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START+$100,y iny bne :- : lda RXTX_DATA0+0 sta ETHER_FRAME_START+$200,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START+$200,y iny dex bne :- beq @done @read2pages: ; y=$00 from dey:beq lda RXTX_DATA0+0 sta ETHER_FRAME_START+$000,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START+$000,y iny bne @read2pages : lda RXTX_DATA0+0 sta ETHER_FRAME_START+$100,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START+$100,y iny dex bne :- beq @done @read1page: ; y=$00 from tya:beq lda RXTX_DATA0+0 sta ETHER_FRAME_START,y iny lda RXTX_DATA0+1 sta ETHER_FRAME_START,y iny dex bne @read1page @done: .else ldy #$00 @readloop: lda AREA_START and #$01 tax lda RXTX_DATA0,x sta (AREA_START),y .if USE_COMPACT_CODE jsr advance_area_start jsr area_check_end_16 .else inc AREA_START+0 bne :+ inc AREA_START+1 : lda AREA_START+0 cmp AREA_END+0 bne @readloop lda AREA_START+1 cmp AREA_END+1 .endif bne @readloop .endif ; make sure package received is 16-bit clean ; by padding with $00 byte if not lda AREA_END lsr bcc :+ ; no padding needed ; zero out last byte, if needed lda #$00 tay sta (AREA_END),y inc AREA_END+0 bne :+ inc AREA_END+1 : inc RX_COUNTER jsr cs8900a_print_rx .if USE_DEBUG dec $d020 .endif lda #$00 rts cs8900a_print_rx: ldx #$13 ldy #$10 clc jsr PLOT lda RX_COUNTER jmp hexbyte_out cs8900a_setup_mac: stx TEMP_B_16+0 sty TEMP_B_16+1 .if 0 jsr cs8900a_check_hw bpl :+ rts : .endif pha ldy #$00 : lda (TEMP_B_16),y tax iny tya pha lda (TEMP_B_16),y tay pla pha lsr ora #$AC jsr cs8900a_set_packet_page pla tay iny cpy #$06 bne :- .if USE_MACROS ; RxCTL: ; - ExtraDataA RuntA CRCerrorA BroadcastA IndividualA MulticastA RxOKA PromiscuousA IAHashA 5 ; 0 0 0 0 1 1 1 1 0 0 ; 0 F 0 5 cs8900a_write_page CS_PP_RXCTL, #$0F05 ; $0104 ; LineCTL: ; - LoRxSquelch 2-partDefDis PolarityDis ModBackoffE - AutoAUI/10BT AUIonly SerTxON SerRxON 1 3 ; 0 0 0 0 0 0 0 0 1 1 ; 0 0 D 3 cs8900a_write_page CS_PP_LINECTL, #$00D3 ; $0112 .else lda #$82 ldx #$05 ldy #$0F jsr cs8900a_set_packet_page lda #$89 ldx #$D3 ldy #$00 jsr cs8900a_set_packet_page .endif pla rts cs8900a_set_packet_page: asl sta PP_POINTER+0 lda #$00 rol sta PP_POINTER+1 stx PP_DATA0+0 sty PP_DATA0+1 rts cs8900a_get_packet_page: asl sta PP_POINTER+0 lda #$00 rol sta PP_POINTER+1 ldx PP_DATA0+0 ldy PP_DATA0+1 rts