Marcelo Barros / Mbed 2 deprecated ArduinoShieldSPI

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 
00003 // Microchip ENC28J60 Ethernet Interface Driver
00004 // Author: Guido Socher
00005 // Copyright: GPL V2
00006 // 
00007 // Based on the enc28j60.c file from the AVRlib library by Pascal Stang.
00008 // For AVRlib See http://www.procyonengineering.com/
00009 // Used with explicit permission of Pascal Stang.
00010 //
00011 // 2010-05-20 <jc@wippler.nl>
00012 // 2013-09-20 Modified for mbed by Marcelo Barros de Almeida <marcelobarrosalmeida@gmail.com>
00013 //            http://shiningbits.com/blog/
00014 //            http://br.linkedin.com/in/marcelobarrosalmeida/
00015 
00016 
00017 // ENC28J60 Control Registers
00018 // Control register definitions are a combination of address,
00019 // bank number, and Ethernet/MAC/PHY indicator bits.
00020 // - Register address        (bits 0-4)
00021 // - Bank number        (bits 5-6)
00022 // - MAC/PHY indicator        (bit 7)
00023 #define ADDR_MASK        0x1F
00024 #define BANK_MASK        0x60
00025 #define SPRD_MASK        0x80
00026 // All-bank registers
00027 #define EIE              0x1B
00028 #define EIR              0x1C
00029 #define ESTAT            0x1D
00030 #define ECON2            0x1E
00031 #define ECON1            0x1F
00032 // Bank 0 registers
00033 #define ERDPT           (0x00|0x00)
00034 #define EWRPT           (0x02|0x00)
00035 #define ETXST           (0x04|0x00)
00036 #define ETXND           (0x06|0x00)
00037 #define ERXST           (0x08|0x00)
00038 #define ERXND           (0x0A|0x00)
00039 #define ERXRDPT         (0x0C|0x00)
00040 // #define ERXWRPT         (0x0E|0x00)
00041 #define EDMAST          (0x10|0x00)
00042 #define EDMAND          (0x12|0x00)
00043 // #define EDMADST         (0x14|0x00)
00044 #define EDMACS          (0x16|0x00)
00045 // Bank 1 registers
00046 #define EHT0             (0x00|0x20)
00047 #define EHT1             (0x01|0x20)
00048 #define EHT2             (0x02|0x20)
00049 #define EHT3             (0x03|0x20)
00050 #define EHT4             (0x04|0x20)
00051 #define EHT5             (0x05|0x20)
00052 #define EHT6             (0x06|0x20)
00053 #define EHT7             (0x07|0x20)
00054 #define EPMM0            (0x08|0x20)
00055 #define EPMM1            (0x09|0x20)
00056 #define EPMM2            (0x0A|0x20)
00057 #define EPMM3            (0x0B|0x20)
00058 #define EPMM4            (0x0C|0x20)
00059 #define EPMM5            (0x0D|0x20)
00060 #define EPMM6            (0x0E|0x20)
00061 #define EPMM7            (0x0F|0x20)
00062 #define EPMCS           (0x10|0x20)
00063 // #define EPMO            (0x14|0x20)
00064 #define EWOLIE           (0x16|0x20)
00065 #define EWOLIR           (0x17|0x20)
00066 #define ERXFCON          (0x18|0x20)
00067 #define EPKTCNT          (0x19|0x20)
00068 // Bank 2 registers
00069 #define MACON1           (0x00|0x40|0x80)
00070 #define MACON2           (0x01|0x40|0x80)
00071 #define MACON3           (0x02|0x40|0x80)
00072 #define MACON4           (0x03|0x40|0x80)
00073 #define MABBIPG          (0x04|0x40|0x80)
00074 #define MAIPG           (0x06|0x40|0x80)
00075 #define MACLCON1         (0x08|0x40|0x80)
00076 #define MACLCON2         (0x09|0x40|0x80)
00077 #define MAMXFL          (0x0A|0x40|0x80)
00078 #define MAPHSUP          (0x0D|0x40|0x80)
00079 #define MICON            (0x11|0x40|0x80)
00080 #define MICMD            (0x12|0x40|0x80)
00081 #define MIREGADR         (0x14|0x40|0x80)
00082 #define MIWR            (0x16|0x40|0x80)
00083 #define MIRD            (0x18|0x40|0x80)
00084 // Bank 3 registers
00085 #define MAADR1           (0x00|0x60|0x80)
00086 #define MAADR0           (0x01|0x60|0x80)
00087 #define MAADR3           (0x02|0x60|0x80)
00088 #define MAADR2           (0x03|0x60|0x80)
00089 #define MAADR5           (0x04|0x60|0x80)
00090 #define MAADR4           (0x05|0x60|0x80)
00091 #define EBSTSD           (0x06|0x60)
00092 #define EBSTCON          (0x07|0x60)
00093 #define EBSTCS          (0x08|0x60)
00094 #define MISTAT           (0x0A|0x60|0x80)
00095 #define EREVID           (0x12|0x60)
00096 #define ECOCON           (0x15|0x60)
00097 #define EFLOCON          (0x17|0x60)
00098 #define EPAUS           (0x18|0x60)
00099 
00100 // ENC28J60 ERXFCON Register Bit Definitions
00101 #define ERXFCON_UCEN     0x80
00102 #define ERXFCON_ANDOR    0x40
00103 #define ERXFCON_CRCEN    0x20
00104 #define ERXFCON_PMEN     0x10
00105 #define ERXFCON_MPEN     0x08
00106 #define ERXFCON_HTEN     0x04
00107 #define ERXFCON_MCEN     0x02
00108 #define ERXFCON_BCEN     0x01
00109 // ENC28J60 EIE Register Bit Definitions
00110 #define EIE_INTIE        0x80
00111 #define EIE_PKTIE        0x40
00112 #define EIE_DMAIE        0x20
00113 #define EIE_LINKIE       0x10
00114 #define EIE_TXIE         0x08
00115 #define EIE_WOLIE        0x04
00116 #define EIE_TXERIE       0x02
00117 #define EIE_RXERIE       0x01
00118 // ENC28J60 EIR Register Bit Definitions
00119 #define EIR_PKTIF        0x40
00120 #define EIR_DMAIF        0x20
00121 #define EIR_LINKIF       0x10
00122 #define EIR_TXIF         0x08
00123 #define EIR_WOLIF        0x04
00124 #define EIR_TXERIF       0x02
00125 #define EIR_RXERIF       0x01
00126 // ENC28J60 ESTAT Register Bit Definitions
00127 #define ESTAT_INT        0x80
00128 #define ESTAT_LATECOL    0x10
00129 #define ESTAT_RXBUSY     0x04
00130 #define ESTAT_TXABRT     0x02
00131 #define ESTAT_CLKRDY     0x01
00132 // ENC28J60 ECON2 Register Bit Definitions
00133 #define ECON2_AUTOINC    0x80
00134 #define ECON2_PKTDEC     0x40
00135 #define ECON2_PWRSV      0x20
00136 #define ECON2_VRPS       0x08
00137 // ENC28J60 ECON1 Register Bit Definitions
00138 #define ECON1_TXRST      0x80
00139 #define ECON1_RXRST      0x40
00140 #define ECON1_DMAST      0x20
00141 #define ECON1_CSUMEN     0x10
00142 #define ECON1_TXRTS      0x08
00143 #define ECON1_RXEN       0x04
00144 #define ECON1_BSEL1      0x02
00145 #define ECON1_BSEL0      0x01
00146 // ENC28J60 MACON1 Register Bit Definitions
00147 #define MACON1_LOOPBK    0x10
00148 #define MACON1_TXPAUS    0x08
00149 #define MACON1_RXPAUS    0x04
00150 #define MACON1_PASSALL   0x02
00151 #define MACON1_MARXEN    0x01
00152 // ENC28J60 MACON2 Register Bit Definitions
00153 #define MACON2_MARST     0x80
00154 #define MACON2_RNDRST    0x40
00155 #define MACON2_MARXRST   0x08
00156 #define MACON2_RFUNRST   0x04
00157 #define MACON2_MATXRST   0x02
00158 #define MACON2_TFUNRST   0x01
00159 // ENC28J60 MACON3 Register Bit Definitions
00160 #define MACON3_PADCFG2   0x80
00161 #define MACON3_PADCFG1   0x40
00162 #define MACON3_PADCFG0   0x20
00163 #define MACON3_TXCRCEN   0x10
00164 #define MACON3_PHDRLEN   0x08
00165 #define MACON3_HFRMLEN   0x04
00166 #define MACON3_FRMLNEN   0x02
00167 #define MACON3_FULDPX    0x01
00168 // ENC28J60 MICMD Register Bit Definitions
00169 #define MICMD_MIISCAN    0x02
00170 #define MICMD_MIIRD      0x01
00171 // ENC28J60 MISTAT Register Bit Definitions
00172 #define MISTAT_NVALID    0x04
00173 #define MISTAT_SCAN      0x02
00174 #define MISTAT_BUSY      0x01
00175 
00176 // ENC28J60 EBSTCON Register Bit Definitions
00177 #define EBSTCON_PSV2     0x80
00178 #define EBSTCON_PSV1     0x40
00179 #define EBSTCON_PSV0     0x20
00180 #define EBSTCON_PSEL     0x10
00181 #define EBSTCON_TMSEL1   0x08
00182 #define EBSTCON_TMSEL0   0x04
00183 #define EBSTCON_TME      0x02
00184 #define EBSTCON_BISTST    0x01
00185 
00186 // PHY registers
00187 #define PHCON1           0x00
00188 #define PHSTAT1          0x01
00189 #define PHHID1           0x02
00190 #define PHHID2           0x03
00191 #define PHCON2           0x10
00192 #define PHSTAT2          0x11
00193 #define PHIE             0x12
00194 #define PHIR             0x13
00195 #define PHLCON           0x14
00196 
00197 // ENC28J60 PHY PHCON1 Register Bit Definitions
00198 #define PHCON1_PRST      0x8000
00199 #define PHCON1_PLOOPBK   0x4000
00200 #define PHCON1_PPWRSV    0x0800
00201 #define PHCON1_PDPXMD    0x0100
00202 // ENC28J60 PHY PHSTAT1 Register Bit Definitions
00203 #define PHSTAT1_PFDPX    0x1000
00204 #define PHSTAT1_PHDPX    0x0800
00205 #define PHSTAT1_LLSTAT   0x0004
00206 #define PHSTAT1_JBSTAT   0x0002
00207 // ENC28J60 PHY PHCON2 Register Bit Definitions
00208 #define PHCON2_FRCLINK   0x4000
00209 #define PHCON2_TXDIS     0x2000
00210 #define PHCON2_JABBER    0x0400
00211 #define PHCON2_HDLDIS    0x0100
00212 
00213 // ENC28J60 Packet Control Byte Bit Definitions
00214 #define PKTCTRL_PHUGEEN  0x08
00215 #define PKTCTRL_PPADEN   0x04
00216 #define PKTCTRL_PCRCEN   0x02
00217 #define PKTCTRL_POVERRIDE 0x01
00218 
00219 // SPI operation codes
00220 #define ENC28J60_READ_CTRL_REG       0x00
00221 #define ENC28J60_READ_BUF_MEM        0x3A
00222 #define ENC28J60_WRITE_CTRL_REG      0x40
00223 #define ENC28J60_WRITE_BUF_MEM       0x7A
00224 #define ENC28J60_BIT_FIELD_SET       0x80
00225 #define ENC28J60_BIT_FIELD_CLR       0xA0
00226 #define ENC28J60_SOFT_RESET          0xFF
00227 
00228 // The RXSTART_INIT must be zero. See Rev. B4 Silicon Errata point 5.
00229 // Buffer boundaries applied to internal 8K ram
00230 // the entire available packet buffer space is allocated
00231 
00232 #define RXSTART_INIT        0x0000  // start of RX buffer, room for 2 packets
00233 #define RXSTOP_INIT         0x0BFF  // end of RX buffer
00234                             
00235 #define TXSTART_INIT        0x0C00  // start of TX buffer, room for 1 packet
00236 #define TXSTOP_INIT         0x11FF  // end of TX buffer
00237                             
00238 #define SCRATCH_START       0x1200  // start of scratch area
00239 #define SCRATCH_LIMIT       0x2000  // past end of area, i.e. 3.5 Kb 
00240 #define SCRATCH_PAGE_SHIFT  6       // addressing is in pages of 64 bytes
00241 #define SCRATCH_PAGE_SIZE   (1 << SCRATCH_PAGE_SHIFT)
00242 
00243 // max frame length which the conroller will accept:
00244 // (note: maximum ethernet frame length would be 1518)
00245 #define MAX_FRAMELEN      1500        
00246 
00247 #define FULL_SPEED  1   // switch to full-speed SPI for bulk transfers
00248 
00249  
00250 SPI spi(PTD2,PTD3,PTD1); // mosi, miso, sclk
00251 DigitalOut cs(PTD0);
00252 DigitalIn ethInt(PTD4);
00253 Serial pc(USBTX, USBRX); // tx, rx
00254 
00255 static uint8_t Enc28j60Bank;
00256 static int gNextPacketPtr;
00257 uint8_t macaddr[] = {0x00, 0xFF, 0x7A, 0xA5, 0x06, 0xDD}; // fake mac, please change it
00258 
00259 static void enableChip(void) 
00260 {
00261     cs = 0;
00262 }
00263 
00264 static void disableChip(void) 
00265 {
00266     cs = 1;
00267 }
00268 
00269 static uint8_t readOp(uint8_t op, uint8_t address) 
00270 {
00271     uint8_t result;
00272     
00273     //pc.printf("readOp %02X %02X\r\n",op,address);
00274     
00275     enableChip();
00276     
00277     spi.write(op | (address & ADDR_MASK));
00278     result = spi.write(0x00);
00279     if (address & 0x80)
00280         result = spi.write(0x00);
00281     
00282     disableChip();
00283     
00284     //pc.printf("readOp result %02X\r\n",result);
00285     
00286     return result;
00287 }
00288 
00289 static void writeOp(uint8_t op, uint8_t address, uint8_t data) 
00290 {
00291 
00292     //pc.printf("writeOp %02X %02X %02X\r\n",op,address,data);
00293     
00294     enableChip();
00295     
00296     spi.write(op | (address & ADDR_MASK));
00297     spi.write(data);
00298     
00299     disableChip();
00300 }
00301 
00302 static void SetBank (uint8_t address) 
00303 {
00304     if ((address & BANK_MASK) != Enc28j60Bank) 
00305     {
00306         writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_BSEL1|ECON1_BSEL0);
00307         Enc28j60Bank = address & BANK_MASK;
00308         writeOp(ENC28J60_BIT_FIELD_SET, ECON1, Enc28j60Bank>>5);
00309     }
00310 }
00311 
00312 static uint8_t readRegByte (uint8_t address) 
00313 {
00314     SetBank(address);
00315     return readOp(ENC28J60_READ_CTRL_REG, address);
00316 }
00317 
00318 static uint16_t readReg(uint8_t address) 
00319 {
00320     return readRegByte(address) + (readRegByte(address+1) << 8);
00321 }
00322 
00323 static void writeRegByte (uint8_t address, uint8_t data) 
00324 {
00325     SetBank(address);
00326     writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
00327 }
00328 
00329 static void writeReg(uint8_t address, uint16_t data) 
00330 {
00331     writeRegByte(address, data);
00332     writeRegByte(address + 1, data >> 8);
00333 }
00334 void enableBroadcast () 
00335 {
00336     writeRegByte(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN);
00337 }
00338 
00339 void disableBroadcast () 
00340 {
00341     writeRegByte(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
00342 }
00343 
00344 void disableMulticast () 
00345 { // disable multicast filter , enable multicast reception
00346     writeRegByte(ERXFCON, ERXFCON_CRCEN);
00347 }
00348 static uint16_t readPhyByte(uint8_t address) 
00349 {
00350     writeRegByte(MIREGADR, address);
00351     writeRegByte(MICMD, MICMD_MIIRD);
00352     while (readRegByte(MISTAT) & MISTAT_BUSY);
00353     writeRegByte(MICMD, 0x00);
00354     return readRegByte(MIRD+1);
00355 }
00356 
00357 static void writePhy(uint8_t address, uint16_t data) 
00358 {
00359     writeRegByte(MIREGADR, address);
00360     writeReg(MIWR, data);
00361     while (readRegByte(MISTAT) & MISTAT_BUSY)
00362         ;
00363 }
00364 
00365 static void writeBuf(const uint8_t* data, uint16_t len) 
00366 {
00367     enableChip();
00368     
00369     spi.write(ENC28J60_WRITE_BUF_MEM);
00370     while (len--)
00371         spi.write(*data++);
00372         
00373     disableChip();
00374 }
00375 
00376 static void readBuf(uint8_t* data, uint16_t len) 
00377 {
00378     enableChip();
00379     
00380     spi.write(ENC28J60_READ_BUF_MEM);
00381     while (len--) {
00382         *data++ = spi.write(0x00);
00383     }
00384     
00385     disableChip();
00386 }
00387 
00388 uint8_t isLinkUp(void) 
00389 {
00390     return (readPhyByte(PHSTAT2) >> 2) & 1;
00391 }
00392 
00393 void packetSend(uint8_t *buffer, uint16_t len) 
00394 {
00395     pc.printf("packetSend %d bytes ...\r\n",len);
00396     while (readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_TXRTS)
00397     {
00398         if (readRegByte(EIR) & EIR_TXERIF) 
00399         {
00400             writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
00401             writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
00402         }
00403     }
00404     writeReg(EWRPT, TXSTART_INIT);
00405     writeReg(ETXND, TXSTART_INIT+len);
00406     writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
00407     writeBuf(buffer,len);
00408     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
00409 }
00410 
00411 uint16_t packetReceive(uint8_t *buffer, uint16_t bufferSize) 
00412 {
00413     uint16_t len = 0;
00414     if (readRegByte(EPKTCNT) > 0) 
00415     {
00416         writeReg(ERDPT, gNextPacketPtr);
00417 
00418         struct {
00419             uint16_t nextPacket;
00420             uint16_t byteCount;
00421             uint16_t status;
00422         } header;
00423         
00424         readBuf((uint8_t*) &header, sizeof header);
00425 
00426         gNextPacketPtr  = header.nextPacket;
00427         len = header.byteCount - 4; //remove the CRC count
00428         if (len>bufferSize-1)
00429             len=bufferSize-1;
00430         if ((header.status & 0x80)==0)
00431             len = 0;
00432         else
00433             readBuf(buffer,len);
00434         buffer[len] = 0;
00435         if (gNextPacketPtr - 1 > RXSTOP_INIT)
00436             writeReg(ERXRDPT, RXSTOP_INIT);
00437         else
00438             writeReg(ERXRDPT, gNextPacketPtr - 1);
00439         writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
00440     }
00441     return len;
00442 }
00443 
00444 // Contributed by Alex M. Based on code from: http://blog.derouineau.fr
00445 //                  /2011/07/putting-enc28j60-ethernet-controler-in-sleep-mode/
00446 void powerDown() 
00447 {
00448     writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
00449     while(readRegByte(ESTAT) & ESTAT_RXBUSY);
00450     while(readRegByte(ECON1) & ECON1_TXRTS);
00451     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
00452     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
00453 }
00454 
00455 void powerUp() 
00456 {
00457     writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
00458     while(!readRegByte(ESTAT) & ESTAT_CLKRDY);
00459     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00460 }
00461 
00462 static int initialize(void) 
00463 {    
00464     uint8_t rev;
00465     writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
00466     wait(2);
00467     
00468     while(!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY);
00469 
00470     gNextPacketPtr = RXSTART_INIT;
00471     writeReg(ERXST, RXSTART_INIT);
00472     writeReg(ERXRDPT, RXSTART_INIT);
00473     writeReg(ERXND, RXSTOP_INIT);
00474     writeReg(ETXST, TXSTART_INIT);
00475     writeReg(ETXND, TXSTOP_INIT);
00476     enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam
00477     writeReg(EPMM0, 0x303f);
00478     writeReg(EPMCS, 0xf7f9);
00479     writeRegByte(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
00480     writeRegByte(MACON2, 0x00);
00481     writeOp(ENC28J60_BIT_FIELD_SET, MACON3,
00482                         MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
00483     writeReg(MAIPG, 0x0C12);
00484     writeRegByte(MABBIPG, 0x12);
00485     writeReg(MAMXFL, MAX_FRAMELEN);  
00486     writeRegByte(MAADR5, macaddr[0]);
00487     writeRegByte(MAADR4, macaddr[1]);
00488     writeRegByte(MAADR3, macaddr[2]);
00489     writeRegByte(MAADR2, macaddr[3]);
00490     writeRegByte(MAADR1, macaddr[4]);
00491     writeRegByte(MAADR0, macaddr[5]);
00492     writePhy(PHCON2, PHCON2_HDLDIS);
00493     SetBank(ECON1);
00494     writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
00495     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00496 
00497     rev = readRegByte(EREVID);
00498     // microchip forgot to step the number on the silcon when they
00499     // released the revision B7. 6 is now rev B7. We still have
00500     // to see what they do when they release B8. At the moment
00501     // there is no B8 out yet
00502     if (rev > 5) ++rev;
00503     return rev;
00504 }
00505 
00506 static void setupSPI(void)
00507 {
00508     spi.format(8,0);
00509     spi.frequency(8000000);
00510 }
00511 
00512 int main(void)
00513 {
00514     uint8_t rev;
00515     static uint8_t tx_frame[] = 
00516         { 0xff,  0xff, 0xff, 0xff, 0xff, 0xff,
00517           macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5], 
00518           0x80, 0x00,
00519           0x53, 0x68, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x42, 0x69, 
00520           0x74, 0x73, 0x2C, 0x20, 0x65, 0x6D, 0x62, 0x65, 0x64, 0x64, 
00521           0x65, 0x64, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x6C, 0x6C, 0x69, 
00522           0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x21 
00523         }; // dummy frame
00524     static uint8_t rx_frame[1560];
00525 
00526     pc.printf("Setup SPI ...\r\n");
00527     setupSPI();
00528     pc.printf("Setup ethernet ...\r\n");
00529     rev = initialize();
00530     
00531     pc.printf("REV = %d\r\n",rev);
00532     
00533     while(1)
00534     {
00535         uint8_t link = isLinkUp();
00536         pc.printf("LINK = %d\r\n",isLinkUp());
00537         if(link)
00538             break;
00539         wait(1);
00540     }
00541     
00542     while(1)
00543     {
00544         uint8_t reg = readRegByte(EIR);
00545         if(reg & EIR_PKTIF)
00546         {
00547             uint16_t len;
00548             pc.printf("INTERRUPT = %2X\r\n",reg);
00549             len = packetReceive(rx_frame,1560);
00550             pc.printf("RX %d bytes\r\n",len);
00551             writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF);
00552 
00553         }
00554         packetSend(tx_frame,51);
00555         wait(1);
00556     }
00557 }
00558