program probaethernet;
uses all_digital;
{*
 * Project Name:
     enc28j60Demo (Ethernet Library demo for ENC28J60 mcu)
 * Target Platform:
     PIC
 * Copyright:
     (c) mikroElektronika, 2006.
 * Revision History:
     20060810:
       - Initial release. Author: Bruno Gavand.
 *
 * V1.0 : first release
 * V1.1 : bad MIME type for / path request, changed to HTML instead of SCRIPT (thanks Srdjan !)
 *
 * description  :
 *      this code shows how to use the Spi_Ethernet mini library :
 *              the board will reply to ARP & ICMP echo requests
 *              the board will reply to UDP requests on any port :
 *                      returns the request in upper char with a header made of remote host IP & port number
 *              the board will reply to HTTP requests on port 80, GET method with pathnames :
 *                      /               will return the HTML main page
 *                      /s              will return board status as text string
 *                      /t0 ... /t7     will toggle RD0 to RD7 bit and return HTML main page
 *                      all other requests return also HTML main page
 *
 * target devices :
 *      any PIC with integrated SPI and more than 4 Kb ROM memory
 *      32 to 40 MHz clock is recommended to get from 8 to 10 Mhz SPI clock,
 *      otherwise PIC should be clocked by ENC clock output due to ENC silicon bug in SPI hardware
 *      if you try lower PIC clock speed, don't be surprised if the board hang or miss some requests !
 *
 * EP settings :
 *      RA2 & RA3 pots jumper : closed
 *      PORTA : pull-down  (place jumper J1 to lower position)  (board specific)
 *      PORTB : pull-down  (place jumper J2 to lower position)  (board specific)
 *      PORTC : pull-up    (place jumper J3 to upper position)  (board specific)
 *      BUTTONS : pull-up  (place jumper J17 to upper position)  (board specific)
 *
 *      mE Serial Ethernet board on PORTC
 *      RC0 : !RESET    to ENC reset input pin
 *      RC1 : !CS       to ENC chip select input pin
 *      the ENC28J60 SPI bus CLK, SO, SI must be connected to the corresponding SPI pins of the PIC
 *      the INT and WOL signals from the ENC are not used *
 * Test configuration:
     MCU:             PIC18F4520
                      http://ww1.microchip.com/downloads/en/DeviceDoc/39631E.pdf
     Dev.Board:       EasyPIC6
                      http://www.mikroe.com/en/tools/easypic6/
     Oscillator:      HS-PLL4, 08.000MHz
     Ext. Modules:    mE Serial Ethernet board
                      http://www.mikroe.com/en/tools/serialeth/
     SW:              mikroPascal PRO for PIC
                      http://www.mikroe.com/en/compilers/mikropascal/pro/pic/
 * NOTES:
     - Since the ENC28J60 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.
     - External power supply should be used due to Serial Ethernet Board power consumption.
 *}



{***********************************
 * RAM variables
 *}

// mE ehternet NIC pinout
var
  SPI_Ethernet_Rst : sbit at LATA0_bit;  // for writing to output pin always use latch (PIC18 family)
  SPI_Ethernet_CS  : sbit at LATA1_bit;  // for writing to output pin always use latch (PIC18 family)
  SPI_Ethernet_Rst_Direction : sbit at TRISA0_bit;
  SPI_Ethernet_CS_Direction  : sbit at TRISA1_bit;
// end ethernet NIC definitions

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 /';

const indexPage : string[289] =
                   // '<meta http-equiv="refresh" content="3;url=http://192.168.1.60">' +
                    '<HTML><HEAD><TITLE>PIC18F4550 + ENC28J60</TITLE></HEAD>'+
                    '<BODY background="http://windows-xp-secrets.com/wp-content/uploads/2008/09/00813_irishclovers_1680x1050.jpg">'+
                    '<h1 align=middle>PIC18F4550 + ENC28J60 beágyazott webszerver</h1>'+
                    '<h2 align=middle>Tesztoldal</h2><font size=5 face="calibri">';


const pagebr : string[4] = '<br>';
const indexpage2 : string[28] = '</font></font></BODY></HTML>';
const oldalle: string[58] = 'Oldalletöltések száma:&nbsp;&nbsp;&nbsp;<font color="red">';

var    puffer  : array[30] of byte;  // HTTP request buffer
       dyna        : string[30];  // buffer for dynamic response
       httpCounter : word ;              // counter of HTTP requests
       ipcimed: string[25];
       oldalletoltes: string[5];
       
