please dont rip this site

Atmel Avr Tcpip Atmel-crystal.asm

         .include "M103def.inc"
        .list
        .listmac
        .eseg
        .db      "Copyright 1998-1999 Gary T. Desrosiers. All Rights Reserved.",0
        .cseg
        .org    0
         jmp    start
;-----------------------------------------------------------------------+
;                ATmega103 <===> Crystal Interconnects.                 |
;-----------------------------------------------------------------------+
;                                                                       |
;PORTA - Unconnected. Because external SRAM enable bit set in MCUCR,    |
;		 this port becomes the data port (AD0-7).                       |
;                                                                       |
;PORTB - Connected to SA0-SA3 of Crystal board. PB4-PB7 is unconnected  |
;                                                                       |
;PORTC - Unconnected. Because external SRAM enable bit set in MCUCR,    |
;        this port becomes the high order address bus (A8-A15).         |
;                                                                       |
;PORTD - Connected to SD0-SD7 of the Crystal board (Crystal Data Bus).  |
;                                                                       |
;PORTE - Tied to PE0-->>/RD, PE1-->>/WR, PE2-->>/CHIPSEL,               |
;        and PE3<<--INTR on the Crystal board.                          |
;                                                                       |
; Note: When using the STK300 development board, remove the PORTB,      |
;       PORTD, and PORTE jumpers.                                       |
;                                                                       |
;-----------------------------------------------------------------------+
; Note: When using the STK300 development board, perform the following: |
;                                                                       |
;       * Remove the PORTB jumpers (all 8)                              |
;       * Remove the PORTD jumpers (all 8)                              |
;       * Remove PORTE jumpers for RE0/RE1                              |
;       * Move J1 to J2 to disable 3.3v mode and enable 5.0v mode       |
;       * Optionally, connect the 16x1 or 2x8 LCD                       |
;-----------------------------------------------------------------------+
;
.equ CDB=PORTD                          ;Crystal Data Bus
.equ CAB=PORTB                          ;Crystal Address Bus
.equ CSIG=PORTE                         ;Crystal Signals
.equ IOR=0                              ;Read
.equ IOW=1                              ;Write
.equ CHIPSEL=2                          ;Chip Select
.equ INTR=3                             ;Interrupt signal
;
;
;
; *Change these* : Configuration equates. 
;
.equ    ClkFreq = 4000000	            ;4 Mhz crystal
;
.equ    IP1	 =	192                     ;first octet of IP address
.equ    IP2  =  168                     ;second octet of IP address
.equ    IP3  =  1                       ;third octet of IP address
.equ    IP4  =  2                       ;fourth octet of IP address
;
.equ    MAC1 =  0x00                    ;\
.equ    MAC2 =  0x00                    ;  \
.equ    MAC3 =  0x00                    ;    \
.equ    MAC4 =  0x12                    ;    48 bit IEEE OUI (Organizationally Unique Identifier)
.equ    MAC5 =  0x34                    ;  /
.equ    MAC6 =  0x56                    ;/
;
; Some useful macros
;
.macro  ppRD                            ;Read PacketPage port at addr @0
        ldi     offsetL,low(@0)
        ldi     offsetH,high(@0)
        rcall   ReadPP
.endmacro
;
.macro  ppWR                            ;Write PacketPage port (addr,val)
        ldi     offsetL,low(@0)
        ldi     offsetH,high(@0)
        ldi     valueL,low(@1)
        ldi     valueH,high(@1)
        rcall   WritePP
.endmacro

;
.macro  Dinput
        clr     wL                      ;Change the data bus to input
        out     DDRD,wL
.endmacro
;
.macro  Doutput        
        ser     wL                      ;Change the data bus to output
        out     DDRD,wL
.endmacro
;
.macro  ior                             ;I/O port read at @0 
        ldi     wL,@0
        rcall   ioRead
.endmacro
;
.macro  iow                             ;I/O port write at @0
        out     CDB,wL
        ldi     wL,@0
        out     CAB,wL
        rcall   ioWrite
