Fork for fixes

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Enc28j60Eth.cpp Source File

Enc28j60Eth.cpp

00001 /*
00002  Enc28J60Network.cpp
00003  UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
00004 
00005  Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
00006  All rights reserved.
00007 
00008  based on enc28j60.c file from the AVRlib library by Pascal Stang.
00009  For AVRlib See http://www.procyonengineering.com/
00010 
00011  Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
00012 
00013  This program is free software: you can redistribute it and/or modify
00014  it under the terms of the GNU General Public License as published by
00015  the Free Software Foundation, either version 3 of the License, or
00016  (at your option) any later version.
00017 
00018  This program is distributed in the hope that it will be useful,
00019  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  GNU General Public License for more details.
00022 
00023  You should have received a copy of the GNU General Public License
00024  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  */
00026 #include "Enc28j60Eth.h"
00027 #include "mbed.h"
00028 #include "mbed_version.h"
00029 
00030 extern "C"
00031 {
00032 #include "enc28j60.h"
00033 #include "uip.h"
00034 }
00035 
00036 // Static member initialization
00037 uint16_t    Enc28j60Eth::nextPacketPtr;
00038 uint8_t     Enc28j60Eth::bank = 0xff;
00039 struct      memblock Enc28j60Eth::receivePkt;
00040 
00041 /**
00042  * @brief
00043  * @note
00044  * @param
00045  * @retval
00046  */
00047 Enc28j60Eth::Enc28j60Eth(PinName mosi, PinName miso, PinName sclk, PinName cs) :
00048     MemPool(),
00049     _spi(mosi, miso, sclk),
00050     _cs(cs)
00051 { }
00052 
00053 /**
00054  * @brief
00055  * @note
00056  * @param
00057  * @retval
00058  */
00059 void Enc28j60Eth::init(uint8_t* macaddr)
00060 {
00061     MemPool::init();            // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
00062     
00063     // initialize SPI interface
00064     _cs = 1;
00065     _spi.format(8, 0);          // 8-bit, mode 0
00066     _spi.frequency(10000000);   // 10 Mbit/s
00067 #if MBED_MAJOR_VERSION == 2
00068     wait_ms(100);
00069 #else
00070     thread_sleep_for(100);
00071 #endif
00072 
00073     // perform system reset
00074     writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
00075 
00076     // check CLKRDY bit to see if reset is complete
00077     // while(!(readReg(ESTAT) & ESTAT_CLKRDY));
00078     // The CLKRDY does not work. See Rev. B4 Silicon Errata point.
00079     // Just wait.
00080 #if MBED_MAJOR_VERSION == 2
00081     wait_ms(50);
00082 #else
00083     thread_sleep_for(50);
00084 #endif
00085 
00086     // do bank 0 stuff
00087     // initialize receive buffer
00088     // 16-bit transfers, must write low byte first
00089     // set receive buffer start address
00090     nextPacketPtr = RXSTART_INIT;
00091 
00092     // Rx start
00093     writeRegPair(ERXSTL, RXSTART_INIT);
00094 
00095     // set receive pointer address
00096     writeRegPair(ERXRDPTL, RXSTART_INIT);
00097 
00098     // RX end
00099     writeRegPair(ERXNDL, RXEND_INIT);
00100 
00101     //All memory which is not used by the receive buffer is considered the transmission buffer.
00102     // No explicit action is required to initialize the transmission buffer.
00103     // TX start
00104     //writeRegPair(ETXSTL, TXSTART_INIT);
00105     // TX end
00106     //writeRegPair(ETXNDL, TXEND_INIT);
00107     // However, he host controller should leave at least seven bytes between each
00108     // packet and the beginning of the receive buffer.
00109 
00110     // do bank 1 stuff, packet filter:
00111     // For broadcast packets we allow only ARP packtets
00112     // All other packets should be unicast only for our mac (MAADR)
00113     //
00114     // The pattern to match is therefore
00115     // Type     ETH.DST
00116     // ARP      BROADCAST
00117     // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
00118     // in binary these poitions are:11 0000 0011 1111
00119     // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
00120     //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN!
00121     writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN);
00122     writeRegPair(EPMM0, 0x303f);
00123     writeRegPair(EPMCSL, 0xf7f9);
00124 
00125     //
00126     //
00127     // do bank 2 stuff,
00128     // enable MAC receive
00129     // and bring MAC out of reset (writes 0x00 to MACON2)
00130     writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
00131 
00132     // enable automatic padding to 60bytes and CRC operations
00133     writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
00134 
00135     // set inter-frame gap (non-back-to-back)
00136     writeRegPair(MAIPGL, 0x0C12);
00137 
00138     // set inter-frame gap (back-to-back)
00139     writeReg(MABBIPG, 0x12);
00140 
00141     // Set the maximum packet size which the controller will accept
00142     // Do not send packets longer than MAX_FRAMELEN:
00143     writeRegPair(MAMXFLL, MAX_FRAMELEN);
00144 
00145     // do bank 3 stuff
00146     // write MAC address
00147     // NOTE: MAC address in ENC28J60 is byte-backward
00148     writeReg(MAADR5, macaddr[0]);
00149     writeReg(MAADR4, macaddr[1]);
00150     writeReg(MAADR3, macaddr[2]);
00151     writeReg(MAADR2, macaddr[3]);
00152     writeReg(MAADR1, macaddr[4]);
00153     writeReg(MAADR0, macaddr[5]);
00154 
00155     // no loopback of transmitted frames
00156     phyWrite(PHCON2, PHCON2_HDLDIS);
00157 
00158     // switch to bank 0
00159     setBank(ECON1);
00160 
00161     // enable interrutps
00162     writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);
00163 
00164     // enable packet reception
00165     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00166 
00167     //Configure leds
00168     phyWrite(PHLCON, 0x476);
00169 }
00170 
00171 /**
00172  * @brief
00173  * @note
00174  * @param
00175  * @retval
00176  */
00177 memhandle Enc28j60Eth::receivePacket()
00178 {
00179     uint8_t     rxstat;
00180     uint16_t    len;
00181     // check if a packet has been received and buffered
00182     //if( !(readReg(EIR) & EIR_PKTIF) ){
00183     // The above does not work. See Rev. B4 Silicon Errata point 6.
00184     if (readReg(EPKTCNT) != 0) {
00185         uint16_t    readPtr = (nextPacketPtr +
00186             6 > RXEND_INIT) ? (nextPacketPtr +
00187             6 -
00188             RXEND_INIT +
00189             RXSTART_INIT) : (nextPacketPtr +
00190             6);
00191         // Set the read pointer to the start of the received packet
00192         writeRegPair(ERDPTL, nextPacketPtr);
00193 
00194         // read the next packet pointer
00195         nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0);
00196         nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00197 
00198         // read the packet length (see datasheet page 43)
00199         len = readOp(ENC28J60_READ_BUF_MEM, 0);
00200         len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00201         len -= 4;   //remove the CRC count
00202         // read the receive status (see datasheet page 43)
00203         rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
00204 
00205         //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00206 #ifdef ENC28J60DEBUG
00207         uint16_t    start = readPtr;
00208         uint16_t    end = start + len -1; //todo: why -1 ? 
00209 
00210         printf
00211         (
00212             "receivePacket [%d-%d] (%d) (%d), next: %d, stat: %d, count: %d -> ",
00213             readPtr,
00214             (readPtr + len),
00215             len,
00216             (readPtr + len) % (RXEND_INIT + 1),   // todo: what is RXEND_INIT ?
00217             nextPacketPtr,
00218             rxstat,
00219             readReg(EPKTCNT)
00220         );
00221         (rxstat & 0x80) != 0 ? printf("OK") : printf("failed");
00222         
00223         printf("\r\n");
00224         
00225         int j = 1;
00226         for (uint16_t i = start; i < end; i++) {
00227             printf("%02x ", readByte(i));
00228             if (j%8==0) printf("   ");
00229             if (j%16==0) printf("\r\n");
00230             j++;
00231         }
00232         
00233         printf("\r\n");
00234 #endif
00235         // decrement the packet counter indicate we are done with this packet
00236 
00237         writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
00238 
00239         // check CRC and symbol errors (see datasheet page 44, table 7-3):
00240         // The ERXFCON.CRCEN is set by default. Normally we should not
00241         // need to check this.
00242         if ((rxstat & 0x80) != 0) {
00243             receivePkt.begin = readPtr;
00244             receivePkt.size = len;
00245             return UIP_RECEIVEBUFFERHANDLE;
00246         }
00247 
00248         // Move the RX read pointer to the start of the next received packet
00249         // This frees the memory we just read out
00250         setERXRDPT();
00251     }
00252 
00253     return(NOBLOCK);
00254 }
00255 
00256 /**
00257  * @brief
00258  * @note
00259  * @param
00260  * @retval
00261  */
00262 void Enc28j60Eth::setERXRDPT()
00263 {
00264     uint16_t tmp = (nextPacketPtr == RXSTART_INIT) ? RXEND_INIT : nextPacketPtr - 1;       
00265     
00266     #ifdef ENC28J60DEBUG
00267         printf("setERXRDPT set %d start %d end %d \r\n",tmp,RXSTART_INIT,RXEND_INIT);
00268     #endif
00269     
00270     writeRegPair(ERXRDPTL, tmp);
00271 }
00272 
00273 /**
00274  * @brief
00275  * @note
00276  * @param
00277  * @retval
00278  */
00279 size_t Enc28j60Eth::blockSize(memhandle handle)
00280 {
00281     return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
00282 }
00283 
00284 /**
00285  * @brief
00286  * @note
00287  * @param
00288  * @retval
00289  */
00290 void Enc28j60Eth::sendPacket(memhandle handle)
00291 {
00292     memblock*   packet = &blocks[handle];
00293     uint16_t    start = packet->begin - 1;
00294     uint16_t    end = start + packet->size;
00295 
00296     // backup data at control-byte position
00297     uint8_t     data = readByte(start);
00298     // write control-byte (if not 0 anyway)
00299     if (data)
00300         writeByte(start, 0);
00301 
00302 #ifdef ENC28J60DEBUG
00303     printf("sendPacket(%d) [%d-%d]\r\n", handle, start, end);
00304     int j = 1;
00305     for (uint16_t i = start+1; i <= end; i++) {
00306         printf("%02x ", readByte(i));
00307         if (j%8==0) printf("   ");
00308         if (j%16==0) printf("\r\n");
00309         j++;
00310     }
00311 
00312     printf("\r\n");
00313 #endif
00314     // TX start
00315 
00316     writeRegPair(ETXSTL, start);
00317 
00318     // Set the TXND pointer to correspond to the packet size given
00319     writeRegPair(ETXNDL, end);
00320 
00321     // send the contents of the transmit buffer onto the network
00322     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
00323 
00324     // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
00325     if ((readReg(EIR) & EIR_TXERIF)) {
00326         writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
00327     }
00328 
00329     //restore data on control-byte position
00330     if (data)
00331         writeByte(start, data);
00332 }
00333 
00334 /**
00335  * @brief
00336  * @note
00337  * @param
00338  * @retval
00339  */
00340 uint16_t Enc28j60Eth::setReadPtr(memhandle handle, memaddress position, uint16_t len)
00341 {
00342     memblock*   packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle];
00343     memaddress  start = handle == UIP_RECEIVEBUFFERHANDLE &&
00344         packet->begin +
00345         position > RXEND_INIT ? packet->begin +
00346         position -
00347         RXEND_INIT +
00348         RXSTART_INIT : packet->begin +
00349         position;
00350 
00351     writeRegPair(ERDPTL, start);
00352 
00353     if (len > packet->size - position)
00354         len = packet->size - position;
00355     return len;
00356 }
00357 
00358 /**
00359  * @brief
00360  * @note
00361  * @param
00362  * @retval
00363  */
00364 uint16_t Enc28j60Eth::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
00365 {
00366     len = setReadPtr(handle, position, len);
00367     readBuffer(len, buffer);
00368     return len;
00369 }
00370 
00371 /**
00372  * @brief
00373  * @note
00374  * @param
00375  * @retval
00376  */
00377 uint16_t Enc28j60Eth::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
00378 {
00379     memblock*   packet = &blocks[handle];
00380     uint16_t    start = packet->begin + position;
00381 
00382     writeRegPair(EWRPTL, start);
00383 
00384     if (len > packet->size - position)
00385         len = packet->size - position;
00386     writeBuffer(len, buffer);
00387     return len;
00388 }
00389 
00390 /**
00391  * @brief
00392  * @note
00393  * @param
00394  * @retval
00395  */
00396 uint8_t Enc28j60Eth::readByte(uint16_t addr)
00397 {
00398     uint8_t result;
00399 
00400     writeRegPair(ERDPTL, addr);
00401 
00402     _cs = 0;
00403 
00404     // issue read command
00405     _spi.write(ENC28J60_READ_BUF_MEM);
00406 
00407     // read data
00408     result = _spi.write(0x00);
00409     
00410     _cs = 1;
00411     
00412     return(result);
00413 }
00414 
00415 /**
00416  * @brief
00417  * @note
00418  * @param
00419  * @retval
00420  */
00421 void Enc28j60Eth::writeByte(uint16_t addr, uint8_t data)
00422 {
00423     writeRegPair(EWRPTL, addr);
00424 
00425     _cs = 0;
00426 
00427     // issue write command
00428     _spi.write(ENC28J60_WRITE_BUF_MEM);
00429 
00430     // write data
00431     _spi.write(data);
00432     
00433     _cs = 1;
00434 }
00435 
00436 /**
00437  * @brief
00438  * @note
00439  * @param
00440  * @retval
00441  */
00442 void Enc28j60Eth::copyPacket
00443 (
00444     memhandle   dest_pkt,
00445     memaddress  dest_pos,
00446     memhandle   src_pkt,
00447     memaddress  src_pos,
00448     uint16_t    len
00449 )
00450 {
00451     memblock*   dest = &blocks[dest_pkt];
00452     memblock*   src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
00453     memaddress  start = src_pkt == UIP_RECEIVEBUFFERHANDLE &&
00454         src->begin +
00455         src_pos > RXEND_INIT ? src->begin +
00456         src_pos -
00457         RXEND_INIT +
00458         RXSTART_INIT : src->begin +
00459         src_pos;
00460     enc28j60_mempool_block_move_callback(dest->begin + dest_pos, start, len);
00461 
00462     // Move the RX read pointer to the start of the next received packet
00463     // This frees the memory we just read out
00464     //setERXRDPT();
00465 }
00466 
00467 /**
00468  * @brief
00469  * @note
00470  * @param
00471  * @retval
00472  */
00473 void Enc28j60Eth::freePacket()
00474 {
00475     setERXRDPT();
00476 }
00477 
00478 /**
00479  * @brief
00480  * @note
00481  * @param
00482  * @retval
00483  */
00484 uint8_t Enc28j60Eth::readOp(uint8_t op, uint8_t address)
00485 {
00486     uint8_t result;
00487 
00488     _cs = 0;
00489 
00490     // issue read command
00491     _spi.write(op | (address & ADDR_MASK));
00492 
00493     // read data
00494     result = _spi.write(0x00);
00495 
00496     // do dummy read if needed (for mac and mii, see datasheet page 29)
00497     if (address & 0x80)
00498         result = _spi.write(0x00);
00499 
00500     _cs = 1;
00501     return(result);
00502 }
00503 
00504 /**
00505  * @brief
00506  * @note
00507  * @param
00508  * @retval
00509  */
00510 void Enc28j60Eth::writeOp(uint8_t op, uint8_t address, uint8_t data)
00511 {
00512     _cs = 0;
00513 
00514     // issue write command
00515     _spi.write(op | (address & ADDR_MASK));
00516 
00517     // write data
00518     _spi.write(data);
00519     
00520     _cs = 1;
00521 }
00522 
00523 /**
00524  * @brief
00525  * @note
00526  * @param
00527  * @retval
00528  */
00529 void Enc28j60Eth::readBuffer(uint16_t len, uint8_t* data)
00530 {
00531     _cs = 0;
00532 
00533     // issue read command
00534     _spi.write(ENC28J60_READ_BUF_MEM);
00535  
00536     // read data
00537     while (len) {
00538         len--;
00539         *data = _spi.write(0x00);
00540         data++;
00541     }
00542 
00543     *data = '\0';
00544     
00545     _cs = 1;
00546 }
00547 
00548 /**
00549  * @brief
00550  * @note
00551  * @param
00552  * @retval
00553  */
00554 void Enc28j60Eth::writeBuffer(uint16_t len, uint8_t* data)
00555 {
00556     _cs = 0;
00557 
00558     // issue write command
00559     _spi.write(ENC28J60_WRITE_BUF_MEM);
00560 
00561     // write data
00562     while (len) {
00563         len--;
00564         _spi.write(*data);
00565         data++;
00566     }
00567 
00568     _cs = 1;
00569 }
00570 
00571 /**
00572  * @brief
00573  * @note
00574  * @param
00575  * @retval
00576  */
00577 void Enc28j60Eth::setBank(uint8_t address)
00578 {
00579     // set the bank (if needed)
00580     if ((address & BANK_MASK) != bank) {
00581         // set the bank
00582         writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));
00583         writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);
00584         bank = (address & BANK_MASK);
00585     }
00586 }
00587 
00588 /**
00589  * @brief
00590  * @note
00591  * @param
00592  * @retval
00593  */
00594 uint8_t Enc28j60Eth::readReg(uint8_t address)
00595 {
00596     // set the bank
00597     setBank(address);
00598 
00599     // do the read
00600     return readOp(ENC28J60_READ_CTRL_REG, address);
00601 }
00602 
00603 /**
00604  * @brief
00605  * @note
00606  * @param
00607  * @retval
00608  */
00609 void Enc28j60Eth::writeReg(uint8_t address, uint8_t data)
00610 {
00611     // set the bank
00612     setBank(address);
00613 
00614     // do the write
00615     writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
00616 }
00617 
00618 /**
00619  * @brief
00620  * @note
00621  * @param
00622  * @retval
00623  */
00624 void Enc28j60Eth::writeRegPair(uint8_t address, uint16_t data)
00625 {
00626     // set the bank
00627     setBank(address);
00628 
00629     // do the write
00630     writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF));
00631     writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8);
00632 }
00633 
00634 /**
00635  * @brief
00636  * @note
00637  * @param
00638  * @retval
00639  */
00640 void Enc28j60Eth::phyWrite(uint8_t address, uint16_t data)
00641 {
00642     // set the PHY register address
00643     writeReg(MIREGADR, address);
00644 
00645     // write the PHY data
00646     writeRegPair(MIWRL, data);
00647 
00648     // wait until the PHY write completes
00649     while (readReg(MISTAT) & MISTAT_BUSY) {
00650         wait_us(15);
00651     }
00652 }
00653 
00654 /**
00655  * @brief
00656  * @note
00657  * @param
00658  * @retval
00659  */
00660 uint16_t Enc28j60Eth::phyRead(uint8_t address)
00661 {
00662     writeReg(MIREGADR, address);
00663     writeReg(MICMD, MICMD_MIIRD);
00664 
00665     // wait until the PHY read completes
00666     while (readReg(MISTAT) & MISTAT_BUSY) {
00667         wait_us(15);
00668     }   //and MIRDH
00669 
00670     writeReg(MICMD, 0);
00671     return(readReg(MIRDL) | readReg(MIRDH) << 8);
00672 }
00673 
00674 /**
00675  * @brief
00676  * @note
00677  * @param
00678  * @retval
00679  */
00680 void Enc28j60Eth::clkout(uint8_t clk)
00681 {
00682     //setup clkout: 2 is 12.5MHz:
00683     writeReg(ECOCON, clk & 0x7);
00684 }
00685 
00686 // read the revision of the chip:
00687 uint8_t Enc28j60Eth::getrev()
00688 {
00689     return(readReg(EREVID));
00690 }
00691 
00692 /**
00693  * @brief
00694  * @note
00695  * @param
00696  * @retval
00697  */
00698 uint16_t Enc28j60Eth::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len)
00699 {
00700     uint8_t     spdr;
00701     uint16_t    t;
00702     uint16_t    i;
00703 
00704     len = setReadPtr(handle, pos, len) - 1;
00705     _cs = 0;
00706 
00707     // issue read command
00708     spdr = _spi.write(ENC28J60_READ_BUF_MEM);
00709     for (i = 0; i < len; i += 2) {
00710         // read data
00711         spdr = _spi.write(0x00);
00712         t = spdr << 8;
00713         spdr = _spi.write(0x00);
00714         t += spdr;
00715         sum += t;
00716         if (sum < t) {
00717             sum++;  /* carry */
00718         }
00719     }
00720 
00721     if (i == len) {
00722         spdr = _spi.write(0x00);
00723         t = (spdr << 8) + 0;
00724         sum += t;
00725         if (sum < t) {
00726             sum++;  /* carry */
00727         }
00728     }
00729 
00730     _cs = 1;
00731 
00732     /* Return sum in host byte order. */
00733     return sum;
00734 }
00735 
00736 /**
00737  * @brief
00738  * @note
00739  * @param
00740  * @retval
00741  */
00742 void Enc28j60Eth::powerOff()
00743 {
00744     writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
00745 #if MBED_MAJOR_VERSION == 2
00746     wait_ms(50);
00747 #else
00748     thread_sleep_for(50);
00749 #endif
00750     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
00751 #if MBED_MAJOR_VERSION == 2
00752     wait_ms(50);
00753 #else
00754     thread_sleep_for(50);
00755 #endif
00756     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
00757 }
00758 
00759 /**
00760  * @brief
00761  * @note
00762  * @param
00763  * @retval
00764  */
00765 void Enc28j60Eth::powerOn()
00766 {
00767     writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
00768 #if MBED_MAJOR_VERSION == 2
00769     wait_ms(50);
00770 #else
00771     thread_sleep_for(50);
00772 #endif
00773     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00774 #if MBED_MAJOR_VERSION == 2
00775     wait_ms(50);
00776 #else
00777     thread_sleep_for(50);
00778 #endif
00779 }
00780 
00781 /**
00782  * @brief
00783  * @note
00784  * @param
00785  * @retval
00786  */
00787 bool Enc28j60Eth::linkStatus()
00788 {
00789     return(phyRead(PHSTAT2) & 0x0400) > 0;
00790 }