ورود به حساب ثبت نام جدید فراموشی کلمه عبور
برای ورود به حساب کاربری خود، نام کاربری و کلمه عبورتان را در زیر وارد کرده و روی «ورود به سایت» کلیک کنید.





اگر فرم ثبت نام برای شما نمایش داده نمی‌شود، اینجا را کلیک کنید.









اگر فرم بازیابی کلمه عبور برای شما نمایش داده نمی‌شود، اینجا را کلیک کنید.





کاربران برچسب زده شده

صفحه 1 از 3 123 آخرین
نمایش نتایج: از 1 به 10 از 21
  1. #1
    2014/05/31
    نصف جهان
    150
    26

    راه اندازی tcp/ip

    سلام به همه ی دوستان

    اگرکسی در زمینه ی tcp/ip کاری کرده لطفا یک نمونه کد قراربده

    من تاجایی که تحقیق کردم برای ای سی های متفاوت شبکه باید توی کدها دست کاری کرد من از سخت افزار ecaاستفاده می کنم وبرای شنود هم از برنامه معروف hercules استفاده می کنم اگردوستان کمک کنند ممنون می شوم
    پ.ن: انجمن خیلی خوندم وراهنمایی های زیادی شده بود هیچ جا نبود که یک رشته ی ساده را بشه ارسال کرد حالا یا توسط udp یا tcp
  2. #2
    2013/09/03
    1,984
    648

    پاسخ : راه اندازی tcp/ip

    سلام
    دوست عزیز خودم قبلا این کارو کردم...برنامشو هم گذاشتم تو سایت ولی الان هرچی سرچ میکنم نمیاد(مربوط به ورژن قبلی انجمن بود)
    با اون برنامه از طریق مرورگر میتونستی رشته بفرستی و بگیری...
  3. #3
    2014/05/31
    نصف جهان
    150
    26

    پاسخ : راه اندازی tcp/ip

    نقل قول نوشته اصلی توسط Mahdi.Faani

    مهمان عزیز شما حق دیدن لینک ها را ندارید

    عضویت

    سلام
    دوست عزیز خودم قبلا این کارو کردم...برنامشو هم گذاشتم تو سایت ولی الان هرچی سرچ میکنم نمیاد(مربوط به ورژن قبلی انجمن بود)
    با اون برنامه از طریق مرورگر میتونستی رشته بفرستی و بگیری...
    دوست عزیز شما از طریق http دیتا جابجا کردید درسته؟من خود tcpوudpمی خوام که از طریق یک برنامه تحت ویندز که خودم می نویسم دیتا جابجا کنم شما خودتون udpو tcpنوشتید؟
  4. #4
    2013/09/03
    1,984
    648

    پاسخ : راه اندازی tcp/ip

    بله
    کدش رو نوشتم داخل فلش میکرو به صورت یه رشته ذخیره کردم...واسه نمایش صفحه وب مثلا یه آیپی رو میزنی بعدش اون وب پیج از حافظه فلش میکرو لود میشه....
    حالا میتونی یه تکست باکس یا هرچی رو بذاری و اطلاعاتتو اینطوری بفرستی به میکرو...میکرو چیزای اضافی اطرافشو حذف میکنه و اطلاعات مورد نظر رو برداشت میکنه
  5. #5
    2014/05/31
    نصف جهان
    150
    26

    پاسخ : راه اندازی tcp/ip

    نقل قول نوشته اصلی توسط Mahdi.Faani

    مهمان عزیز شما حق دیدن لینک ها را ندارید

    عضویت

    بله
    کدش رو نوشتم داخل فلش میکرو به صورت یه رشته ذخیره کردم...واسه نمایش صفحه وب مثلا یه آیپی رو میزنی بعدش اون وب پیج از حافظه فلش میکرو لود میشه....
    حالا میتونی یه تکست باکس یا هرچی رو بذاری و اطلاعاتتو اینطوری بفرستی به میکرو...میکرو چیزای اضافی اطرافشو حذف میکنه و اطلاعات مورد نظر رو برداشت میکنه
    خوب مهدی جان می شه کد بگذارید؟برای سخت افزار ecaبود؟

    پ.ن:من تاصفحه 20انجمن یک ضرب خوندمش پیداش نکردم کد شمارا چه تاریخی بوده حدودا؟ اگه می شه مجدد اپلود کنید ممنون می شوم
  6. #6
    2013/09/03
    1,984
    648

    پاسخ : راه اندازی tcp/ip

    واسه آی سی enc28j60 بود
    والا الان کد همرام نیست(فرمت شدن هارد! ) وگرنه همون اول آپلود میکردم...فکر میکنم اواخر تابستون بود....
    ببخشین ولی کدش همرام نیست...
  7. #7
    2014/05/31
    نصف جهان
    150
    26

    پاسخ : راه اندازی tcp/ip

    نقل قول نوشته اصلی توسط Mahdi.Faani

    مهمان عزیز شما حق دیدن لینک ها را ندارید

    عضویت

    واسه آی سی enc28j60 بود
    والا الان کد همرام نیست(فرمت شدن هارد! ) وگرنه همون اول آپلود میکردم...فکر میکنم اواخر تابستون بود....
    ببخشین ولی کدش همرام نیست...
    مرسی ازشما اقا مهدی
    کسی دیگه ای از دوستان نیست کمک کنه؟
    ویرایش توسط Ali Chiefer : 2016/06/01 در ساعت 22:10
  8. #8
    2014/05/31
    نصف جهان
    150
    26

    پاسخ : راه اندازی tcp/ip

    پ.ن:لطفا از دوستان یک سورس کد قراربدید
  9. #9
    2013/09/03
    1,984
    648

    پاسخ : راه اندازی tcp/ip

    دوست عزیز کتابخونشو پیدا کردم

    یکم سرچ کنی میتونی نمونه کد مثال هم پیدا کنی:

    کد:
    #ifndef _ETHERNET_H_
    #define _ETHERNET_H_
    
    #include <delay.h>
    
    ////////////////////////////////////////////////////////////////////////////////
    // high level functions
    ////////////////////////////////////////////////////////////////////////////////
    void ethernet_init(unsigned char *dev_mac, unsigned char *dev_ip, unsigned int port_tcp, unsigned int port_udp);
    void ethernet_process();
    unsigned int ethernet_tcp(unsigned char* request, unsigned char* response);
    unsigned char ethernet_udp(unsigned char* data, unsigned char data_len);
    unsigned int concatstr(char *buf, unsigned int pos, const char *s);
    unsigned int concatstrf(char *buf, unsigned int pos, const flash char *s);
    
    ////////////////////////////////////////////////////////////////////////////////
    // integer type definition
    ////////////////////////////////////////////////////////////////////////////////
    typedef unsigned char   uint8_t;
    typedef   signed char   int8_t;
    typedef unsigned short  uint16_t;
    typedef   signed short  int16_t;
    typedef unsigned long   uint32_t;
    typedef   signed long    int32_t;
    
    #pragma used+
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 functions
    ////////////////////////////////////////////////////////////////////////////////
    uint8_t enc28j60ReadOp(uint8_t op, uint8_t address);
    void    enc28j60WriteOp(uint8_t op, uint8_t address, uint8_t data);
    void    enc28j60ReadBuffer(uint16_t len, uint8_t* data);
    void    enc28j60WriteBuffer(uint16_t len, uint8_t* data);
    void    enc28j60SetBank(uint8_t address);
    uint8_t enc28j60Read(uint8_t address);
    void    enc28j60Write(uint8_t address, uint8_t data);
    void    enc28j60PhyWrite(uint8_t address, uint16_t data);
    void    enc28j60clkout(uint8_t clk);
    void    enc28j60Init(uint8_t* macaddr);
    void    enc28j60PacketSend(uint16_t len, uint8_t* packet);
    uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet);
    uint8_t enc28j60getrev(void);
    uint8_t enc28j60linkup(void);
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp functions
    ////////////////////////////////////////////////////////////////////////////////
    uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len);
    uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len);
    void make_arp_answer_from_request(uint8_t *buf);
    void make_echo_reply_from_request(uint8_t *buf,uint16_t len);
    void make_udp_reply_from_request(uint8_t *buf, uint8_t datalen);
    void make_tcp_synack_from_syn(uint8_t *buf);
    uint16_t get_tcp_data_pointer(uint8_t *buf);
    void make_tcp_ack_from_any(uint8_t *buf);
    void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen);
    
    ////////////////////////////////////////////////////////////////////////////////
    // needed macros
    ////////////////////////////////////////////////////////////////////////////////
    #define LOBYTE(a)       ((a)&0x00FF)
    #define HIBYTE(a)       ((a)>>8)
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp definitions
    ////////////////////////////////////////////////////////////////////////////////
    // ******* ETH *******
    #define ETH_HEADER_LEN    14
    // values of certain bytes:
    #define ETHTYPE_ARP_H_V 0x08
    #define ETHTYPE_ARP_L_V 0x06
    #define ETHTYPE_IP_H_V  0x08
    #define ETHTYPE_IP_L_V  0x00
    // byte positions in the ethernet frame:
    //
    // Ethernet type field (2bytes):
    #define ETH_TYPE_H_P 12
    #define ETH_TYPE_L_P 13
    //
    #define ETH_DST_MAC 0
    #define ETH_SRC_MAC 6
    
    
    // ******* ARP *******
    #define ETH_ARP_OPCODE_REPLY_H_V 0x0
    #define ETH_ARP_OPCODE_REPLY_L_V 0x02
    // arp.opcode
    #define ETH_ARP_OPCODE_H_P 0x14
    #define ETH_ARP_OPCODE_L_P 0x15
    // arp.src.mac
    #define ETH_ARP_SRC_MAC_P 0x16
    #define ETH_ARP_SRC_IP_P 0x1c
    #define ETH_ARP_DST_MAC_P 0x20
    #define ETH_ARP_DST_IP_P 0x26
    
    // ******* IP *******
    #define IP_HEADER_LEN    20
    // ip.src
    #define IP_SRC_P 0x1a
    #define IP_DST_P 0x1e
    #define IP_HEADER_LEN_VER_P 0xe
    #define IP_CHECKSUM_P 0x18
    #define IP_TTL_P 0x16
    #define IP_FLAGS_P 0x14
    #define IP_P 0xe
    #define IP_TOTLEN_H_P 0x10
    #define IP_TOTLEN_L_P 0x11
    
    #define IP_PROTO_P 0x17
    
    #define IP_PROTO_ICMP_V 1
    #define IP_PROTO_TCP_V 6
    // 17=0x11
    #define IP_PROTO_UDP_V 17
    // ******* ICMP *******
    #define ICMP_TYPE_ECHOREPLY_V 0
    #define ICMP_TYPE_ECHOREQUEST_V 8
    //
    #define ICMP_TYPE_P 0x22
    #define ICMP_CHECKSUM_P 0x24
    
    // ******* UDP *******
    #define UDP_HEADER_LEN    8
    //
    #define UDP_SRC_PORT_H_P 0x22
    #define UDP_SRC_PORT_L_P 0x23
    #define UDP_DST_PORT_H_P 0x24
    #define UDP_DST_PORT_L_P 0x25
    //
    #define UDP_LEN_H_P 0x26
    #define UDP_LEN_L_P 0x27
    #define UDP_CHECKSUM_H_P 0x28
    #define UDP_CHECKSUM_L_P 0x29
    #define UDP_DATA_P 0x2a
    
    // ******* TCP *******
    #define TCP_SRC_PORT_H_P 0x22
    #define TCP_SRC_PORT_L_P 0x23
    #define TCP_DST_PORT_H_P 0x24
    #define TCP_DST_PORT_L_P 0x25
    // the tcp seq number is 4 bytes 0x26-0x29
    #define TCP_SEQ_H_P 0x26
    #define TCP_SEQACK_H_P 0x2a
    // flags: SYN=2
    #define TCP_FLAGS_P             0x2f
    #define TCP_FLAGS_SYN_V         0x02
    #define TCP_FLAGS_FIN_V         0x01
    #define TCP_FLAGS_PUSH_V        0x08
    #define TCP_FLAGS_SYNACK_V      0x12
    #define TCP_FLAGS_ACK_V         0x10
    #define TCP_FLAGS_PSHACK_V      0x18
    //  plain len without the options:
    #define TCP_HEADER_LEN_PLAIN    20
    #define TCP_HEADER_LEN_P        0x2e
    #define TCP_CHECKSUM_H_P        0x32
    #define TCP_CHECKSUM_L_P        0x33
    #define TCP_OPTIONS_P   0x36
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 definitions
    ////////////////////////////////////////////////////////////////////////////////
    // ENC28J60 Control Registers
    // Control register definitions are a combination of address,
    // bank number, and Ethernet/MAC/PHY indicator bits.
    // - Register address        (bits 0-4)
    // - Bank number        (bits 5-6)
    // - MAC/PHY indicator        (bit 7)
    #define ADDR_MASK        0x1F
    #define BANK_MASK        0x60
    #define SPRD_MASK        0x80
    // All-bank registers
    #define EIE              0x1B
    #define EIR              0x1C
    #define ESTAT            0x1D
    #define ECON2            0x1E
    #define ECON1            0x1F
    // Bank 0 registers
    #define ERDPTL           (0x00|0x00)
    #define ERDPTH           (0x01|0x00)
    #define EWRPTL           (0x02|0x00)
    #define EWRPTH           (0x03|0x00)
    #define ETXSTL           (0x04|0x00)
    #define ETXSTH           (0x05|0x00)
    #define ETXNDL           (0x06|0x00)
    #define ETXNDH           (0x07|0x00)
    #define ERXSTL           (0x08|0x00)
    #define ERXSTH           (0x09|0x00)
    #define ERXNDL           (0x0A|0x00)
    #define ERXNDH           (0x0B|0x00)
    #define ERXRDPTL         (0x0C|0x00)
    #define ERXRDPTH         (0x0D|0x00)
    #define ERXWRPTL         (0x0E|0x00)
    #define ERXWRPTH         (0x0F|0x00)
    #define EDMASTL          (0x10|0x00)
    #define EDMASTH          (0x11|0x00)
    #define EDMANDL          (0x12|0x00)
    #define EDMANDH          (0x13|0x00)
    #define EDMADSTL         (0x14|0x00)
    #define EDMADSTH         (0x15|0x00)
    #define EDMACSL          (0x16|0x00)
    #define EDMACSH          (0x17|0x00)
    // Bank 1 registers
    #define EHT0             (0x00|0x20)
    #define EHT1             (0x01|0x20)
    #define EHT2             (0x02|0x20)
    #define EHT3             (0x03|0x20)
    #define EHT4             (0x04|0x20)
    #define EHT5             (0x05|0x20)
    #define EHT6             (0x06|0x20)
    #define EHT7             (0x07|0x20)
    #define EPMM0            (0x08|0x20)
    #define EPMM1            (0x09|0x20)
    #define EPMM2            (0x0A|0x20)
    #define EPMM3            (0x0B|0x20)
    #define EPMM4            (0x0C|0x20)
    #define EPMM5            (0x0D|0x20)
    #define EPMM6            (0x0E|0x20)
    #define EPMM7            (0x0F|0x20)
    #define EPMCSL           (0x10|0x20)
    #define EPMCSH           (0x11|0x20)
    #define EPMOL            (0x14|0x20)
    #define EPMOH            (0x15|0x20)
    #define EWOLIE           (0x16|0x20)
    #define EWOLIR           (0x17|0x20)
    #define ERXFCON          (0x18|0x20)
    #define EPKTCNT          (0x19|0x20)
    // Bank 2 registers
    #define MACON1           (0x00|0x40|0x80)
    #define MACON2           (0x01|0x40|0x80)
    #define MACON3           (0x02|0x40|0x80)
    #define MACON4           (0x03|0x40|0x80)
    #define MABBIPG          (0x04|0x40|0x80)
    #define MAIPGL           (0x06|0x40|0x80)
    #define MAIPGH           (0x07|0x40|0x80)
    #define MACLCON1         (0x08|0x40|0x80)
    #define MACLCON2         (0x09|0x40|0x80)
    #define MAMXFLL          (0x0A|0x40|0x80)
    #define MAMXFLH          (0x0B|0x40|0x80)
    #define MAPHSUP          (0x0D|0x40|0x80)
    #define MICON            (0x11|0x40|0x80)
    #define MICMD            (0x12|0x40|0x80)
    #define MIREGADR         (0x14|0x40|0x80)
    #define MIWRL            (0x16|0x40|0x80)
    #define MIWRH            (0x17|0x40|0x80)
    #define MIRDL            (0x18|0x40|0x80)
    #define MIRDH            (0x19|0x40|0x80)
    // Bank 3 registers
    #define MAADR1           (0x00|0x60|0x80)
    #define MAADR0           (0x01|0x60|0x80)
    #define MAADR3           (0x02|0x60|0x80)
    #define MAADR2           (0x03|0x60|0x80)
    #define MAADR5           (0x04|0x60|0x80)
    #define MAADR4           (0x05|0x60|0x80)
    #define EBSTSD           (0x06|0x60)
    #define EBSTCON          (0x07|0x60)
    #define EBSTCSL          (0x08|0x60)
    #define EBSTCSH          (0x09|0x60)
    #define MISTAT           (0x0A|0x60|0x80)
    #define EREVID           (0x12|0x60)
    #define ECOCON           (0x15|0x60)
    #define EFLOCON          (0x17|0x60)
    #define EPAUSL           (0x18|0x60)
    #define EPAUSH           (0x19|0x60)
    // PHY registers
    #define PHCON1           0x00
    #define PHSTAT1          0x01
    #define PHHID1           0x02
    #define PHHID2           0x03
    #define PHCON2           0x10
    #define PHSTAT2          0x11
    #define PHIE             0x12
    #define PHIR             0x13
    #define PHLCON           0x14
    
    // ENC28J60 ERXFCON Register Bit Definitions
    #define ERXFCON_UCEN     0x80
    #define ERXFCON_ANDOR    0x40
    #define ERXFCON_CRCEN    0x20
    #define ERXFCON_PMEN     0x10
    #define ERXFCON_MPEN     0x08
    #define ERXFCON_HTEN     0x04
    #define ERXFCON_MCEN     0x02
    #define ERXFCON_BCEN     0x01
    // ENC28J60 EIE Register Bit Definitions
    #define EIE_INTIE        0x80
    #define EIE_PKTIE        0x40
    #define EIE_DMAIE        0x20
    #define EIE_LINKIE       0x10
    #define EIE_TXIE         0x08
    #define EIE_WOLIE        0x04
    #define EIE_TXERIE       0x02
    #define EIE_RXERIE       0x01
    // ENC28J60 EIR Register Bit Definitions
    #define EIR_PKTIF        0x40
    #define EIR_DMAIF        0x20
    #define EIR_LINKIF       0x10
    #define EIR_TXIF         0x08
    #define EIR_WOLIF        0x04
    #define EIR_TXERIF       0x02
    #define EIR_RXERIF       0x01
    // ENC28J60 ESTAT Register Bit Definitions
    #define ESTAT_INT        0x80
    #define ESTAT_LATECOL    0x10
    #define ESTAT_RXBUSY     0x04
    #define ESTAT_TXABRT     0x02
    #define ESTAT_CLKRDY     0x01
    // ENC28J60 ECON2 Register Bit Definitions
    #define ECON2_AUTOINC    0x80
    #define ECON2_PKTDEC     0x40
    #define ECON2_PWRSV      0x20
    #define ECON2_VRPS       0x08
    // ENC28J60 ECON1 Register Bit Definitions
    #define ECON1_TXRST      0x80
    #define ECON1_RXRST      0x40
    #define ECON1_DMAST      0x20
    #define ECON1_CSUMEN     0x10
    #define ECON1_TXRTS      0x08
    #define ECON1_RXEN       0x04
    #define ECON1_BSEL1      0x02
    #define ECON1_BSEL0      0x01
    // ENC28J60 MACON1 Register Bit Definitions
    #define MACON1_LOOPBK    0x10
    #define MACON1_TXPAUS    0x08
    #define MACON1_RXPAUS    0x04
    #define MACON1_PASSALL   0x02
    #define MACON1_MARXEN    0x01
    // ENC28J60 MACON2 Register Bit Definitions
    #define MACON2_MARST     0x80
    #define MACON2_RNDRST    0x40
    #define MACON2_MARXRST   0x08
    #define MACON2_RFUNRST   0x04
    #define MACON2_MATXRST   0x02
    #define MACON2_TFUNRST   0x01
    // ENC28J60 MACON3 Register Bit Definitions
    #define MACON3_PADCFG2   0x80
    #define MACON3_PADCFG1   0x40
    #define MACON3_PADCFG0   0x20
    #define MACON3_TXCRCEN   0x10
    #define MACON3_PHDRLEN   0x08
    #define MACON3_HFRMLEN   0x04
    #define MACON3_FRMLNEN   0x02
    #define MACON3_FULDPX    0x01
    // ENC28J60 MICMD Register Bit Definitions
    #define MICMD_MIISCAN    0x02
    #define MICMD_MIIRD      0x01
    // ENC28J60 MISTAT Register Bit Definitions
    #define MISTAT_NVALID    0x04
    #define MISTAT_SCAN      0x02
    #define MISTAT_BUSY      0x01
    // ENC28J60 PHY PHCON1 Register Bit Definitions
    #define PHCON1_PRST      0x8000
    #define PHCON1_PLOOPBK   0x4000
    #define PHCON1_PPWRSV    0x0800
    #define PHCON1_PDPXMD    0x0100
    // ENC28J60 PHY PHSTAT1 Register Bit Definitions
    #define PHSTAT1_PFDPX    0x1000
    #define PHSTAT1_PHDPX    0x0800
    #define PHSTAT1_LLSTAT   0x0004
    #define PHSTAT1_JBSTAT   0x0002
    // ENC28J60 PHY PHCON2 Register Bit Definitions
    #define PHCON2_FRCLINK   0x4000
    #define PHCON2_TXDIS     0x2000
    #define PHCON2_JABBER    0x0400
    #define PHCON2_HDLDIS    0x0100
    
    // ENC28J60 Packet Control Byte Bit Definitions
    #define PKTCTRL_PHUGEEN  0x08
    #define PKTCTRL_PPADEN   0x04
    #define PKTCTRL_PCRCEN   0x02
    #define PKTCTRL_POVERRIDE 0x01
    
    // SPI operation codes
    #define ENC28J60_READ_CTRL_REG       0x00
    #define ENC28J60_READ_BUF_MEM        0x3A
    #define ENC28J60_WRITE_CTRL_REG      0x40
    #define ENC28J60_WRITE_BUF_MEM       0x7A
    #define ENC28J60_BIT_FIELD_SET       0x80
    #define ENC28J60_BIT_FIELD_CLR       0xA0
    #define ENC28J60_SOFT_RESET          0xFF
    
    // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
    // buffer boundaries applied to internal 8K ram
    // the entire available packet buffer space is allocated
    // start with recbuf at 0/
    #define RXSTART_INIT    0x0
    // receive buffer end
    #define RXSTOP_INIT     (0x1FFF-0x0600-1)
    // start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
    #define TXSTART_INIT    (0x1FFF-0x0600)
    // stp TX buffer at end of mem
    #define TXSTOP_INIT     0x1FFF
    // max frame length which the conroller will accept:
    #define MAX_FRAMELEN    1500        // (note: maximum ethernet frame length would be 1518)
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 functions implementation
    ////////////////////////////////////////////////////////////////////////////////
    static uint8_t Enc28j60Bank;
    static uint16_t NextPacketPtr;
    
    // set CS to 0 = active
    #define CSACTIVE        ENC28J60_SPI_PORT&=~(1<<ENC28J60_SPI_CS)
    // set CS to 1 = passive
    #define CSPASSIVE       ENC28J60_SPI_PORT|=(1<<ENC28J60_SPI_CS)
    //
    #define SPI2X   0
    #define SPE     6
    #define MSTR    4
    #define SPIF    7
    // wait for spi operation
    #define waitspi()       while(!(SPSR&(1<<SPIF)))
    
    uint8_t enc28j60ReadOp(uint8_t op, uint8_t address)
    {
            CSACTIVE;
            // issue read command
            SPDR = op | (address & ADDR_MASK);
            waitspi();
            // read data
            SPDR = 0x00;
            waitspi();
            // do dummy read if needed (for mac and mii, see datasheet page 29)
            if(address & 0x80)
            {
                    SPDR = 0x00;
                    waitspi();
            }
            // release CS
            CSPASSIVE;
            return(SPDR);
    }
    
    void enc28j60WriteOp(uint8_t op, uint8_t address, uint8_t data)
    {
            CSACTIVE;
            // issue write command
            SPDR = op | (address & ADDR_MASK);
            waitspi();
            // write data
            SPDR = data;
            waitspi();
            CSPASSIVE;
    }
    
    void enc28j60ReadBuffer(uint16_t len, uint8_t* data)
    {
            CSACTIVE;
            // issue read command
            SPDR = ENC28J60_READ_BUF_MEM;
            waitspi();
            while(len)
            {
                    len--;
                    // read data
                    SPDR = 0x00;
                    waitspi();
                    *data = SPDR;
                    data++;
            }
            *data='\0';
            CSPASSIVE;
    }
    
    void enc28j60WriteBuffer(uint16_t len, uint8_t* data)
    {
            CSACTIVE;
            // issue write command
            SPDR = ENC28J60_WRITE_BUF_MEM;
            waitspi();
            while(len)
            {
                    len--;
                    // write data
                    SPDR = *data;
                    data++;
                    waitspi();
            }
            CSPASSIVE;
    }
    
    void enc28j60SetBank(uint8_t address)
    {
            // set the bank (if needed)
            if((address & BANK_MASK) != Enc28j60Bank)
            {
                    // set the bank
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
                    Enc28j60Bank = (address & BANK_MASK);
            }
    }
    
    uint8_t enc28j60Read(uint8_t address)
    {
            // set the bank
            enc28j60SetBank(address);
            // do the read
            return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
    }
    
    // read upper 8 bits
    uint16_t enc28j60PhyReadH(uint8_t address)
    {
        // Set the right address and start the register read operation
        enc28j60Write(MIREGADR, address);
        enc28j60Write(MICMD, MICMD_MIIRD);
            delay_us(15);
    
        // wait until the PHY read completes
        while(enc28j60Read(MISTAT) & MISTAT_BUSY);
    
        // reset reading bit
        enc28j60Write(MICMD, 0x00);
    
        return (enc28j60Read(MIRDH));
    }
    
    void enc28j60Write(uint8_t address, uint8_t data)
    {
            // set the bank
            enc28j60SetBank(address);
            // do the write
            enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
    }
    
    void enc28j60PhyWrite(uint8_t address, uint16_t data)
    {
            // set the PHY register address
            enc28j60Write(MIREGADR, address);
            // write the PHY data
            enc28j60Write(MIWRL, data);
            enc28j60Write(MIWRH, data>>8);
            // wait until the PHY write completes
            while(enc28j60Read(MISTAT) & MISTAT_BUSY){
                    delay_us(15);
            }
    }
    
    void enc28j60clkout(uint8_t clk)
    {
            //0->0; 1->25M; 2->12.5M; 3->8.33M; 4->6.25M; 5->3.125M;
        enc28j60Write(ECOCON, clk & 0x7);
    }
    
    void enc28j60Init(uint8_t* macaddr)
    {
        // initialize I/O
            // MOSI & SCK are output & low
            // CS is output & high
            // MISO is input
        ENC28J60_SPI_DDR &= ~(1<<ENC28J60_SPI_MISO);
        ENC28J60_SPI_DDR |= (1<<ENC28J60_SPI_MOSI) | (1<<ENC28J60_SPI_SCK) | (1<<ENC28J60_SPI_CS);
        ENC28J60_SPI_PORT &= ~((1<<ENC28J60_SPI_MOSI) | (1<<ENC28J60_SPI_SCK));
        ENC28J60_SPI_PORT |= (1<<ENC28J60_SPI_CS);
        // initialize SPI interface
        // master mode and Fosc/2 clock:
            SPCR = (1<<SPE)|(1<<MSTR);
            SPSR |= (1<<SPI2X);
    
        // perform system reset
        enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
        delay_ms(50);
        // check CLKRDY bit to see if reset is complete
            // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
        //while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
        // do bank 0 stuff
        // initialize receive buffer
        // 16-bit transfers, must write low byte first
        // set receive buffer start address
        NextPacketPtr = RXSTART_INIT;
            // Rx start
        enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
        enc28j60Write(ERXSTH, RXSTART_INIT>>8);
        // set receive pointer address
        enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
        enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
        // RX end
        enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
        enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
        // TX start
        enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
        enc28j60Write(ETXSTH, TXSTART_INIT>>8);
        // TX end
        enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF);
        enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
        // do bank 1 stuff, packet filter:
            // For broadcast packets we allow only ARP packtets
            // All other packets should be unicast only for our mac (MAADR)
            //
            // The pattern to match on is therefore
            // Type     ETH.DST
            // ARP      BROADCAST
            // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
            // in binary these poitions are:11 0000 0011 1111
            // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
        enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
        enc28j60Write(EPMM0, 0x3f);
        enc28j60Write(EPMM1, 0x30);
        enc28j60Write(EPMCSL, 0xf9);
        enc28j60Write(EPMCSH, 0xf7);
            //
            //
        // do bank 2 stuff
        // enable MAC receive
        enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
        // bring MAC out of reset
        enc28j60Write(MACON2, 0x00);
        // enable automatic padding to 60bytes and CRC operations
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
        // set inter-frame gap (non-back-to-back)
        enc28j60Write(MAIPGL, 0x12);
        enc28j60Write(MAIPGH, 0x0C);
        // set inter-frame gap (back-to-back)
        enc28j60Write(MABBIPG, 0x12);
        // Set the maximum packet size which the controller will accept
            // Do not send packets longer than MAX_FRAMELEN:
        enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
        enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
        // do bank 3 stuff
            // write MAC address
            // NOTE: MAC address in ENC28J60 is byte-backward
            enc28j60Write(MAADR5, macaddr[0]);
            enc28j60Write(MAADR4, macaddr[1]);
            enc28j60Write(MAADR3, macaddr[2]);
            enc28j60Write(MAADR2, macaddr[3]);
            enc28j60Write(MAADR1, macaddr[4]);
            enc28j60Write(MAADR0, macaddr[5]);
        // no loopback of transmitted frames
        enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
        // switch to bank 0
        enc28j60SetBank(ECON1);
        // enable interrutps
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
        // enable packet reception
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
    
            // LEDA=links status, LEDB=receive/transmit
            enc28j60PhyWrite(PHLCON,0x0476);
            delay_ms(20);
    }
    
    // read the revision of the chip:
    uint8_t enc28j60getrev(void)
    {
        return(enc28j60Read(EREVID));
    }
    
    // link status
    uint8_t enc28j60linkup(void)
    {
            // bit 10 (= bit 3 in upper reg)
        return(enc28j60PhyReadH(PHSTAT2) && 4);
    }
    
    void enc28j60PacketSend(uint16_t len, uint8_t* packet)
    {
        // Set the write pointer to start of transmit buffer area
        enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
        enc28j60Write(EWRPTH, TXSTART_INIT>>8);
        // Set the TXND pointer to correspond to the packet size given
        enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
        enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
        // write per-packet control byte (0x00 means use macon3 settings)
        enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
        // copy the packet into the transmit buffer
        enc28j60WriteBuffer(len, packet);
        // send the contents of the transmit buffer onto the network
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
            // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
        if( (enc28j60Read(EIR) & EIR_TXERIF) ){
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
            }
    }
    
    // Gets a packet from the network receive buffer, if one is available.
    // The packet will by headed by an ethernet header.
    //      maxlen  The maximum acceptable length of a retrieved packet.
    //      packet  Pointer where packet data should be stored.
    // Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
    uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet)
    {
        uint16_t rxstat;
        uint16_t len;
        // check if a packet has been received and buffered
        //if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
            // The above does not work. See Rev. B4 Silicon Errata point 6.
        if( enc28j60Read(EPKTCNT) ==0 ){
            return(0);
            }
    
        // Set the read pointer to the start of the received packet
        enc28j60Write(ERDPTL, (NextPacketPtr));
        enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
        // read the next packet pointer
        NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
        // read the packet length (see datasheet page 43)
        len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
            len-=4; //remove the CRC count
        // read the receive status (see datasheet page 43)
        rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        rxstat |= ((uint16_t)enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0))<<8;
        // limit retrieve length
            if (len>maxlen-1){
                    len=maxlen-1;
            }
            // check CRC and symbol errors (see datasheet page 44, table 7-3):
            // The ERXFCON.CRCEN is set by default. Normally we should not
            // need to check this.
            if ((rxstat & 0x80)==0){
                    // invalid
                    len=0;
            }else{
                    // copy the packet from the receive buffer
                    enc28j60ReadBuffer(len, packet);
            }
        // Move the RX read pointer to the start of the next received packet
        // This frees the memory we just read out
        enc28j60Write(ERXRDPTL, (NextPacketPtr));
        enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
        // decrement the packet counter indicate we are done with this packet
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
        return(len);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp functions implementation
    ////////////////////////////////////////////////////////////////////////////////
    
    unsigned char eth_buf[BUFFER_SIZE+1];
    static uint16_t wwwport=80;
    static uint16_t udpport=1200;
    static uint8_t macaddr[6];
    static uint8_t ipaddr[4];
    static int16_t info_hdr_len=0;
    static int16_t info_data_len=0;
    static uint8_t seqnum=0xa; // my initial tcp sequence number
    
    // The Ip checksum is calculated over the ip header only starting
    // with the header length field and a total length of 20 bytes
    // unitl ip.dst
    // You must set the IP checksum field to zero before you start
    // the calculation.
    // len for ip is 20.
    //
    // For UDP/TCP we do not make up the required pseudo header. Instead we
    // use the ip.src and ip.dst fields of the real packet:
    // The udp checksum calculation starts with the ip.src field
    // Ip.src=4bytes,Ip.dst=4 bytes,Udp header=8bytes + data length=16+len
    // In other words the len here is 8 + length over which you actually
    // want to calculate the checksum.
    // You must set the checksum field to zero before you start
    // the calculation.
    // len for udp is: 8 + 8 + data length
    // len for tcp is: 4+4 + 20 + option len + data length
    //
    // For more information on how this algorithm works see:
    // http://www.netfor2.com/checksum.html
    // http://www.msc.uky.edu/ken/cs471/notes/chap3.htm
    // The RFC has also a C code example: http://www.faqs.org/rfcs/rfc1071.html
    uint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type){
            // type 0=ip
            //      1=udp
            //      2=tcp
            uint32_t sum = 0;
    
            //if(type==0){
            //        // do not add anything
            //}
            if(type==1){
                    sum+=IP_PROTO_UDP_V; // protocol udp
                    // the length here is the length of udp (data+header len)
                    // =length given to this function - (IP.scr+IP.dst length)
                    sum+=len-8; // = real tcp len
            }
            if(type==2){
                    sum+=IP_PROTO_TCP_V;
                    // the length here is the length of tcp (data+header len)
                    // =length given to this function - (IP.scr+IP.dst length)
                    sum+=len-8; // = real tcp len
            }
            // build the sum of 16bit words
            while(len >1){
                    sum += 0xFFFF & (((uint32_t)*buf<<8)|*(buf+1));
                    buf+=2;
                    len-=2;
            }
            // if there is a byte left then add it (padded with zero)
            if (len){
                    sum += ((uint32_t)(0xFF & *buf))<<8;
            }
            // now calculate the sum over the bytes in the sum
            // until the result is only 16bit long
            while (sum>>16){
                    sum = (sum & 0xFFFF)+(sum >> 16);
            }
            // build 1's complement:
            return( (uint16_t) sum ^ 0xFFFF);
    }
    
    uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len){
            uint8_t i=0;
            //
            if (len<41){
                    return(0);
            }
            if(buf[ETH_TYPE_H_P] != ETHTYPE_ARP_H_V ||
               buf[ETH_TYPE_L_P] != ETHTYPE_ARP_L_V){
                    return(0);
            }
            while(i<4){
                    if(buf[ETH_ARP_DST_IP_P+i] != ipaddr[i]){
                            return(0);
                    }
                    i++;
            }
            return(1);
    }
    
    uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len){
            uint8_t i=0;
            //eth+ip+udp header is 42
            if (len<42){
                    return(0);
            }
            if(buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V ||
               buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V){
                    return(0);
            }
            if (buf[IP_HEADER_LEN_VER_P]!=0x45){
                    // must be IP V4 and 20 byte header
                    return(0);
            }
            while(i<4){
                    if(buf[IP_DST_P+i]!=ipaddr[i]){
                            return(0);
                    }
                    i++;
            }
            return(1);
    }
    // make a return eth header from a received eth packet
    void make_eth(uint8_t *buf)
    {
            uint8_t i=0;
            //
            //copy the destination mac from the source and fill my mac into src
            while(i<6){
                    buf[ETH_DST_MAC +i]=buf[ETH_SRC_MAC +i];
                    buf[ETH_SRC_MAC +i]=macaddr[i];
                    i++;
            }
    }
    void fill_ip_hdr_checksum(uint8_t *buf)
    {
            uint16_t ck;
            // clear the 2 byte checksum
            buf[IP_CHECKSUM_P]=0;
            buf[IP_CHECKSUM_P+1]=0;
            buf[IP_FLAGS_P]=0x40; // don't fragment
            buf[IP_FLAGS_P+1]=0;  // fragement offset
            buf[IP_TTL_P]=64; // ttl
            // calculate the checksum:
            ck=checksum(&buf[IP_P], IP_HEADER_LEN,0);
            buf[IP_CHECKSUM_P]=ck>>8;
            buf[IP_CHECKSUM_P+1]=ck& 0xff;
    }
    
    // make a return ip header from a received ip packet
    void make_ip(uint8_t *buf)
    {
            uint8_t i=0;
            while(i<4){
                    buf[IP_DST_P+i]=buf[IP_SRC_P+i];
                    buf[IP_SRC_P+i]=ipaddr[i];
                    i++;
            }
            fill_ip_hdr_checksum(buf);
    }
    
    // make a return tcp header from a received tcp packet
    // rel_ack_num is how much we must step the seq number received from the
    // other side. We do not send more than 255 bytes of text (=data) in the tcp packet.
    // If mss=1 then mss is included in the options list
    //
    // After calling this function you can fill in the first data byte at TCP_OPTIONS_P+4
    // If cp_seq=0 then an initial sequence number is used (should be use in synack)
    // otherwise it is copied from the packet we received
    void make_tcphead(uint8_t *buf,uint16_t rel_ack_num,uint8_t mss,uint8_t cp_seq)
    {
            uint8_t i=0;
            uint8_t tseq;
    
            buf[TCP_DST_PORT_H_P] = buf[TCP_SRC_PORT_H_P];
            buf[TCP_DST_PORT_L_P] = buf[TCP_SRC_PORT_L_P];
            // set source port  (http):
            buf[TCP_SRC_PORT_L_P] = LOBYTE(wwwport);
            buf[TCP_SRC_PORT_H_P] = HIBYTE(wwwport);
            i=4;
            // sequence numbers:
            // add the rel ack num to SEQACK
            while(i>0){
                    rel_ack_num=buf[TCP_SEQ_H_P+i-1]+rel_ack_num;
                    tseq=buf[TCP_SEQACK_H_P+i-1];
                    buf[TCP_SEQACK_H_P+i-1]=0xff&rel_ack_num;
                    if (cp_seq){
                            // copy the acknum sent to us into the sequence number
                            buf[TCP_SEQ_H_P+i-1]=tseq;
                    }else{
                            buf[TCP_SEQ_H_P+i-1]= 0; // some preset vallue
                    }
                    rel_ack_num=rel_ack_num>>8;
                    i--;
            }
            if (cp_seq==0){
                    // put inital seq number
                    buf[TCP_SEQ_H_P+0]= 0;
                    buf[TCP_SEQ_H_P+1]= 0;
                    // we step only the second byte, this allows us to send packts
                    // with 255 bytes or 512 (if we step the initial seqnum by 2)
                    buf[TCP_SEQ_H_P+2]= seqnum;
                    buf[TCP_SEQ_H_P+3]= 0;
                    // step the inititial seq num by something we will not use
                    // during this tcp session:
                    seqnum+=2;
            }
            // zero the checksum
            buf[TCP_CHECKSUM_H_P]=0;
            buf[TCP_CHECKSUM_L_P]=0;
    
            // The tcp header length is only a 4 bit field (the upper 4 bits).
            // It is calculated in units of 4 bytes.
            // E.g 24 bytes: 24/4=6 => 0x60=header len field
            //buf[TCP_HEADER_LEN_P]=(((TCP_HEADER_LEN_PLAIN+4)/4)) <<4; // 0x60
            if (mss){
                    // the only option we set is MSS to 1408:
                    // 1408 in hex is 0x580
                    buf[TCP_OPTIONS_P]=2;
                    buf[TCP_OPTIONS_P+1]=4;
                    buf[TCP_OPTIONS_P+2]=0x05;
                    buf[TCP_OPTIONS_P+3]=0x80;
                    // 24 bytes:
                    buf[TCP_HEADER_LEN_P]=0x60;
            }else{
                    // no options:
                    // 20 bytes:
                    buf[TCP_HEADER_LEN_P]=0x50;
            }
    }
    
    void make_arp_answer_from_request(uint8_t *buf)
    {
            uint8_t i=0;
            //
            make_eth(buf);
            buf[ETH_ARP_OPCODE_H_P]=ETH_ARP_OPCODE_REPLY_H_V;
            buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V;
            // fill the mac addresses:
            while(i<6){
                    buf[ETH_ARP_DST_MAC_P+i]=buf[ETH_ARP_SRC_MAC_P+i];
                    buf[ETH_ARP_SRC_MAC_P+i]=macaddr[i];
                    i++;
            }
            i=0;
            while(i<4){
                    buf[ETH_ARP_DST_IP_P+i]=buf[ETH_ARP_SRC_IP_P+i];
                    buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
                    i++;
            }
            // eth+arp is 42 bytes:
            enc28j60PacketSend(42,buf);
    }
    
    void make_echo_reply_from_request(uint8_t *buf,uint16_t len)
    {
            make_eth(buf);
            make_ip(buf);
            buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V;
            // we changed only the icmp.type field from request(=8) to reply(=0).
            // we can therefore easily correct the checksum:
            if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)){
                    buf[ICMP_CHECKSUM_P+1]++;
            }
            buf[ICMP_CHECKSUM_P]+=0x08;
            //
            enc28j60PacketSend(len,buf);
    }
    
    // you can send a max of 220 bytes of data
    void make_udp_reply_from_request(uint8_t *buf, uint8_t datalen)
    {
            uint8_t i=0;
            uint16_t ck;
            make_eth(buf);
            if (datalen>220){
                    datalen=220;
            }
            // total length field in the IP header must be set:
            buf[IP_TOTLEN_H_P]=0;
            buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
            make_ip(buf);
            // send to port:
            //buf[UDP_DST_PORT_H_P]=port>>8;
            //buf[UDP_DST_PORT_L_P]=port & 0xff;
            // sent to port of sender and use "port" as own source:
            buf[UDP_DST_PORT_H_P]=buf[UDP_SRC_PORT_H_P];
            buf[UDP_DST_PORT_L_P]= buf[UDP_SRC_PORT_L_P];
            buf[UDP_SRC_PORT_H_P]=HIBYTE(udpport);
            buf[UDP_SRC_PORT_L_P]=LOBYTE(udpport);
            // calculte the udp length:
            buf[UDP_LEN_H_P]=0;
            buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;
            // zero the checksum
            buf[UDP_CHECKSUM_H_P]=0;
            buf[UDP_CHECKSUM_L_P]=0;
    /*
            // copy the data:
            while(i<datalen){
                    buf[UDP_DATA_P+i]=data[i];
                    i++;
            }
    */
            ck=checksum(&buf[IP_SRC_P], 16 + datalen,1);
            buf[UDP_CHECKSUM_H_P]=ck>>8;
            buf[UDP_CHECKSUM_L_P]=ck& 0xff;
            enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
    }
    
    void make_tcp_synack_from_syn(uint8_t *buf)
    {
            uint16_t ck;
            make_eth(buf);
            // total length field in the IP header must be set:
            // 20 bytes IP + 24 bytes (20tcp+4tcp options)
            buf[IP_TOTLEN_H_P]=0;
            buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4;
            make_ip(buf);
            buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V;
            make_tcphead(buf,1,1,0);
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + 4 (one option: mss)
            ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+4,2);
            buf[TCP_CHECKSUM_H_P]=ck>>8;
            buf[TCP_CHECKSUM_L_P]=ck& 0xff;
            // add 4 for option mss:
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);
    }
    
    // get a pointer to the start of tcp data in buf
    // Returns 0 if there is no data
    uint16_t get_tcp_data_pointer(uint8_t *buf)
    {
            info_data_len=(((int16_t)buf[IP_TOTLEN_H_P])<<8)|(buf[IP_TOTLEN_L_P]&0xff);
            info_data_len-=IP_HEADER_LEN;
            info_hdr_len=(buf[TCP_HEADER_LEN_P]>>4)*4; // generate len in bytes;
            info_data_len-=info_hdr_len;
            if (info_data_len<=0){
                    info_data_len=0;
                    return(0);
            }
            return((uint16_t)TCP_SRC_PORT_H_P+info_hdr_len);
    }
    
    // concatenate string to buffer at pos and return final position
    uint16_t concatstrf(uint8_t *buf, uint16_t pos, const flash char *s)
    {
            char c;
            while ((c = *s++)!=0)
            {
                    buf[pos]=c;
                    pos++;
            }
            return(pos);
    }
    
    // concatenate string to buffer at pos and return final position
    uint16_t concatstr(uint8_t *buf, uint16_t pos, const char *s)
    {
            char c;
            while ((c = *s++)!=0)
            {
                    buf[pos]=c;
                    pos++;
            }
            return(pos);
    }
    
    // Make just an ack packet with no tcp data inside
    // This will modify the eth/ip/tcp header
    void make_tcp_ack_from_any(uint8_t *buf)
    {
            uint16_t j;
            make_eth(buf);
            // fill the header:
            buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V;
            if (info_data_len==0){
                    // if there is no data then we must still acknoledge one packet
                    make_tcphead(buf,1,0,1); // no options
            }else{
                    make_tcphead(buf,info_data_len,0,1); // no options
            }
    
            // total length field in the IP header must be set:
            // 20 bytes IP + 20 bytes tcp (when no options)
            j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN;
            buf[IP_TOTLEN_H_P]=j>>8;
            buf[IP_TOTLEN_L_P]=j& 0xff;
            make_ip(buf);
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
            j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN,2);
            buf[TCP_CHECKSUM_H_P]=j>>8;
            buf[TCP_CHECKSUM_L_P]=j& 0xff;
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN,buf);
    }
    
    // you must have called get_tcp_data_pointer at some time before calling this function
    // dlen is the amount of tcp data (http data) we send in this packet
    // You can use this function only immediately after make_tcp_ack_from_any
    // This is because this function will NOT modify the eth/ip/tcp header except for
    // length and checksum
    void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen)
    {
            uint16_t j;
            // fill the header:
            // This code requires that we send only one data packet
            // because we keep no state information. We must therefore set
            // the fin here:
            buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V;
    
            // total length field in the IP header must be set:
            // 20 bytes IP + 20 bytes tcp (when no options) + len of data
            j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen;
            buf[IP_TOTLEN_H_P]=j>>8;
            buf[IP_TOTLEN_L_P]=j& 0xff;
            fill_ip_hdr_checksum(buf);
            // zero the checksum
            buf[TCP_CHECKSUM_H_P]=0;
            buf[TCP_CHECKSUM_L_P]=0;
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
            j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlen,2);
            buf[TCP_CHECKSUM_H_P]=j>>8;
            buf[TCP_CHECKSUM_L_P]=j& 0xff;
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen+ETH_HEADER_LEN,buf);
    }
    
    
    // you must call this function once before you use any of the other functions:
    void ethernet_init(unsigned char *dev_mac, unsigned char *dev_ip, unsigned int port_tcp, unsigned int port_udp)
    {
            uint8_t i=0;
            wwwport=port_tcp;
            udpport=port_udp;
            while(i<4){
                    ipaddr[i]=dev_ip[i];
                    i++;
            }
            i=0;
            while(i<6){
                    macaddr[i]=dev_mac[i];
                    i++;
            }
            // initialize enc28j60
            enc28j60Init(dev_mac);
    }
    
    void ethernet_process()
    {
            uint16_t plen;
            uint16_t data_p;
            uint8_t data_len;
    
            plen = enc28j60PacketReceive(BUFFER_SIZE, eth_buf);
            if(plen!=0)
            {
                    // arp is broadcast if unknown but a host may also verify
                    // the mac address by sending it to a unicast address.
                    if(eth_type_is_arp_and_my_ip(eth_buf,plen))
                    {
                            make_arp_answer_from_request(eth_buf);
                    }
                    // check if ip packets are for us:
                    else if(eth_type_is_ip_and_my_ip(eth_buf,plen))
                    {
                            if( eth_buf[IP_PROTO_P]==IP_PROTO_ICMP_V
                            && eth_buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V )
                            {
                                    // a ping packet, let's send pong
                                    make_echo_reply_from_request(eth_buf,plen);
                            }
                            // we listen to tcp port
                            else if (eth_buf[IP_PROTO_P]==IP_PROTO_TCP_V
                                    &&eth_buf[TCP_DST_PORT_H_P]==HIBYTE(wwwport)
                                    &&eth_buf[TCP_DST_PORT_L_P]==LOBYTE(wwwport) )
                            {
                                    if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
                                            // make_tcp_synack_from_syn does already send the syn,ack
                                            make_tcp_synack_from_syn(eth_buf);
                                    else if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
                                    {
                                            // we can possibly have no data, just ack:
                                            data_p=get_tcp_data_pointer(eth_buf);
                                            if (data_p==0)
                                            {
                                                    // just an ack with no data, wait for next packet
                                                    if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
                                                    {
                                                            // finack, answer with ack
                                                            make_tcp_ack_from_any(eth_buf);
                                                    }
                                            }
                                            else
                                            {
                                                    plen = ethernet_tcp( eth_buf+data_p, eth_buf+TCP_CHECKSUM_L_P+3 );
                                                    make_tcp_ack_from_any(eth_buf); // send ack for http get
                                                    make_tcp_ack_with_data(eth_buf, plen); // send data
                                            }
                                    }
                            }
                            // we listen to udp port
                            else if (eth_buf[IP_PROTO_P]==IP_PROTO_UDP_V
                                    &&eth_buf[UDP_DST_PORT_H_P]==HIBYTE(udpport)
                                    &&eth_buf[UDP_DST_PORT_L_P]==LOBYTE(udpport) )
                            {
                                    data_len = eth_buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
                                    data_len = ethernet_udp( eth_buf+UDP_DATA_P, data_len);
                                    make_udp_reply_from_request(eth_buf, data_len);
                            }
                    }
            }
    }
    
    #pragma used-
    
    #endif
  10. #10
    2014/05/31
    نصف جهان
    150
    26

    پاسخ : راه اندازی tcp/ip

    نقل قول نوشته اصلی توسط Mahdi.Faani

    مهمان عزیز شما حق دیدن لینک ها را ندارید

    عضویت

    دوست عزیز کتابخونشو پیدا کردم

    یکم سرچ کنی میتونی نمونه کد مثال هم پیدا کنی:

    کد:
    #ifndef _ETHERNET_H_
    #define _ETHERNET_H_
    
    #include <delay.h>
    
    ////////////////////////////////////////////////////////////////////////////////
    // high level functions
    ////////////////////////////////////////////////////////////////////////////////
    void ethernet_init(unsigned char *dev_mac, unsigned char *dev_ip, unsigned int port_tcp, unsigned int port_udp);
    void ethernet_process();
    unsigned int ethernet_tcp(unsigned char* request, unsigned char* response);
    unsigned char ethernet_udp(unsigned char* data, unsigned char data_len);
    unsigned int concatstr(char *buf, unsigned int pos, const char *s);
    unsigned int concatstrf(char *buf, unsigned int pos, const flash char *s);
    
    ////////////////////////////////////////////////////////////////////////////////
    // integer type definition
    ////////////////////////////////////////////////////////////////////////////////
    typedef unsigned char   uint8_t;
    typedef   signed char   int8_t;
    typedef unsigned short  uint16_t;
    typedef   signed short  int16_t;
    typedef unsigned long   uint32_t;
    typedef   signed long    int32_t;
    
    #pragma used+
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 functions
    ////////////////////////////////////////////////////////////////////////////////
    uint8_t enc28j60ReadOp(uint8_t op, uint8_t address);
    void    enc28j60WriteOp(uint8_t op, uint8_t address, uint8_t data);
    void    enc28j60ReadBuffer(uint16_t len, uint8_t* data);
    void    enc28j60WriteBuffer(uint16_t len, uint8_t* data);
    void    enc28j60SetBank(uint8_t address);
    uint8_t enc28j60Read(uint8_t address);
    void    enc28j60Write(uint8_t address, uint8_t data);
    void    enc28j60PhyWrite(uint8_t address, uint16_t data);
    void    enc28j60clkout(uint8_t clk);
    void    enc28j60Init(uint8_t* macaddr);
    void    enc28j60PacketSend(uint16_t len, uint8_t* packet);
    uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet);
    uint8_t enc28j60getrev(void);
    uint8_t enc28j60linkup(void);
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp functions
    ////////////////////////////////////////////////////////////////////////////////
    uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len);
    uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len);
    void make_arp_answer_from_request(uint8_t *buf);
    void make_echo_reply_from_request(uint8_t *buf,uint16_t len);
    void make_udp_reply_from_request(uint8_t *buf, uint8_t datalen);
    void make_tcp_synack_from_syn(uint8_t *buf);
    uint16_t get_tcp_data_pointer(uint8_t *buf);
    void make_tcp_ack_from_any(uint8_t *buf);
    void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen);
    
    ////////////////////////////////////////////////////////////////////////////////
    // needed macros
    ////////////////////////////////////////////////////////////////////////////////
    #define LOBYTE(a)       ((a)&0x00FF)
    #define HIBYTE(a)       ((a)>>8)
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp definitions
    ////////////////////////////////////////////////////////////////////////////////
    // ******* ETH *******
    #define ETH_HEADER_LEN    14
    // values of certain bytes:
    #define ETHTYPE_ARP_H_V 0x08
    #define ETHTYPE_ARP_L_V 0x06
    #define ETHTYPE_IP_H_V  0x08
    #define ETHTYPE_IP_L_V  0x00
    // byte positions in the ethernet frame:
    //
    // Ethernet type field (2bytes):
    #define ETH_TYPE_H_P 12
    #define ETH_TYPE_L_P 13
    //
    #define ETH_DST_MAC 0
    #define ETH_SRC_MAC 6
    
    
    // ******* ARP *******
    #define ETH_ARP_OPCODE_REPLY_H_V 0x0
    #define ETH_ARP_OPCODE_REPLY_L_V 0x02
    // arp.opcode
    #define ETH_ARP_OPCODE_H_P 0x14
    #define ETH_ARP_OPCODE_L_P 0x15
    // arp.src.mac
    #define ETH_ARP_SRC_MAC_P 0x16
    #define ETH_ARP_SRC_IP_P 0x1c
    #define ETH_ARP_DST_MAC_P 0x20
    #define ETH_ARP_DST_IP_P 0x26
    
    // ******* IP *******
    #define IP_HEADER_LEN    20
    // ip.src
    #define IP_SRC_P 0x1a
    #define IP_DST_P 0x1e
    #define IP_HEADER_LEN_VER_P 0xe
    #define IP_CHECKSUM_P 0x18
    #define IP_TTL_P 0x16
    #define IP_FLAGS_P 0x14
    #define IP_P 0xe
    #define IP_TOTLEN_H_P 0x10
    #define IP_TOTLEN_L_P 0x11
    
    #define IP_PROTO_P 0x17
    
    #define IP_PROTO_ICMP_V 1
    #define IP_PROTO_TCP_V 6
    // 17=0x11
    #define IP_PROTO_UDP_V 17
    // ******* ICMP *******
    #define ICMP_TYPE_ECHOREPLY_V 0
    #define ICMP_TYPE_ECHOREQUEST_V 8
    //
    #define ICMP_TYPE_P 0x22
    #define ICMP_CHECKSUM_P 0x24
    
    // ******* UDP *******
    #define UDP_HEADER_LEN    8
    //
    #define UDP_SRC_PORT_H_P 0x22
    #define UDP_SRC_PORT_L_P 0x23
    #define UDP_DST_PORT_H_P 0x24
    #define UDP_DST_PORT_L_P 0x25
    //
    #define UDP_LEN_H_P 0x26
    #define UDP_LEN_L_P 0x27
    #define UDP_CHECKSUM_H_P 0x28
    #define UDP_CHECKSUM_L_P 0x29
    #define UDP_DATA_P 0x2a
    
    // ******* TCP *******
    #define TCP_SRC_PORT_H_P 0x22
    #define TCP_SRC_PORT_L_P 0x23
    #define TCP_DST_PORT_H_P 0x24
    #define TCP_DST_PORT_L_P 0x25
    // the tcp seq number is 4 bytes 0x26-0x29
    #define TCP_SEQ_H_P 0x26
    #define TCP_SEQACK_H_P 0x2a
    // flags: SYN=2
    #define TCP_FLAGS_P             0x2f
    #define TCP_FLAGS_SYN_V         0x02
    #define TCP_FLAGS_FIN_V         0x01
    #define TCP_FLAGS_PUSH_V        0x08
    #define TCP_FLAGS_SYNACK_V      0x12
    #define TCP_FLAGS_ACK_V         0x10
    #define TCP_FLAGS_PSHACK_V      0x18
    //  plain len without the options:
    #define TCP_HEADER_LEN_PLAIN    20
    #define TCP_HEADER_LEN_P        0x2e
    #define TCP_CHECKSUM_H_P        0x32
    #define TCP_CHECKSUM_L_P        0x33
    #define TCP_OPTIONS_P   0x36
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 definitions
    ////////////////////////////////////////////////////////////////////////////////
    // ENC28J60 Control Registers
    // Control register definitions are a combination of address,
    // bank number, and Ethernet/MAC/PHY indicator bits.
    // - Register address        (bits 0-4)
    // - Bank number        (bits 5-6)
    // - MAC/PHY indicator        (bit 7)
    #define ADDR_MASK        0x1F
    #define BANK_MASK        0x60
    #define SPRD_MASK        0x80
    // All-bank registers
    #define EIE              0x1B
    #define EIR              0x1C
    #define ESTAT            0x1D
    #define ECON2            0x1E
    #define ECON1            0x1F
    // Bank 0 registers
    #define ERDPTL           (0x00|0x00)
    #define ERDPTH           (0x01|0x00)
    #define EWRPTL           (0x02|0x00)
    #define EWRPTH           (0x03|0x00)
    #define ETXSTL           (0x04|0x00)
    #define ETXSTH           (0x05|0x00)
    #define ETXNDL           (0x06|0x00)
    #define ETXNDH           (0x07|0x00)
    #define ERXSTL           (0x08|0x00)
    #define ERXSTH           (0x09|0x00)
    #define ERXNDL           (0x0A|0x00)
    #define ERXNDH           (0x0B|0x00)
    #define ERXRDPTL         (0x0C|0x00)
    #define ERXRDPTH         (0x0D|0x00)
    #define ERXWRPTL         (0x0E|0x00)
    #define ERXWRPTH         (0x0F|0x00)
    #define EDMASTL          (0x10|0x00)
    #define EDMASTH          (0x11|0x00)
    #define EDMANDL          (0x12|0x00)
    #define EDMANDH          (0x13|0x00)
    #define EDMADSTL         (0x14|0x00)
    #define EDMADSTH         (0x15|0x00)
    #define EDMACSL          (0x16|0x00)
    #define EDMACSH          (0x17|0x00)
    // Bank 1 registers
    #define EHT0             (0x00|0x20)
    #define EHT1             (0x01|0x20)
    #define EHT2             (0x02|0x20)
    #define EHT3             (0x03|0x20)
    #define EHT4             (0x04|0x20)
    #define EHT5             (0x05|0x20)
    #define EHT6             (0x06|0x20)
    #define EHT7             (0x07|0x20)
    #define EPMM0            (0x08|0x20)
    #define EPMM1            (0x09|0x20)
    #define EPMM2            (0x0A|0x20)
    #define EPMM3            (0x0B|0x20)
    #define EPMM4            (0x0C|0x20)
    #define EPMM5            (0x0D|0x20)
    #define EPMM6            (0x0E|0x20)
    #define EPMM7            (0x0F|0x20)
    #define EPMCSL           (0x10|0x20)
    #define EPMCSH           (0x11|0x20)
    #define EPMOL            (0x14|0x20)
    #define EPMOH            (0x15|0x20)
    #define EWOLIE           (0x16|0x20)
    #define EWOLIR           (0x17|0x20)
    #define ERXFCON          (0x18|0x20)
    #define EPKTCNT          (0x19|0x20)
    // Bank 2 registers
    #define MACON1           (0x00|0x40|0x80)
    #define MACON2           (0x01|0x40|0x80)
    #define MACON3           (0x02|0x40|0x80)
    #define MACON4           (0x03|0x40|0x80)
    #define MABBIPG          (0x04|0x40|0x80)
    #define MAIPGL           (0x06|0x40|0x80)
    #define MAIPGH           (0x07|0x40|0x80)
    #define MACLCON1         (0x08|0x40|0x80)
    #define MACLCON2         (0x09|0x40|0x80)
    #define MAMXFLL          (0x0A|0x40|0x80)
    #define MAMXFLH          (0x0B|0x40|0x80)
    #define MAPHSUP          (0x0D|0x40|0x80)
    #define MICON            (0x11|0x40|0x80)
    #define MICMD            (0x12|0x40|0x80)
    #define MIREGADR         (0x14|0x40|0x80)
    #define MIWRL            (0x16|0x40|0x80)
    #define MIWRH            (0x17|0x40|0x80)
    #define MIRDL            (0x18|0x40|0x80)
    #define MIRDH            (0x19|0x40|0x80)
    // Bank 3 registers
    #define MAADR1           (0x00|0x60|0x80)
    #define MAADR0           (0x01|0x60|0x80)
    #define MAADR3           (0x02|0x60|0x80)
    #define MAADR2           (0x03|0x60|0x80)
    #define MAADR5           (0x04|0x60|0x80)
    #define MAADR4           (0x05|0x60|0x80)
    #define EBSTSD           (0x06|0x60)
    #define EBSTCON          (0x07|0x60)
    #define EBSTCSL          (0x08|0x60)
    #define EBSTCSH          (0x09|0x60)
    #define MISTAT           (0x0A|0x60|0x80)
    #define EREVID           (0x12|0x60)
    #define ECOCON           (0x15|0x60)
    #define EFLOCON          (0x17|0x60)
    #define EPAUSL           (0x18|0x60)
    #define EPAUSH           (0x19|0x60)
    // PHY registers
    #define PHCON1           0x00
    #define PHSTAT1          0x01
    #define PHHID1           0x02
    #define PHHID2           0x03
    #define PHCON2           0x10
    #define PHSTAT2          0x11
    #define PHIE             0x12
    #define PHIR             0x13
    #define PHLCON           0x14
    
    // ENC28J60 ERXFCON Register Bit Definitions
    #define ERXFCON_UCEN     0x80
    #define ERXFCON_ANDOR    0x40
    #define ERXFCON_CRCEN    0x20
    #define ERXFCON_PMEN     0x10
    #define ERXFCON_MPEN     0x08
    #define ERXFCON_HTEN     0x04
    #define ERXFCON_MCEN     0x02
    #define ERXFCON_BCEN     0x01
    // ENC28J60 EIE Register Bit Definitions
    #define EIE_INTIE        0x80
    #define EIE_PKTIE        0x40
    #define EIE_DMAIE        0x20
    #define EIE_LINKIE       0x10
    #define EIE_TXIE         0x08
    #define EIE_WOLIE        0x04
    #define EIE_TXERIE       0x02
    #define EIE_RXERIE       0x01
    // ENC28J60 EIR Register Bit Definitions
    #define EIR_PKTIF        0x40
    #define EIR_DMAIF        0x20
    #define EIR_LINKIF       0x10
    #define EIR_TXIF         0x08
    #define EIR_WOLIF        0x04
    #define EIR_TXERIF       0x02
    #define EIR_RXERIF       0x01
    // ENC28J60 ESTAT Register Bit Definitions
    #define ESTAT_INT        0x80
    #define ESTAT_LATECOL    0x10
    #define ESTAT_RXBUSY     0x04
    #define ESTAT_TXABRT     0x02
    #define ESTAT_CLKRDY     0x01
    // ENC28J60 ECON2 Register Bit Definitions
    #define ECON2_AUTOINC    0x80
    #define ECON2_PKTDEC     0x40
    #define ECON2_PWRSV      0x20
    #define ECON2_VRPS       0x08
    // ENC28J60 ECON1 Register Bit Definitions
    #define ECON1_TXRST      0x80
    #define ECON1_RXRST      0x40
    #define ECON1_DMAST      0x20
    #define ECON1_CSUMEN     0x10
    #define ECON1_TXRTS      0x08
    #define ECON1_RXEN       0x04
    #define ECON1_BSEL1      0x02
    #define ECON1_BSEL0      0x01
    // ENC28J60 MACON1 Register Bit Definitions
    #define MACON1_LOOPBK    0x10
    #define MACON1_TXPAUS    0x08
    #define MACON1_RXPAUS    0x04
    #define MACON1_PASSALL   0x02
    #define MACON1_MARXEN    0x01
    // ENC28J60 MACON2 Register Bit Definitions
    #define MACON2_MARST     0x80
    #define MACON2_RNDRST    0x40
    #define MACON2_MARXRST   0x08
    #define MACON2_RFUNRST   0x04
    #define MACON2_MATXRST   0x02
    #define MACON2_TFUNRST   0x01
    // ENC28J60 MACON3 Register Bit Definitions
    #define MACON3_PADCFG2   0x80
    #define MACON3_PADCFG1   0x40
    #define MACON3_PADCFG0   0x20
    #define MACON3_TXCRCEN   0x10
    #define MACON3_PHDRLEN   0x08
    #define MACON3_HFRMLEN   0x04
    #define MACON3_FRMLNEN   0x02
    #define MACON3_FULDPX    0x01
    // ENC28J60 MICMD Register Bit Definitions
    #define MICMD_MIISCAN    0x02
    #define MICMD_MIIRD      0x01
    // ENC28J60 MISTAT Register Bit Definitions
    #define MISTAT_NVALID    0x04
    #define MISTAT_SCAN      0x02
    #define MISTAT_BUSY      0x01
    // ENC28J60 PHY PHCON1 Register Bit Definitions
    #define PHCON1_PRST      0x8000
    #define PHCON1_PLOOPBK   0x4000
    #define PHCON1_PPWRSV    0x0800
    #define PHCON1_PDPXMD    0x0100
    // ENC28J60 PHY PHSTAT1 Register Bit Definitions
    #define PHSTAT1_PFDPX    0x1000
    #define PHSTAT1_PHDPX    0x0800
    #define PHSTAT1_LLSTAT   0x0004
    #define PHSTAT1_JBSTAT   0x0002
    // ENC28J60 PHY PHCON2 Register Bit Definitions
    #define PHCON2_FRCLINK   0x4000
    #define PHCON2_TXDIS     0x2000
    #define PHCON2_JABBER    0x0400
    #define PHCON2_HDLDIS    0x0100
    
    // ENC28J60 Packet Control Byte Bit Definitions
    #define PKTCTRL_PHUGEEN  0x08
    #define PKTCTRL_PPADEN   0x04
    #define PKTCTRL_PCRCEN   0x02
    #define PKTCTRL_POVERRIDE 0x01
    
    // SPI operation codes
    #define ENC28J60_READ_CTRL_REG       0x00
    #define ENC28J60_READ_BUF_MEM        0x3A
    #define ENC28J60_WRITE_CTRL_REG      0x40
    #define ENC28J60_WRITE_BUF_MEM       0x7A
    #define ENC28J60_BIT_FIELD_SET       0x80
    #define ENC28J60_BIT_FIELD_CLR       0xA0
    #define ENC28J60_SOFT_RESET          0xFF
    
    // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
    // buffer boundaries applied to internal 8K ram
    // the entire available packet buffer space is allocated
    // start with recbuf at 0/
    #define RXSTART_INIT    0x0
    // receive buffer end
    #define RXSTOP_INIT     (0x1FFF-0x0600-1)
    // start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
    #define TXSTART_INIT    (0x1FFF-0x0600)
    // stp TX buffer at end of mem
    #define TXSTOP_INIT     0x1FFF
    // max frame length which the conroller will accept:
    #define MAX_FRAMELEN    1500        // (note: maximum ethernet frame length would be 1518)
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // enc28j60 functions implementation
    ////////////////////////////////////////////////////////////////////////////////
    static uint8_t Enc28j60Bank;
    static uint16_t NextPacketPtr;
    
    // set CS to 0 = active
    #define CSACTIVE        ENC28J60_SPI_PORT&=~(1<<ENC28J60_SPI_CS)
    // set CS to 1 = passive
    #define CSPASSIVE       ENC28J60_SPI_PORT|=(1<<ENC28J60_SPI_CS)
    //
    #define SPI2X   0
    #define SPE     6
    #define MSTR    4
    #define SPIF    7
    // wait for spi operation
    #define waitspi()       while(!(SPSR&(1<<SPIF)))
    
    uint8_t enc28j60ReadOp(uint8_t op, uint8_t address)
    {
            CSACTIVE;
            // issue read command
            SPDR = op | (address & ADDR_MASK);
            waitspi();
            // read data
            SPDR = 0x00;
            waitspi();
            // do dummy read if needed (for mac and mii, see datasheet page 29)
            if(address & 0x80)
            {
                    SPDR = 0x00;
                    waitspi();
            }
            // release CS
            CSPASSIVE;
            return(SPDR);
    }
    
    void enc28j60WriteOp(uint8_t op, uint8_t address, uint8_t data)
    {
            CSACTIVE;
            // issue write command
            SPDR = op | (address & ADDR_MASK);
            waitspi();
            // write data
            SPDR = data;
            waitspi();
            CSPASSIVE;
    }
    
    void enc28j60ReadBuffer(uint16_t len, uint8_t* data)
    {
            CSACTIVE;
            // issue read command
            SPDR = ENC28J60_READ_BUF_MEM;
            waitspi();
            while(len)
            {
                    len--;
                    // read data
                    SPDR = 0x00;
                    waitspi();
                    *data = SPDR;
                    data++;
            }
            *data='\0';
            CSPASSIVE;
    }
    
    void enc28j60WriteBuffer(uint16_t len, uint8_t* data)
    {
            CSACTIVE;
            // issue write command
            SPDR = ENC28J60_WRITE_BUF_MEM;
            waitspi();
            while(len)
            {
                    len--;
                    // write data
                    SPDR = *data;
                    data++;
                    waitspi();
            }
            CSPASSIVE;
    }
    
    void enc28j60SetBank(uint8_t address)
    {
            // set the bank (if needed)
            if((address & BANK_MASK) != Enc28j60Bank)
            {
                    // set the bank
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
                    Enc28j60Bank = (address & BANK_MASK);
            }
    }
    
    uint8_t enc28j60Read(uint8_t address)
    {
            // set the bank
            enc28j60SetBank(address);
            // do the read
            return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
    }
    
    // read upper 8 bits
    uint16_t enc28j60PhyReadH(uint8_t address)
    {
        // Set the right address and start the register read operation
        enc28j60Write(MIREGADR, address);
        enc28j60Write(MICMD, MICMD_MIIRD);
            delay_us(15);
    
        // wait until the PHY read completes
        while(enc28j60Read(MISTAT) & MISTAT_BUSY);
    
        // reset reading bit
        enc28j60Write(MICMD, 0x00);
    
        return (enc28j60Read(MIRDH));
    }
    
    void enc28j60Write(uint8_t address, uint8_t data)
    {
            // set the bank
            enc28j60SetBank(address);
            // do the write
            enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
    }
    
    void enc28j60PhyWrite(uint8_t address, uint16_t data)
    {
            // set the PHY register address
            enc28j60Write(MIREGADR, address);
            // write the PHY data
            enc28j60Write(MIWRL, data);
            enc28j60Write(MIWRH, data>>8);
            // wait until the PHY write completes
            while(enc28j60Read(MISTAT) & MISTAT_BUSY){
                    delay_us(15);
            }
    }
    
    void enc28j60clkout(uint8_t clk)
    {
            //0->0; 1->25M; 2->12.5M; 3->8.33M; 4->6.25M; 5->3.125M;
        enc28j60Write(ECOCON, clk & 0x7);
    }
    
    void enc28j60Init(uint8_t* macaddr)
    {
        // initialize I/O
            // MOSI & SCK are output & low
            // CS is output & high
            // MISO is input
        ENC28J60_SPI_DDR &= ~(1<<ENC28J60_SPI_MISO);
        ENC28J60_SPI_DDR |= (1<<ENC28J60_SPI_MOSI) | (1<<ENC28J60_SPI_SCK) | (1<<ENC28J60_SPI_CS);
        ENC28J60_SPI_PORT &= ~((1<<ENC28J60_SPI_MOSI) | (1<<ENC28J60_SPI_SCK));
        ENC28J60_SPI_PORT |= (1<<ENC28J60_SPI_CS);
        // initialize SPI interface
        // master mode and Fosc/2 clock:
            SPCR = (1<<SPE)|(1<<MSTR);
            SPSR |= (1<<SPI2X);
    
        // perform system reset
        enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
        delay_ms(50);
        // check CLKRDY bit to see if reset is complete
            // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
        //while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
        // do bank 0 stuff
        // initialize receive buffer
        // 16-bit transfers, must write low byte first
        // set receive buffer start address
        NextPacketPtr = RXSTART_INIT;
            // Rx start
        enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
        enc28j60Write(ERXSTH, RXSTART_INIT>>8);
        // set receive pointer address
        enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
        enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
        // RX end
        enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
        enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
        // TX start
        enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
        enc28j60Write(ETXSTH, TXSTART_INIT>>8);
        // TX end
        enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF);
        enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
        // do bank 1 stuff, packet filter:
            // For broadcast packets we allow only ARP packtets
            // All other packets should be unicast only for our mac (MAADR)
            //
            // The pattern to match on is therefore
            // Type     ETH.DST
            // ARP      BROADCAST
            // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
            // in binary these poitions are:11 0000 0011 1111
            // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
        enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
        enc28j60Write(EPMM0, 0x3f);
        enc28j60Write(EPMM1, 0x30);
        enc28j60Write(EPMCSL, 0xf9);
        enc28j60Write(EPMCSH, 0xf7);
            //
            //
        // do bank 2 stuff
        // enable MAC receive
        enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
        // bring MAC out of reset
        enc28j60Write(MACON2, 0x00);
        // enable automatic padding to 60bytes and CRC operations
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
        // set inter-frame gap (non-back-to-back)
        enc28j60Write(MAIPGL, 0x12);
        enc28j60Write(MAIPGH, 0x0C);
        // set inter-frame gap (back-to-back)
        enc28j60Write(MABBIPG, 0x12);
        // Set the maximum packet size which the controller will accept
            // Do not send packets longer than MAX_FRAMELEN:
        enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
        enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
        // do bank 3 stuff
            // write MAC address
            // NOTE: MAC address in ENC28J60 is byte-backward
            enc28j60Write(MAADR5, macaddr[0]);
            enc28j60Write(MAADR4, macaddr[1]);
            enc28j60Write(MAADR3, macaddr[2]);
            enc28j60Write(MAADR2, macaddr[3]);
            enc28j60Write(MAADR1, macaddr[4]);
            enc28j60Write(MAADR0, macaddr[5]);
        // no loopback of transmitted frames
        enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
        // switch to bank 0
        enc28j60SetBank(ECON1);
        // enable interrutps
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
        // enable packet reception
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
    
            // LEDA=links status, LEDB=receive/transmit
            enc28j60PhyWrite(PHLCON,0x0476);
            delay_ms(20);
    }
    
    // read the revision of the chip:
    uint8_t enc28j60getrev(void)
    {
        return(enc28j60Read(EREVID));
    }
    
    // link status
    uint8_t enc28j60linkup(void)
    {
            // bit 10 (= bit 3 in upper reg)
        return(enc28j60PhyReadH(PHSTAT2) && 4);
    }
    
    void enc28j60PacketSend(uint16_t len, uint8_t* packet)
    {
        // Set the write pointer to start of transmit buffer area
        enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
        enc28j60Write(EWRPTH, TXSTART_INIT>>8);
        // Set the TXND pointer to correspond to the packet size given
        enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
        enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
        // write per-packet control byte (0x00 means use macon3 settings)
        enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
        // copy the packet into the transmit buffer
        enc28j60WriteBuffer(len, packet);
        // send the contents of the transmit buffer onto the network
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
            // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
        if( (enc28j60Read(EIR) & EIR_TXERIF) ){
                    enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
            }
    }
    
    // Gets a packet from the network receive buffer, if one is available.
    // The packet will by headed by an ethernet header.
    //      maxlen  The maximum acceptable length of a retrieved packet.
    //      packet  Pointer where packet data should be stored.
    // Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
    uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet)
    {
        uint16_t rxstat;
        uint16_t len;
        // check if a packet has been received and buffered
        //if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
            // The above does not work. See Rev. B4 Silicon Errata point 6.
        if( enc28j60Read(EPKTCNT) ==0 ){
            return(0);
            }
    
        // Set the read pointer to the start of the received packet
        enc28j60Write(ERDPTL, (NextPacketPtr));
        enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
        // read the next packet pointer
        NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
        // read the packet length (see datasheet page 43)
        len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
            len-=4; //remove the CRC count
        // read the receive status (see datasheet page 43)
        rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
        rxstat |= ((uint16_t)enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0))<<8;
        // limit retrieve length
            if (len>maxlen-1){
                    len=maxlen-1;
            }
            // check CRC and symbol errors (see datasheet page 44, table 7-3):
            // The ERXFCON.CRCEN is set by default. Normally we should not
            // need to check this.
            if ((rxstat & 0x80)==0){
                    // invalid
                    len=0;
            }else{
                    // copy the packet from the receive buffer
                    enc28j60ReadBuffer(len, packet);
            }
        // Move the RX read pointer to the start of the next received packet
        // This frees the memory we just read out
        enc28j60Write(ERXRDPTL, (NextPacketPtr));
        enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
        // decrement the packet counter indicate we are done with this packet
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
        return(len);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    // eth/ip/arp/udp/tcp functions implementation
    ////////////////////////////////////////////////////////////////////////////////
    
    unsigned char eth_buf[BUFFER_SIZE+1];
    static uint16_t wwwport=80;
    static uint16_t udpport=1200;
    static uint8_t macaddr[6];
    static uint8_t ipaddr[4];
    static int16_t info_hdr_len=0;
    static int16_t info_data_len=0;
    static uint8_t seqnum=0xa; // my initial tcp sequence number
    
    // The Ip checksum is calculated over the ip header only starting
    // with the header length field and a total length of 20 bytes
    // unitl ip.dst
    // You must set the IP checksum field to zero before you start
    // the calculation.
    // len for ip is 20.
    //
    // For UDP/TCP we do not make up the required pseudo header. Instead we
    // use the ip.src and ip.dst fields of the real packet:
    // The udp checksum calculation starts with the ip.src field
    // Ip.src=4bytes,Ip.dst=4 bytes,Udp header=8bytes + data length=16+len
    // In other words the len here is 8 + length over which you actually
    // want to calculate the checksum.
    // You must set the checksum field to zero before you start
    // the calculation.
    // len for udp is: 8 + 8 + data length
    // len for tcp is: 4+4 + 20 + option len + data length
    //
    // For more information on how this algorithm works see:
    // http://www.netfor2.com/checksum.html
    // http://www.msc.uky.edu/ken/cs471/notes/chap3.htm
    // The RFC has also a C code example: http://www.faqs.org/rfcs/rfc1071.html
    uint16_t checksum(uint8_t *buf, uint16_t len,uint8_t type){
            // type 0=ip
            //      1=udp
            //      2=tcp
            uint32_t sum = 0;
    
            //if(type==0){
            //        // do not add anything
            //}
            if(type==1){
                    sum+=IP_PROTO_UDP_V; // protocol udp
                    // the length here is the length of udp (data+header len)
                    // =length given to this function - (IP.scr+IP.dst length)
                    sum+=len-8; // = real tcp len
            }
            if(type==2){
                    sum+=IP_PROTO_TCP_V;
                    // the length here is the length of tcp (data+header len)
                    // =length given to this function - (IP.scr+IP.dst length)
                    sum+=len-8; // = real tcp len
            }
            // build the sum of 16bit words
            while(len >1){
                    sum += 0xFFFF & (((uint32_t)*buf<<8)|*(buf+1));
                    buf+=2;
                    len-=2;
            }
            // if there is a byte left then add it (padded with zero)
            if (len){
                    sum += ((uint32_t)(0xFF & *buf))<<8;
            }
            // now calculate the sum over the bytes in the sum
            // until the result is only 16bit long
            while (sum>>16){
                    sum = (sum & 0xFFFF)+(sum >> 16);
            }
            // build 1's complement:
            return( (uint16_t) sum ^ 0xFFFF);
    }
    
    uint8_t eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len){
            uint8_t i=0;
            //
            if (len<41){
                    return(0);
            }
            if(buf[ETH_TYPE_H_P] != ETHTYPE_ARP_H_V ||
               buf[ETH_TYPE_L_P] != ETHTYPE_ARP_L_V){
                    return(0);
            }
            while(i<4){
                    if(buf[ETH_ARP_DST_IP_P+i] != ipaddr[i]){
                            return(0);
                    }
                    i++;
            }
            return(1);
    }
    
    uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len){
            uint8_t i=0;
            //eth+ip+udp header is 42
            if (len<42){
                    return(0);
            }
            if(buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V ||
               buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V){
                    return(0);
            }
            if (buf[IP_HEADER_LEN_VER_P]!=0x45){
                    // must be IP V4 and 20 byte header
                    return(0);
            }
            while(i<4){
                    if(buf[IP_DST_P+i]!=ipaddr[i]){
                            return(0);
                    }
                    i++;
            }
            return(1);
    }
    // make a return eth header from a received eth packet
    void make_eth(uint8_t *buf)
    {
            uint8_t i=0;
            //
            //copy the destination mac from the source and fill my mac into src
            while(i<6){
                    buf[ETH_DST_MAC +i]=buf[ETH_SRC_MAC +i];
                    buf[ETH_SRC_MAC +i]=macaddr[i];
                    i++;
            }
    }
    void fill_ip_hdr_checksum(uint8_t *buf)
    {
            uint16_t ck;
            // clear the 2 byte checksum
            buf[IP_CHECKSUM_P]=0;
            buf[IP_CHECKSUM_P+1]=0;
            buf[IP_FLAGS_P]=0x40; // don't fragment
            buf[IP_FLAGS_P+1]=0;  // fragement offset
            buf[IP_TTL_P]=64; // ttl
            // calculate the checksum:
            ck=checksum(&buf[IP_P], IP_HEADER_LEN,0);
            buf[IP_CHECKSUM_P]=ck>>8;
            buf[IP_CHECKSUM_P+1]=ck& 0xff;
    }
    
    // make a return ip header from a received ip packet
    void make_ip(uint8_t *buf)
    {
            uint8_t i=0;
            while(i<4){
                    buf[IP_DST_P+i]=buf[IP_SRC_P+i];
                    buf[IP_SRC_P+i]=ipaddr[i];
                    i++;
            }
            fill_ip_hdr_checksum(buf);
    }
    
    // make a return tcp header from a received tcp packet
    // rel_ack_num is how much we must step the seq number received from the
    // other side. We do not send more than 255 bytes of text (=data) in the tcp packet.
    // If mss=1 then mss is included in the options list
    //
    // After calling this function you can fill in the first data byte at TCP_OPTIONS_P+4
    // If cp_seq=0 then an initial sequence number is used (should be use in synack)
    // otherwise it is copied from the packet we received
    void make_tcphead(uint8_t *buf,uint16_t rel_ack_num,uint8_t mss,uint8_t cp_seq)
    {
            uint8_t i=0;
            uint8_t tseq;
    
            buf[TCP_DST_PORT_H_P] = buf[TCP_SRC_PORT_H_P];
            buf[TCP_DST_PORT_L_P] = buf[TCP_SRC_PORT_L_P];
            // set source port  (http):
            buf[TCP_SRC_PORT_L_P] = LOBYTE(wwwport);
            buf[TCP_SRC_PORT_H_P] = HIBYTE(wwwport);
            i=4;
            // sequence numbers:
            // add the rel ack num to SEQACK
            while(i>0){
                    rel_ack_num=buf[TCP_SEQ_H_P+i-1]+rel_ack_num;
                    tseq=buf[TCP_SEQACK_H_P+i-1];
                    buf[TCP_SEQACK_H_P+i-1]=0xff&rel_ack_num;
                    if (cp_seq){
                            // copy the acknum sent to us into the sequence number
                            buf[TCP_SEQ_H_P+i-1]=tseq;
                    }else{
                            buf[TCP_SEQ_H_P+i-1]= 0; // some preset vallue
                    }
                    rel_ack_num=rel_ack_num>>8;
                    i--;
            }
            if (cp_seq==0){
                    // put inital seq number
                    buf[TCP_SEQ_H_P+0]= 0;
                    buf[TCP_SEQ_H_P+1]= 0;
                    // we step only the second byte, this allows us to send packts
                    // with 255 bytes or 512 (if we step the initial seqnum by 2)
                    buf[TCP_SEQ_H_P+2]= seqnum;
                    buf[TCP_SEQ_H_P+3]= 0;
                    // step the inititial seq num by something we will not use
                    // during this tcp session:
                    seqnum+=2;
            }
            // zero the checksum
            buf[TCP_CHECKSUM_H_P]=0;
            buf[TCP_CHECKSUM_L_P]=0;
    
            // The tcp header length is only a 4 bit field (the upper 4 bits).
            // It is calculated in units of 4 bytes.
            // E.g 24 bytes: 24/4=6 => 0x60=header len field
            //buf[TCP_HEADER_LEN_P]=(((TCP_HEADER_LEN_PLAIN+4)/4)) <<4; // 0x60
            if (mss){
                    // the only option we set is MSS to 1408:
                    // 1408 in hex is 0x580
                    buf[TCP_OPTIONS_P]=2;
                    buf[TCP_OPTIONS_P+1]=4;
                    buf[TCP_OPTIONS_P+2]=0x05;
                    buf[TCP_OPTIONS_P+3]=0x80;
                    // 24 bytes:
                    buf[TCP_HEADER_LEN_P]=0x60;
            }else{
                    // no options:
                    // 20 bytes:
                    buf[TCP_HEADER_LEN_P]=0x50;
            }
    }
    
    void make_arp_answer_from_request(uint8_t *buf)
    {
            uint8_t i=0;
            //
            make_eth(buf);
            buf[ETH_ARP_OPCODE_H_P]=ETH_ARP_OPCODE_REPLY_H_V;
            buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V;
            // fill the mac addresses:
            while(i<6){
                    buf[ETH_ARP_DST_MAC_P+i]=buf[ETH_ARP_SRC_MAC_P+i];
                    buf[ETH_ARP_SRC_MAC_P+i]=macaddr[i];
                    i++;
            }
            i=0;
            while(i<4){
                    buf[ETH_ARP_DST_IP_P+i]=buf[ETH_ARP_SRC_IP_P+i];
                    buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
                    i++;
            }
            // eth+arp is 42 bytes:
            enc28j60PacketSend(42,buf);
    }
    
    void make_echo_reply_from_request(uint8_t *buf,uint16_t len)
    {
            make_eth(buf);
            make_ip(buf);
            buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V;
            // we changed only the icmp.type field from request(=8) to reply(=0).
            // we can therefore easily correct the checksum:
            if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)){
                    buf[ICMP_CHECKSUM_P+1]++;
            }
            buf[ICMP_CHECKSUM_P]+=0x08;
            //
            enc28j60PacketSend(len,buf);
    }
    
    // you can send a max of 220 bytes of data
    void make_udp_reply_from_request(uint8_t *buf, uint8_t datalen)
    {
            uint8_t i=0;
            uint16_t ck;
            make_eth(buf);
            if (datalen>220){
                    datalen=220;
            }
            // total length field in the IP header must be set:
            buf[IP_TOTLEN_H_P]=0;
            buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
            make_ip(buf);
            // send to port:
            //buf[UDP_DST_PORT_H_P]=port>>8;
            //buf[UDP_DST_PORT_L_P]=port & 0xff;
            // sent to port of sender and use "port" as own source:
            buf[UDP_DST_PORT_H_P]=buf[UDP_SRC_PORT_H_P];
            buf[UDP_DST_PORT_L_P]= buf[UDP_SRC_PORT_L_P];
            buf[UDP_SRC_PORT_H_P]=HIBYTE(udpport);
            buf[UDP_SRC_PORT_L_P]=LOBYTE(udpport);
            // calculte the udp length:
            buf[UDP_LEN_H_P]=0;
            buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;
            // zero the checksum
            buf[UDP_CHECKSUM_H_P]=0;
            buf[UDP_CHECKSUM_L_P]=0;
    /*
            // copy the data:
            while(i<datalen){
                    buf[UDP_DATA_P+i]=data[i];
                    i++;
            }
    */
            ck=checksum(&buf[IP_SRC_P], 16 + datalen,1);
            buf[UDP_CHECKSUM_H_P]=ck>>8;
            buf[UDP_CHECKSUM_L_P]=ck& 0xff;
            enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
    }
    
    void make_tcp_synack_from_syn(uint8_t *buf)
    {
            uint16_t ck;
            make_eth(buf);
            // total length field in the IP header must be set:
            // 20 bytes IP + 24 bytes (20tcp+4tcp options)
            buf[IP_TOTLEN_H_P]=0;
            buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4;
            make_ip(buf);
            buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V;
            make_tcphead(buf,1,1,0);
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + 4 (one option: mss)
            ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+4,2);
            buf[TCP_CHECKSUM_H_P]=ck>>8;
            buf[TCP_CHECKSUM_L_P]=ck& 0xff;
            // add 4 for option mss:
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);
    }
    
    // get a pointer to the start of tcp data in buf
    // Returns 0 if there is no data
    uint16_t get_tcp_data_pointer(uint8_t *buf)
    {
            info_data_len=(((int16_t)buf[IP_TOTLEN_H_P])<<8)|(buf[IP_TOTLEN_L_P]&0xff);
            info_data_len-=IP_HEADER_LEN;
            info_hdr_len=(buf[TCP_HEADER_LEN_P]>>4)*4; // generate len in bytes;
            info_data_len-=info_hdr_len;
            if (info_data_len<=0){
                    info_data_len=0;
                    return(0);
            }
            return((uint16_t)TCP_SRC_PORT_H_P+info_hdr_len);
    }
    
    // concatenate string to buffer at pos and return final position
    uint16_t concatstrf(uint8_t *buf, uint16_t pos, const flash char *s)
    {
            char c;
            while ((c = *s++)!=0)
            {
                    buf[pos]=c;
                    pos++;
            }
            return(pos);
    }
    
    // concatenate string to buffer at pos and return final position
    uint16_t concatstr(uint8_t *buf, uint16_t pos, const char *s)
    {
            char c;
            while ((c = *s++)!=0)
            {
                    buf[pos]=c;
                    pos++;
            }
            return(pos);
    }
    
    // Make just an ack packet with no tcp data inside
    // This will modify the eth/ip/tcp header
    void make_tcp_ack_from_any(uint8_t *buf)
    {
            uint16_t j;
            make_eth(buf);
            // fill the header:
            buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V;
            if (info_data_len==0){
                    // if there is no data then we must still acknoledge one packet
                    make_tcphead(buf,1,0,1); // no options
            }else{
                    make_tcphead(buf,info_data_len,0,1); // no options
            }
    
            // total length field in the IP header must be set:
            // 20 bytes IP + 20 bytes tcp (when no options)
            j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN;
            buf[IP_TOTLEN_H_P]=j>>8;
            buf[IP_TOTLEN_L_P]=j& 0xff;
            make_ip(buf);
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
            j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN,2);
            buf[TCP_CHECKSUM_H_P]=j>>8;
            buf[TCP_CHECKSUM_L_P]=j& 0xff;
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN,buf);
    }
    
    // you must have called get_tcp_data_pointer at some time before calling this function
    // dlen is the amount of tcp data (http data) we send in this packet
    // You can use this function only immediately after make_tcp_ack_from_any
    // This is because this function will NOT modify the eth/ip/tcp header except for
    // length and checksum
    void make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen)
    {
            uint16_t j;
            // fill the header:
            // This code requires that we send only one data packet
            // because we keep no state information. We must therefore set
            // the fin here:
            buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V;
    
            // total length field in the IP header must be set:
            // 20 bytes IP + 20 bytes tcp (when no options) + len of data
            j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen;
            buf[IP_TOTLEN_H_P]=j>>8;
            buf[IP_TOTLEN_L_P]=j& 0xff;
            fill_ip_hdr_checksum(buf);
            // zero the checksum
            buf[TCP_CHECKSUM_H_P]=0;
            buf[TCP_CHECKSUM_L_P]=0;
            // calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
            j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlen,2);
            buf[TCP_CHECKSUM_H_P]=j>>8;
            buf[TCP_CHECKSUM_L_P]=j& 0xff;
            enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen+ETH_HEADER_LEN,buf);
    }
    
    
    // you must call this function once before you use any of the other functions:
    void ethernet_init(unsigned char *dev_mac, unsigned char *dev_ip, unsigned int port_tcp, unsigned int port_udp)
    {
            uint8_t i=0;
            wwwport=port_tcp;
            udpport=port_udp;
            while(i<4){
                    ipaddr[i]=dev_ip[i];
                    i++;
            }
            i=0;
            while(i<6){
                    macaddr[i]=dev_mac[i];
                    i++;
            }
            // initialize enc28j60
            enc28j60Init(dev_mac);
    }
    
    void ethernet_process()
    {
            uint16_t plen;
            uint16_t data_p;
            uint8_t data_len;
    
            plen = enc28j60PacketReceive(BUFFER_SIZE, eth_buf);
            if(plen!=0)
            {
                    // arp is broadcast if unknown but a host may also verify
                    // the mac address by sending it to a unicast address.
                    if(eth_type_is_arp_and_my_ip(eth_buf,plen))
                    {
                            make_arp_answer_from_request(eth_buf);
                    }
                    // check if ip packets are for us:
                    else if(eth_type_is_ip_and_my_ip(eth_buf,plen))
                    {
                            if( eth_buf[IP_PROTO_P]==IP_PROTO_ICMP_V
                            && eth_buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V )
                            {
                                    // a ping packet, let's send pong
                                    make_echo_reply_from_request(eth_buf,plen);
                            }
                            // we listen to tcp port
                            else if (eth_buf[IP_PROTO_P]==IP_PROTO_TCP_V
                                    &&eth_buf[TCP_DST_PORT_H_P]==HIBYTE(wwwport)
                                    &&eth_buf[TCP_DST_PORT_L_P]==LOBYTE(wwwport) )
                            {
                                    if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
                                            // make_tcp_synack_from_syn does already send the syn,ack
                                            make_tcp_synack_from_syn(eth_buf);
                                    else if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
                                    {
                                            // we can possibly have no data, just ack:
                                            data_p=get_tcp_data_pointer(eth_buf);
                                            if (data_p==0)
                                            {
                                                    // just an ack with no data, wait for next packet
                                                    if (eth_buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
                                                    {
                                                            // finack, answer with ack
                                                            make_tcp_ack_from_any(eth_buf);
                                                    }
                                            }
                                            else
                                            {
                                                    plen = ethernet_tcp( eth_buf+data_p, eth_buf+TCP_CHECKSUM_L_P+3 );
                                                    make_tcp_ack_from_any(eth_buf); // send ack for http get
                                                    make_tcp_ack_with_data(eth_buf, plen); // send data
                                            }
                                    }
                            }
                            // we listen to udp port
                            else if (eth_buf[IP_PROTO_P]==IP_PROTO_UDP_V
                                    &&eth_buf[UDP_DST_PORT_H_P]==HIBYTE(udpport)
                                    &&eth_buf[UDP_DST_PORT_L_P]==LOBYTE(udpport) )
                            {
                                    data_len = eth_buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
                                    data_len = ethernet_udp( eth_buf+UDP_DATA_P, data_len);
                                    make_udp_reply_from_request(eth_buf, data_len);
                            }
                    }
            }
    }
    
    #pragma used-
    
    #endif
    سلام اقامهدی گل این لایبری httpهست درسته؟
صفحه 1 از 3 123 آخرین
نمایش نتایج: از 1 به 10 از 21

موضوعات مشابه

  1. راه اندازی یک شرکت تولیدی (مراحل مختلف از راه اندازی تا ثبت شرکت)
    توسط مهران چمنی در انجمن مباحث علمی عمومی
    پاسخ: 91
    آخرين نوشته: 2016/02/28, 21:23

کلمات کلیدی این موضوع

علاقه مندي ها (Bookmarks)

علاقه مندي ها (Bookmarks)

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید
  •