.endmacro
;
; Crystal CS8900 PacketPage equates
;
.equ portRxTxData    =  0x00            ;Receive/Transmit data (port 0)
.equ portRxTxData1   =  0x02            ;Receive/Transmit data (port 0)
.equ portTxCmd       =  0x04            ;Transmit Commnad
.equ portTxLength    =  0x06            ;Transmit Length
.equ portISQ         =  0x08            ;Interrupt status queue
.equ portPtr         =  0x0a            ;PacketPage pointer
.equ portData        =  0x0c            ;PacketPage data (port 0)
.equ portData1       =  0x0e            ;PacketPage data (port 1)
;
; CS8900 PacketPage Offsets 
;
.equ ppEISA          =  0x0000          ;EISA Registration number of CS8900
.equ ppProdID        =  0x0002          ;Product ID Number
.equ ppIOBase        =  0x0020          ;I/O Base Address
.equ ppIntNum        =  0x0022          ;Interrupt number (0,1,2, or 3)
.equ ppMemBase       =  0x002C          ;Memory Base address register (20 bit)
.equ ppRxCfg         =  0x0102          ;Receiver Configuration
.equ ppRxCtl         =  0x0104          ;Receiver Control
.equ ppTxCfg         =  0x0106          ;Transmit Configuration
.equ ppBufCfg        =  0x010A          ;Buffer Configuration
.equ ppLineCtl       =  0x0112          ;Line Control
.equ ppSelfCtl       =  0x0114          ;Self Control
.equ ppBusCtl        =  0x0116          ;Bus Control
.equ ppTestCtl       =  0x0118          ;Test Control
.equ ppISQ           =  0x0120          ;Interrupt status queue
.equ ppRxEvt         =  0x0124          ;Receiver Event
.equ ppTxEvt         =  0x0128          ;Transmitter Event
.equ ppBufEvt        =  0x012C          ;Buffer Event
.equ ppRxMiss        =  0x0130          ;Receiver Miss Counter
.equ ppTxCol         =  0x0132          ;Transmit Collision Counter
.equ ppLineSt        =  0x0134          ;Line Status
.equ ppSelfSt        =  0x0136          ;Self Status
.equ ppBusSt         =  0x0138          ;Bus Status
.equ ppTxCmd         =  0x0144          ;Transmit Command Request
.equ ppTxLength      =  0x0146          ;Transmit Length
.equ ppIndAddr       =  0x0158          ;Individual Address (IA)
.equ ppRxStat        =  0x0400          ;Receive Status
.equ ppRxLength      =  0x0402          ;Receive Length
.equ ppRxFrame       =  0x0404          ;Receive Frame Location
.equ ppTxFrame       =  0x0A00          ;Transmit Frame Location
;
; Register Numbers 
;
.equ REG_NUM_MASK       =    0x003F
.equ REG_NUM_RX_EVENT   =    0x0004
.equ REG_NUM_TX_EVENT   =    0x0008
.equ REG_NUM_BUF_EVENT  =    0x000C
.equ REG_NUM_RX_MISS    =    0x0010
.equ REG_NUM_TX_COL     =    0x0012
;
; Self Control Register
;
.equ SELF_CTL_RESET     =    0x0040
.equ SELF_CTL_HC1E      =    0x2000
.equ SELF_CTL_HCB1      =    0x8000
;
; Self Status Register 
;
.equ SELF_ST_INIT_DONE  =    0x0080
.equ SELF_ST_SI_BUSY    =    0x0100
.equ SELF_ST_EEP_PRES   =    0x0200
.equ SELF_ST_EEP_OK     =    0x0400
.equ SELF_ST_EL_PRES    =    0x0800
;
; Bus Control Register 
;
.equ BUS_CTL_USE_SA     =    0x0200
.equ BUS_CTL_MEM_MODE   =    0x0400
.equ BUS_CTL_IOCHRDY    =    0x1000
.equ BUS_CTL_INT_ENBL   =    0x8000
;
; Bus Status Register 
;
.equ BUS_ST_TX_BID_ERR  =    0x0080
.equ BUS_ST_RDY4TXNOW   =    0x0100
;
; Line Control Register 
;
.equ LINE_CTL_RX_ON     =    0x0040
.equ LINE_CTL_TX_ON     =    0x0080
.equ LINE_CTL_AUI_ONLY  =    0x0100
.equ LINE_CTL_10BASET   =    0x0000
;
; Test Control Register 
;
.equ TEST_CTL_DIS_LT    =    0x0080
.equ TEST_CTL_ENDEC_LP  =    0x0200
.equ TEST_CTL_AUI_LOOP  =    0x0400
.equ TEST_CTL_DIS_BKOFF =    0x0800
.equ TEST_CTL_FDX       =    0x4000
;
; Receiver Configuration Register 
;
.equ RX_CFG_SKIP        =    0x0040
.equ RX_CFG_RX_OK_IE    =    0x0100
.equ RX_CFG_CRC_ERR_IE  =    0x1000
.equ RX_CFG_RUNT_IE     =    0x2000
.equ RX_CFG_X_DATA_IE   =    0x4000
;
; Receiver Event Register 
;
.equ RX_EVENT_RX_OK     =    0x0100
.equ RX_EVENT_IND_ADDR  =    0x0400
.equ RX_EVENT_BCAST     =    0x0800
.equ RX_EVENT_CRC_ERR   =    0x1000
.equ RX_EVENT_RUNT      =    0x2000
.equ RX_EVENT_X_DATA    =    0x4000
;
;Receiver Control Register 
;
.equ RX_CTL_RX_OK_A     =    0x0100
.equ RX_CTL_MCAST_A     =    0x0200
.equ RX_CTL_IND_A       =    0x0400
.equ RX_CTL_BCAST_A     =    0x0800
.equ RX_CTL_CRC_ERR_A   =    0x1000
.equ RX_CTL_RUNT_A      =    0x2000
.equ RX_CTL_X_DATA_A    =    0x4000
;
;Transmit Configuration Register 
;
.equ TX_CFG_LOSS_CRS_IE =    0x0040
.equ TX_CFG_SQE_ERR_IE  =    0x0080
.equ TX_CFG_TX_OK_IE    =    0x0100
.equ TX_CFG_OUT_WIN_IE  =    0x0200
.equ TX_CFG_JABBER_IE   =    0x0400
.equ TX_CFG_16_COLL_IE  =    0x8000
.equ TX_CFG_ALL_IE      =    0x8FC0
;
;Transmit Event Register 
;
.equ TX_EVENT_TX_OK     =    0x0100
.equ TX_EVENT_OUT_WIN   =    0x0200
.equ TX_EVENT_JABBER    =    0x0400
.equ TX_EVENT_16_COLL   =    0x1000
;
; Transmit Command Register
;
.equ TX_CMD_START_5     =    0x0000
.equ TX_CMD_START_381   =    0x0080
.equ TX_CMD_START_1021  =    0x0040
.equ TX_CMD_START_ALL   =    0x00C0
.equ TX_CMD_FORCE       =    0x0100
.equ TX_CMD_ONE_COLL    =    0x0200
.equ TX_CMD_NO_CRC      =    0x1000
.equ TX_CMD_NO_PAD      =    0x2000
;
;Buffer Configuration Register 
;
.equ BUF_CFG_SW_INT     =    0x0040
.equ BUF_CFG_RDY4TX_IE  =    0x0100
.equ BUF_CFG_TX_UNDR_IE =    0x0200
;
;
; Register file assignments
;
.def count=r14
.def lcdPos=r15
.def wL=r16
.def wH=r17
.def offsetL=r18
.def offsetH=r19
.def valueL=r20
.def valueH=r21
.def tempL=r22
.def tempH=r23
.def flags=r24
.def scratch=r25
.def lengthL=r26
.def lengthH=r27
.def chksumL=r0
.def chksumM=r1
.def chksumH=r2

