Ethernet PIC18FxxJ60 Library

PIC18FxxJ60 family of microcontrollers feature an embedded Ethernet controller module. This is a complete connectivity solution, including full implementations of both Media Access Control (MAC) and Physical Layer transceiver (PHY) modules. Two pulse transformers and a few passive components are all that are required to connect the microcontroller directly to an Ethernet network.

The Ethernet module meets all of the IEEE 802.3 specifications for 10-BaseT connectivity to a twisted-pair network. It incorporates a number of packet filtering schemes to limit incoming packets. It also provides an internal DMA module for fast data throughput and hardware assisted IP checksum calculations. Provisions are also made for two LED outputs to indicate link and network activity

This library provides the posibility to easily utilize ethernet feature of the above mentioned MCUs.

Ethernet PIC18FxxJ60 library supports:

  Important :

Library Routines

Ethernet_Init

Prototype

procedure Ethernet_Init(var mac : array[6] of byte; var ip : array[4] of byte; fullDuplex : byte);

Returns

Nothing.

Description

This is MAC module routine. It initializes Ethernet controller. This function is internaly splited into 2 parts to help linker when coming short of memory.

Ethernet controller settings (parameters not mentioned here are set to default):

  • receive buffer start address : 0x0000.
  • receive buffer end address : 0x19AD.
  • transmit buffer start address: 0x19AE.
  • transmit buffer end address : 0x1FFF.
  • RAM buffer read/write pointers in auto-increment mode.
  • receive filters set to default: CRC + MAC Unicast + MAC Broadcast in OR mode.
  • flow control with TX and RX pause frames in full duplex mode.
  • frames are padded to 60 bytes + CRC.
  • maximum packet size is set to 1518.
  • Back-to-Back Inter-Packet Gap: 0x15 in full duplex mode; 0x12 in half duplex mode.
  • Non-Back-to-Back Inter-Packet Gap: 0x0012 in full duplex mode; 0x0C12 in half duplex mode.
  • half duplex loopback disabled.
  • LED configuration: default (LEDA-link status, LEDB-link activity).

Parameters:

  • mac: RAM buffer containing valid MAC address.
  • ip: RAM buffer containing valid IP address.
  • fullDuplex: ethernet duplex mode switch. Valid values: 0 (half duplex mode, predefined library const Ethernet_HALFDUPLEX) and 1 (full duplex mode, predefined library const Ethernet_FULLDUPLEX).
  Note : If a DHCP server is to be used, IP address should be set to 0.0.0.0.
Requires Nothing.
Example
var 
  myMacAddr : array[6] of byte; // my MAC address	
  myIpAddr  : array[4] of byte; // my IP addr
  ...
  myMacAddr[0] := 0x00;
  myMacAddr[1] := 0x14;
  myMacAddr[2] := 0xA5;
  myMacAddr[3] := 0x76;
  myMacAddr[4] := 0x19;
  myMacAddr[5] := 0x3F;

  myIpAddr[0]  := 192;
  myIpAddr[1]  := 168;
  myIpAddr[2]  := 20;
  myIpAddr[3]  := 60;
  
  Ethernet_Init(myMacAddr, myIpAddr, Ethernet_FULLDUPLEX);
          

Ethernet_Enable

Prototype

procedure Ethernet_Enable(enFlt : byte);

Returns

Nothing.

Description

This is MAC module routine. This routine enables appropriate network traffic on the MCU's internal Ethernet module by the means of it's receive filters (unicast, multicast, broadcast, crc). Specific type of network traffic will be enabled if a corresponding bit of this routine's input parameter is set. Therefore, more than one type of network traffic can be enabled at the same time. For this purpose, predefined library constants (see the table below) can be ORed to form appropriate input value.

Parameters:

  • enFlt: network traffic/receive filter flags. Each bit corresponds to the appropriate network traffic/receive filter:
  • Bit Mask Description Predefined library const
    0 0x01 MAC Broadcast traffic/receive filter flag. When set, MAC broadcast traffic will be enabled. _Ethernet_BROADCAST
    1 0x02 MAC Multicast traffic/receive filter flag. When set, MAC multicast traffic will be enabled. _Ethernet_MULTICAST
    2 0x04 not used none
    3 0x08 not used none
    4 0x10 not used none
    5 0x20 CRC check flag. When set, packets with invalid CRC field will be discarded. _Ethernet_CRC
    6 0x40 not used none
    7 0x80 MAC Unicast traffic/receive filter flag. When set, MAC unicast traffic will be enabled. _Ethernet_UNICAST

      Note :
    • Advanced filtering available in the MCU's internal Ethernet module such as Pattern Match, Magic Packet and Hash Table can not be enabled by this routine.
      Additionaly, all filters, except CRC, enabled with this routine will work in OR mode, which means that packet will be received if any of the enabled filters accepts it.
    • This routine will change receive filter configuration on-the-fly. It will not, in any way, mess with enabling/disabling receive/transmit logic or any other part of the MCU's internal Ethernet module.
      The MCU's internal Ethernet module should be properly cofigured by the means of Ethernet_Init routine.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
