Enables fast realtime communication over Ethernet by using plain Ethernet frames (overhead of TCP/IP network layers is stripped away).

Dependents:   RawEthernet_Hello

RawEthernet.h

Committer:
hudakz
Date:
2018-08-20
Revision:
0:ca476e0a1a28

File content as of revision 0:ca476e0a1a28:

#ifndef RAW_ETHERNET_H
#define RAW_ETHERNET_H

#include "mbed.h"

//------------------------------------------------------------------------------
// Functions for using an ENC28J60 ethernet controller, optimized for 
// communication speed.
//
// Written by Rogier Schouten for AVR micro controllers http://www.rogiershikes.tk
// Based on code by Guido Socher http://www.tuxgraphics.org
// Idea modified and further updated by Guido Socher
// Ported to MBED by Zoltan Hudak hudakz@outlook.com
// License: GPL V2
//
// Enables to read sensor data or control IO-ports with less than a millisecond delay. 
// The trick is in removing the TCP/IP overhead and use raw Ethernet frames. 
// A Linux application using raw network sockets is controlling this slave device.
//
// Assumptions:
// - Max. payload data: 255 bytes per packet
// - The network consists of a master PC and one or more slave devices. 
//   Only plain hubs and switches are allowed between PC and ethernet device.
//   Note that some wlan routers have internal switches which switch only
//   IP packets. They will discard plain ethernet frames. A normal 100Mbit 
//   office/workgroup switch will however work.
// 
// Based on these assumptions, we can optimize the protocol for faster communication:
// - Master and slave send unicast packets.
// - We use raw ethernet and no higher-level protocol such as UDP or TCP/IP
// - We use the EtherType field of a packet as a length field. Actually, we only
//   use one byte of it since we have max 255 length packets.
//  
// Furthermore, there are a few code optimizations:
// - Minimize communication between ENC and MCU.
// - No unnecessary memory bank checks
// 

class RawEthernet
{
public:
    /**
     * Constructor
     *
     * \param mosi mbed pin to use SPI
     * \param miso mbed pin to use SPI
     * \param sclk mbed pin to use SPI
     * \param cs pin to select the ENC28J60 chip
     */
    RawEthernet(PinName mosi, PinName miso, PinName sclk, PinName cs, uint8_t myMac[6], uint8_t myIp[4]);
    void     linkTo(uint8_t remoteMac[6]);
    void     packetSend(uint16_t len, uint8_t* packet);
    bool     isLinkUp(void);
    uint8_t  receive(uint8_t* buf, uint8_t maxlen);
    void     gratuitousArp();
    void     send(uint8_t* buf, uint8_t len);
    uint8_t  getRev(void);
protected:
    uint8_t  readOp(uint8_t op, uint8_t address);
    void     writeOp(uint8_t op, uint8_t address, uint8_t data);
    uint8_t  readReg(uint8_t address);
    void     writeReg(uint8_t address, uint8_t data);
    void     setBank(uint8_t address);
    void     readBuffer(uint16_t len, uint8_t* data);
    void     writeBuffer(uint16_t len, uint8_t* data);
    uint16_t phyReadH(uint8_t address);
    void     phyWrite(uint8_t address, uint16_t data);
private:
    SPI         _spi;
    DigitalOut  _cs;
    uint8_t     _bank;
    int16_t     _nextPacketPtr;
    uint8_t     _lastTransmitPayloadLen;
    uint8_t     _mac[6];
    uint8_t     _ip[4];
    uint8_t     _remoteMac[6];
    static char _arpReqHdr[10];
};
#endif // RAW_ETHERNET_H