;
;  start of packet data in sram
;
.equ packet = 0x60
;
; Packet offset equates
;
;
; Packet header
;
.equ pktLenH  =  0x00
.equ pktLenL  =  0x01
.equ pktDest0H=  0x02
.equ pktDest0L=  0x03
.equ pktDest1H=  0x04
.equ pktDest1L=  0x05
.equ pktDest2H=  0x06
.equ pktDest2L=  0x07
.equ pktSrc0H =  0x08
.equ pktSrc0L =  0x09
.equ pktSrc1H =  0x0a
.equ pktSrc1L =  0x0b
.equ pktSrc2H =  0x0c
.equ pktSrc2L =  0x0d
.equ pktTypeH =  0x0e
.equ pktTypeL =  0x0f
;
; ARP
;
.equ ar_hwtype=  0x10                   ;hardware type
.equ ar_prtype=  0x12                   ;protocol type
.equ ar_hwlen =  0x14                   ;hardware address length
.equ ar_prlen =  0x15                   ;protocol address length
.equ ar_op    =  0x16                   ;ARP operation (1=request, 2=reply)
.equ ar_sha   =  0x18                   ;senders hardware address
.equ ar_spa   =  0x1e                   ;senders IP address
.equ ar_tha   =  0x22                   ;target hardware address
.equ ar_tpa   =  0x28                   ;target IP address
;
; IP header
;
.equ ip_verlen=  0x10                   ;IP version and header length(in longs)
.equ ip_tos   =  0x11                   ;IP type of service
.equ ip_len   =  0x12                   ;packet length (length-header_length)
.equ ip_id    =  0x14                   ;datagram id
.equ ip_fragoff= 0x16                   ;fragment offset
.equ ip_ttl   =  0x18                   ;time to live (in gateway hops)
.equ ip_proto =  0x19                   ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17)
.equ ip_cksum =  0x1a                   ;header checksum
.equ ip_src   =  0x1c                   ;IP address of source
.equ ip_dst   =  0x20                   ;IP addess of destination
.equ ip_data  =  0x24
;
; IP value equates
;
.equ IPT_ICMP =  1                      ;protocol type for ICMP packets
.equ IPT_TCP  =  6                      ;protocol type for TCP packets
.equ IPT_EGP  =  8                      ;protocol type for EGP packets
.equ IPT_UDP  =  0x11                   ;protocol type for UDP packets
;
; ICMP header
;
.equ ic_type  =  ip_data                ;0=reply, 8=request, others=who-cares
.equ ic_code  =  ic_type+1              ;code
.equ ic_cksum =  ic_code+1              ;checksum of header+data
.equ ic_id    =  ic_cksum+2             ;message id
.equ ic_seq   =  ic_id+2                ;sequence number
;
; UDP Header
;
.equ u_src    =  ip_data                ;source udp port number
.equ u_dst    =  u_src+2                ;destination UDP port number
.equ u_len    =  u_dst+2                ;length of UDP header+data
.equ u_cksum  =  u_len+2                ;checksum  (see note)
.equ u_data   =  u_cksum+2              ;start of data
;
; Note: checksum is calculated by taking the 16 bit sums of the ip_src, ip_dst,
; ip_proto, u_len, and the sum starting at u_src for a length of u_len
; yes, this means that u_len is taken twice! u_cksum is zero during the calc.
; The sum is then one's complemented. This is the checksum
;
;
start:
        ldi     wL,low(RAMEND)
        out     SPL,wL
        ldi     wL,high(RAMEND)		    ;setup the stack
        out     SPH,wL
		ldi     wL,$c0		            ;Setup for external
		out     MCUCR,wL		        ; SRAM Enable and Wait State Enable
        ldi     wL,0b11110111           ;PORTE INTR signal input all others output
        out     DDRE,wL                 
        sbi     CSIG,IOR                ;no read
        sbi     CSIG,IOW                ;no write
        sbi     CSIG,CHIPSEL            ;don't select chip
        ser     wL
        out     DDRB,wL                 ;PORTB (Crystal Address Bus) output
        clr     count                   ;packet counter
        Dinput

        ldi     scratch,255             ;wait
        rcall   wait
        
        rcall   lcd_reset               ;reset LCD

        rcall   VerChip                 ;make sure that the CS8900 is connected, Z set if true
        ldi     wL,'>'                  ;success indicator
        breq    VerOK
        ldi     wL,'<'                  ;failure indicator on LCD
VerOK:  rcall   lcd_write
        rcall   ResetChip               ;reset CS8900
        rcall   InitChip                ;initialize CS8900


;
; We already did this in VerChip but get the signature bytes for the CS8900 and display
; them on the LCD. Should be 3000 630E 0500
;
        Dinput
        ior     portPtr+1               ;read PacketPage Ptr for high order byte
        mov     valueH,wL               ;save high low
        ior     portPtr                 ;read PacketPage Ptr for high order byte
        mov     valueL,wL               ;save high low
        rcall   outHL

        ppRD    ppEISA                  ;get the EISA number whoch should be 0x630E
        rcall   outHL

        ppRD    ppProdID                ;get the Product ID which should be 000x xxxx 0000 0000
        rcall   outHL

        clr     flags                   ;Packet flags

loop:
        sbis    PINE,INTR               ;wait for interrupt
        rjmp    loop
        rcall   ProcessISQ              ;process the queue
        sbrs    flags,0                 ;received frame flag
        rjmp    loop
        cbr     flags,1                 ;clear the receive flag
