C guru needed

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
User avatar
JWinters
Posts: 106
Joined: Mon Feb 04, 2008 4:56 pm
Location: North Carolina, USA
Contact:

C guru needed

Post by JWinters » Sun May 18, 2008 1:54 am

I'm trying to port some C code to make the TCP/IP stack work with the 18F97J60 family. I know just enough C to be dangerous so it's been a slow process. The following function has stumped me. How in the world do I translate something like PRODL = ((WORD_VAL*)&Data)->v[0]; into SF? It looks like there is some pointer magic going on there but I've never even seen a "->" operator before.

Code: Select all

/******************************************************************************
 * Function:        WritePHYReg
 *
 * PreCondition:    Ethernet module must be enabled (ECON1.ETHEN = 1).
 *
 * Input:           Address of the PHY register to write to.
 *					16 bits of data to write to PHY register.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        WritePHYReg performs an MII write operation.  While in 
 *					progress, it simply polls the MII BUSY bit wasting time 
 *					(10.24us).
 *
 * Note:            None
 *****************************************************************************/
void WritePHYReg(BYTE Register, WORD Data)
{
	BYTE GIESave;

	// Write the register address
	MIREGADR = Register;

	// Write the data through the MIIM interface
	// Order is important: write low byte first, high byte last
	//
	// Due to a silicon problem, you cannot access any register with LSb address 
	// bits of 0x16 between your write to MIWRL and MIWRH or else the value in 
	// MIWRL will be corrupted.  This inline assembly prevents this by copying 
	// the value to PRODH:PRODL first, which is at fixed locations of 
	// 0xFF4:0xFF3.  These addresses have LSb address bits of 0x14 and 0x13.
	// Interrupts must be disabled to prevent arbitrary ISR code from accessing
	// memory with LSb bits of 0x16 and corrupting the MIWRL value.
	PRODL = ((WORD_VAL*)&Data)->v[0];
	PRODH = ((WORD_VAL*)&Data)->v[1];
	GIESave = INTCON & 0xC0;		// Save GIEH and GIEL bits
	INTCON &= 0x3F;					// Clear INTCONbits.GIEH and INTCONbits.GIEL
	#if defined(HI_TECH_C)
		asm("movff	_PRODL, _MIWRL");
		asm("nop");
		asm("movff	_PRODH, _MIWRH");
	#else
		_asm
		movff	PRODL, MIWRL
		nop
		movff	PRODH, MIWRH
		_endasm
	#endif
	INTCON |= GIESave;				// Restore GIEH and GIEL value

	// Wait until the PHY register has been written
	// This operation requires 10.24us
    while(MISTATbits.BUSY);
}//end WritePHYReg   
Would this be a correct translation?

Code: Select all

   PRODL = @Data.Byte0
   PRODH = @Data.Byte1

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Sun May 18, 2008 9:35 am

The joys of porting C.

Code: Select all

((WORD_VAL*)&Data)->v[0]
ported to swordfish is just

Code: Select all

Data.Byte0
No pointers are required. If you examine 'WritePHYReg()' in 'ENC28J60.bas' you will see

Code: Select all

Sub WritePHYReg(Register As Byte, Data As Word)
   Dim RegVal As REG
   
   // Write the register address
   BankSel(MIREGADR)
   WriteReg(Byte(MIREGADR), Register)
	
   // Write the data
   // Order is important: write low byte first, high byte last
   WriteReg(Byte(MIWRL), Data.Byte0)  // 1st byte
   WriteReg(Byte(MIWRH), Data.Byte1)  // 2nd byte

   // Wait until the PHY register has been written
   BankSel(MISTAT)
   RegVal = ReadMACReg(Byte(MISTAT))
   While RegVal.MISTATbits.BUSY
      RegVal = ReadMACReg(Byte(MISTAT))
   Wend
   BankSel(ERDPTL)	// Return to Bank 0
End Sub
which has been ported from the following

Code: Select all

void WritePHYReg(BYTE Register, WORD Data)
{
	// Write the register address
	BankSel(MIREGADR);
	WriteReg((BYTE)MIREGADR, Register);
	
	// Write the data
	// Order is important: write low byte first, high byte last
	WriteReg((BYTE)MIWRL, ((WORD_VAL*)&Data)->v[0]);	
	WriteReg((BYTE)MIWRH, ((WORD_VAL*)&Data)->v[1]);

	// Wait until the PHY register has been written
	BankSel(MISTAT);
	while(ReadMACReg((BYTE)MISTAT).MISTATbits.BUSY);

	BankSel(ERDPTL);	// Return to Bank 0
}//end WritePHYReg
Note the use of (WORD_VAL*)&Data)->v[0] in the above...

tass
Posts: 19
Joined: Sat Jan 19, 2008 8:37 am
Location: France

Post by tass » Sun May 18, 2008 12:04 pm

hi jwinters,
i have made the porting few weeks ago but i have no tested it because i have no hardware at this time so i will be very happy if you test an debug it
here is wat i have do:

Code: Select all