Ethernet_Enable(_Ethernet_CRC or _Ethernet_UNICAST); // enable CRC checking and Unicast traffic

Ethernet_Disable

Prototype

procedure Ethernet_Disable(disFlt : byte);

Returns

Nothing.

Description

This is MAC module routine. This routine disables appropriate network traffic on the MCU's internal Ethernet module by the means of it's receive filters (unicast, multicast, broadcast, crc). Specific type of network traffic will be disabled if a corresponding bit of this routine's input parameter is set. Therefore, more than one type of network traffic can be disabled at the same time. For this purpose, predefined library constants (see the table below) can be ORed to form appropriate input value.

Parameters:

  • disFlt: network traffic/receive filter flags. Each bit corresponds to the appropriate network traffic/receive filter:
  • Bit Mask Description Predefined library const
    0 0x01 MAC Broadcast traffic/receive filter flag. When set, MAC broadcast traffic will be disabled. _Ethernet_BROADCAST
    1 0x02 MAC Multicast traffic/receive filter flag. When set, MAC multicast traffic will be disabled. _Ethernet_MULTICAST
    2 0x04 not used none
    3 0x08 not used none
    4 0x10 not used none
    5 0x20 CRC check flag. When set, CRC check will be disabled and packets with invalid CRC field will be accepted. _Ethernet_CRC
    6 0x40 not used none
    7 0x80 MAC Unicast traffic/receive filter flag. When set, MAC unicast traffic will be disabled. _Ethernet_UNICAST

      Note :
    • Advance filtering available in the MCU's internal Ethernet module such as Pattern Match, Magic Packet and Hash Table can not be disabled by this routine.
    • This routine will change receive filter configuration on-the-fly. It will not, in any way, mess with enabling/disabling receive/transmit logic or any other part of the MCU's internal Ethernet module.
    • The MCU's internal Ethernet module should be properly cofigured by the means of Ethernet_Init routine.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
Ethernet_Disable(_Ethernet_CRC or _Ethernet_UNICAST); // disable CRC checking and Unicast traffic

Ethernet_doPacket

Prototype

function Ethernet_doPacket() : byte;

Returns

  • 0 - upon successful packet processing (zero packets received or received packet processed successfully).
  • 1 - upon reception error or receive buffer corruption. Ethernet controller needs to be restarted.
  • 2 - received packet was not sent to us (not our IP, nor IP broadcast address).
  • 3 - received IP packet was not IPv4.
  • 4 - received packet was of type unknown to the library.

Description

This is MAC module routine. It processes next received packet if such exists. Packets are processed in the following manner:

  • ARP & ICMP requests are replied automatically.
  • upon TCP request the Ethernet_UserTCP function is called for further processing.
  • upon UDP request the Ethernet_UserUDP function is called for further processing.
  Note : Ethernet_doPacket must be called as often as possible in user's code.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
while true do
  begin
    ...
    Ethernet_doPacket(); // process received packets
    ...
  end;

Ethernet_putByte

Prototype

procedure Ethernet_putByte(v : byte);

Returns

Nothing.

Description

This is MAC module routine. It stores one byte to address pointed by the current Ethernet controller's write pointer (EWRPT).

Parameters:

  • v: value to store
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  data : byte;
  ...
  Ethernet_putByte(data);  // put an byte into ethernet buffer

Ethernet_putBytes

Prototype

procedure Ethernet_putBytes(ptr : ^byte; n : word);

Returns

Nothing.

Description

This is MAC module routine. It stores requested number of bytes into Ethernet controller's RAM starting from current Ethernet controller's write pointer (EWRPT) location.

Parameters:

  • ptr: RAM buffer containing bytes to be written into Ethernet controller's RAM.
  • n: number of bytes to be written.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  buffer : array[17] of byte;	 
  ...
  buffer := 'mikroElektronika';	 
  ...
  Ethernet_putBytes(buffer, 16); // put an RAM array into ethernet buffer

Ethernet_putConstBytes

Prototype

procedure Ethernet_putConstBytes(const ptr : ^byte; n : word);

Returns

Nothing.

Description