;
; We're going to display on the LCD, t: CC LLLL FFFF
; Where t=r for recieved frame, a=arp request, p=ping request
;       CC=count of frames received so far
;       LLLL=length of this frame
;       FFFF=frame type. For example 0800 for IP, 0806 for ARP
;
        rcall   lcd_clear
        clr     lcdPos  
        inc     lcdPos                  ;start in second LCD position
        ldi     wL,':'
        rcall   lcd_write
		mov		wL,count
        rcall   toHexH
		rcall   lcd_write
        mov		wL,count                ;display the count of received frames
        rcall   toHexL
        rcall   lcd_write
        ldi     wL,' '
        rcall   lcd_write
        lds     valueH,packet+pktLenH   ;display the packet length
        lds     valueL,packet+pktLenL
        rcall   outHL
        lds     valueH,packet+pktTypeH  ;and the packet type
        lds     valueL,packet+pktTypeL
        rcall   outHL

        sbrc    flags,1                 ;bit set when valid arp
        rjmp    ArpRequest
        sbrc    flags,2                 ;bit set when valid UDP Request on port 7
        rjmp    UDP7Request
        sbrc    flags,3                 ;bit set when valid ICMP Ping request received
        rjmp    PingRequest
        clr     lcdPos
        ldi     wL,'r'
        rcall   lcd_write
        rjmp    loop

ArpRequest:
        cbr     flags,2                 ;clear the valid arp request flag
        clr     lcdPos
        ldi     wL,'a'
        rcall   lcd_write
        rcall   WriteARP                ;respond to the ARP request with our IP/MAC
        rjmp    loop
PingRequest:
        cbr     flags,8                 ;clear the valid ICMP ping request flag
        clr     lcdPos
        ldi     wL,'p'
        rcall   lcd_write
        rcall   WritePing               ;respond to the ping
        rjmp    loop
UDP7Request:
        cbr     flags,4                 ;clear the valid UDP port 7 request flag
        clr     lcdPos
        ldi     wL,'u'
        rcall   lcd_write
        rcall   WriteUDP                ;echo reply
        rjmp    loop


;
; Converts the valueH/valueL to hex and displays it on the LCD
;
outHL:
		mov		wL,valueH
        rcall   toHexH
		rcall	lcd_write
        mov		wL,valueH
        rcall   toHexL
        rcall   lcd_write
        mov		wL,valueL
        rcall   toHexH
		rcall	lcd_write
		mov		wL,valueL
        rcall   toHexL
        rcall   lcd_write
        ldi     wL,' '
        rcall   lcd_write
        ret
toHexL:
		andi	wL,0x0f
		ori		wL,0x30
		cpi		wL,0x3a
		brlo	thlX
        ldi     wH,7
		add  	wL,wH
thlX:   ret
toHexH:
		lsr		wL
		lsr		wL
		lsr		wL
		lsr		wL
		ori		wL,0x30
		cpi		wL,0x3a
		brlo	thhX
        ldi     wH,7
		add	    wL,wH
thhX:   ret

;
; Send the reset sequence to the LCD's HD44780 controller. 
;
lcd_reset:
        ldi     scratch,20          ;wait 20 milliseconds
        rcall   wait
		ldi		wL,$30				;Spec said to send this init sequence
		sts		$8000,wL
        ldi     scratch,4
		rcall	wait    			;Wait 4ms
		ldi		wL,$30				;Spec said to send this init sequence
		sts		$8000,wL			;Send init sequence again
		rcall	delay100us			;Wait 100us
		ldi		wL,$30				;Spec said to send this init sequence
		sts		$8000,wL			;and one last time
		rcall	delay100us			;Wait 100us
		ldi		wL,$3F				;Display off
		sts		$8000,wL
        ldi     scratch,4
		rcall	wait    			;Wait 4ms
		ldi		wL,$0F				;Display on
		sts		$8000,wL
        ldi     scratch,4
		rcall	wait    			;Wait 4ms
		ldi		wL,$06				;Entry Mode Set
		sts		$8000,wL
        ldi     scratch,4
		rcall	wait    			;Wait 4ms
        rcall   lcd_clear           ;clear display
        clr     lcdPos              ;position of character on LCD
		ret
;
; Clear the LCD display
;
lcd_clear:
		ldi		wL,$01				;Clear Display
		sts		$8000,wL
        ldi     scratch,4
		rcall	wait    			;Wait 4ms
        clr     lcdPos              ;position of character on LCD
        ret

		
;
; Sends the character in r16 to the LCD. The register "lcdPos" is
; incremented to the next position. The register value is a modulous 8
; and the LCD is broken into two sections (as is typical for HD44780 based LCDs),
; position 0-7 on LCD1 and 0-7 on LCD2.
;
lcd_write:
		mov		r17,lcdPos	
		sbrs	r17,3
		rjmp 	lcd_1
        andi    r17,0x07
		ori		r17,0x40
        rjmp    lcd_2
lcd_1:	andi    r17,0x07
lcd_2:  ori		r17,0x80
		sts		$8000,r17
		rcall	delay40us
		sts		$C000,r16
		rcall	delay40us
		inc		lcdPos
		ret	
		
delay40us:
        push    wL
		ldi		wL,$40
loop3:	dec		wL		
		brne	loop3	
        pop     wL	
		ret

delay100us:
        push    wL
		ldi		wL,$88
loop4:	dec		wL		
		brne	loop4
        pop     wL		
		ret

        
;
; wait for W milliseconds
;
;delay the given number of milliseconds using a software loop
;	Enter:	scratch = number of milliseconds to delay
;	Exit:	scratch,wL,wH = undefined
wait:
wait1:  ldi	    wH,high((ClkFreq / 1000) / 4)
	    ldi     wL,low((ClkFreq / 1000) / 4)
wait2:	subi	wL,1			;(1)
	    sbci	wH,0			;(1)
	    brne	wait2			;(2)
	    dec	    scratch
	    brne	wait1
	    ret

;************************************************************************
;*         C S 8 9 0 0   D r i v e r   F u n c t i o n s                *
;************************************************************************
;
; WriteARP - Send a response ARP to the requestor 
;
WriteARP:
        ldi     zL,low(packet)
        ldi     zH,high(packet)         ;load the z reg with the packet address
        clr     wL
        st      z,wL
        ldi     wL,42  				    ;length of ARP response frame
        std     z+2,wL