{
 *****************************************************************************
 *  Name    : ETH97J60.BAS                                                   *
 *  Date    : 03/04/2008                                                     *
 *  Version : 1.0 - Based around Microchip TCP/IP stack version 4.18         *
 *  Notes   :                                                                *
 * ========================================================================= *
 *	Medium Access Control (MAC) Layer for Microchip PIC18F97J60 family       * 
 *  Module for Microchip TCP/IP Stack                                        *
 *	 -Provides access to PIC18F97J60 family Ethernet controller              *
 *	 -Reference: PIC18F97J60 Family data sheet, IEEE 802.3 Standard          *
 *                                                                           *
 *****************************************************************************
 * Software License Agreement                                                *
 *                                                                           *
 * Copyright © 2002-2007 Microchip Technology Inc.  All rights               *
 * reserved.                                                                 *
 *                                                                           *
 * Microchip licenses to you the right to use, modify, copy, and             *
 * distribute:                                                               *
 * (i)  the Software when embedded on a Microchip microcontroller or         *
 *      digital signal controller product (“Device”) which is                *
 *      integrated into Licensee’s product  or                               *
 * (ii) ONLY the Software driver source files ENC28J60.c and                 *
 *      ENC28J60.h ported to a non-Microchip device used in                  *
 *      conjunction with a Microchip ethernet controller for the             *
 *      sole purpose of interfacing with the ethernet controller.            *
 *                                                                           *
 * You should refer to the license agreement accompanying this               *
 * Software for additional information regarding your rights and             *
 * obligations.                                                              *
 *                                                                           *
 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT               *
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT        *
 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A                *
 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL         *
 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR              *
 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF                 *
 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS       *
 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE                *
 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER              *
 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT            *
 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.                 *
 *****************************************************************************
                                                                             
                                                                             
                                                                             
/(*********************** D E F I N I T I O N S ******************************
// Since the Ethernet PHY doesn't support auto-negotiation, full-duplex mode is 
// not compatible with most switches/routers.  If a dedicated network is used 
// where the duplex of the remote node can be manually configured, you may 
// change this configuration.  Otherwise, half duplex should always be used.}

Module ETH97J60

Include "NETConfig.bas"
Include "NETTypes.bas"
Include "NETUtils.bas"
Include "system.bas"

#define HALF_DUPLEX
//#define FULL_DUPLEX

// Rest are Receive Buffers
Public Const
   MAC_IP      = ($00),
   MAC_ARP     = ($06),
   MAC_UNKNOWN = ($FF) 
   
Const
   ETHER_IP     = ($00),
   ETHER_ARP    = ($06)
   // A generic structure representing the Ethernet header starting all Ethernet 
// frames
Public Structure MAC_ETHER_HEADER
   DestMACAddr As MAC_ADDR
   SourceMACAddr As MAC_ADDR
   _Type As WORD_VAL
End Structure
  
  // TXSTATUS bits...
Structure TXBits
   v(7) As Byte
   ByteCount As v(0).AsWord                  // 16
   _CollisionCount As v(2)                   // 4
   CRCError As v(2).4                        // 1
   LengthCheckError As v(2).5                // 1
   LengthOutOfRange As v(2).6                // 1
   Done As v(2).7                            // 1
   Multicast As v(3).0                       // 1
   Broadcast As v(3).1                       // 1
   PacketDefer As v(3).2                     // 1
   ExcessiveDefer As v(3).3                  // 1
   MaximumCollisions As v(3).4               // 1
   LateCollision As v(3).5                   // 1
   Giant As v(3).6                           // 1
   Underrun As v(3).7                        // 1
   BytesTransmittedOnWire As v(4).AsWord     // 16
   ControlFrame As v(6).0                    // 1
   PauseControlFrame As v(6).1               // 1
   BackpressureApplied As v(6).2             // 1
   VLANTaggedFrame As v(6).3                 // 1
                                             // 4 zeros
   End Structure
   // TXSTATUS...
Structure TXStatus
   v(7) As Byte
   Bits As TXBits Union
End Structure

// RXSTATUS bits...
Structure RXBits
   v(4) As Byte
   ByteCount As v(0).AsWord           // 16
   PreviouslyIgnored As v(2).0        // 1
   RXDCPreviouslySeen As v(2).1       // 1
   CarrierPreviouslySeen As v(2).2    // 1
   CodeViolation As v(2).3            // 1
   CRCError As v(2).4                 // 1
   LengthCheckError As v(2).5         // 1
   LengthOutOfRange As v(2).6         // 1
   ReceiveOk As v(2).Booleans(7)      // 1
   Multicast As v(3).0                // 1
   Broadcast As v(3).1                // 1
   DribbleNibble As v(3).2            // 1
   ControlFrame As v(3).3             // 1
   PauseControlFrame As v(3).4        // 1
   UnsupportedOpcode As v(3).5        // 1 
   VLANType As v(3).6                 // 1
   zero As v(3).7                    // 1 zero
End Structure   

// RXSTATUS
Structure RXSTATUS
   v(4) As Byte
   Bits As RXBits Union
End Structure
// A header appended at the start of all RX frames by the hardware
Structure ENC_PREAMBLE
   NextPacketPointer As Word
   StatusVector As RXSTATUS
   DestMACAddr As MAC_ADDR
   SourceMACAddr As MAC_ADDR
   _Type As WORD_VAL
End Structure

// Internal MAC level variables and flags.
Dim
   NextPacketLocation As WORD_VAL,
   CurrentPacketLocation As WORD_VAL,
   WasDiscarded As Boolean,
   wTXWatchdog As Word,
   TxRequestToSend As ECON1.booleans(3),
   PHYClockIsReady As ESTAT.booleans(0),
   BUSY As MISTAT.booleans(0),
   DMAST As ECON1.booleans(5)
Public Const
   MAC_TX_BUFFER_SIZE = _MAC_TX_BUFFER_SIZE,
   RAMSIZE = _RAMSIZE,
   TXSTART = _TXSTART,
   RXSTART = _RXSTART,
   RXSTOP = _RXSTOP,
   RXSIZE = _RXSIZE,
   BASE_TX_ADDR = _BASE_TX_ADDR,
   BASE_TCB_ADDR = _BASE_TCB_ADDR,
   BASE_HTTPB_ADDR = _BASE_HTTPB_ADDR
   


Structure TPHCON1
   Val As Word
   PDPXMD As Val.8
   PPWRSV As Val.11
   PLOOPBK As Val.14
   PRST As Val.15
End Structure

Structure TPHSTAT1
   Val As Word
   JBSTAT As Val.1
   LLSTAT As Val.Booleans(2)
   PHDPX As Val.11
   PFDPX As Val.12
End Structure

Structure TPHID2
   Val As Word
   PREV0 As Val.0
   PREV1 As Val.1
   PREV2 As Val.2
   PREV3 As Val.3
   PPN0 As Val.4
   PPN1 As Val.5
   PPN2 As Val.6
   PPN3 As Val.7
   PPN4 As Val.8
   PPN5 As Val.9
   PID19 As Val.10
   PID20 As Val.11
   PID21 As Val.12
   PID22 As Val.13
   PID23 As Val.14
   PID24 As Val.15
   
   // alt
   PREV As Val         // 0..3   (bits 4)
   PPNL As Val         // 4..7   (bits 4)
   PPNH As Val.Byte1   // 8..9   (bits 2)
   PID As Val.Byte1    // 10..15 (bits 6)
End Structure

Structure TPHCON2
   Val As Word
   HDLDIS As Val.8
   JABBER As Val.10
   TXDIS As Val.13
   FRCLNK As Val.14
End Structure

Structure TPHSTAT2
   Val As Word
   PLRITY As Val.5
   DPXSTAT As Val.9
   LSTAT As Val.10
   COLSTAT As Val.11
   RXSTAT As Val.12
   TXSTAT As Val.13
End Structure

Structure TPHIE
   Val As Word
   PGEIE As Val.1
   PLNKIE As Val.4
End Structure

Structure TPHIR
   Val As Word
   PGIF As Val.2
   PLNKIF As Val.4
End Structure

Structure TPHLCON
   Val As Word
   STRCH As Val.1
   LFRQ0 As Val.2
   LFRQ1 As Val.3
   LBCFG0 As Val.4
   LBCFG1 As Val.5
   LBCFG2 As Val.6
   LBCFG3 As Val.7
   LACFG0 As Val.8
   LACFG1 As Val.9
   LACFG2 As Val.10
   LACFG3 As Val.11

   // alt...
   LFRQ As Val         // 2..3  (bits 2)
   LBCFG As Val        // 4..7  (bits 4)
   LACFG As Val.Byte1  // 8..11 (bits 4)
End Structure

Public Structure PHYREG
   Val As WORD_VAL
   PHCON1bits As TPHCON1 Union
   PHSTAT1bits As TPHSTAT1 Union
   PHID2bits As TPHID2 Union
   PHCON2bits As TPHCON2 Union
   PHSTAT2bits As TPHSTAT2 Union
   PHIEbits As TPHIE Union
   PHIRbits As TPHIR Union
   PHLCONbits As TPHLCON Union
End Structure
 // PH Register Locations
Public Const
   PHCON1       = $00,
   PHSTAT1	    = $01,
   PHID1	    = $02,
   PHID2	    = $03,
   PHCON2	    = $10,
   PHSTAT2	    = $11,
   PHIE	        = $12,
   PHIR	        = $13,
   PHLCON	    = $14



{*******************************************************************************
* Individual Register Bits
********************************************************************************}
Const
// ETH/MAC/MII bits

// EIE bits ----------
	EIE_PKTIE	=	(1<<6),
	EIE_DMAIE	=	(1<<5),
	EIE_LINKIE	=	(1<<4),
	EIE_TXIE	=	(1<<3),
	EIE_TXERIE	=	(1<<1),
	EIE_RXERIE	=	(1),

// EIR bits ----------
	EIR_PKTIF	=	(1<<6),
	EIR_DMAIF	=	(1<<5),
	EIR_LINKIF	=	(1<<4),
	EIR_TXIF	=	(1<<3),
	EIR_TXERIF	=	(1<<1),
	EIR_RXERIF	=	(1),
	
// ESTAT bits ---------
	ESTAT_BUFER	=	(1<<6),
	ESTAT_RXBUSY =	(1<<2),
	ESTAT_TXABRT =	(1<<1),
	ESTAT_PHYRDY =	(1),
	
// ECON2 bits --------
	ECON2_AUTOINC =	(1<<7),
	ECON2_PKTDEC =	(1<<6),
	ECON2_ETHEN	 =	(1<<5),
	
// ECON1 bits --------
	ECON1_TXRST	=	(1<<7),
	ECON1_RXRST	= 	(1<<6),
	ECON1_DMAST	=	(1<<5),
	ECON1_CSUMEN =	(1<<4),
	ECON1_TXRTS	=	(1<<3),
	ECON1_RXEN	=	(1<<2),
	
// ERXFCON bits ------
	ERXFCON_UCEN =	(1<<7),
	ERXFCON_ANDOR =	(1<<6),
	ERXFCON_CRCEN =	(1<<5),
	ERXFCON_PMEN =	(1<<4),
	ERXFCON_MPEN =  (1<<3),
	ERXFCON_HTEN =	(1<<2),
	ERXFCON_MCEN =	(1<<1),
	ERXFCON_BCEN =	(1),
	
// MACON1 bits --------
	MACON1_TXPAUS =	(1<<3),
	MACON1_RXPAUS =	(1<<2),
	MACON1_PASSALL =(1<<1),
	MACON1_MARXEN =	(1),
	
// MACON3 bits --------
	MACON3_PADCFG2	=    (1<<7),
	MACON3_PADCFG1	=    (1<<6),
	MACON3_PADCFG0	=    (1<<5),
	MACON3_TXCRCEN	=    (1<<4),
	MACON3_PHDREN	=    (1<<3),
	MACON3_HFRMEN	=    (1<<2),
	MACON3_FRMLNEN	=    (1<<1),
	MACON3_FULDPX	=    (1),
	
// MACON4 bits --------
	MACON4_DEFER	=    (1<<6),
	
// MICMD bits ---------
	MICMD_MIISCAN	=    (1<<1),
	MICMD_MIIRD		=    (1),

// MISTAT bits --------
	MISTAT_NVALID	=    (1<<2),
	MISTAT_SCAN		=    (1<<1),
	MISTAT_BUSY		=    (1),
	
// EFLOCON bits -----
	EFLOCON_FCEN1	=    (1<<1),
	EFLOCON_FCEN0	=    (1),



// PHY bits

// PHCON1 bits ----------
	PHCON1_PDPXMD	As Word =    (1<<8),

// PHSTAT1 bits --------
	PHSTAT1_LLSTAT	As Word =    (1<<2),

// PHCON2 bits ----------
	PHCON2_FRCLNK	As Word =    (1<<14),
	PHCON2_HDLDIS	As Word =    (1<<8),
 PHCON2_RXAPDIS	As Word =    (1<<4),

// PHSTAT2 bits --------
	PHSTAT2_TXSTAT	As Word =    (1<<13),
	PHSTAT2_RXSTAT	As Word =    (1<<12),
	PHSTAT2_COLSTAT	As Word =    (1<<11),
	PHSTAT2_LSTAT	As Word =    (1<<10),

// PHIE bits -----------
	PHIE_PLNKIE		As Word =    (1<<4),
	PHIE_PGEIE		As Word =    (1<<1),

// PHIR bits -----------
	PHIR_PLNKIF		As Word =    (1<<4),
	PHIR_PGIF		As Word =    (1<<2),

// PHLCON bits -------
	PHLCON_LACFG3	As Word =    (1<<11),
	PHLCON_LACFG2	As Word =    (1<<10),
	PHLCON_LACFG1	As Word =    (1<<9),
	PHLCON_LACFG0	As Word =    (1<<8),
	PHLCON_LBCFG3	As Word =    (1<<7),
	PHLCON_LBCFG2	As Word =    (1<<6),
	PHLCON_LBCFG1	As Word =    (1<<5),
	PHLCON_LBCFG0	As Word =    (1<<4),
	PHLCON_LFRQ1	As Word =    (1<<3),
	PHLCON_LFRQ0    As Word =    (1<<2),
	PHLCON_STRCH    As Word	=    (1<<1)


 (******************************************************************************
 * Function:         MACPut(Byte Val)
 *
 * PreCondition:    EWRPT must point To the location To begin writing.
 *
 * Input:           Byte To Write into the Ethernet buffer memory
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Writes To the EDATA Register, which will indirectly 
*					increment EWRPTH:EWRPTL.
 *
 * Note:            None
 *****************************************************************************)
Public Sub MACPut(Val As Byte)

	// Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
	// write to EDATA or else the read pointer (ERDPT) will inadvertently 
	// increment.
	PRODL = Val 

		ASM
        movff	PRODL, EDATA 
        End ASM
End Sub
(******************************************************************************
 * Function:        Byte MACGet()
 *
 * PreCondition:    ERDPT must point To the place To Read from.
 *
 * Input:           None
 *
 * Output:          Byte Read from the Ethernet's buffer RAM
 *
 * Side Effects:    None
 *
 * Overview:        MACGet returns the Byte pointed To by ERDPT And 
 *					increments ERDPT so MACGet() can be called again.  The 
 *					increment will follo the receive buffer wrapping boundary.
 *
 * Note:            For better performance, implement this Function As a macro:
 *					#define MACGet()	(EDATA)
 *****************************************************************************)
Public Function MACGet() As EDATA
   // result = EDATA 
End Function
//end MACGet

(******************************************************************************
 * Function:        Word MACGetArray(Byte *Val, Word len)
 *
 * PreCondition:    ERDPT must point To the place To Read from.
 *
 * Input:           *Val: Pointer To storage location
 *					len:  Number of Bytes To Read from the data buffer.
 *
 * Output:          Byte(s) of data Read from the data buffer.
 *
 * Side Effects:    None
 *
 * Overview:        Reads several sequential Bytes from the data buffer 
 *					And places them into local memory.  ERDPT is incremented 
 *					after each Byte, folloing the same rules As MACGet().
 *
 * Note:            None
 *****************************************************************************)
 Public Function MACGetArray(Val As Word, Len As Word) As Word 
   Dim i As Word
   Dim Dummy As Byte

   	
   Dec(Val)
  
   // Read the data
   While i < Len 
	  Inc(i)
      If Val <> 0 Then
         Inc(Val)        
         FSR0 = Val
         INDF0 = EDATA
      Else
  	     Dummy = EDATA
      EndIf 
   Wend
   result = i  
End Function



(******************************************************************************
 * Function:         MACPutArray(Byte *Val, Word len)
 *
 * PreCondition:    EWRPT must point To the location To begin writing.
 *
 * Input:           *Val: Pointer To source of Bytes To copy.
 *					len:  Number of Bytes To Write To the data buffer.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPutArray writes several sequential Bytes To the 
 *					Ethernet buffer RAM.  It performs faster than multiple MACPut()
 *					calls.  EWRPT is incremented by len.
 *
 * Note:            None
 *****************************************************************************)

Public Sub MACPutArray(Val As Word, Len As Word)
  
   	// Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
		// write to EDATA or else the read pointer (ERDPT) will inadvertently 
		// increment.
   While Len <> 0
      FSR0 = Val
      PRODL = INDF0	// Start sending the byte
      ASM
        movff	PRODL, EDATA 
      End ASM
      Inc(Val)				
      Dec(Len)				     
   Wend
End Sub

(******************************************************************************
 * Function:        ReadPHYReg
 *
 * PreCondition:    Ethernet Module must be enabled (ECON1.ETHEN = 1).
 *
 * Input:           Address of the PHY Register To Read from.
 *
 * Output:          16 Bits of data Read from the PHY Register.
 *
 * Side Effects:    None
 *
 * Overview:        ReadPHYReg performs an MII Read operation.  While in 
 *					progress, it simply polls the MII BUSY Bit wasting time 
 *					(10.24us).
 *
 * Note:            None
 *****************************************************************************)
 Function ReadPHYReg(Register As Byte) As PHYREG 

	Dim Res As PHYREG

	// Set the right address and start the register read operation
    MIREGADR = Register  Nop() 
    MICMD = MICMD_MIIRD  Nop() 

	// Loop to wait until the PHY register has been read through the MII
	// This requires 10.24us
    While BUSY  
    Wend
	// Stop reading
    MICMD = $00  Nop() 
	
	// Obtain results and return
    Res.Val.v(0) = MIRDL 
    Nop() 
    Res.Val.v(1) = MIRDH 

	Result = Res
End Function
  {******************************************************************************
 * Function:        WritePHYReg
 *
 * PreCondition:    Ethernet Module must be enabled (ECON1.ETHEN = 1).
 *
 * Input:           Address of the PHY Register To write To.
 *					16 Bits of data To write To PHY Register.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        WritePHYReg performs an MII write operation.  While in 
 *					progress, it simply polls the MII BUSY Bit wasting time 
 *					(10.24us).
 *
 * Note:            None
 *****************************************************************************}
Sub  WritePHYReg( Register As Byte,  Data As Word)

	// Write the data through the MIIM interface
	// Order is important: write lo byte first,  hi byte last
	//
	// Due to a silicon problem, you cannot access any register with LSb address 
	// bits of $16 between your write to MIWRL and MIWRH or else the value in 
	// MIWRL will be corrupted.  This inline assembly prevents this by copying 
	// the value to PRODH:PRODL first, which is at fixed locations of 
	// $FF4:$FF3.  These addresses have LSb address bits of $14 and $13.
	// Interrupts must be disabled to prevent arbitrary ISR code from accessing
	// memory with LSb bits of $16 and corrupting the MIWRL value.
	
  Dim GIESave As Byte
  GIESave = INTCON And $C0  		  // Save GIEH and GIEL bits
  INTCON = INTCON And $3F  				  // Clear INTCONbits.GIEH and INTCONbits.GIEL 
  MIREGADR = register       // Address to MIREGADR
  PRODL = data.Byte0
  PRODH = data.Byte1  
  MIWRL = PRODL                     // Lo byte to MIWRL
  MIWRH = PRODH                     // Hi byte to MIWRH
  INTCON = INTCON Or GIESave    // Restore GIEH and GIEL value
  // Wait until the PHY register has been written
  // This operation requires 10.24us
   While BUSY Wend
 End Sub
 (*
 ******************************************************************************
 * Macro:        	void SetLEDConfig(Word NewConfig)
 * PreCondition:    SPI bus must be initialized (done in MACInit()).
 * Input:           NewConfig - xxx0: Pulse stretching disabled
 *								xxx2: Pulse stretch To 40ms (default)
 *								xxx6: Pulse stretch To 73ms
 *								xxxA: Pulse stretch To 139ms
 *								
 *								xx1x: LEDB - TX
 *								xx2x: LEDB - RX (default)
 *								xx3x: LEDB - collisions
 *								xx4x: LEDB - link
 *								xx5x: LEDB - duplex
 *								xx7x: LEDB - TX And RX
 *								xx8x: LEDB - on
 *								xx9x: LEDB - off
 *								xxAx: LEDB - blink fast
 *								xxBx: LEDB - blink slow
 *								xxCx: LEDB - link And RX
 *								xxDx: LEDB - link And TX And RX
 *								xxEx: LEDB - duplex And collisions
 *
 *								x1xx: LEDA - TX
 *								x2xx: LEDA - RX
 *								x3xx: LEDA - collisions
 *								x4xx: LEDA - link (default)
 *								x5xx: LEDA - duplex
 *								x7xx: LEDA - TX And RX
 *								x8xx: LEDA - on
 *								x9xx: LEDA - off
 *								xAxx: LEDA - blink fast
 *								xBxx: LEDA - blink slow
 *								xCxx: LEDA - link And RX
 *								xDxx: LEDA - link And TX And RX
 *								xExx: LEDA - duplex And collisions
 * Output:          None
 * Side Effects:    None
 * Overview:        Writes the value of NewConfig into the PHLCON PHY register.  
 *					The LED pins will beginning outputting the new 
 *					configuration immediately.
 * Note:            
 *****************************************************************************/
*)
Public Sub SetLEDConfig(NewConfig As Word)
   WritePHYReg(PHLCON, NewConfig)
End Sub
{******************************************************************************
 * Function:         MACInit()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACInit enables the Ethernet Module, waits For the 
 *                  To become ready, And programs all registers For future 
 *                  TX/RX operations.
 *
 * Note:            This Function blocks For at least 1ms, waiting For the 
 *                  hardware To stabilize.
 *****************************************************************************}
Public Sub MACInit()
//Dim i As Byte 
  LATA.0 = 0
  LATA.1 = 0
  TRISA.0 = 0   // Set LED0 as output
  TRISA.1 = 0   // Set LED1 as output
  FSR2 = AddressOf(ECON2)
  INDF2.5 = 1      // Enable Ethernet!
 // FSR2 = AddressOf(ESTAT)
  While Not PHYClockIsReady Wend//INDF2.0 <> 1 Wend   // Wait for PHYRDY to become set.
  DelayMS(1)
   
   // Configure the receive buffer boundary pointers 
	// and the buffer write protect pointer (receive buffer read pointer)
	WasDiscarded = TRUE
	NextPacketLocation.Val = RXSTART
	
	FSR2 = AddressOf(ERXSTL)
	POSTINC2 = Lo(RXSTART)
	INDF2 = Hi(RXSTART)
	
	FSR2 = AddressOf(ERXRDPTL)
	POSTINC2 = Lo(RXSTOP) 	// Write lo byte first
	INDF2 = Hi(RXSTOP) // Write  hi byte last
	
	FSR2 = AddressOf(ERXNDL)
	POSTINC2 = Lo(RXSTOP) 	// Write lo byte first
	INDF2 = Hi(RXSTOP) // Write  hi byte last
	
	FSR2 = AddressOf(ETXSTL)
    POSTINC2 = Lo(RXSTART)
	INDF2 = Hi(RXSTART)
	
	// Write a permanant per packet control byte of $00
	FSR2 = AddressOf(EWRPTL)
    POSTINC2 = Lo(RXSTART)
	INDF2 = Hi(RXSTART)
	
	MACPut($00)

	// Configure Receive Filters 
	// (No need to reconfigure - Unicast OR Broadcast with CRC checking is 
	// acceptable)
	//ERXFCON = ERXFCON_CRCEN      // Promiscious mode

	// Configure the MAC
	// Enable the receive portion of the MAC
    MACON1 = MACON1_TXPAUS Or MACON1_RXPAUS Or MACON1_MARXEN  
    Nop() 

	// Pad packets to 60 bytes, add CRC, and check Type/Length field.
#if defined(FULL_DUPLEX)
	MACON3 = MACON3_PADCFG0 Or MACON3_TXCRCEN Or MACON3_FRMLNEN Or MACON3_FULDPX  
    Nop() 
	MABBIPG = $15  
    Nop() 
#else
	MACON3 = MACON3_PADCFG0 Or MACON3_TXCRCEN Or MACON3_FRMLNEN  
    Nop() 
	MABBIPG = $12  
    Nop() 
#endif

    // Allow infinite deferals if the medium is continuously busy 
    // (do not time out a transmission if the half duplex medium is 
    // completely saturated with other people's data)
    MACON4 = MACON4_DEFER  
    Nop() 

	// Set non-back-to-back inter-packet gap to 9.6us.  The back-to-back 
	// inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called 
	// later.
    MAIPGL = $12  
    Nop() 
    MAIPGH = $0C  
    Nop() 

	// Set the maximum packet size which the controller will accept
    MAMXFLL = Lo(6+6+2+1500+4)  
    Nop() 
    MAMXFLH = Hi(6+6+2+1500+4)  
    Nop() 
	
    // Initialize physical MAC address registers
	MAADR1 = AppConfig.MyMACAddr.v(0)  
    Nop() 
	MAADR2 = AppConfig.MyMACAddr.v(1)  
    Nop() 
	MAADR3 = AppConfig.MyMACAddr.v(2)  
    Nop() 
	MAADR4 = AppConfig.MyMACAddr.v(3)  
    Nop() 
	MAADR5 = AppConfig.MyMACAddr.v(4)  
    Nop() 
	MAADR6 = AppConfig.MyMACAddr.v(5)  
    Nop() 

	// Disable half duplex loopback in PHY and set RXAPDIS bit as per errata 
	WritePHYReg(PHCON2, PHCON2_HDLDIS Or PHCON2_RXAPDIS) 

	// Configure LEDA to display LINK status, LEDB to display TX/RX activity
	SetLEDConfig($3472) 
	
	// Set the PHY into the proper duplex state
#if defined(FULL_DUPLEX)
	WritePHYReg(PHCON1, PHCON1_PDPXMD)
#else
	WritePHYReg(PHCON1, $0000)
#endif

	// Enable packet reception
    ECON1.2 = 1
End Sub
//end MACInit


{******************************************************************************
 * Function:        BOOL MACIsLinked()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TRUE: If the PHY reports that a link partner is present 
 *						  And the link has been up continuously since the last 
 *						  call To MACIsLinked()
 *					FALSE: If the PHY reports no link partner, Or the link went 
 *						   down momentarily since the last call To MACIsLinked()
 *
 * Side Effects:    None
 *
 * Overview:        Returns the PHSTAT1.LLSTAT Bit.
 *
 * Note:            None
 *****************************************************************************}
Public Function MACIsLinked() As Boolean

	Dim PHYRegister As PHYREG
   // LLSTAT is a latching low link status bit.  Therefore, if the link 
   // goes down and comes back up before a higher level stack program calls
   // MACIsLinked(), MACIsLinked() will still return FALSE.  The next 
   // call to MACIsLinked() will return TRUE (unless the link goes down 
   // again).
   PHYRegister = ReadPHYReg(PHSTAT1)
   result = PHYRegister.PHSTAT1bits.LLSTAT
End Function

{******************************************************************************
 * Function:        BOOL MACIsTxReady()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TRUE: If no Ethernet transmission is in progress
 *					FALSE: If a previous transmission was started, And it has 
 *						   Not completed yet.  While FALSE, the data in the 
 *						   transmit buffer And the TXST/TXND pointers must Not
 *						   be changed.
 *
 * Side Effects:    None
 *
 * Overview:        Returns the ECON1.3 Bit
 *
 * Note:            None
 *****************************************************************************}
Public Function MACIsTxReady() As Boolean

result = Not TxRequestToSend    //ECON1.3
End Function


{******************************************************************************
 * Function:         MACDiscardRx()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Marks the last received packet (obtained using 
 *					MACGetHeader())As being processed And frees the buffer 
 *					memory associated With it
 *
 * Note:            Is is safe To call this Function multiple times between 
 *					MACGetHeader() calls.  Extra packets won't be thrown away 
 *					Until MACGetHeader() makes it available.
 *****************************************************************************}
Public Sub MACDiscardRx()

 Dim NewRXRDLocation As WORD_VAL

   // Make sure the current packet was not already discarded
   If WasDiscarded Then
      Exit
   EndIf
   WasDiscarded = true
	
   // Decrement the next packet pointer before writing it into 
   // the ERXRDPT registers.  This is a silicon errata workaround.
   // RX buffer wrapping must be taken into account if the 
   // NextPacketLocation is precisely RXSTART.
   NewRXRDLocation.Val = NextPacketLocation.Val - 1
   If NewRXRDLocation.Val > RXSTOP Then
      NewRXRDLocation.Val = RXSTOP
   EndIf
	

	// Decrement the RX packet counter register, EPKTCNT
    ECON2.6 = 1 

	// Move the receive read pointer to unwrite-protect the memory used by the 
	// last packet.  The writing order is important: set the lo byte first, 
	//  hi byte last.
    ERXRDPTL = NewRXRDLocation.v(0) 
	ERXRDPTH = NewRXRDLocation.v(1) 
	
	// The PKTIF flag should automatically be cleared by hardware, but 
	// early beta silicon requires that you manually clear it.  This should be 
	// unneeded for production A0 silicon and later.
	EIR.6 = 0 
 End Sub


(******************************************************************************
 * Function:        Word MACGetFreeRxSize()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          A Word estimate of how much RX buffer space is free at 
 *					the present time.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 *****************************************************************************)
Public Function MACGetFreeRxSize() As Word
Dim ReadPT, WritePT As WORD_VAL
   
   // Read the Ethernet hardware buffer write pointer.  Because packets can be 
   // received at any time, it can change between reading the low and high 
   // bytes.  A loop is necessary to make certain a proper low/high byte pair
   // is read.
   Repeat
      // Save EPKTCNT in a temporary location
	  ReadPT.v(0) = EPKTCNT
	  WritePT.v(0) = ERXWRPTL
	  WritePT.v(1) = ERXWRPTH
	     
   Until  EPKTCNT = ReadPT.v(0)
	
   // Determine where the write protection pointer is

   ReadPT.v(0) = ERXRDPTL
   ReadPT.v(1) = ERXRDPTH
	
   // Calculate the difference between the pointers, taking care to account 
   // for buffer wrapping conditions
   If WritePT.Val > ReadPT.Val Then
      result = (RXSTOP - RXSTART) - (WritePT.Val - ReadPT.Val)
   ElseIf WritePT.Val = ReadPT.Val Then
      result = RXSIZE - 1
   Else
     result = ReadPT.Val - WritePT.Val - 1
   EndIf
End Function

(******************************************************************************
 * Function:        BOOL MACGetHeader(MAC_ADDR *remote, Byte* Type)
 *
 * PreCondition:    None
 *
 * Input:           *remote: Location To store the Source MAC address of the 
 *							 received frame.
 *					*Type: Location of a Byte To store the constant 
 *						   MAC_UNKNOWN, ETHER_IP, Or ETHER_ARP, representing 
 *						   the contents of the Ethernet Type field.
 *
 * Output:          TRUE: If a packet was waiting in the RX buffer.  The 
 *						  remote, And Type values are updated.
 *					FALSE: If a packet was Not pending.  remote And Type are 
 *						   Not changed.
 *
 * Side Effects:    Last packet is discarded If MACDiscardRx() hasn't already
 *					been called.
 *
 * Overview:        None
 *
 * Note:            None
 *****************************************************************************)
 Public Function MACGetHeader(ByRef remote As MAC_ADDR, ByRef _Type As Byte) As Boolean
   Dim header As ENC_PREAMBLE
   Dim PacketCount As Byte

   // Test if at least one packet has been received and is waiting
   FSR2 = AddressOf(EPKTCNT)
   PacketCount = INDF2
   If PacketCount = 0 Then
      result = false
      Exit
   EndIf

   // Make absolutely certain that any previous packet was discarded
   If WasDiscarded = false Then
      MACDiscardRx()
      result = false
      Exit
   EndIf

   // Set the read pointer to the beginning of the next unprocessed packet
   FSR2 = AddressOf(ERDPTL)
   CurrentPacketLocation.Val = NextPacketLocation.Val
   POSTINC2 = CurrentPacketLocation.v(0)
   INDF2 = CurrentPacketLocation.v(1)

   // Obtain the MAC header from the Ethernet buffer
   MACGetArray(@header, SizeOf(header))

   // The EtherType field, like most items transmitted on the Ethernet medium
   // are in big endian.
   header._Type.Val = NETUtils.swaps(header._Type.Val)
   

   // Do a sanity check.  There might be a bug in code someplace if this 
	// Reset() ever happens.  Check for potential errors in array/pointer writing code.

   If header.NextPacketPointer > RXSTOP Or 
      header.NextPacketPointer.0 <> 0 Or 
	  header.StatusVector.Bits.zero <> 0 Or
	  header.StatusVector.Bits.CRCError <> 0 Or
	  header.StatusVector.Bits.ByteCount > 1518 Or
	  Not header.StatusVector.Bits.ReceiveOk Then
      Reset()
   EndIf

   // Save the location where the hardware will write the next packet to
   NextPacketLocation.Val = header.NextPacketPointer

   // Return the Ethernet frame's Source MAC address field to the caller
   // This parameter is useful for replying to requests without requiring an 
   // ARP cycle.
   // memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, SizeOf( *remote));
   remote.v = header.SourceMACAddr.v

	// Return a simplified version of the EtherType field to the caller
    _Type = MAC_UNKNOWN
    If  (header._Type.v(1) = $08) And (header._Type.v(0) = ETHER_IP Or header._Type.v(0) = ETHER_ARP) Then
   	   _Type = header._Type.v(0)
   	EndIf

    // Mark this packet as discardable
    WasDiscarded = false
	result = true
End Function


(******************************************************************************
 * Function:         MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
 *
 * PreCondition:    MACIsTxReady() must return TRUE.
 *
 * Input:           *remote: Pointer to memory which contains the destination
 * 							 MAC address (6 bytes)
 *					type: The constant ETHER_ARP or ETHER_IP, defining which 
 *						  value to write into the Ethernet header's type field.
 *					dataLen: Length of the Ethernet data payload
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            Because of the dataLen parameter, it is probably 
 *					advantagous to call this function immediately before 
 *					transmitting a packet rather than initially when the 
 *					packet is first created.  The order in which the packet
 *					is constructed (header first or data first) is not 
 *					important.
 *****************************************************************************)
 Public Sub MACPutHeader(ByRef remote As MAC_ADDR, _Type As Byte, dataLen As Word)
 
   FSR2 = AddressOf(EWRPTL)
   POSTINC2 = Lo(TXSTART+1)
   INDF2 =  Hi(TXSTART+1)

   // Calculate where to put the TXND pointer
   dataLen = dataLen + SizeOf(MAC_ETHER_HEADER) + TXSTART

   // Write the TXND pointer into the registers, given the dataLen given
   FSR2 = AddressOf(ETXNDL)
   POSTINC2 = dataLen.Byte0
   INDF2 =  dataLen.Byte0
   // Set the per-packet control byte and write the Ethernet destination 
   // address
   MACPutArray(@remote, SizeOf(MAC_ADDR))

   // Write our MAC address in the Ethernet source field
   MACPutArray(@AppConfig.MyMACAddr, SizeOf(AppConfig.MyMACAddr))

   // Write the appropriate Ethernet Type WORD for the protocol being used
   MACPut($08)
   If _Type = MAC_IP Then
      MACPut(ETHER_IP)
   Else
      MACPut(ETHER_ARP)
   EndIf
End Sub

(******************************************************************************
 * Function:         MACFlush()
 *
 * PreCondition:    A packet has been created by calling MACPut() And 
 *					MACPutHeader().
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACFlush causes the current TX packet To be sent out on 
 *					the Ethernet medium.  The hardware MAC will take control
 *					And handle CRC generation, collision retransmission And 
 *					other details.
 *
 * Note:			After transmission completes (MACIsTxReady() returns TRUE), 
 *					the packet can be modified And transmitted again by calling 
 *					MACFlush() again.  Until MACPutHeader() Or MACPut() is 
 *					called (in the TX data area), the data in the TX buffer 
 *					will Not be corrupted.
 *****************************************************************************)
 Public Sub MACFlush()

	// Reset the Ethernet TX logic.  This is a (suspected) errata workaround to 
	// prevent the TXRTS bit from getting stuck set indefinitely, causing the 
	// stack to lock up under certain bad conditions.
	ECON1.7 = 1 
	ECON1.7 = 0 	

	// Wait at least 1.6us after TX Reset before setting TXRTS.
	// If you don't wait long enough, the TX logic won't be finished resetting.
	DelayUS(2)	
	EIR.1 = 0 

	// Start the transmission
	// After transmission completes (MACIsTxReady() returns TRUE), the packet 
	// can be modified and transmitted again by calling MACFlush() again.
	// Until MACPutHeader() is called, the data in the TX buffer will not be 
	// corrupted.
    ECON1.3 = 1 
	//wTXWatchdog = TickGet() 
End Sub


(******************************************************************************
 * Function:         MACSetReadPtrInRx(Word offset)
 *
 * PreCondition:    A packet has been obtained by calling MACGetHeader() And 
 *					getting a TRUE result.
 *
 * Input:           offset: Word specifying how many Bytes beyond the Ethernet 
 *							header's type field to relocate the SPI read 
 *							pointer.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        SPI Read pointer are updated.  All calls To 
 *					MACGet() And MACGetArray() will use these new values.
 *
 * Note:			RXSTOP must be statically defined As being > RXSTART For 
 *					this Function To work correctly.  In other Words, do Not 
 *					define an RX buffer which spans the $1FFF->$0000 memory
 *					boundary.
 *****************************************************************************)
Public Sub MACSetReadPtrInRx(offset As Word )

	Dim ReadPT As WORD_VAL  

	// Determine the address of the beginning of the entire packet
	// and adjust the address to the desired location
	ReadPT.Val = CurrentPacketLocation.Val + SizeOf(ENC_PREAMBLE) + offset 
	
	// Since the receive buffer is circular, adjust if a wraparound is needed
	If ReadPT.Val > RXSTOP Then
		ReadPT.Val = ReadPT.Val - RXSIZE 
	EndIf
	// Set the read pointer to the new calculated value
	ERDPTL = ReadPT.v(0) 
	ERDPTH = ReadPT.v(1) 

End Sub

(******************************************************************************
 * Function:        Word MACSetWritePtr(Word Address)
 *
 * PreCondition:    None
 *
 * Input:           Address: Address To seek To
 *
 * Output:          Word: Old EWRPT location
 *
 * Side Effects:    None
 *
 * Overview:        SPI Write pointer is updated.  All calls To 
 *					MACPut() And MACPutArray() will use this new value.
 *
 * Note:			None
 *****************************************************************************)
Public Function MACSetWritePtr(address As Word )As Word 

Dim oldVal As WORD_VAL

   oldVal.v(0) = EWRPTL
   oldVal.v(1) = EWRPTH

   // Set the SPI write pointer to the new calculated value
   EWRPTL = Address.Byte0
   EWRPTH = Address.Byte1

   result = oldVal.Val
End Function

(******************************************************************************
 * Function:        Word MACSetReadPtr(Word Address)
 *
 * PreCondition:    None
 *
 * Input:           Address: Address To seek To
 *
 * Output:          Word: Old ERDPT value
 *
 * Side Effects:    None
 *
 * Overview:        SPI Write pointer is updated.  All calls To 
 *					MACPut() And MACPutArray() will use this new value.
 *
 * Note:			None
 *****************************************************************************)
Public Function MACSetReadPtr(Address As Word) As Word
Dim oldVal As WORD_VAL

   oldVal.v(0) = ERDPTL
   oldVal.v(1) = ERDPTH

   // Set the SPI write pointer to the new calculated value
   ERDPTL = Address.Byte0
   ERDPTH = Address.Byte1

   result = oldVal.Val
End Function
 

(******************************************************************************
 * Function:        Word CalcIPBufferChecksum(Word len)
 *
 * PreCondition:    Read buffer pointer set To starting of checksum data
 *
 * Input:           len: Total number of Bytes To calculate the checksum over. 
 *						 The first Byte included in the checksum is the Byte 
 *						 pointed To by ERDPT, which is updated by calls To 
 *						 MACSetReadPtr(), MACGet(), MACGetArray(), 
 *						 MACGetHeader(), etc.
 *
 * Output:          16-Bit checksum As defined by RFC 793
 *
 * Side Effects:    None
 *
 * Overview:        This Function performs a checksum calculation in the MAC
 *                  buffer itself
 *
 * Note:            This Function works either in the RX buffer area Or the TX
 *					buffer area.  No validation is Done on the len parameter.
 *****************************************************************************)
Public Function CalcIPBufferChecksum(len As Word) As Word
 Dim Start As	WORD_VAL
   Dim Checksum As DWORD_VAL 
   Dim ChunkLen, Temp As Word
   Dim DataBuffer(20) As Byte	// Must be an even size
   Dim DataPtr As FSR0
   
   Checksum.Val = $00000000
   
   // Save the SPI read pointer starting address
   Start.v(0) = ERDPTL
   Start.v(1) = ERDPTH

   While Len <> 0
      // Obtain a chunk of data (less SPI overhead compared 
	  // to requesting one byte at a time)
	  If Len > SizeOf(DataBuffer) Then
	     ChunkLen = SizeOf(DataBuffer)
	  Else
	     ChunkLen = Len
      EndIf
         
      MACGetArray(@DataBuffer, ChunkLen)

      Len = Len - ChunkLen

      // Take care of a last odd numbered data byte
      If ChunkLen.0 <> 0 Then
         DataBuffer(ChunkLen) = $00
         Inc(ChunkLen)
      EndIf

      // Calculate the checksum over this chunk
      DataPtr = @DataBuffer
      While ChunkLen <> 0
         Temp.Byte0 = POSTINC0
         Temp.Byte1 = POSTINC0
         Checksum.Val = Checksum.Val + Temp
         Dec(ChunkLen, 2)
      Wend
   Wend
    
   // Restore old read pointer location
   ERDPTL = Start.v(0)
   ERDPTH = Start.v(1)
	
   // Do an end-around carry (one's complement arrithmatic)
   Checksum.Val = Checksum.w(0) + Checksum.w(1)

   // Do another end-around carry in case if the prior add 
   // caused a carry out
   Checksum.w(0) = Checksum.w(0) + Checksum.w(1)

   // Return the resulting checksum
   result = Not Checksum.w(0)
End Function

(******************************************************************************
 * Function:        Word MACCalcRxChecksum(Word offset, Word len)
 *
 * PreCondition:    None
 *
 * Input:           offset	- Number of Bytes beyond the beginning of the 
 *							Ethernet data (first Byte after the Type field) 
 *							where the checksum should begin
 *					len		- Total number of Bytes To Include in the checksum
 *
 * Output:          16-Bit checksum As defined by RFC 793.
 *
 * Side Effects:    None
 *
 * Overview:        This Function performs a checksum calculation in the MAC
 *                  buffer itself
 *
 * Note:            None
 *****************************************************************************)
 Public Function MACCalcRxChecksum(offset As Word, Len As Word) As Word
   Dim temp As WORD_VAL
   Dim RDSave As WORD_VAL

   // Add the offset requested by firmware plus the Ethernet header
   temp.Val = CurrentPacketLocation.Val + SizeOf(ENC_PREAMBLE) + offset
   If temp.Val > RXSTOP Then		// Adjust value if a wrap is needed
      temp.Val = temp.Val - RXSIZE
   EndIf
   
   RDSave.v(0) = ERDPTL
   RDSave.v(1) = ERDPTH

   ERDPTL = temp.v(0)
   ERDPTH = temp.v(1)
	
   temp.Val = CalcIPBufferChecksum(Len)

   ERDPTL = RDSave.v(0)
   ERDPTH = RDSave.v(1)
   result = temp.Val
End Function




 
(******************************************************************************
 * Function:         MACMemCopyAsync(Word destAddr, Word sourceAddr, Word len)
 *
 * PreCondition:    None
 *
 * Input:           destAddr:	Destination address in the Ethernet memory To 
 *								copy To.  If the MSb is set, the current EWRPT 
 *								value will be used instead.
 *					sourceAddr:	Source address To Read from.  If the MSb is 
 *								set, the current ERDPT value will be used 
 *								instead.
 *					len:		Number of Bytes To copy
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Bytes are asynchrnously transfered within the buffer.  Call 
 *					MACIsMemCopyDone() To see when the transfer is complete.  
 *
 * Note:            If a prior transfer is already in progress prior To 
 *					calling this Function, this Function will block Until it 
 *					can start this transfer.
 *****************************************************************************)
  
 Public Sub MACMemCopyAsync(destAddr As Word, sourceAddr As Word, Len As Word)
   Dim ReadSave, WriteSave As WORD_VAL
   Dim UpdateWritePointer As Boolean
   Dim UpdateReadPointer As Boolean 
   

   UpdateWritePointer = false
   UpdateReadPointer = false
 
   If destAddr.15 <> 0 Then
      UpdateWritePointer = true
      destAddr.Byte0 = EWRPTL
	  destAddr.Byte1 = EWRPTH
   EndIf   

	 If sourceAddr.15 <> 0 Then
      UpdateReadPointer = true
	  sourceAddr.Byte0 = ERDPTL
	  sourceAddr.Byte1 = ERDPTH
   EndIf

   // Handle special conditions where len == 0 or len == 1
   // The DMA module is not capable of handling those corner cases
   If Len <= 1 Then
      If Not UpdateReadPointer Then
         ReadSave.v(0) = ERDPTL
         ReadSave.v(1) = ERDPTH
      EndIf
      
      If Not UpdateWritePointer Then
         WriteSave.v(0) = EWRPTL
		 WriteSave.v(1) = EWRPTH
      EndIf

      ERDPTL = sourceAddr.Byte0
	  ERDPTH = sourceAddr.Byte1
	  EWRPTL = destAddr.Byte0
	  EWRPTH = destAddr.Byte1
      While Len <> 0
         MACPut(MACGet())
         Dec(Len)
      Wend   
      If Not UpdateReadPointer Then
         ERDPTL =  ReadSave.v(0)
         ERDPTH =  ReadSave.v(1)
      EndIf
       If Not UpdateWritePointer Then
         EWRPTL = WriteSave.v(0)
         EWRPTH = WriteSave.v(1)
      EndIf
   Else
      If UpdateWritePointer Then
         WriteSave.Val = destAddr + Len
         EWRPTL = WriteSave.v(0)
		 EWRPTH = WriteSave.v(1)
      EndIf
      Len = Len + (sourceAddr - 1)
      While DMAST
      Wend
      
      EDMASTL = sourceAddr.Byte0
	  EDMASTH = sourceAddr.Byte1
      EDMADSTL = destAddr.Byte0
	  EDMADSTH = destAddr.Byte1
	
      If (sourceAddr <= RXSTOP) And (Len > RXSTOP) Then //&& (sourceAddr >= RXSTART))
         Len = Len - RXSIZE
      EndIf
         
      EDMANDL = Len.Byte0
	  EDMANDH = Len.Byte1
	  
      ECON1.4 = 0
      ECON1.5 = 1
      If UpdateReadPointer Then
         Inc(Len)
         If (sourceAddr <= RXSTOP) And (Len > RXSTOP) Then //&& (sourceAddr >= RXSTART))
		    Len = Len - RXSIZE
		 EndIf   
	     ERDPTL = Len.Byte0
		 ERDPTH = Len.Byte1
      EndIf
   EndIf
End Sub

Public Function MACIsMemCopyDone() As Boolean 
   result = Not DMAST
End Function   





(*
 ******************************************************************************
 * Function:        void MACPutROMArray(ROM Byte *Val, Word len)
 * PreCondition:    SPI bus must be initialized (Done in MACInit()).
 * 					EWRPT must point To the location To begin writing.
 * Input:           *Val: Pointer To source of Bytes To copy.
 *					len:  Number of Bytes To write To the data buffer.
 * Output:          None
 * Side Effects:    None
 * Overview:        MACPutArray writes several sequential Bytes To the 
 *					ENC28J60 RAM.  It performs faster than multiple MACPut()
 *					calls.  EWRPT is incremented by len.
 * Note:            None
 *****************************************************************************/
*)
Public Sub MACPutROMArray(Val As TROMAddress, Len As Word)
    	// Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
		// write to EDATA or else the read pointer (ERDPT) will inadvertently 
		// increment.
   While Len <> 0
      PRODL = ReadROM(Val)	// Start sending the byte
     ASM
        movff	PRODL, EDATA 
      End ASM
      Inc(Val)				
      Dec(Len)
   Wend
End Sub







{******************************************************************************
 * Function:         MACPowerDown()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPowerDown disables the Ethernet Module.
 *					All MAC And PHY registers should Not be accessed.
 *
 * Note:            Normally, this Function would be called before putting the 
 *					PIC To sleep.  If a packet is being transmitted While this 
 *					Function is called, this Function will block Until it is 
 *					it complete. If anything is being received, it will be 
 *					completed.
 *					
 *					The Ethernet Module will Continue To draw significant 
 *					power in sleep mode If this Function is Not called first.
 *****************************************************************************}
Sub MACPowerDown()

	// Disable packet reception
	ECON1.2 = 0 

	// Make sure any last packet which was in-progress when RXEN was cleared 
	// is completed
	While BUSY Wend

	// If a packet is being transmitted, wait for it to finish
	While ECON1.3 <> 0 Wend 
	
	// Disable the Ethernet module
	ECON2.5 = 0 
//end MACPowerDown
End Sub
(******************************************************************************
 * Function:         MACPowerUp()
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACPowerUp returns the Ethernet Module back To normal operation
 *					after a previous call To MACPowerDown().  Calling this 
 *					Function when already powered up will have no effect.
 *
 * Note:            If a link partner is present, it will take 10s of 
 *					milliseconds before a new link will be established after
 *					waking up.  While Not linked, packets which are 
 *					transmitted will most likely be lost.  MACIsLinked() can 
 *					be called To determine If a link is established.
 *****************************************************************************)
 Sub MACPowerUp()
	
	// Power up the Ethernet module
	ECON2.5 = 1 

	// Wait for PHY to become ready
	While Not PHYClockIsReady Wend

	// Enable packet reception
	ECON1.2 = 1 
//end MACPowerUp
End Sub

i have also modified MAC.BAS:

Code: Select all

{
*****************************************************************************
*  Name    : MAC.BAS                                                        *
*  Date    : 28/08/2007                                                     *
*  Version : 1.0 - Based around Microchip TCP/IP stack version 4.13         *
*  Notes   :                                                                *
* ========================================================================= *
* Software License Agreement                                                *
*                                                                           *
* Copyright © 2002-2007 Microchip Technology Inc.  All rights reserved.     *
*                                                                           *
* Microchip licenses to you the right to use, modify, copy, and distribute: *
* (i)  the Software when embedded on a Microchip microcontroller or digital *
*      signal controller product (“Device”) which is integrated into        *
*      Licensee’s product; or                                               *
* (ii) ONLY the Software driver source files ENC28J60.c and ENC28J60.h      *
*      ported to a non-Microchip device used in conjunction with a          *
*      Microchip ethernet controller for the sole purpose of interfacing    *
*      with the ethernet controller.                                        *
*                                                                           *
* You should refer to the license agreement accompanying this Software for  *
* additional information regarding your rights and obligations.             *
*                                                                           *
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF   *
* ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY    *
* WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND  *
* NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY           *
* INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR   *
* LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR         *
* SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY   *
* DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER      *
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING *
* NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.                            *
*****************************************************************************
}
Module MAC

// The MAC_TX_BUFFER_COUNT must be equal to MAX_TCP_SOCKETS + 1
// (1 reserved for high priority messages), or else calls to 
// TCPPut may fail when multiple TCP sockets have data pending 
// in the output buffer that hasn't been ACKed.  Changing this 
// value is recommended only if the rammifications of doing so 
// are properly understood.  
#define _MAC_TX_BUFFER_SIZE     = (1500)
  
// This value will change if TCP is enabled...
#ifndef RESERVED_TCP_MEMORY
   #define RESERVED_TCP_MEMORY = 0
#endif

#ifndef STACK_USE_HTTP_SERVER
   #define RESERVED_HTTP_MEMORY = 0
#endif

#ifndef STACK_USE_SSL_SERVER
	#define RESERVED_SSL_MEMORY = 0
#endif

// MAC RAM definitions
#define _RAMSIZE	     = 8192		
#define _TXSTART         = (_RAMSIZE - (1 + 1514 +7) - RESERVED_TCP_MEMORY - RESERVED_HTTP_MEMORY - RESERVED_SSL_MEMORY)
#define _RXSTART	     = (0)						// Should be an even memory address; must be 0 for errata
#define	_RXSTOP	         = ((_TXSTART - 2) Or $0001)	// Odd for errata workaround
#define _RXSIZE	         = (_RXSTOP - _RXSTART + 1)

#define _BASE_TX_ADDR	 = (_TXSTART + 1)
#define _BASE_TCB_ADDR	 = (_BASE_TX_ADDR + (1514 + 7))
#define _BASE_HTTPB_ADDR = (_BASE_TCB_ADDR + RESERVED_TCP_MEMORY)
#define _BASE_SSLB_ADDR	 = (_BASE_HTTPB_ADDR + RESERVED_HTTP_MEMORY)

#if _RXSIZE < 1400
   #warning "Ethernet RX buffer is tiny.  Reduce MAX_TCP_SOCKETS, TCP_TX_FIFO_SIZE, Or TCP_RX_FIFO_SIZE"
#endif

(*
   This MAC module is the interface to all other stack modules - none of the
   stack modules will interface to a hardware layer (for example, ENC28J60)
   directly.  
*)
// import ENC28J60 
#if _ethernet = 0 
 Include "ENC28J60.bas"
Public Type
   ETHER_HEADER = MAC_ETHER_HEADER   
Public Const
   MAC_IP      = ENC28J60.MAC_IP,
   MAC_ARP     = ENC28J60.MAC_ARP,
   MAC_UNKNOWN = ENC28J60.MAC_UNKNOWN, 
   MAC_TX_BUFFER_SIZE = ENC28J60.MAC_TX_BUFFER_SIZE,
   RAMSIZE = ENC28J60.RAMSIZE,
   TXSTART = ENC28J60.TXSTART,
   RXSTART = ENC28J60.RXSTART,
   RXSTOP = ENC28J60.RXSTOP,
   RXSIZE = ENC28J60.RXSIZE,
   BASE_TX_ADDR = ENC28J60.BASE_TX_ADDR,
   BASE_TCB_ADDR = ENC28J60.BASE_TCB_ADDR,
   BASE_HTTPB_ADDR = ENC28J60.BASE_HTTPB_ADDR
Public Dim
   MACInit As ENC28J60.MACInit, 
   MACIsLinked As ENC28J60.MACIsLinked,
   MACGetHeader As ENC28J60.MACGetHeader,
   MACSetReadPtrInRx As ENC28J60.MACSetReadPtrInRx,
   MACSetWritePtr As ENC28J60.MACSetWritePtr,
   MACSetReadPtr As ENC28J60.MACSetReadPtr,
   MACGet As ENC28J60.MACGet,
   MACGetArray As ENC28J60.MACGetArray,
   MACDiscardRx As ENC28J60.MACDiscardRx,
   MACGetFreeRxSize As ENC28J60.MACGetFreeRxSize,
   MACMemCopyAsync As ENC28J60.MACMemCopyAsync,
   MACIsMemCopyDone As ENC28J60.MACIsMemCopyDone,
   MACPutHeader As ENC28J60.MACPutHeader,
   MACIsTxReady As ENC28J60.MACIsTxReady,
   MACPut As ENC28J60.MACPut,
   MACPutArray As ENC28J60.MACPutArray,
   MACPutROMArray As ENC28J60.MACPutROMArray,
   MACFlush As ENC28J60.MACFlush,
   MACCalcRxChecksum As ENC28J60.MACCalcRxChecksum,
   CalcIPBufferChecksum As ENC28J60.CalcIPBufferChecksum

// other implementations go here...
#else
   //#error "Ethernet MCUs not implemented. ENC28J60 is the only device currently supported"
   (*
      It is very important that with any new harware implementation, the types, 
      constants, functions and subroutines shown above in the ENC28J60 import 
      section are included
   *)
   Include "ETH97J60.bas"
Public Type
   ETHER_HEADER = MAC_ETHER_HEADER   
Public Const
   MAC_IP      = ETH97J60.MAC_IP,
   MAC_ARP     = ETH97J60.MAC_ARP,
   MAC_UNKNOWN = ETH97J60.MAC_UNKNOWN, 
   MAC_TX_BUFFER_SIZE = ETH97J60.MAC_TX_BUFFER_SIZE,
   RAMSIZE = ETH97J60.RAMSIZE,
   TXSTART = ETH97J60.TXSTART,
   RXSTART = ETH97J60.RXSTART,
   RXSTOP = ETH97J60.RXSTOP,
   RXSIZE = ETH97J60.RXSIZE,
   BASE_TX_ADDR = ETH97J60.BASE_TX_ADDR,
   BASE_TCB_ADDR = ETH97J60.BASE_TCB_ADDR,
   BASE_HTTPB_ADDR = ETH97J60.BASE_HTTPB_ADDR
Public Dim
   MACInit As ETH97J60.MACInit, 
   MACIsLinked As ETH97J60.MACIsLinked,
   MACGetHeader As ETH97J60.MACGetHeader,
   MACSetReadPtrInRx As ETH97J60.MACSetReadPtrInRx,
   MACSetWritePtr As ETH97J60.MACSetWritePtr,
   MACSetReadPtr As ETH97J60.MACSetReadPtr,
   MACGet As ETH97J60.MACGet,
   MACGetArray As ETH97J60.MACGetArray,
   MACDiscardRx As ETH97J60.MACDiscardRx,
   MACGetFreeRxSize As ETH97J60.MACGetFreeRxSize,
   MACMemCopyAsync As ETH97J60.MACMemCopyAsync,
   MACIsMemCopyDone As ETH97J60.MACIsMemCopyDone,
   MACPutHeader As ETH97J60.MACPutHeader,
   MACIsTxReady As ETH97J60.MACIsTxReady,
   MACPut As ETH97J60.MACPut,
   MACPutArray As ETH97J60.MACPutArray,
   MACPutROMArray As ETH97J60.MACPutROMArray,
   MACFlush As ETH97J60.MACFlush,
   MACCalcRxChecksum As ETH97J60.MACCalcRxChecksum,
   CalcIPBufferChecksum As ETH97J60.CalcIPBufferChecksum
#endif
now i am finishing the portage of HTTP2.c and MPFS2.c and i am planning to buy a board for testing
ps: i have moved Hi() and Low() subs present in ENC28J60.bas to netutils.bas and make them public for sharing them with ETH97J60.bas
please tell us if it works

User avatar
JWinters
Posts: 106
Joined: Mon Feb 04, 2008 4:56 pm
Location: North Carolina, USA
Contact:

Post by JWinters » Sun May 18, 2008 4:36 pm

Thanks tass, no point in re-inventing the wheel!

I'm getting an ASM error when I compile:
[ASM Error]: Error[115]... 2636 Duplicate label ("EDATA" or redefining symbol that cannot be redefined)

The offending code seems to be coming from MACPutArray:

Code: Select all

Public Sub MACPutArray(Val As Word, Len As Word)
 
      // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to
      // write to EDATA or else the read pointer (ERDPT) will inadvertently
      // increment.
   While Len <> 0
      FSR0 = Val
      PRODL = INDF0   // Start sending the byte
      ASM
        movff   PRODL, EDATA
      End ASM
      Inc(Val)            
      Dec(Len)                 
   Wend
End Sub
with the assembler being:

Code: Select all

WHILE_17
	MOVF F2_U16H,0,0
	IORWF F2_U16,0,0
NOP;#REQ#_BJUMP 1,STATUS,2,FALSE_25
?I000744_F014_000530_I000146 ; L#MK FSR0 = VAL
	MOVFF F0_U16H,_FSR0L#M0_U16H
	MOVFF F0_U16,_FSR0L#M0_U16
?I000745_F014_000531_I000146 ; L#MK PRODL = INDF0   // START SENDING THE BYTE
	MOVFF INDF0,PRODL
?I000746_F014_000532_I000146 ; L#MK ASM
 LIST
;[SB#START_OF_ASM]
   VARIABLE EDATA = ADF_M3968_U08    // <-  THIS IS LINE 2636
        movff   PRODL, EDATA
;[SB#END_OF_ASM]
 LIST
?I000747_F014_000535_I000146 ; L#MK INC(VAL)
	INFSNZ F0_U16,1,0
	INCF F0_U16H,1,0
?I000748_F014_000536_I000146 ; L#MK DEC(LEN)
	DECF F2_U16,1,0
	MOVLW 0
	SUBWFB F2_U16H,1,0
NOP;#REQ#_GOTO WHILE_17
I'm testing this on a 18F66J65. In the module for that device, EDATA is aliased as a public Dim absolute byte $0F80 instead of $0F61 as stated in the datasheet. If I change it, the code compiles... though I'm still not sure about functionality yet. What do you think?

tass
Posts: 19
Joined: Sat Jan 19, 2008 8:37 am
Location: France

Post by tass » Wed May 21, 2008 12:42 pm

dear JWinters,
try this ustead of using EDATA directly:
add to ETH97J60.bas this variable

Code: Select all

Public Dim EDATA_reg As Byte Absolute $0F61
and replace all ocurences of EDATA in the code by EDATA_reg

User avatar
JWinters
Posts: 106
Joined: Mon Feb 04, 2008 4:56 pm
Location: North Carolina, USA
Contact:

Post by JWinters » Wed May 21, 2008 1:57 pm

So far this ETH97J60.bas module 'almost' works. I found a few things that I think are mistakes in the code but I want to get a second opinion.

1) MACGetArray: the variable i was not initialized, I added i=0 to the beginning of the sub

2) MACPutHeader: Changed this

Code: Select all

   POSTINC2 = dataLen.Byte0
   INDF2 =  dataLen.Byte0
to this

Code: Select all

   POSTINC2 = dataLen.Byte0
   INDF2 =  dataLen.Byte1
3) WritePHYReg: The instructions are a little out of order compared with the c version. Although I suspect this isn't really a problem. I changed this sub to:

Code: Select all

Sub  WritePHYReg( Register As Byte,  Data As Word)
  Dim GIESave As Byte
  
  MIREGADR = register       
  PRODL = data.Byte0
  PRODH = data.Byte1 
  GIESave = INTCON And $C0         
  INTCON = INTCON And $3F                
 
   ASM      
    movff PRODL, MIWRL
    movff PRODH, MIWRH
   End ASM
 
  INTCON = INTCON Or GIESave  
  While BUSY Wend

 End Sub
I also modified the device module to point EDATA to $0F61 instead of PORTA @ $0F80. I think that has the same affect as tass's last suggestions with EDATA_reg.

As for funcitonality:

It doesn't work yet. I'm testing this with a custom 18F66J65 board which I know works. (I can load up Florin's web server module on it and everything works fine.) All I'm attempting to do right now is get an ICMP ping working. The incoming packets appear to be detected to processed but something is going wrong during the processing. Almost like next incoming packet doesn't get parsed correctly.

I have a UART.Write statement at the beginning of every sub and function in the both the ETH97J60.bas and ENC28J60.bas (on a different board obviously) to track the program flow. This is the output during a successful ping using the ENC28J60.bas:

Code: Select all

MACInit
looking for network...
.
Check MACIsLInked
ReadPHYReg
.
Check MACIsLInked
ReadPHYReg
Network found!
MACGetHeader
MACGetArray = 70,0,64,0,192,3,255,255,255,255,255,255,0,64,69,24,133,137,8,6,
cFrameType = 6 (StackTsk.bas)
Case ARP (StackTsk.bas)
MACGetArray = 0,1,8,0,6,4,0,1,0,64,69,24,133,137,192,168,1,104,0,0,0,0,0,0,192,168,1,130,
MACDiscardRx
MACIsTxReady
MACSetWritePtr
MACPutHeader
MACPutArray
MACPutArray
MACPut
MACPut
MACPutArray
MACFlush
MACGetArray = 64,0,192,0,64,0,0,
MACGetHeader
MACGetArray = 154,0,78,0,192,0,0,4,163,0,0,0,0,64,69,24,133,137,8,0,
cFrameType=0 (StackTsk.bas)
Case MAC_IP (StackTsk.bas)
IPGetHeader (IP.bas)
MACGetArray = 69,0,0,60,126,117,0,0,128,1,56,17,192,168,1,104,192,168,1,130,
MACCalcRxChecksum
CalcIPBufferChecksum
MACGetArray = 69,0,0,60,126,117,0,0,128,1,56,17,192,168,1,104,192,168,1,130,
MACSetReadPtrInRx
MAC IP frame type=1 (StackTsk.bas)
ICMPProcess (ICMP.bas)  
Now the output using the ETH97J60.bas:

Code: Select all

MACInit
MACPut
WritePHYReg
SetLEDConfig
WritePHYReg
WritePHYReg
Check MACIsLInked
ReadPHYReg
looking for network...
.
Check MACIsLInked
ReadPHYReg
.
Check MACIsLInked
ReadPHYReg
.
Network found!
MACGetHeader
MACGetArray = 70,0,64,0,192,3,255,255,255,255,255,255,0,64,69,24,133,137,8,6,
cFrameType=6 (StackTsk.bas)
Case ARP (StackTsk.bas)
MACGetArray = 0,1,8,0,6,4,0,1,0,64,69,24,133,137,192,168,1,104,0,0,0,0,0,0,192,168,1,130,
MACDiscardRx
MACIsTxReady
MACSetWritePtr
MACPutHeader
MACPutArray
MACPutArray
MACPut
MACPut
MACPutArray
MACFlush
MACGetHeader
MACGetArray = 140,0,64,0,192,3,255,255,255,255,255,255,0,64,69,24,133,137,8,6,
cFrameType=6 (StackTsk.bas)
Case ARP (StackTsk.bas)
MACGetArray = 0,1,8,0,6,4,0,1,0,64,69,24,133,137,192,168,1,104,0,0,0,0,0,0,192,168,1,130,
MACDiscardRx
MACIsTxReady
MACSetWritePtr
MACPutHeader
MACPutArray
MACPutArray
MACPut
MACPut
MACPutArray
MACFlush                   
//  End of first ping

// Second incoming ping
MACGetHeader
MACGetArray = 188,1,42,1,192,3,255,255,255,255,255,255,0,15,61,5,240,145,8,0,
cFrameType=0 (StackTsk.bas)
Case MAC_IP
It seems like something is going wrong when the second data frame comes in. The MACGetArray data should be identical in both cases but it isn't.

tass
Posts: 19
Joined: Sat Jan 19, 2008 8:37 am
Location: France

Post by tass » Fri Jun 13, 2008 2:28 pm

hi JWinters,
sorry for my late answer because I am in journey abroad
i have found another mistake in MACInit in ETH60J97.bas :
change this:

Code: Select all

FSR0 = AddressOf(ETXSTL)
    POSTINC0 = Lo(RXSTART)
	INDF0 = Hi(RXSTART)
	
	// Write a permanant per packet control byte of $00
	FSR0 = AddressOf(EWRPTL)
    POSTINC0 = Lo(RXSTART)
	INDF0 = Hi(RXSTART)
to this:

Code: Select all

	FSR0 = AddressOf(ETXSTL)
    POSTINC0 = Lo(TXSTART)
	INDF0 = Hi(TXSTART)
	
	// Write a permanant per packet control byte of $00
	FSR0 = AddressOf(EWRPTL)
    POSTINC0 = Lo(TXSTART)
	INDF0 = Hi(TXSTART)

User avatar
JWinters
Posts: 106
Joined: Mon Feb 04, 2008 4:56 pm
Location: North Carolina, USA
Contact:

Post by JWinters » Mon Jun 30, 2008 1:58 pm

no problem tass, I haven't been able to try out your changes though. I don't have access to my dev board at the moment. When I get it back, I'll try out your code.

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Fri Feb 20, 2009 5:02 am

Jason,

Did you ever get this port up and working? I am guessing you have since iobridge seems to be working out okay? Any chance you would share this with the community?
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

User avatar
JWinters
Posts: 106
Joined: Mon Feb 04, 2008 4:56 pm
Location: North Carolina, USA
Contact:

Post by JWinters » Fri Feb 20, 2009 2:14 pm

Actually, I ended up just using the original ethernet library Dave ported for the ENC28J60.

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Fri Feb 20, 2009 2:43 pm

I tried getting things up and running last night with an easy pic 3 and the mikroe ethernet board, but had no luck. I have a picdem net2 board coming in and thought I might try things out with that...does the iobridge have a icsp header on it? Maybe I should have gone that route instead.
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

Anonymous

&#24555;&#25773;&#20808;&#29983;

Post by Anonymous » Sat Aug 01, 2009 6:30 am

快播先生和小锤免费电影里都有好多精彩的电影,都是免费的.告诉大家个秘密,还有甜性涩爱呢!

dman776
Posts: 115
Joined: Mon May 28, 2007 3:59 pm
Location: Texas

Post by dman776 » Mon Aug 03, 2009 3:31 am

Sure would be nice if the "Report Abuse" buttons were enabled on the forums here.... :-)

Post Reply