This is MAC module routine. It stores requested number of const bytes into Ethernet controller's RAM starting from current Ethernet controller's write pointer (EWRPT) location.

Parameters:

  • ptr: const buffer containing bytes to be written into Ethernet controller's RAM.
  • n: number of bytes to be written.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
const 
  buffer : array[17] of byte;	 
  ...
  buffer := 'mikroElektronika';	 
  ...
  Ethernet_putConstBytes(buffer, 16); // put a const array into ethernet buffer

Ethernet_putString

Prototype

function Ethernet_putString(ptr : ^byte) : word;

Returns

Number of bytes written into Ethernet controller's RAM.

Description

This is MAC module routine. It stores whole string (excluding null termination) into Ethernet controller's RAM starting from current Ethernet controller's write pointer (EWRPT) location.

Parameters:

  • ptr: string to be written into Ethernet controller's RAM.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  buffer : string[16];	 
  ...
  buffer := 'mikroElektronika';	 
  ...
  Ethernet_putString(buffer); // put a RAM string into ethernet buffer

Ethernet_putConstString

Prototype

function Ethernet_putConstString(const ptr : ^byte) : word;

Returns

Number of bytes written into Ethernet controller's RAM.

Description

This is MAC module routine. It stores whole const string (excluding null termination) into Ethernet controller's RAM starting from current Ethernet controller's write pointer (EWRPT) location.

Parameters:

  • ptr: const string to be written into Ethernet controller's RAM.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
const 
  buffer : string[16];	 
  ...
  buffer := 'mikroElektronika';	 
  ...
  Ethernet_putConstString(buffer); // put a const string into ethernet buffer

Ethernet_getByte

Prototype

function Ethernet_getByte() : byte;

Returns

Byte read from Ethernet controller's RAM.

Description

This is MAC module routine. It fetches a byte from address pointed to by current Ethernet controller's read pointer (ERDPT).

Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  buffer : byte; 
  ...
  buffer := Ethernet_getByte(); // read a byte from ethernet buffer

Ethernet_getBytes

Prototype

procedure Ethernet_getBytes(ptr : ^byte; addr : word; n : word);

Returns

Nothing.

Description

This is MAC module routine. It fetches equested number of bytes from Ethernet controller's RAM starting from given address. If value of 0xFFFF is passed as the address parameter, the reading will start from current Ethernet controller's read pointer (ERDPT) location.

Parameters:

  • ptr: buffer for storing bytes read from Ethernet controller's RAM.
  • addr: Ethernet controller's RAM start address. Valid values: 0..8192.
  • n: number of bytes to be read.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  buffer: array[16] of byte;	 
  ...
  Ethernet_getBytes(buffer, 0x100, 16); // read 16 bytes, starting from address 0x100

Ethernet_UserTCP

Prototype

function Ethernet_UserTCP(var remoteHost : array[4] of byte; remotePort, localPort, reqLength : word; var flags: TEthPktFlags) : word;

Returns

  • 0 - there should not be a reply to the request.
  • Length of TCP reply data field - otherwise.

Description

This is TCP module routine. It is internally called by the library. The user accesses to the TCP request by using some of the Ethernet_get routines. The user puts data in the transmit buffer by using some of the Ethernet_put routines. The function must return the length in bytes of the TCP reply, or 0 if there is nothing to transmit. If there is no need to reply to the TCP requests, just define this function with return(0) as a single statement.

Parameters:

  • remoteHost: client's IP address.
  • remotePort: client's TCP port.
  • localPort: port to which the request is sent.
  • reqLength: TCP request data field length.
  • flags: record consisted of two fields :
    type TEthPktFlags = record
      canCloseTCP: boolean;  // flag which closes socket
      isBroadcast: boolean;  // flag which denotes that the IP package has been received via subnet broadcast address (not used for PIC16 family)
    end;
    
  Note : The function source code is provided with appropriate example projects. The code should be adjusted by the user to achieve desired reply.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example

This function is internally called by the library and should not be called by the user's code.

Ethernet_UserUDP

Prototype

function Ethernet_UserUDP(var remoteHost : array[4] of byte; remotePort, destPort, reqLength : word; var flags: TEthPktFlags) : word;

Returns

  • 0 - there should not be a reply to the request.
  • Length of UDP reply data field - otherwise.

Description

This is UDP module routine. It is internally called by the library. The user accesses to the UDP request by using some of the Ethernet_get routines. The user puts data in the transmit buffer by using some of the Ethernet_put routines. The function must return the length in bytes of the UDP reply, or 0 if nothing to transmit. If you don't need to reply to the UDP requests, just define this function with a return(0) as single statement.