; Target HW address MAC (6)
        lds     wL,packet+pktSrc0H
        sts     packet+ar_tha,wL
        sts     packet+pktDest0H,wL
        lds     wL,packet+pktSrc0L
        sts     packet+ar_tha+1,wL
        sts     packet+pktDest0L,wL
        lds     wL,packet+pktSrc1H
        sts     packet+ar_tha+2,wL
        sts     packet+pktDest1H,wL
        lds     wL,packet+pktSrc1L
        sts     packet+ar_tha+3,wL
        sts     packet+pktDest1L,wL
        lds     wL,packet+pktSrc2H
        sts     packet+ar_tha+4,wL
        sts     packet+pktDest2H,wL
        lds     wL,packet+pktSrc2L
        sts     packet+ar_tha+5,wL
        sts     packet+pktDest2L,wL
; Target IP    (4)
        lds     wL,packet+ar_spa
        sts     packet+ar_tpa,wL
        lds     wL,packet+ar_spa+1
        sts     packet+ar_tpa+1,wL
        lds     wL,packet+ar_spa+2
        sts     packet+ar_tpa+2,wL
        lds     wL,packet+ar_spa+3
        sts     packet+ar_tpa+3,wL
; Senders IP    (4)
        ldi     wL,IP1
        sts     packet+ar_spa,wL
        ldi     wL,IP2
        sts     packet+ar_spa+1,wL
        ldi     wL,IP3
        sts     packet+ar_spa+2,wL
        ldi     wL,IP4
        sts     packet+ar_spa+3,wL

; Src HW Address MAC    (6)
        ldi     wL,MAC1
        sts     packet+ar_sha,wL
        sts     packet+pktSrc0H,wL
        ldi     wL,MAC2
        sts     packet+ar_sha+1,wL
        sts     packet+pktSrc0L,wL
        ldi     wL,MAC3    
        sts     packet+ar_sha+2,wL
        sts     packet+pktSrc1H,wL
        ldi     wL,MAC4
        sts     packet+ar_sha+3,wL
        sts     packet+pktSrc1L,wL
        ldi     wL,MAC5
        sts     packet+ar_sha+4,wL
        sts     packet+pktSrc2H,wL
        ldi     wL,MAC6
        sts     packet+ar_sha+5,wL
        sts     packet+pktSrc2L,wL
; Packet type    (2)
        ldi     wL,0x08
        sts     packet+pktTypeH,wL
        ldi     wL,0x06
        sts     packet+pktTypeL,wL
; Hardware type    (2)
        ldi     wL,0x00
        sts     packet+ar_hwtype,wL
        ldi     wL,0x01   
        sts     packet+ar_hwtype+1,wL
; Protocol type (2)
        ldi     wL,0x08
        sts     packet+ar_prtype,wL
        ldi     wL,0x00
        sts     packet+ar_prtype+1,wL
; Hardware and protocol address lengths (2)
        ldi     wL,0x06
        sts     packet+ar_hwlen,wL
        ldi     wL,0x04
        sts     packet+ar_prlen,wL
; Operation (response) (2)
        ldi     wL,0x00
        sts     packet+ar_op,wL
        ldi     wL,0x02
        sts     packet+ar_op+1,wL
        rcall   WritePacket
        ret