function SPI_Ethernet_UserTCP(var remoteHost : array[4] of byte;
                                  remotePort, localPort, reqLength : word; var canClose: byte) : word;
  var  i : word ;       // my reply length
       tmp: string[11]; // to copy const array to ram for memcmp
       
  begin
    latb.4:= 1;
    result := 0;

    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 29 do
      puffer[i] := SPI_Ethernet_getByte() ;

    // copy httpMethod to ram for use in memcmp routine
    for i := 0 to 4 do
      tmp[i] := httpMethod[i];

    if(memcmp(@puffer, @tmp, 5) <> 0) then  // only GET method is supported here
      begin
        result := 0 ;
        exit;
      end;

    dyna:= '';
    ipcimed:= 'IP címed: <font color="red">';

    byteToStr(remoteHost[0], dyna) ;           // first IP address byte
    for i:= 0 to 2 do
      begin
        if dyna[i] <> ' ' then
          begin
            ipcimed:= ipcimed + dyna[i];
          end;
      end;
    ipcimed:= ipcimed + '.';
    
    byteToStr(remoteHost[1], dyna) ;           // first IP address byte
    for i:= 0 to 2 do
      begin
        if dyna[i] <> ' ' then
          begin
            ipcimed:= ipcimed + dyna[i];
          end;
      end;
    ipcimed:= ipcimed + '.';
    
    byteToStr(remoteHost[2], dyna) ;           // first IP address byte
    for i:= 0 to 2 do
      begin
        if dyna[i] <> ' ' then
          begin
            ipcimed:= ipcimed + dyna[i];
          end;
      end;
    ipcimed:= ipcimed + '.';
    
    byteToStr(remoteHost[3], dyna) ;           // first IP address byte
    for i:= 0 to 2 do
      begin
        if dyna[i] <> ' ' then
          begin
            ipcimed:= ipcimed + dyna[i];
          end;
      end;
    ipcimed:= ipcimed + '</font>';
    
    {dyna:= '';
    if (puffer[6] = 'S') and (puffer[7] = 'Z') and (puffer[8] = 'O') then
      begin
        i:= 13;
        while puffer[i] <> '&' do
          begin
            dyna[i-13] :=  puffer[i];
            inc(i);
          end;
      end;        }

    inc(httpCounter);
    wordtostr(httpCounter, oldalletoltes);
    
    result := SPI_Ethernet_putConstString(@httpHeader) ;                 // HTTP header
    result := result + SPI_Ethernet_putConstString(@httpMimeTypeHTML) ;  // with HTML MIME type
    result := result + SPI_Ethernet_putConstString(@indexPage) ;         // HTML page first part
    result := result + SPI_Ethernet_putConstString(@Pagebr) ;
    result := result + SPI_Ethernet_putConstString(@Pagebr) ;
    result := result + SPI_Ethernet_putString(@ipcimed);
    result := result + SPI_Ethernet_putConstString(@Pagebr) ;
    result := result + SPI_Ethernet_putConstString(@oldalle) ;
    result := result + SPI_Ethernet_putString(@oldalletoltes);
    result := result + SPI_Ethernet_putConstString(@indexPage2) ;

    latb.4:= 0;
end;

{*
 * this function is called by the library
 * the user accesses to the UDP request by successive calls to SPI_Ethernet_getByte()
 * the user puts data in the transmit buffer by successive calls to SPI_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 SPI_Ethernet_UserUDP(var remoteHost : array[4] of byte;
                                  remotePort, destPort, reqLength : word) : 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
    SPI_Ethernet_putBytes(@dyna, 28) ;

    // then puts the request string converted into upper char into the transmit buffer
    while(reqLength <> 0) do
      begin
        SPI_Ethernet_putByte(SPI_Ethernet_getByte()) ;
        reqLength := reqLength - 1;
      end;
    // back to the library with the length of the UDP reply
  end;

begin
  alldigital();

  PORTA  := 0 ;
  TRISA  := 0xff ;          // set PORTA as input for ADC

  PORTB  := 0 ;
  TRISB  := 0 ;          // 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] := 1;
  myIpAddr[3] := 60;

  // set gateway address
  gwIpAddr[0]  := 192;
  gwIpAddr[1]  := 168;
  gwIpAddr[2]  := 1;
  gwIpAddr[3]  := 1;

  // set dns address
  dnsIpAddr[0] := 192;
  dnsIpAddr[1] := 168;
  dnsIpAddr[2] := 1;
  dnsIpAddr[3] := 1;

  // set subnet mask
  ipMask[0]    := 255;
  ipMask[1]    := 255;
  ipMask[2]    := 255;
  ipMask[3]    := 0;

  SPI1_Init();  // init spi module
  SPI_Ethernet_Init(myMacAddr, myIpAddr, _SPI_Ethernet_FULLDUPLEX) ;          // init ethernet module
  SPI_Ethernet_setUserHandlers(@SPI_Ethernet_UserTCP, @SPI_Ethernet_UserUDP); // set user handlers

  // dhcp will not be used here, so use preconfigured addresses
  SPI_Ethernet_confNetwork(ipMask, gwIpAddr, dnsIpAddr) ;

  while true do                   // do forever
    begin
      SPI_Ethernet_doPacket() ;   // process incoming Ethernet packets


    end;
end.