Parameters:

  • remoteHost: client's IP address.
  • remotePort: client's port.
  • destPort: port to which the request is sent.
  • flags: record consisted of two fields :
    type TEthPktFlags = record
      canCloseTCP: boolean;  // flag which closes socket (not relevant to UDP)
      isBroadcast: boolean;  // flag which denotes that the IP package has been received via subnet broadcast address (not used for PIC16 family)
    end;
    
  Note : The function source code is provided with appropriate example projects. The code should be adjusted by the user to achieve desired reply.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example

This function is internally called by the library and should not be called by the user's code.

Ethernet_getIpAddress

Prototype

function Ethernet_getIpAddress() : word;

Returns Ponter to the global variable holding IP address.
Description

This routine should be used when DHCP server is present on the network to fetch assigned IP address.

  Note : User should always copy the IP address from the RAM location returned by this routine into it's own IP address buffer. These locations should not be altered by the user in any case!
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  ipAddr : array[4] of byte;  // user IP address buffer
  ...	
  memcpy(ipAddr, Ethernet_getIpAddress(), 4); // fetch IP address

Ethernet_getGwIpAddress

Prototype

function Ethernet_getGwIpAddress() : word;

Returns Ponter to the global variable holding gateway IP address.
Description

This routine should be used when DHCP server is present on the network to fetch assigned gateway IP address.

  Note : User should always copy the IP address from the RAM location returned by this routine into it's own gateway IP address buffer. These locations should not be altered by the user in any case!
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  gwIpAddr : array[4] of byte;  // user gateway IP address buffer
  ...	
  memcpy(gwIpAddr, Ethernet_getGwIpAddress(), 4); // fetch gateway IP address 

Ethernet_getDnsIpAddress

Prototype

function Ethernet_getDnsIpAddress() : word;

Returns Ponter to the global variable holding DNS IP address.
Description

This routine should be used when DHCP server is present on the network to fetch assigned DNS IP address.

  Note : User should always copy the IP address from the RAM location returned by this routine into it's own DNS IP address buffer. These locations should not be altered by the user in any case!
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  dnsIpAddr : array[4] of byte;  // user DNS IP address buffer
  ...	
  memcpy(dnsIpAddr, Ethernet_getDnsIpAddress(), 4); // fetch DNS server address 

Ethernet_getIpMask

Prototype

function Ethernet_getIpMask() : word;

Returns Ponter to the global variable holding IP subnet mask.
Description

This routine should be used when DHCP server is present on the network to fetch assigned IP subnet mask.

  Note : User should always copy the IP address from the RAM location returned by this routine into it's own IP subnet mask buffer. These locations should not be altered by the user in any case!
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  IpMask : array[4] of byte;  // user IP subnet mask buffer
  ...	
  memcpy(IpMask, Ethernet_getIpMask(), 4); // fetch IP subnet mask

Ethernet_confNetwork

Prototype

procedure Ethernet_confNetwork(var ipMask, gwIpAddr, dnsIpAddr : array[4] of byte);

Returns Nothing.
Description

Configures network parameters (IP subnet mask, gateway IP address, DNS IP address) when DHCP is not used.

Parameters:

  • ipMask: IP subnet mask.
  • gwIpAddr gateway IP address.
  • dnsIpAddr: DNS IP address.
  Note : The above mentioned network parameters should be set by this routine only if DHCP module is not used. Otherwise DHCP will override these settings.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  ipMask    : array[4] of byte;  // network mask (for example : 255.255.255.0)
  gwIpAddr  : array[4] of byte;  // gateway (router) IP address
  dnsIpAddr : array[4] of byte;  // DNS server IP address
  ...	
  gwIpAddr[0]  := 192;
  gwIpAddr[1]  := 168;
  gwIpAddr[2]  := 20;
  gwIpAddr[3]  := 6;

  dnsIpAddr[0] := 192;
  dnsIpAddr[1] := 168;
  dnsIpAddr[2] := 20;
  dnsIpAddr[3] := 100;

  ipMask[0]    := 255;
  ipMask[1]    := 255;
  ipMask[2]    := 255;
  ipMask[3]    := 0;
  ...
  Ethernet_confNetwork(ipMask, gwIpAddr, dnsIpAddr); // set network configuration parameters

Ethernet_arpResolve

Prototype

function Ethernet_arpResolve(var ip : array[4] of byte; tmax : byte) : word;

Returns
  • MAC address behind the IP address - the requested IP address was resolved.
  • 0 - otherwise.
Description

This is ARP module routine. It sends an ARP request for given IP address and waits for ARP reply. If the requested IP address was resolved, an ARP cash entry is used for storing the configuration. ARP cash can store up to 3 entries. For ARP cash structure refer to "eth_j60LibDef.h" header file in the compiler's Uses/P18 folder.

Parameters:

  • ip: IP address to be resolved.
  • tmax: time in seconds to wait for an reply.
  Note : The Ethernet services are not stopped while this routine waits for ARP reply. The incoming packets will be processed normaly during this time.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  IpAddr : array[4] of byte;  // IP address
  ...	
  IpAddr[0] := 192;
  IpAddr[0] := 168;
  IpAddr[0] := 1;
  IpAddr[0] := 1;
  ...
  Ethernet_arpResolve(IpAddr, 5); // get MAC address behind the above IP address, wait 5 secs for the response

Ethernet_sendUDP

Prototype

function Ethernet_sendUDP(var destIP : array[4] of byte; sourcePort, destPort : word; pkt : ^byte; pktLen : word) : byte;

Returns
  • 1 - UDP packet was sent successfully.
  • 0 - otherwise.
Description

This is UDP module routine. It sends an UDP packet on the network.

Parameters:

  • destIP: remote host IP address.
  • sourcePort: local UDP source port number.
  • destPort: destination UDP port number.
  • pkt: packet to transmit.
  • pktLen: length in bytes of packet to transmit.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  IpAddr : array[4] of byte;  // remote IP address
  ...	
  IpAddr[0] := 192;
  IpAddr[0] := 168;
  IpAddr[0] := 1;
  IpAddr[0] := 1;
  ...
  Ethernet_sendUDP(IpAddr, 10001, 10001, 'Hello', 5); // send Hello message to the above IP address, from UDP port 10001 to UDP port 10001 

Ethernet_dnsResolve

Prototype

function Ethernet_dnsResolve(var host : array[4] of byte; tmax : byte) : word;

Returns
  • pointer to the location holding the IP address - the requested host name was resolved.
  • 0 - otherwise.
Description

This is DNS module routine. It sends an DNS request for given host name and waits for DNS reply. If the requested host name was resolved, it's IP address is stored in library global variable and a pointer containing this address is returned by the routine. UDP port 53 is used as DNS port.

Parameters:

  • host: host name to be resolved.
  • tmax: time in seconds to wait for an reply.
  Note :
  • The Ethernet services are not stopped while this routine waits for DNS reply. The incoming packets will be processed normaly during this time.
  • User should always copy the IP address from the RAM location returned by this routine into it's own resolved host IP address buffer. These locations should not be altered by the user in any case!
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
var 
  remoteHostIpAddr : array[4] of byte;	// user host IP address buffer
  ...
  // SNTP server:
  // Zurich, Switzerland: Integrated Systems Lab, Swiss Fed. Inst. of Technology
  // 129.132.2.21: swisstime.ethz.ch
  // Service Area: Switzerland and Europe	
  memcpy(remoteHostIpAddr, Ethernet_dnsResolve('swisstime.ethz.ch', 5), 4);

Ethernet_initDHCP

Prototype

function Ethernet_initDHCP(tmax : byte) : byte;

Returns
  • 1 - network parameters were obtained successfully.
  • 0 - otherwise.
Description

This is DHCP module routine. It sends an DHCP request for network parameters (IP, gateway, DNS addresses and IP subnet mask) and waits for DHCP reply. If the requested parameters were obtained successfully, their values are stored into the library global variables.

These parameters can be fetched by using appropriate library IP get routines:

UDP port 68 is used as DHCP client port and UDP port 67 is used as DHCP server port.

Parameters:

  • tmax: time in seconds to wait for an reply.
  Note :
  • The Ethernet services are not stopped while this routine waits for DNS reply. The incoming packets will be processed normaly during this time.
  • When DHCP module is used, global library variable Ethernet_userTimerSec is used to keep track of time. It is user responsibility to increment this variable each second in it's code.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
  ...	
  Ethernet_initDHCP(5); // get network configuration from DHCP server, wait 5 sec for the response 
  ...

Ethernet_doDHCPLeaseTime

Prototype

function Ethernet_doDHCPLeaseTime() : byte;

Returns
  • 0 - lease time has not expired yet.
  • 1 - lease time has expired, it's time to renew it.
Description

This is DHCP module routine. It takes care of IP address lease time by decrementing the global lease time library counter. When this time expires, it's time to contact DHCP server and renew the lease.

Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
while true do
  begin
    ...
    if(Ethernet_doDHCPLeaseTime() <> 0) then
      begin
        ... // it's time to renew the IP address lease                  
      end;  
  end;

Ethernet_renewDHCP

Prototype

function Ethernet_renewDHCP(tmax : byte) : byte;

Returns
  • 1 - upon success (lease time was renewed).
  • 0 - otherwise (renewal request timed out).
Description

This is DHCP module routine. It sends IP address lease time renewal request to DHCP server.

Parameters:

  • tmax: time in seconds to wait for an reply.
Requires

Ethernet module has to be initialized. See Ethernet_Init.

Example
while true do
  begin 
    ...
    if(Ethernet_doDHCPLeaseTime() <> 0) then
      begin
        Ethernet_renewDHCP(5); // it's time to renew the IP address lease, with 5 secs for a reply                  
      end;  
    ...  
  end;  

Library Example

This code shows how to use the PIC18FxxJ60 Ethernet library :

Copy Code To ClipboardCopy Code To Clipboard
program http_Demo;

{***********************************
 * RAM variables
 *}

var myMacAddr   : array[6] of byte  ; // my MAC address
    myIpAddr    : array[4] of byte  ; // my IP address
    gwIpAddr    : array[4] of byte  ; // gateway (router) IP address
    ipMask      : array[4] of byte  ; // network mask (for example : 255.255.255.0)
    dnsIpAddr   : array[4] of byte  ; // DNS server IP address

{************************************************************
 * ROM constant strings
 *}
const httpHeader : string[30] = 'HTTP/1.1 200 OK'+#10+'Content-type: ' ;  // HTTP header
const httpMimeTypeHTML : string[11]   = 'text/html'+#10+#10 ;              // HTML MIME type
const httpMimeTypeScript : string[12] = 'text/plain'+#10+#10 ;           // TEXT MIME type
const httpMethod : string[5] = 'GET /';
{*
 * web page, splited into 2 parts :
 * when coming short of ROM, fragmented data is handled more efficiently by linker
 *
 * this HTML page calls the boards to get its status, and builds itself with javascript
 *}
const indexPage : string[759] =
                    '<meta http-equiv="refresh" content="3;url=http://192.168.20.60">' +
                    '<HTML><HEAD></HEAD><BODY>'+
                    '<h1>PIC18FxxJ60 Mini Web Server</h1>'+
                    '<a href=/>Reload</a>'+
                    '<script src=/s></script>'+
                    '<table><tr><td valign=top><table border=1 style="font-size:20px ;font-family: terminal ;">'+
                    '<tr><th colspan=2>ADC</th></tr>'+
                    '<tr><td>AN2</td><td><script>document.write(AN2)</script></td></tr>'+
                    '<tr><td>AN3</td><td><script>document.write(AN3)</script></td></tr>'+
                    '</table></td><td><table border=1 style="font-size:20px ;font-family: terminal ;">'+
                    '<tr><th colspan=2>PORTB</th></tr>'+
                    '<script>'+
                    'var str,i;'+
                    'str="";'+
                    'for(i=0;i<8;i++)'+
                    '{str+="<tr><td bgcolor=pink>BUTTON #"+i+"</td>";'+
                    'if(PORTB&(1<<i)){str+="<td bgcolor=red>ON";}'+
                    'else {str+="<td bgcolor=#cccccc>OFF";}'+
                    'str+="</td></tr>";}'+
                    'document.write(str) ;'+
                    '</script>';

const indexPage2 : string[466] =
                    '</table></td><td>'+
                    '<table border=1 style="font-size:20px ;font-family: terminal ;">'+
                    '<tr><th colspan=3>PORTD</th></tr>'+
                    '<script>'+
                    'var str,i;'+
                    'str="";'+
                    'for(i=0;i<3;i++)'+
                    '{str+="<tr><td bgcolor=yellow>LED #"+i+"</td>";'+
                    'if(PORTD&(1<<i)){str+="<td bgcolor=red>ON";}'+
                    'else {str+="<td bgcolor=#cccccc>OFF";}'+
                    'str+="</td><td><a href=/t"+i+">Toggle</a></td></tr>";}'+
                    'document.write(str) ;'+
                    '</script>'+
                    '</table></td></tr></table>'+
                    'This is HTTP request #<script>document.write(REQ)</script></BODY></HTML>';

var    getRequest  : array[15] of byte;  // HTTP request buffer
       dyna        : array[30] of char;  // buffer for dynamic response
       httpCounter : word ;              // counter of HTTP requests

{*******************************************
 * user defined functions
 *}

{*
 * this function is called by the library
 * the user accesses to the HTTP request by successive calls to Ethernet_getByte()
 * the user puts data in the transmit buffer by successive calls to Ethernet_putByte()
 * the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
 *
 * if you don't need to reply to HTTP requests,
 * just define this function with a return(0) as single statement
 *
 *}

function Ethernet_UserTCP(var remoteHost : array[4] of byte;
                          remotePort, localPort, reqLength : word; var flags: TEthJ60PktFlags) : word;  var  i : word ;       // my reply length
       bitMask : byte ; // for bit mask
       tmp: string[11]; // to copy const array to ram for memcmp
  begin
    result := 0;
    
    // should we close tcp socket after response is sent?
    // library closes tcp socket by default if canClose flag is not reset here
    // flags.canCloseTCP := 0; // 0 - do not close socket
                               // otherwise - close socket

    if(localPort <> 80) then  // I listen only to web request on port 80
      begin
        result := 0;
        exit;
      end;

    // get 10 first bytes only of the request, the rest does not matter here
    for i := 0 to 9 do
      getRequest[i] := Ethernet_getByte() ;
    getRequest[i] := 0 ;

    // copy httpMethod to ram for use in memcmp routine
    for i := 0 to 4 do
      tmp[i] := httpMethod[i];

    if(memcmp(@getRequest, @tmp, 5) <> 0) then  // only GET method is supported here
      begin
        result := 0 ;
        exit;
      end;

    Inc(httpCounter) ;                          // one more request done

    if(getRequest[5] = 's') then                // if request path name starts with s, store dynamic data in transmit buffer
      begin
        // the text string replied by this request can be interpreted as javascript statements
        // by browsers
        result := Ethernet_putConstString(@httpHeader) ;                   // HTTP header
        result := result + Ethernet_putConstString(@httpMimeTypeScript) ;  // with text MIME type

        // add AN2 value to reply
        WordToStr(ADC_Read(2), dyna) ;
        tmp := 'var AN2=';
        result := result + Ethernet_putString(@tmp) ;
        result := result + Ethernet_putString(@dyna) ;
        tmp := ';';
        result := result + Ethernet_putString(@tmp) ;

        // add AN3 value to reply
        WordToStr(ADC_Read(3), dyna) ;
        tmp := 'var AN3=';
        result := result + Ethernet_putString(@tmp) ;
        result := result + Ethernet_putString(@dyna) ;
        tmp := ';';
        result := result + Ethernet_putString(@tmp) ;

        // add PORTB value (buttons) to reply
        tmp := 'var PORTB= ';
        result := result + Ethernet_putString(@tmp) ;
        WordToStr(PORTB, dyna) ;
        result := result + Ethernet_putString(@dyna) ;
        tmp := ';';
        result := result + Ethernet_putString(@tmp) ;

        // add PORTD value (LEDs) to reply
        tmp := 'var PORTD= ';
        result := result + Ethernet_putString(@tmp) ;
        WordToStr(PORTD, dyna) ;
        result := result + Ethernet_putString(@dyna) ;
        tmp := ';';
        result := result + Ethernet_putString(@tmp) ;

        // add HTTP requests counter to reply
        WordToStr(httpCounter, dyna) ;
        tmp := 'var REQ=   ';
        result := result + Ethernet_putString(@tmp) ;
        result := result + Ethernet_putString(@dyna) ;
        tmp := ';';
        result := result + Ethernet_putString(@tmp) ;
      end
    else
      if(getRequest[5] = 't') then                        // if request path name starts with t, toggle PORTD (LED) bit number that comes after
        begin
          bitMask := 0;
          if(isdigit(getRequest[6]) <> 0) then            // if 0 <= bit number <= 9, bits 8 & 9 does not exist but does not matter
            begin
              bitMask := getRequest[6] - '0' ;            // convert ASCII to integer
              bitMask := 1 shl bitMask ;                  // create bit mask
              PORTD   := PORTD xor bitMask ;              // toggle PORTD with xor operator
            end;
        end;

    if(result = 0) then // what do to by default
      begin
        result := Ethernet_putConstString(@httpHeader) ;              // HTTP header
        result := result + Ethernet_putConstString(@httpMimeTypeHTML) ;  // with HTML MIME type
        result := result + Ethernet_putConstString(@indexPage) ;         // HTML page first part
        result := result + Ethernet_putConstString(@indexPage2) ;        // HTML page second part
      end;
    // return to the library with the number of bytes to transmit
end;

{*
 * this function is called by the library
 * the user accesses to the UDP request by successive calls to Ethernet_getByte()
 * the user puts data in the transmit buffer by successive calls to Ethernet_putByte()
 * the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
 *
 * if you don't need to reply to UDP requests,
 * just define this function with a return(0) as single statement
 *
 *}
function Ethernet_UserUDP(var remoteHost : array[4] of byte;
                          remotePort, destPort, reqLength : word; var flags: TEthJ60PktFlags) : word;
  var tmp : string[5];
  begin
    result := 0;
    // reply is made of the remote host IP address in human readable format
    byteToStr(remoteHost[0], dyna) ;           // first IP address byte
    dyna[3] := '.' ;
    byteToStr(remoteHost[1], tmp) ;            // second
    dyna[4] := tmp[0];
    dyna[5] := tmp[1];
    dyna[6] := tmp[2];
    dyna[7] := '.' ;
    byteToStr(remoteHost[2], tmp) ;            // second
    dyna[8] := tmp[0];
    dyna[9] := tmp[1];
    dyna[10] := tmp[2];
    dyna[11] := '.' ;
    byteToStr(remoteHost[3], tmp) ;            // second
    dyna[12] := tmp[0];
    dyna[13] := tmp[1];
    dyna[14] := tmp[2];

    dyna[15] := ':' ;                          // add separator

    // then remote host port number
    WordToStr(remotePort, tmp) ;
    dyna[16] := tmp[0];
    dyna[17] := tmp[1];
    dyna[18] := tmp[2];
    dyna[19] := tmp[3];
    dyna[20] := tmp[4];
    dyna[21] := '[' ;
    WordToStr(destPort, tmp) ;
    dyna[22] := tmp[0];
    dyna[23] := tmp[1];
    dyna[24] := tmp[2];
    dyna[25] := tmp[3];
    dyna[26] := tmp[4];
    dyna[27] := ']' ;
    dyna[28] := 0 ;

    // the total length of the request is the length of the dynamic string plus the text of the request
    result := 28 + reqLength ;

    // puts the dynamic string into the transmit buffer
    Ethernet_putBytes(@dyna, 28) ;

    // then puts the request string converted into upper char into the transmit buffer
    while(reqLength <> 0) do
      begin
        Ethernet_putByte(Ethernet_getByte()) ;
        reqLength := reqLength - 1;
      end;
    // back to the library with the length of the UDP reply
  end;

begin
  ADCON1 := 0x0B ;          // ADC convertors will be used with AN2 and AN3
  CMCON  := 0x07 ;          // turn off comparators

  PORTA  := 0 ;
  TRISA  := 0x0C ;          // RA2:RA3 - analog inputs
                            // RA1:RA0 - ethernet LEDA:LEDB

  PORTB  := 0 ;
  TRISB  := 0xff ;          // set PORTB as input for buttons

  PORTD  := 0 ;
  TRISD  := 0 ;             // set PORTD as output

  httpCounter := 0;

  // set mac address
  myMacAddr[0] := 0x00;
  myMacAddr[1] := 0x14;
  myMacAddr[2] := 0xA5;
  myMacAddr[3] := 0x76;
  myMacAddr[4] := 0x19;
  myMacAddr[5] := 0x3F;

  // set IP address
  myIpAddr[0] := 192;
  myIpAddr[1] := 168;
  myIpAddr[2] := 20;
  myIpAddr[3] := 60;
  
  // set gateway address
  gwIpAddr[0]  := 192;
  gwIpAddr[1]  := 168;
  gwIpAddr[2]  := 20;
  gwIpAddr[3]  := 6;

  // set dns address
  dnsIpAddr[0] := 192;
  dnsIpAddr[1] := 168;
  dnsIpAddr[2] := 20;
  dnsIpAddr[3] := 1;

  // set subnet mask
  ipMask[0]    := 255;
  ipMask[1]    := 255;
  ipMask[2]    := 255;
  ipMask[3]    := 0;

  {*
   * starts ENC28J60 with :
   * reset bit on PORTC.B0
   * CS bit on PORTC.B1
   * my MAC & IP address
   * full duplex
   *}
  Ethernet_Init(myMacAddr, myIpAddr, _Ethernet_FULLDUPLEX) ; // init ethernet module
  Ethernet_setUserHandlers(@Ethernet_UserTCP, @Ethernet_UserUDP); // set user handlers

  // dhcp will not be used here, so use preconfigured addresses
  Ethernet_confNetwork(ipMask, gwIpAddr, dnsIpAddr) ;

  while true do                // do forever
    begin
      Ethernet_doPacket() ;   // process incoming Ethernet packets

      {*
       * add your stuff here if needed
       * Ethernet_doPacket() must be called as often as possible
       * otherwise packets could be lost
       *}
    end;
end.
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code