;
; WriteUDP - Send a response to the port 7 UDP echo request
;
WriteUDP:
        clr     wL
        sts     packet+ip_cksum,wL      ;clear
        sts     packet+ip_cksum+1,wL    ; checksum

        lds     wL,packet+ip_src        ;move
        sts     packet+ip_dst,wL        ; ip
        lds     wL,packet+ip_src+1      ;  of 
        sts     packet+ip_dst+1,wL      ;   source
        lds     wL,packet+ip_src+2      ;    to
        sts     packet+ip_dst+2,wL      ;     dest
        lds     wL,packet+ip_src+3 
        sts     packet+ip_dst+3,wL
   
        ldi     wL,IP1                  ;move
        sts     packet+ip_src,wL        ; our
        ldi     wL,IP2                  ;  ip
        sts     packet+ip_src+1,wL      ;   address
        ldi     wL,IP3                  ;    to
        sts     packet+ip_src+2,wL      ;     source
        ldi     wL,IP4   
        sts     packet+ip_src+3,wL

        lds     wL,packet+pktSrc0H      ;move
        sts     packet+pktDest0H,wL     ; mac src to dest
        lds     wL,packet+pktSrc0L      
        sts     packet+pktDest0L,wL       
        lds     wL,packet+pktSrc1H      ;move
        sts     packet+pktDest1H,wL     ; mac src to dest
        lds     wL,packet+pktSrc1L      
        sts     packet+pktDest1L,wL       
        lds     wL,packet+pktSrc2H      ;move
        sts     packet+pktDest2H,wL     ; mac src to dest
        lds     wL,packet+pktSrc2L      
        sts     packet+pktDest2L,wL

        ldi     wL,MAC1                 ;move
        sts     packet+pktSrc0H,wL      ; our
        ldi     wL,MAC2                 ;  MAC
        sts     packet+pktSrc0L,wL      ;   address
        ldi     wL,MAC3                 ;    to 
        sts     packet+pktSrc1H,wL      ;     source
        ldi     wL,MAC4
        sts     packet+pktSrc1L,wL
        ldi     wL,MAC5
        sts     packet+pktSrc2H,wL
        ldi     wL,MAC6
        sts     packet+pktSrc2L,wL

        ldi     lengthL,20              ;length of IP header
        clr     lengthH
        ldi     zL,low(packet+ip_verlen)
        ldi     zH,high(packet+ip_verlen)
        rcall   cksum
        sts     packet+ip_cksum,valueH  ;save new IP checksum
        sts     packet+ip_cksum+1,valueL

        lds     wH,packet+u_src         ;get src port
        lds     wL,packet+u_dst         ;put dest port 
        sts     packet+u_src,wL         ;in source
        sts     packet+u_dst,wH         ;put source port in dest

        lds     wH,packet+u_src+1       ;get src port
        lds     wL,packet+u_dst+1       ;put dest port 
        sts     packet+u_src+1,wL       ;in source
        sts     packet+u_dst+1,wH       ;put source port in dest

        clr     wL
        sts     packet+u_cksum,wL       ;clear UDP checksum for new calc
        sts     packet+u_cksum+1,wL     ;clear byte two

        ldi     zl,low(packet+ip_src)
        ldi     zh,high(packet+ip_src)
        lds     lengthH,packet+ip_len
        lds     lengthL,packet+ip_len+1
        ldi     wL,20-8                 ;ip_len-20+8 (20 is the length of an IP header.
        clr     wH                      ;  8 is the length of the two IP fields (ip_src/ip_dst)
        sub     lengthL,wL
        sbc     lengthH,wH
        rcall   cksum

        clr     wH
        lds     wL,packet+ip_proto      ;get protocol (1 byte)
        sub     valueL,wL               ;add to accum
        sbc     valueH,wH
        lds     wH,packet+u_len         ;add in UDP len
        lds     wL,packet+u_len+1
        sub     valueL,wL
        sbc     valueH,wH

        sts     packet+u_cksum,valueH
        sts     packet+u_cksum+1,valueL

        rcall   WritePacket

        ret


;
; WritePing - Send a ICMP Ping response
;
WritePing:
       ;we might want to check in the future for IA or broadcast requests
        clr     wL
        sts     packet+ip_cksum,wL
        sts     packet+ip_cksum+1,wL    ;clear checksum

        lds     wL,packet+ip_src        ;move
        sts     packet+ip_dst,wL        ; ip
        lds     wL,packet+ip_src+1      ;  of 
        sts     packet+ip_dst+1,wL      ;   source
        lds     wL,packet+ip_src+2      ;    to
        sts     packet+ip_dst+2,wL      ;     dest
        lds     wL,packet+ip_src+3 
        sts     packet+ip_dst+3,wL   
        ldi     wL,IP1                  ;move
        sts     packet+ip_src,wL        ; our
        ldi     wL,IP2                  ;  ip
        sts     packet+ip_src+1,wL      ;   address
        ldi     wL,IP3                  ;    to
        sts     packet+ip_src+2,wL      ;     source
        ldi     wL,IP4   
        sts     packet+ip_src+3,wL

        clr     wL
        sts     packet+ic_cksum,wL      ;clear ICMP
        sts     packet+ic_cksum+1,wL    ; checksum

        sts     packet+ic_type,wL       ;make type a reply
        sts     packet+ic_code,wL       ;clear code

        lds     wL,packet+pktSrc0H      ;move
        sts     packet+pktDest0H,wL     ; mac src to dest
        lds     wL,packet+pktSrc0L      
        sts     packet+pktDest0L,wL       
        lds     wL,packet+pktSrc1H      ;move
        sts     packet+pktDest1H,wL     ; mac src to dest
        lds     wL,packet+pktSrc1L      
        sts     packet+pktDest1L,wL       
        lds     wL,packet+pktSrc2H      ;move
        sts     packet+pktDest2H,wL     ; mac src to dest
        lds     wL,packet+pktSrc2L      
        sts     packet+pktDest2L,wL

        ldi     wL,MAC1                 ;move
        sts     packet+pktSrc0H,wL      ; our
        ldi     wL,MAC2                 ;  MAC
        sts     packet+pktSrc0L,wL      ;   address
        ldi     wL,MAC3                 ;    to 
        sts     packet+pktSrc1H,wL      ;     source
        ldi     wL,MAC4
        sts     packet+pktSrc1L,wL
        ldi     wL,MAC5
        sts     packet+pktSrc2H,wL
        ldi     wL,MAC6
        sts     packet+pktSrc2L,wL


        ldi     lengthL,20              ;set length of
        clr     lengthH                 ; checksum calculation =  length of IP header
        ldi     zL,low(packet+ip_verlen);displacement to start of IP header
        ldi     zH,high(packet+ip_verlen)
        rcall   cksum                   ;calculate the checksum

        sts     packet+ip_cksum,valueH  ;set new checksum
        sts     packet+ip_cksum+1,valueL

        lds     lengthH,packet+ip_len   ;get length high
        lds     lengthL,packet+ip_len+1 ;calc length of ICMP header+data
        subi    lengthL,20              ;-length of IP header
        sbci    lengthH,0
        ldi     zL,low(packet+ic_type)  ;start of ICMP header
        ldi     zH,high(packet+ic_type) ;start of ICMP header
        rcall   cksum

        sts     packet+ic_cksum,valueH  ;set new checksum
        sts     packet+ic_cksum+1,valueL

        rcall   WritePacket
ICMPDone:
        ret


;----------------------------------------------------------------------
; Receive Event
; Input with RxEvent in valueH
;
ReceiveEvent:
;
; It's important to read the status and length high-order
; byte first. 
;
        Dinput                          ;make data bus input
        ior     portRxTxData+1          ;read and discard status
        ior     portRxTxData            ;read and discard status
        ldi     yL,low(packet)          ;set indirect
        ldi     yH,high(packet)
        ior     portRxTxData+1          ;get length high
        st      y+,wL                   ;save in header
        mov     lengthH,wL              ; and in lengthH
        ior     portRxTxData            ;get length low
        st      y+,wL                   ;save in header area
        mov     lengthL,wL              ; and in lengthL
        sbrc    lengthL,0               ;odd length?
        adiw    lengthL,1               ;yes, increment lengthL/lengthH by 1
        lsr     lengthH                 ;divide high by 2 and set carry appropriately
        ror     lengthL                 ;rotate carry into lower and divide by 2
ReadFrame:
        ior     portRxTxData            ;read from CS8900
        st      y+,wL                   ;write it to sram
        ior     portRxTxData+1          ;read from CS8900
        st      y+,wL                   ;write it to sram
        sbiw    lengthL,1               ;decrement lengthL/lengthH
        brpl    ReadFrame

        inc     count                   ;increment packet counter
        sbr     flags,1                 ;flag frame read

        lds     wL,packet+pktTypeH      ;check if packet type
        cpi     wL,0x08                 ; is 0x0806 (ARP)
        brne    ChkIP                    
        lds     wL,packet+pktTypeL
        cpi     wL,0x06
        breq    DoArp                    
ChkIP:
        lds     wL,packet+pktTypeH      ;check if packet type
        cpi     wL,0x08                 ; is 0x0806 (ARP)
        brne    REReturn                       
        lds     wL,packet+pktTypeL
        cpi     wL,0x00
        breq    DoIP                    
REReturn:
        ret

;
; It's an arp request, Could be a request or a response.
; ARP packets are small so the whole thing is always in
; the register file.
;
DoArp:
        lds     wL,packet+ar_hwtype+1   ;make sure it's 1
        cpi     wL,0x01
        brne    DoArpX

        lds     wL,packet+ar_prtype     ;compare to high
        cpi     wL,0x08                 ;make sure it's 0x0800
        brne    DoArpX

        lds     wL,packet+ar_prtype+1   ;compare to high
        cpi     wL,0x00                 ;make sure it's 0x0800
        brne    DoArpX

        lds     wL,packet+ar_hwlen      ;make sure it's 6 for hwlen
        cpi     wL,0x06                 ;compare to high
        brne    DoArpX

        lds     wL,packet+ar_prlen      ;make sure it's 4 for protocol length
        cpi     wL,0x04                 ;compare to low
        brne    DoArpX

        lds     wL,packet+ar_op+1       ;make sure it's 0x0001 for arp request
        cpi     wL,0x01                 ;compare to low
        brne    DoArpX

        lds     wL,packet+ar_tpa
        cpi     wL,IP1
        brne    DoArpX        
        lds     wL,packet+ar_tpa+1
        cpi     wL,IP2
        brne    DoArpX        
        lds     wL,packet+ar_tpa+2
        cpi     wL,IP3
        brne    DoArpX        
        lds     wL,packet+ar_tpa+3
        cpi     wL,IP4
        brne    DoArpX        

; If we got to here, then we have a valid ARP request for our IP address

        sbr     flags,2                 ;set ARP flag
DoArpX:
        ret

;
; Process IP packet for ICMP or UDP requests
;
DoIP:
        lds     wL,packet+ip_proto      ;compare to this packet's proto
        cpi     wL,IPT_ICMP             ; to ICMP?
        breq    DoICMP                  ;go process the ICMP packet
        cpi     wL,IPT_UDP              ;  to UDP?
        breq    DoUDP                   ;go process the UDP packet
        ret                             ;just return, we dont process this type

;
; Process UDP Port 7 echo requests
;
DoUDP:
        lds     wL,packet+u_dst+1       ;compare to UDP packet
        cpi     wL,7                    ;port we're listing for requests on
        brne    DoUDPDone
        sbr     flags,4                 ;we have a request for our port 7
DoUDPDone:
        ret

;
; Process ICMP (ping) requests
;
DoICMP:
        sbr     flags,8                 ;set flag to indicate ICMP ping request
        ret


;
; Calc checksum. Reads packet at offset zL/zH for
; lengthH/lengthL bytes and calculates the checksum
; in valueH/valueL.
;
cksum:  clr     chksumL                 ;we do the arithmetic
        clr     chksumM                 ; using a 24
        clr     chksumH                 ;  bit area
	    sbrs    lengthL,0		        ;odd length?
	    rjmp	cksumC
	    mov	    yL,zL
	    mov	    yH,zH
	    add	    yL,lengthL
	    adc	    yH,lengthH
    	clr	    wL
	    st	    y,wL		        	;clear byte after last
	    adiw	lengthL,1
cksumC: lsr	    lengthH
    	ror	    lengthL
cksuml: ld      wH,z+                   ;get high byte of 16-bit word
        ld      wL,z+
        add     chksumL,wL              ;add to accum
        brcc    noLcarry
        ldi     wL,1
        add     chksumM,wL
        brcc    noLcarry
        add     chksumH,wL
noLcarry:
        add     chksumM,wH              ;add in the high byte
        brcc    noHcarry
        inc     chksumH
noHcarry:
        subi    lengthL,1
        sbci    lengthH,0
        clr     wL
        cpi     lengthL,0
        cpc     lengthH,wL
        breq    CkDone
        brpl    cksuml    
CkDone: add     chksumL,chksumH         ;add in the third byte of 24 bit area
        brcc    CkDone1
        inc     chksumM
CkDone1:mov     valueL,chksumL
	    com	    valueL
        mov     valueH,chksumM
	    com	    valueH
        ret


;
; Transmit Event
;
TransmitEvent:
        ret
;
; Processes the pending interrupt requests from the Interrupt Status Queue
;
ProcessISQ:
        ; Read the ISQ
NextEvt:
        Dinput
        ior     portISQ                 ;read interrupt status queue
        mov     valueL,wL               ;save value low
        ior     portISQ+1               ;read interrupt status queue high
        mov     valueH,wL               ;save value high
        tst     valueL                  ;get val
        breq    EvtRet
        cpi     valueL,REG_NUM_RX_EVENT 
        breq    evtRecv
        cpi     valueL,REG_NUM_TX_EVENT 
        breq    evtTran                 ;Ingore BufEvent, RxMiss, and TxCol
        rjmp    NextEvt
evtRecv:
        rcall   ReceiveEvent
        rjmp    NextEvt
evtTran:
        rcall   TransmitEvent
        rjmp    NextEvt
EvtRet: ret


;
; Initializes the chip 
;
InitChip:
         ppWR   ppLineCtl,LINE_CTL_10BASET  ;set to 10BaseT
         ppWR   ppTestCtl,TEST_CTL_FDX      ;set to full duplex
         ppWR   ppRxCfg,RX_CFG_RX_OK_IE     ;enable RxOK interrupt
         ppWR   ppRxCtl,(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A)
         ppWR   ppTxCfg,TX_CFG_ALL_IE
;
; Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff
;
         ppWR   ppIndAddr,(MAC2<<8|MAC1)    ;0xbbaa Write
         ppWR   ppIndAddr+2,(MAC4<<8|MAC3)  ;0xddcc  out
         ppWR   ppIndAddr+4,(MAC6<<8|MAC5)  ;0xffee   48 bit IA
         ppWR   ppIntNum,0x00               ;INT is on INTRQ0

         ppRD   ppBusCtl                    ;get Bus Control
         sbr    valueH,0x80                 ;enable irq
         rcall  WritePP


         ppRD   ppLineCtl                   ;get Line Control
         sbr    valueL,0xc0                 ;set SerRxOn and SerTxOn
         rcall  WritePP
         ret

;
; Resets the CS8900
;
ResetChip: 
        ppWR    ppSelfCtl,SELF_CTL_RESET ;issue a reset to the chip
ResetWait:
        ldi     scratch,1               ;wait for
        rcall   wait                    ;a millisecond
        ppRD    ppSelfCtl               ;get the Self Control status
        sbrc    valueL,6                ;see it bit 6 (RESET) was cleared
        rjmp    ResetWait               ;no, then still in reset, wait some more
        ppRD    ppSelfSt                ;get self status
        sbrs    valueL,7                ;bit 7 is INITD     
        rjmp    ResetWait               ; when set, initialization of the CS8900 is done
        ret
    
;
; Verifies that the CS8900 is attached and sets the STATUS,Z flag to
; indicate success or not set if failure.
;
VerChip:
        Dinput                          ;make the data bus input
        ; first, get the signature at portPtr which should be 0x3000
        ior     portPtr                 ;read PacketPage Ptr
        mov     valueL,wL               ;save value low
        ior     portPtr+1               ;read PacketPage Ptr for high order byte
        mov     valueH,wL               ;save high low
        tst     valueL                  ;should be 0 (i.e. 0x3000 low is 0x00)
        brne    VerBad
        cpi     valueH,0x30             ;high part of 0x3000
        brne    VerBad
        ppRD    ppEISA                  ;get the EISA number whoch should be 0x630E
        cpi     valueL,0x0e
        brne    VerBad
        cpi     valueH,0x63
        brne    VerBad
        ppRD    ppProdID                ;get the Product ID which should be 000x xxxx 0000 0000
                                        ;where x xxxx = 0 0011 for rev E and 0 0101 for rev F
        tst     valueL                  ;set return status
VerBad: ret                             ;return with Z indicating success or not.

;
; Writes the packet for lengthL/lengthH
;
WritePacket:
        Doutput
        ldi     wL,TX_CMD_START_ALL
        iow     portTxCmd
        clr     wL
        iow     portTxCmd+1
        lds     wL,packet+pktLenL       ;length 
        iow     portTxLength            ; of packet 
        lds     wL,packet+pktLenH       ;  to send
        iow     portTxLength+1
WPGetStat:
        ppRD    ppBusSt                 ;get BusStatus
        sbrs    valueH,0                ;is BUS_ST_RDY4TXNOW (ready for transmit)
        rjmp    WPGetStat               ;no, wait for it

        Doutput
        ldi     zL,low(packet+pktDest0H)
        ldi     zH,high(packet+pktDest0H)
        lds     lengthH,packet+pktLenH
        lds     lengthL,packet+pktLenL
        sbrs    lengthL,0               ;odd length?
        rjmp    PacketEven              ;nope, continue
        adiw    lengthL,1               ;increment length
PacketEven:
        lsr     lengthH                 ;divide high by 2 and set carry appropriately
        ror     lengthL                 ;rotate carry into lower and divide by 2
PacketWriteLoop:
        ld      wL,z+                   ;get next byte
        iow     portRxTxData
        ld      wL,z+                   ;get next byte
        iow     portRxTxData+1
        sbiw    lengthL,1               ;decrement lengthL/lengthH
        brpl    PacketWriteLoop         
        ret


;
; Writes the value at valueH/valueL to the PagePacket register who's
; address is in offsetH/offsetL
;
WritePP:
        Doutput                         ;make the data bus output
        mov     wL,offsetL              ;get the low order byte
        iow     portPtr                 ;write to PacketPage Ptr
        mov     wL,offsetH              ;get the high order byte
        iow     portPtr+1               ;write to PacketPage ptr
        mov     wL,valueL               ;get low order value to write
        iow     portData                ;write to PacketPage data
        mov     wL,valueH               ;get high order data
        iow     portData+1              ;write to PacketPage data
        ret
;
; Reads the PagePacket at offsetH/offsetL and returns the result in
; valueH/valueL.
;
ReadPP:
        Doutput                         ;make the data bus output
        mov     wL,offsetL              ;get the offset to read
        iow     portPtr                 ;write to PacketPage Ptr
        mov     wL,offsetH              ;get the high order offset
        iow     portPtr+1               ;PagePacket Pointer Register high byte
        Dinput                          ;make the data bus input
        ior     portData                ;read the PacketPage data
        mov     valueL,wL               ;save value low
        ior     portData+1              ;read the high order byte
        mov     valueH,wL               ;save the high order byte value
        ret

ioRead:
        out     CAB,wL
        cbi     CSIG,CHIPSEL
        cbi     CSIG,IOR    
        nop
        nop
        in      wL,PIND      
        sbi     CSIG,IOR    
        sbi     CSIG,CHIPSEL
        ret
;
ioWrite:
        cbi     CSIG,CHIPSEL
        cbi     CSIG,IOW      
        nop
        sbi     CSIG,IOW       
        sbi     CSIG,CHIPSEL  
        ret




file: /Techref/atmel/avr/tcpip/atmel-crystal.asm, 43KB, , updated: 1999/6/4 13:02, local time: 2024/10/3 12:44,
TOP NEW HELP FIND: 
3.237.15.145:LOG IN
©2024 PLEASE DON'T RIP! THIS SITE CLOSES OCT 28, 2024 SO LONG AND THANKS FOR ALL THE FISH!

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/techref/atmel/avr/tcpip/atmel-crystal.asm"> atmel avr tcpip atmel-crystal</A>

Did you find what you needed?

 

Welcome to massmind.org!

 

Welcome to massmind.org!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .