123

Committer:
hudakz
Date:
Tue Aug 27 15:01:10 2019 +0000
Revision:
9:a156d3de5647
Mbed OS 5 support added and API modified.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 9:a156d3de5647 1 /*
hudakz 9:a156d3de5647 2 Enc28J60Network.cpp
hudakz 9:a156d3de5647 3 UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
hudakz 9:a156d3de5647 4
hudakz 9:a156d3de5647 5 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
hudakz 9:a156d3de5647 6 All rights reserved.
hudakz 9:a156d3de5647 7
hudakz 9:a156d3de5647 8 based on enc28j60.c file from the AVRlib library by Pascal Stang.
hudakz 9:a156d3de5647 9 For AVRlib See http://www.procyonengineering.com/
hudakz 9:a156d3de5647 10
hudakz 9:a156d3de5647 11 Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
hudakz 9:a156d3de5647 12
hudakz 9:a156d3de5647 13 This program is free software: you can redistribute it and/or modify
hudakz 9:a156d3de5647 14 it under the terms of the GNU General Public License as published by
hudakz 9:a156d3de5647 15 the Free Software Foundation, either version 3 of the License, or
hudakz 9:a156d3de5647 16 (at your option) any later version.
hudakz 9:a156d3de5647 17
hudakz 9:a156d3de5647 18 This program is distributed in the hope that it will be useful,
hudakz 9:a156d3de5647 19 but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 9:a156d3de5647 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 9:a156d3de5647 21 GNU General Public License for more details.
hudakz 9:a156d3de5647 22
hudakz 9:a156d3de5647 23 You should have received a copy of the GNU General Public License
hudakz 9:a156d3de5647 24 along with this program. If not, see <http://www.gnu.org/licenses/>.
hudakz 9:a156d3de5647 25 */
hudakz 9:a156d3de5647 26 #include "Enc28j60Py.h"
hudakz 9:a156d3de5647 27 #include "mbed.h"
hudakz 9:a156d3de5647 28
hudakz 9:a156d3de5647 29 extern "C"
hudakz 9:a156d3de5647 30 {
hudakz 9:a156d3de5647 31 #include "enc28j60.h"
hudakz 9:a156d3de5647 32 #include "uip.h"
hudakz 9:a156d3de5647 33 }
hudakz 9:a156d3de5647 34
hudakz 9:a156d3de5647 35 // Static member initialization
hudakz 9:a156d3de5647 36 uint16_t Enc28j60Phy::nextPacketPtr;
hudakz 9:a156d3de5647 37 uint8_t Enc28j60Phy::bank = 0xff;
hudakz 9:a156d3de5647 38 struct memblock Enc28j60Phy::receivePkt;
hudakz 9:a156d3de5647 39
hudakz 9:a156d3de5647 40 /**
hudakz 9:a156d3de5647 41 * @brief
hudakz 9:a156d3de5647 42 * @note
hudakz 9:a156d3de5647 43 * @param
hudakz 9:a156d3de5647 44 * @retval
hudakz 9:a156d3de5647 45 */
hudakz 9:a156d3de5647 46 Enc28j60Phy::Enc28j60Phy(PinName mosi, PinName miso, PinName sclk, PinName cs) :
hudakz 9:a156d3de5647 47 MemPool(),
hudakz 9:a156d3de5647 48 _spi(mosi, miso, sclk),
hudakz 9:a156d3de5647 49 _cs(cs)
hudakz 9:a156d3de5647 50 { }
hudakz 9:a156d3de5647 51
hudakz 9:a156d3de5647 52 /**
hudakz 9:a156d3de5647 53 * @brief
hudakz 9:a156d3de5647 54 * @note
hudakz 9:a156d3de5647 55 * @param
hudakz 9:a156d3de5647 56 * @retval
hudakz 9:a156d3de5647 57 */
hudakz 9:a156d3de5647 58 void Enc28j60Phy::init(uint8_t* macaddr)
hudakz 9:a156d3de5647 59 {
hudakz 9:a156d3de5647 60 MemPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
hudakz 9:a156d3de5647 61 // initialize SPI interface
hudakz 9:a156d3de5647 62 _spi.format(8, 0); // 8-bit, mode 0
hudakz 9:a156d3de5647 63 _spi.frequency(10000000); // 10 Mbit/s
hudakz 9:a156d3de5647 64 wait_ms(1000); // 1 second for stable state
hudakz 9:a156d3de5647 65 // Release SPI
hudakz 9:a156d3de5647 66 _cs = 1;
hudakz 9:a156d3de5647 67
hudakz 9:a156d3de5647 68 // perform system reset
hudakz 9:a156d3de5647 69 writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
hudakz 9:a156d3de5647 70
hudakz 9:a156d3de5647 71 // check CLKRDY bit to see if reset is complete
hudakz 9:a156d3de5647 72 //while(!(readReg(ESTAT) & ESTAT_CLKRDY));
hudakz 9:a156d3de5647 73 // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
hudakz 9:a156d3de5647 74 wait_ms(50);
hudakz 9:a156d3de5647 75
hudakz 9:a156d3de5647 76 // do bank 0 stuff
hudakz 9:a156d3de5647 77 // initialize receive buffer
hudakz 9:a156d3de5647 78 // 16-bit transfers, must write low byte first
hudakz 9:a156d3de5647 79 // set receive buffer start address
hudakz 9:a156d3de5647 80 nextPacketPtr = RXSTART_INIT;
hudakz 9:a156d3de5647 81
hudakz 9:a156d3de5647 82 // Rx start
hudakz 9:a156d3de5647 83 writeRegPair(ERXSTL, RXSTART_INIT);
hudakz 9:a156d3de5647 84
hudakz 9:a156d3de5647 85 // set receive pointer address
hudakz 9:a156d3de5647 86 writeRegPair(ERXRDPTL, RXSTART_INIT);
hudakz 9:a156d3de5647 87
hudakz 9:a156d3de5647 88 // RX end
hudakz 9:a156d3de5647 89 writeRegPair(ERXNDL, RXSTOP_INIT);
hudakz 9:a156d3de5647 90
hudakz 9:a156d3de5647 91 // TX start
hudakz 9:a156d3de5647 92 //writeRegPair(ETXSTL, TXSTART_INIT);
hudakz 9:a156d3de5647 93 // TX end
hudakz 9:a156d3de5647 94 //writeRegPair(ETXNDL, TXSTOP_INIT);
hudakz 9:a156d3de5647 95 // do bank 1 stuff, packet filter:
hudakz 9:a156d3de5647 96 // For broadcast packets we allow only ARP packtets
hudakz 9:a156d3de5647 97 // All other packets should be unicast only for our mac (MAADR)
hudakz 9:a156d3de5647 98 //
hudakz 9:a156d3de5647 99 // The pattern to match on is therefore
hudakz 9:a156d3de5647 100 // Type ETH.DST
hudakz 9:a156d3de5647 101 // ARP BROADCAST
hudakz 9:a156d3de5647 102 // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
hudakz 9:a156d3de5647 103 // in binary these poitions are:11 0000 0011 1111
hudakz 9:a156d3de5647 104 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
hudakz 9:a156d3de5647 105 //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN!
hudakz 9:a156d3de5647 106 writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN);
hudakz 9:a156d3de5647 107 writeRegPair(EPMM0, 0x303f);
hudakz 9:a156d3de5647 108 writeRegPair(EPMCSL, 0xf7f9);
hudakz 9:a156d3de5647 109
hudakz 9:a156d3de5647 110 //
hudakz 9:a156d3de5647 111 //
hudakz 9:a156d3de5647 112 // do bank 2 stuff
hudakz 9:a156d3de5647 113 // enable MAC receive
hudakz 9:a156d3de5647 114 // and bring MAC out of reset (writes 0x00 to MACON2)
hudakz 9:a156d3de5647 115 writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
hudakz 9:a156d3de5647 116
hudakz 9:a156d3de5647 117 // enable automatic padding to 60bytes and CRC operations
hudakz 9:a156d3de5647 118 writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
hudakz 9:a156d3de5647 119
hudakz 9:a156d3de5647 120 // set inter-frame gap (non-back-to-back)
hudakz 9:a156d3de5647 121 writeRegPair(MAIPGL, 0x0C12);
hudakz 9:a156d3de5647 122
hudakz 9:a156d3de5647 123 // set inter-frame gap (back-to-back)
hudakz 9:a156d3de5647 124 writeReg(MABBIPG, 0x12);
hudakz 9:a156d3de5647 125
hudakz 9:a156d3de5647 126 // Set the maximum packet size which the controller will accept
hudakz 9:a156d3de5647 127 // Do not send packets longer than MAX_FRAMELEN:
hudakz 9:a156d3de5647 128 writeRegPair(MAMXFLL, MAX_FRAMELEN);
hudakz 9:a156d3de5647 129
hudakz 9:a156d3de5647 130 // do bank 3 stuff
hudakz 9:a156d3de5647 131 // write MAC address
hudakz 9:a156d3de5647 132 // NOTE: MAC address in ENC28J60 is byte-backward
hudakz 9:a156d3de5647 133 writeReg(MAADR5, macaddr[0]);
hudakz 9:a156d3de5647 134 writeReg(MAADR4, macaddr[1]);
hudakz 9:a156d3de5647 135 writeReg(MAADR3, macaddr[2]);
hudakz 9:a156d3de5647 136 writeReg(MAADR2, macaddr[3]);
hudakz 9:a156d3de5647 137 writeReg(MAADR1, macaddr[4]);
hudakz 9:a156d3de5647 138 writeReg(MAADR0, macaddr[5]);
hudakz 9:a156d3de5647 139
hudakz 9:a156d3de5647 140 // no loopback of transmitted frames
hudakz 9:a156d3de5647 141 phyWrite(PHCON2, PHCON2_HDLDIS);
hudakz 9:a156d3de5647 142
hudakz 9:a156d3de5647 143 // switch to bank 0
hudakz 9:a156d3de5647 144 setBank(ECON1);
hudakz 9:a156d3de5647 145
hudakz 9:a156d3de5647 146 // enable interrutps
hudakz 9:a156d3de5647 147 writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);
hudakz 9:a156d3de5647 148
hudakz 9:a156d3de5647 149 // enable packet reception
hudakz 9:a156d3de5647 150 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
hudakz 9:a156d3de5647 151
hudakz 9:a156d3de5647 152 //Configure leds
hudakz 9:a156d3de5647 153 phyWrite(PHLCON, 0x476);
hudakz 9:a156d3de5647 154 }
hudakz 9:a156d3de5647 155
hudakz 9:a156d3de5647 156 /**
hudakz 9:a156d3de5647 157 * @brief
hudakz 9:a156d3de5647 158 * @note
hudakz 9:a156d3de5647 159 * @param
hudakz 9:a156d3de5647 160 * @retval
hudakz 9:a156d3de5647 161 */
hudakz 9:a156d3de5647 162 memhandle Enc28j60Phy::receivePacket()
hudakz 9:a156d3de5647 163 {
hudakz 9:a156d3de5647 164 uint8_t rxstat;
hudakz 9:a156d3de5647 165 uint16_t len;
hudakz 9:a156d3de5647 166 // check if a packet has been received and buffered
hudakz 9:a156d3de5647 167 //if( !(readReg(EIR) & EIR_PKTIF) ){
hudakz 9:a156d3de5647 168 // The above does not work. See Rev. B4 Silicon Errata point 6.
hudakz 9:a156d3de5647 169 if (readReg(EPKTCNT) != 0) {
hudakz 9:a156d3de5647 170 uint16_t readPtr = nextPacketPtr +
hudakz 9:a156d3de5647 171 6 > RXSTOP_INIT ? nextPacketPtr +
hudakz 9:a156d3de5647 172 6 -
hudakz 9:a156d3de5647 173 RXSTOP_INIT +
hudakz 9:a156d3de5647 174 RXSTART_INIT : nextPacketPtr +
hudakz 9:a156d3de5647 175 6;
hudakz 9:a156d3de5647 176 // Set the read pointer to the start of the received packet
hudakz 9:a156d3de5647 177 writeRegPair(ERDPTL, nextPacketPtr);
hudakz 9:a156d3de5647 178
hudakz 9:a156d3de5647 179 // read the next packet pointer
hudakz 9:a156d3de5647 180 nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 9:a156d3de5647 181 nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 9:a156d3de5647 182
hudakz 9:a156d3de5647 183 // read the packet length (see datasheet page 43)
hudakz 9:a156d3de5647 184 len = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 9:a156d3de5647 185 len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 9:a156d3de5647 186 len -= 4; //remove the CRC count
hudakz 9:a156d3de5647 187 // read the receive status (see datasheet page 43)
hudakz 9:a156d3de5647 188 rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 9:a156d3de5647 189
hudakz 9:a156d3de5647 190 //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 9:a156d3de5647 191 #ifdef ENC28J60DEBUG
hudakz 9:a156d3de5647 192 printf
hudakz 9:a156d3de5647 193 (
hudakz 9:a156d3de5647 194 "receivePacket [%d-%d], next: %d, stat: %d, count: %d -> ",
hudakz 9:a156d3de5647 195 readPtr,
hudakz 9:a156d3de5647 196 (readPtr + len) % (RXSTOP_INIT + 1),
hudakz 9:a156d3de5647 197 nextPacketPtr,
hudakz 9:a156d3de5647 198 rxstat,
hudakz 9:a156d3de5647 199 readReg(EPKTCNT)
hudakz 9:a156d3de5647 200 );
hudakz 9:a156d3de5647 201 (rxstat & 0x80) != 0 ? printf("OK") : printf("failed");
hudakz 9:a156d3de5647 202 printf("\r\n");
hudakz 9:a156d3de5647 203 #endif
hudakz 9:a156d3de5647 204 // decrement the packet counter indicate we are done with this packet
hudakz 9:a156d3de5647 205
hudakz 9:a156d3de5647 206 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
hudakz 9:a156d3de5647 207
hudakz 9:a156d3de5647 208 // check CRC and symbol errors (see datasheet page 44, table 7-3):
hudakz 9:a156d3de5647 209 // The ERXFCON.CRCEN is set by default. Normally we should not
hudakz 9:a156d3de5647 210 // need to check this.
hudakz 9:a156d3de5647 211 if ((rxstat & 0x80) != 0) {
hudakz 9:a156d3de5647 212 receivePkt.begin = readPtr;
hudakz 9:a156d3de5647 213 receivePkt.size = len;
hudakz 9:a156d3de5647 214 return UIP_RECEIVEBUFFERHANDLE;
hudakz 9:a156d3de5647 215 }
hudakz 9:a156d3de5647 216
hudakz 9:a156d3de5647 217 // Move the RX read pointer to the start of the next received packet
hudakz 9:a156d3de5647 218 // This frees the memory we just read out
hudakz 9:a156d3de5647 219 setERXRDPT();
hudakz 9:a156d3de5647 220 }
hudakz 9:a156d3de5647 221
hudakz 9:a156d3de5647 222 return(NOBLOCK);
hudakz 9:a156d3de5647 223 }
hudakz 9:a156d3de5647 224
hudakz 9:a156d3de5647 225 /**
hudakz 9:a156d3de5647 226 * @brief
hudakz 9:a156d3de5647 227 * @note
hudakz 9:a156d3de5647 228 * @param
hudakz 9:a156d3de5647 229 * @retval
hudakz 9:a156d3de5647 230 */
hudakz 9:a156d3de5647 231 void Enc28j60Phy::setERXRDPT()
hudakz 9:a156d3de5647 232 {
hudakz 9:a156d3de5647 233 writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1);
hudakz 9:a156d3de5647 234 }
hudakz 9:a156d3de5647 235
hudakz 9:a156d3de5647 236 /**
hudakz 9:a156d3de5647 237 * @brief
hudakz 9:a156d3de5647 238 * @note
hudakz 9:a156d3de5647 239 * @param
hudakz 9:a156d3de5647 240 * @retval
hudakz 9:a156d3de5647 241 */
hudakz 9:a156d3de5647 242 memaddress Enc28j60Phy::blockSize(memhandle handle)
hudakz 9:a156d3de5647 243 {
hudakz 9:a156d3de5647 244 return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
hudakz 9:a156d3de5647 245 }
hudakz 9:a156d3de5647 246
hudakz 9:a156d3de5647 247 /**
hudakz 9:a156d3de5647 248 * @brief
hudakz 9:a156d3de5647 249 * @note
hudakz 9:a156d3de5647 250 * @param
hudakz 9:a156d3de5647 251 * @retval
hudakz 9:a156d3de5647 252 */
hudakz 9:a156d3de5647 253 void Enc28j60Phy::sendPacket(memhandle handle)
hudakz 9:a156d3de5647 254 {
hudakz 9:a156d3de5647 255 memblock* packet = &blocks[handle];
hudakz 9:a156d3de5647 256 uint16_t start = packet->begin - 1;
hudakz 9:a156d3de5647 257 uint16_t end = start + packet->size;
hudakz 9:a156d3de5647 258
hudakz 9:a156d3de5647 259 // backup data at control-byte position
hudakz 9:a156d3de5647 260 uint8_t data = readByte(start);
hudakz 9:a156d3de5647 261 // write control-byte (if not 0 anyway)
hudakz 9:a156d3de5647 262 if (data)
hudakz 9:a156d3de5647 263 writeByte(start, 0);
hudakz 9:a156d3de5647 264
hudakz 9:a156d3de5647 265 #ifdef ENC28J60DEBUG
hudakz 9:a156d3de5647 266 printf("sendPacket(%d) [%d-%d]: ", handle, start, end);
hudakz 9:a156d3de5647 267 for (uint16_t i = start; i <= end; i++) {
hudakz 9:a156d3de5647 268 printf("%d ", readByte(i));
hudakz 9:a156d3de5647 269 }
hudakz 9:a156d3de5647 270
hudakz 9:a156d3de5647 271 printf("\r\n");
hudakz 9:a156d3de5647 272 #endif
hudakz 9:a156d3de5647 273 // TX start
hudakz 9:a156d3de5647 274
hudakz 9:a156d3de5647 275 writeRegPair(ETXSTL, start);
hudakz 9:a156d3de5647 276
hudakz 9:a156d3de5647 277 // Set the TXND pointer to correspond to the packet size given
hudakz 9:a156d3de5647 278 writeRegPair(ETXNDL, end);
hudakz 9:a156d3de5647 279
hudakz 9:a156d3de5647 280 // send the contents of the transmit buffer onto the network
hudakz 9:a156d3de5647 281 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
hudakz 9:a156d3de5647 282
hudakz 9:a156d3de5647 283 // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
hudakz 9:a156d3de5647 284 if ((readReg(EIR) & EIR_TXERIF)) {
hudakz 9:a156d3de5647 285 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
hudakz 9:a156d3de5647 286 }
hudakz 9:a156d3de5647 287
hudakz 9:a156d3de5647 288 //restore data on control-byte position
hudakz 9:a156d3de5647 289 if (data)
hudakz 9:a156d3de5647 290 writeByte(start, data);
hudakz 9:a156d3de5647 291 }
hudakz 9:a156d3de5647 292
hudakz 9:a156d3de5647 293 /**
hudakz 9:a156d3de5647 294 * @brief
hudakz 9:a156d3de5647 295 * @note
hudakz 9:a156d3de5647 296 * @param
hudakz 9:a156d3de5647 297 * @retval
hudakz 9:a156d3de5647 298 */
hudakz 9:a156d3de5647 299 uint16_t Enc28j60Phy::setReadPtr(memhandle handle, memaddress position, uint16_t len)
hudakz 9:a156d3de5647 300 {
hudakz 9:a156d3de5647 301 memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle];
hudakz 9:a156d3de5647 302 memaddress start = handle == UIP_RECEIVEBUFFERHANDLE &&
hudakz 9:a156d3de5647 303 packet->begin +
hudakz 9:a156d3de5647 304 position > RXSTOP_INIT ? packet->begin +
hudakz 9:a156d3de5647 305 position -
hudakz 9:a156d3de5647 306 RXSTOP_INIT +
hudakz 9:a156d3de5647 307 RXSTART_INIT : packet->begin +
hudakz 9:a156d3de5647 308 position;
hudakz 9:a156d3de5647 309
hudakz 9:a156d3de5647 310 writeRegPair(ERDPTL, start);
hudakz 9:a156d3de5647 311
hudakz 9:a156d3de5647 312 if (len > packet->size - position)
hudakz 9:a156d3de5647 313 len = packet->size - position;
hudakz 9:a156d3de5647 314 return len;
hudakz 9:a156d3de5647 315 }
hudakz 9:a156d3de5647 316
hudakz 9:a156d3de5647 317 /**
hudakz 9:a156d3de5647 318 * @brief
hudakz 9:a156d3de5647 319 * @note
hudakz 9:a156d3de5647 320 * @param
hudakz 9:a156d3de5647 321 * @retval
hudakz 9:a156d3de5647 322 */
hudakz 9:a156d3de5647 323 uint16_t Enc28j60Phy::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
hudakz 9:a156d3de5647 324 {
hudakz 9:a156d3de5647 325 len = setReadPtr(handle, position, len);
hudakz 9:a156d3de5647 326 readBuffer(len, buffer);
hudakz 9:a156d3de5647 327 return len;
hudakz 9:a156d3de5647 328 }
hudakz 9:a156d3de5647 329
hudakz 9:a156d3de5647 330 /**
hudakz 9:a156d3de5647 331 * @brief
hudakz 9:a156d3de5647 332 * @note
hudakz 9:a156d3de5647 333 * @param
hudakz 9:a156d3de5647 334 * @retval
hudakz 9:a156d3de5647 335 */
hudakz 9:a156d3de5647 336 uint16_t Enc28j60Phy::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
hudakz 9:a156d3de5647 337 {
hudakz 9:a156d3de5647 338 memblock* packet = &blocks[handle];
hudakz 9:a156d3de5647 339 uint16_t start = packet->begin + position;
hudakz 9:a156d3de5647 340
hudakz 9:a156d3de5647 341 writeRegPair(EWRPTL, start);
hudakz 9:a156d3de5647 342
hudakz 9:a156d3de5647 343 if (len > packet->size - position)
hudakz 9:a156d3de5647 344 len = packet->size - position;
hudakz 9:a156d3de5647 345 writeBuffer(len, buffer);
hudakz 9:a156d3de5647 346 return len;
hudakz 9:a156d3de5647 347 }
hudakz 9:a156d3de5647 348
hudakz 9:a156d3de5647 349 /**
hudakz 9:a156d3de5647 350 * @brief
hudakz 9:a156d3de5647 351 * @note
hudakz 9:a156d3de5647 352 * @param
hudakz 9:a156d3de5647 353 * @retval
hudakz 9:a156d3de5647 354 */
hudakz 9:a156d3de5647 355 uint8_t Enc28j60Phy::readByte(uint16_t addr)
hudakz 9:a156d3de5647 356 {
hudakz 9:a156d3de5647 357 uint8_t result;
hudakz 9:a156d3de5647 358
hudakz 9:a156d3de5647 359 writeRegPair(ERDPTL, addr);
hudakz 9:a156d3de5647 360
hudakz 9:a156d3de5647 361 _cs = 0;
hudakz 9:a156d3de5647 362
hudakz 9:a156d3de5647 363 // issue read command
hudakz 9:a156d3de5647 364 _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 9:a156d3de5647 365
hudakz 9:a156d3de5647 366 // read data
hudakz 9:a156d3de5647 367 result = _spi.write(0x00);
hudakz 9:a156d3de5647 368 _cs = 1;
hudakz 9:a156d3de5647 369 return(result);
hudakz 9:a156d3de5647 370 }
hudakz 9:a156d3de5647 371
hudakz 9:a156d3de5647 372 /**
hudakz 9:a156d3de5647 373 * @brief
hudakz 9:a156d3de5647 374 * @note
hudakz 9:a156d3de5647 375 * @param
hudakz 9:a156d3de5647 376 * @retval
hudakz 9:a156d3de5647 377 */
hudakz 9:a156d3de5647 378 void Enc28j60Phy::writeByte(uint16_t addr, uint8_t data)
hudakz 9:a156d3de5647 379 {
hudakz 9:a156d3de5647 380 writeRegPair(EWRPTL, addr);
hudakz 9:a156d3de5647 381
hudakz 9:a156d3de5647 382 _cs = 0;
hudakz 9:a156d3de5647 383
hudakz 9:a156d3de5647 384 // issue write command
hudakz 9:a156d3de5647 385 _spi.write(ENC28J60_WRITE_BUF_MEM);
hudakz 9:a156d3de5647 386
hudakz 9:a156d3de5647 387 // write data
hudakz 9:a156d3de5647 388 _spi.write(data);
hudakz 9:a156d3de5647 389 _cs = 1;
hudakz 9:a156d3de5647 390 }
hudakz 9:a156d3de5647 391
hudakz 9:a156d3de5647 392 /**
hudakz 9:a156d3de5647 393 * @brief
hudakz 9:a156d3de5647 394 * @note
hudakz 9:a156d3de5647 395 * @param
hudakz 9:a156d3de5647 396 * @retval
hudakz 9:a156d3de5647 397 */
hudakz 9:a156d3de5647 398 void Enc28j60Phy::copyPacket
hudakz 9:a156d3de5647 399 (
hudakz 9:a156d3de5647 400 memhandle dest_pkt,
hudakz 9:a156d3de5647 401 memaddress dest_pos,
hudakz 9:a156d3de5647 402 memhandle src_pkt,
hudakz 9:a156d3de5647 403 memaddress src_pos,
hudakz 9:a156d3de5647 404 uint16_t len
hudakz 9:a156d3de5647 405 )
hudakz 9:a156d3de5647 406 {
hudakz 9:a156d3de5647 407 memblock* dest = &blocks[dest_pkt];
hudakz 9:a156d3de5647 408 memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
hudakz 9:a156d3de5647 409 memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE &&
hudakz 9:a156d3de5647 410 src->begin +
hudakz 9:a156d3de5647 411 src_pos > RXSTOP_INIT ? src->begin +
hudakz 9:a156d3de5647 412 src_pos -
hudakz 9:a156d3de5647 413 RXSTOP_INIT +
hudakz 9:a156d3de5647 414 RXSTART_INIT : src->begin +
hudakz 9:a156d3de5647 415 src_pos;
hudakz 9:a156d3de5647 416 enc28j60_mempool_block_move_callback(dest->begin + dest_pos, start, len);
hudakz 9:a156d3de5647 417
hudakz 9:a156d3de5647 418 // Move the RX read pointer to the start of the next received packet
hudakz 9:a156d3de5647 419 // This frees the memory we just read out
hudakz 9:a156d3de5647 420 setERXRDPT();
hudakz 9:a156d3de5647 421 }
hudakz 9:a156d3de5647 422
hudakz 9:a156d3de5647 423 /**
hudakz 9:a156d3de5647 424 * @brief
hudakz 9:a156d3de5647 425 * @note
hudakz 9:a156d3de5647 426 * @param
hudakz 9:a156d3de5647 427 * @retval
hudakz 9:a156d3de5647 428 */
hudakz 9:a156d3de5647 429 void Enc28j60Phy::freePacket()
hudakz 9:a156d3de5647 430 {
hudakz 9:a156d3de5647 431 setERXRDPT();
hudakz 9:a156d3de5647 432 }
hudakz 9:a156d3de5647 433
hudakz 9:a156d3de5647 434 /**
hudakz 9:a156d3de5647 435 * @brief
hudakz 9:a156d3de5647 436 * @note
hudakz 9:a156d3de5647 437 * @param
hudakz 9:a156d3de5647 438 * @retval
hudakz 9:a156d3de5647 439 */
hudakz 9:a156d3de5647 440 uint8_t Enc28j60Phy::readOp(uint8_t op, uint8_t address)
hudakz 9:a156d3de5647 441 {
hudakz 9:a156d3de5647 442 uint8_t result;
hudakz 9:a156d3de5647 443
hudakz 9:a156d3de5647 444 _cs = 0;
hudakz 9:a156d3de5647 445
hudakz 9:a156d3de5647 446 // issue read command
hudakz 9:a156d3de5647 447 _spi.write(op | (address & ADDR_MASK));
hudakz 9:a156d3de5647 448
hudakz 9:a156d3de5647 449 // read data
hudakz 9:a156d3de5647 450 result = _spi.write(0x00);
hudakz 9:a156d3de5647 451
hudakz 9:a156d3de5647 452 // do dummy read if needed (for mac and mii, see datasheet page 29)
hudakz 9:a156d3de5647 453 if (address & 0x80)
hudakz 9:a156d3de5647 454 result = _spi.write(0x00);
hudakz 9:a156d3de5647 455
hudakz 9:a156d3de5647 456 // release CS
hudakz 9:a156d3de5647 457 _cs = 1;
hudakz 9:a156d3de5647 458 return(result);
hudakz 9:a156d3de5647 459 }
hudakz 9:a156d3de5647 460
hudakz 9:a156d3de5647 461 /**
hudakz 9:a156d3de5647 462 * @brief
hudakz 9:a156d3de5647 463 * @note
hudakz 9:a156d3de5647 464 * @param
hudakz 9:a156d3de5647 465 * @retval
hudakz 9:a156d3de5647 466 */
hudakz 9:a156d3de5647 467 void Enc28j60Phy::writeOp(uint8_t op, uint8_t address, uint8_t data)
hudakz 9:a156d3de5647 468 {
hudakz 9:a156d3de5647 469 _cs = 0;
hudakz 9:a156d3de5647 470
hudakz 9:a156d3de5647 471 // issue write command
hudakz 9:a156d3de5647 472 _spi.write(op | (address & ADDR_MASK));
hudakz 9:a156d3de5647 473
hudakz 9:a156d3de5647 474 // write data
hudakz 9:a156d3de5647 475 _spi.write(data);
hudakz 9:a156d3de5647 476 _cs = 1;
hudakz 9:a156d3de5647 477 }
hudakz 9:a156d3de5647 478
hudakz 9:a156d3de5647 479 /**
hudakz 9:a156d3de5647 480 * @brief
hudakz 9:a156d3de5647 481 * @note
hudakz 9:a156d3de5647 482 * @param
hudakz 9:a156d3de5647 483 * @retval
hudakz 9:a156d3de5647 484 */
hudakz 9:a156d3de5647 485 void Enc28j60Phy::readBuffer(uint16_t len, uint8_t* data)
hudakz 9:a156d3de5647 486 {
hudakz 9:a156d3de5647 487 _cs = 0;
hudakz 9:a156d3de5647 488
hudakz 9:a156d3de5647 489 // issue read command
hudakz 9:a156d3de5647 490 _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 9:a156d3de5647 491 while (len) {
hudakz 9:a156d3de5647 492 len--;
hudakz 9:a156d3de5647 493
hudakz 9:a156d3de5647 494 // read data
hudakz 9:a156d3de5647 495 *data = _spi.write(0x00);
hudakz 9:a156d3de5647 496 data++;
hudakz 9:a156d3de5647 497 }
hudakz 9:a156d3de5647 498
hudakz 9:a156d3de5647 499 *data = '\0';
hudakz 9:a156d3de5647 500 _cs = 1;
hudakz 9:a156d3de5647 501 }
hudakz 9:a156d3de5647 502
hudakz 9:a156d3de5647 503 /**
hudakz 9:a156d3de5647 504 * @brief
hudakz 9:a156d3de5647 505 * @note
hudakz 9:a156d3de5647 506 * @param
hudakz 9:a156d3de5647 507 * @retval
hudakz 9:a156d3de5647 508 */
hudakz 9:a156d3de5647 509 void Enc28j60Phy::writeBuffer(uint16_t len, uint8_t* data)
hudakz 9:a156d3de5647 510 {
hudakz 9:a156d3de5647 511 _cs = 0;
hudakz 9:a156d3de5647 512
hudakz 9:a156d3de5647 513 // issue write command
hudakz 9:a156d3de5647 514 _spi.write(ENC28J60_WRITE_BUF_MEM);
hudakz 9:a156d3de5647 515 while (len) {
hudakz 9:a156d3de5647 516 len--;
hudakz 9:a156d3de5647 517
hudakz 9:a156d3de5647 518 // write data
hudakz 9:a156d3de5647 519 _spi.write(*data);
hudakz 9:a156d3de5647 520 data++;
hudakz 9:a156d3de5647 521 }
hudakz 9:a156d3de5647 522
hudakz 9:a156d3de5647 523 _cs = 1;
hudakz 9:a156d3de5647 524 }
hudakz 9:a156d3de5647 525
hudakz 9:a156d3de5647 526 /**
hudakz 9:a156d3de5647 527 * @brief
hudakz 9:a156d3de5647 528 * @note
hudakz 9:a156d3de5647 529 * @param
hudakz 9:a156d3de5647 530 * @retval
hudakz 9:a156d3de5647 531 */
hudakz 9:a156d3de5647 532 void Enc28j60Phy::setBank(uint8_t address)
hudakz 9:a156d3de5647 533 {
hudakz 9:a156d3de5647 534 // set the bank (if needed)
hudakz 9:a156d3de5647 535 if ((address & BANK_MASK) != bank) {
hudakz 9:a156d3de5647 536 // set the bank
hudakz 9:a156d3de5647 537 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));
hudakz 9:a156d3de5647 538 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);
hudakz 9:a156d3de5647 539 bank = (address & BANK_MASK);
hudakz 9:a156d3de5647 540 }
hudakz 9:a156d3de5647 541 }
hudakz 9:a156d3de5647 542
hudakz 9:a156d3de5647 543 /**
hudakz 9:a156d3de5647 544 * @brief
hudakz 9:a156d3de5647 545 * @note
hudakz 9:a156d3de5647 546 * @param
hudakz 9:a156d3de5647 547 * @retval
hudakz 9:a156d3de5647 548 */
hudakz 9:a156d3de5647 549 uint8_t Enc28j60Phy::readReg(uint8_t address)
hudakz 9:a156d3de5647 550 {
hudakz 9:a156d3de5647 551 // set the bank
hudakz 9:a156d3de5647 552 setBank(address);
hudakz 9:a156d3de5647 553
hudakz 9:a156d3de5647 554 // do the read
hudakz 9:a156d3de5647 555 return readOp(ENC28J60_READ_CTRL_REG, address);
hudakz 9:a156d3de5647 556 }
hudakz 9:a156d3de5647 557
hudakz 9:a156d3de5647 558 /**
hudakz 9:a156d3de5647 559 * @brief
hudakz 9:a156d3de5647 560 * @note
hudakz 9:a156d3de5647 561 * @param
hudakz 9:a156d3de5647 562 * @retval
hudakz 9:a156d3de5647 563 */
hudakz 9:a156d3de5647 564 void Enc28j60Phy::writeReg(uint8_t address, uint8_t data)
hudakz 9:a156d3de5647 565 {
hudakz 9:a156d3de5647 566 // set the bank
hudakz 9:a156d3de5647 567 setBank(address);
hudakz 9:a156d3de5647 568
hudakz 9:a156d3de5647 569 // do the write
hudakz 9:a156d3de5647 570 writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
hudakz 9:a156d3de5647 571 }
hudakz 9:a156d3de5647 572
hudakz 9:a156d3de5647 573 /**
hudakz 9:a156d3de5647 574 * @brief
hudakz 9:a156d3de5647 575 * @note
hudakz 9:a156d3de5647 576 * @param
hudakz 9:a156d3de5647 577 * @retval
hudakz 9:a156d3de5647 578 */
hudakz 9:a156d3de5647 579 void Enc28j60Phy::writeRegPair(uint8_t address, uint16_t data)
hudakz 9:a156d3de5647 580 {
hudakz 9:a156d3de5647 581 // set the bank
hudakz 9:a156d3de5647 582 setBank(address);
hudakz 9:a156d3de5647 583
hudakz 9:a156d3de5647 584 // do the write
hudakz 9:a156d3de5647 585 writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF));
hudakz 9:a156d3de5647 586 writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8);
hudakz 9:a156d3de5647 587 }
hudakz 9:a156d3de5647 588
hudakz 9:a156d3de5647 589 /**
hudakz 9:a156d3de5647 590 * @brief
hudakz 9:a156d3de5647 591 * @note
hudakz 9:a156d3de5647 592 * @param
hudakz 9:a156d3de5647 593 * @retval
hudakz 9:a156d3de5647 594 */
hudakz 9:a156d3de5647 595 void Enc28j60Phy::phyWrite(uint8_t address, uint16_t data)
hudakz 9:a156d3de5647 596 {
hudakz 9:a156d3de5647 597 // set the PHY register address
hudakz 9:a156d3de5647 598 writeReg(MIREGADR, address);
hudakz 9:a156d3de5647 599
hudakz 9:a156d3de5647 600 // write the PHY data
hudakz 9:a156d3de5647 601 writeRegPair(MIWRL, data);
hudakz 9:a156d3de5647 602
hudakz 9:a156d3de5647 603 // wait until the PHY write completes
hudakz 9:a156d3de5647 604 while (readReg(MISTAT) & MISTAT_BUSY) {
hudakz 9:a156d3de5647 605 wait_us(15);
hudakz 9:a156d3de5647 606 }
hudakz 9:a156d3de5647 607 }
hudakz 9:a156d3de5647 608
hudakz 9:a156d3de5647 609 /**
hudakz 9:a156d3de5647 610 * @brief
hudakz 9:a156d3de5647 611 * @note
hudakz 9:a156d3de5647 612 * @param
hudakz 9:a156d3de5647 613 * @retval
hudakz 9:a156d3de5647 614 */
hudakz 9:a156d3de5647 615 uint16_t Enc28j60Phy::phyRead(uint8_t address)
hudakz 9:a156d3de5647 616 {
hudakz 9:a156d3de5647 617 writeReg(MIREGADR, address);
hudakz 9:a156d3de5647 618 writeReg(MICMD, MICMD_MIIRD);
hudakz 9:a156d3de5647 619
hudakz 9:a156d3de5647 620 // wait until the PHY read completes
hudakz 9:a156d3de5647 621 while (readReg(MISTAT) & MISTAT_BUSY) {
hudakz 9:a156d3de5647 622 wait_us(15);
hudakz 9:a156d3de5647 623 } //and MIRDH
hudakz 9:a156d3de5647 624
hudakz 9:a156d3de5647 625 writeReg(MICMD, 0);
hudakz 9:a156d3de5647 626 return(readReg(MIRDL) | readReg(MIRDH) << 8);
hudakz 9:a156d3de5647 627 }
hudakz 9:a156d3de5647 628
hudakz 9:a156d3de5647 629 /**
hudakz 9:a156d3de5647 630 * @brief
hudakz 9:a156d3de5647 631 * @note
hudakz 9:a156d3de5647 632 * @param
hudakz 9:a156d3de5647 633 * @retval
hudakz 9:a156d3de5647 634 */
hudakz 9:a156d3de5647 635 void Enc28j60Phy::clkout(uint8_t clk)
hudakz 9:a156d3de5647 636 {
hudakz 9:a156d3de5647 637 //setup clkout: 2 is 12.5MHz:
hudakz 9:a156d3de5647 638 writeReg(ECOCON, clk & 0x7);
hudakz 9:a156d3de5647 639 }
hudakz 9:a156d3de5647 640
hudakz 9:a156d3de5647 641 // read the revision of the chip:
hudakz 9:a156d3de5647 642 uint8_t Enc28j60Phy::getrev()
hudakz 9:a156d3de5647 643 {
hudakz 9:a156d3de5647 644 return(readReg(EREVID));
hudakz 9:a156d3de5647 645 }
hudakz 9:a156d3de5647 646
hudakz 9:a156d3de5647 647 /**
hudakz 9:a156d3de5647 648 * @brief
hudakz 9:a156d3de5647 649 * @note
hudakz 9:a156d3de5647 650 * @param
hudakz 9:a156d3de5647 651 * @retval
hudakz 9:a156d3de5647 652 */
hudakz 9:a156d3de5647 653 uint16_t Enc28j60Phy::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len)
hudakz 9:a156d3de5647 654 {
hudakz 9:a156d3de5647 655 uint8_t spdr;
hudakz 9:a156d3de5647 656 uint16_t t;
hudakz 9:a156d3de5647 657 uint16_t i;
hudakz 9:a156d3de5647 658
hudakz 9:a156d3de5647 659 len = setReadPtr(handle, pos, len) - 1;
hudakz 9:a156d3de5647 660 _cs = 0;
hudakz 9:a156d3de5647 661
hudakz 9:a156d3de5647 662 // issue read command
hudakz 9:a156d3de5647 663 spdr = _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 9:a156d3de5647 664 for (i = 0; i < len; i += 2) {
hudakz 9:a156d3de5647 665 // read data
hudakz 9:a156d3de5647 666 spdr = _spi.write(0x00);
hudakz 9:a156d3de5647 667 t = spdr << 8;
hudakz 9:a156d3de5647 668 spdr = _spi.write(0x00);
hudakz 9:a156d3de5647 669 t += spdr;
hudakz 9:a156d3de5647 670 sum += t;
hudakz 9:a156d3de5647 671 if (sum < t) {
hudakz 9:a156d3de5647 672 sum++; /* carry */
hudakz 9:a156d3de5647 673 }
hudakz 9:a156d3de5647 674 }
hudakz 9:a156d3de5647 675
hudakz 9:a156d3de5647 676 if (i == len) {
hudakz 9:a156d3de5647 677 spdr = _spi.write(0x00);
hudakz 9:a156d3de5647 678 t = (spdr << 8) + 0;
hudakz 9:a156d3de5647 679 sum += t;
hudakz 9:a156d3de5647 680 if (sum < t) {
hudakz 9:a156d3de5647 681 sum++; /* carry */
hudakz 9:a156d3de5647 682 }
hudakz 9:a156d3de5647 683 }
hudakz 9:a156d3de5647 684
hudakz 9:a156d3de5647 685 _cs = 1;
hudakz 9:a156d3de5647 686
hudakz 9:a156d3de5647 687 /* Return sum in host byte order. */
hudakz 9:a156d3de5647 688 return sum;
hudakz 9:a156d3de5647 689 }
hudakz 9:a156d3de5647 690
hudakz 9:a156d3de5647 691 /**
hudakz 9:a156d3de5647 692 * @brief
hudakz 9:a156d3de5647 693 * @note
hudakz 9:a156d3de5647 694 * @param
hudakz 9:a156d3de5647 695 * @retval
hudakz 9:a156d3de5647 696 */
hudakz 9:a156d3de5647 697 void Enc28j60Phy::powerOff()
hudakz 9:a156d3de5647 698 {
hudakz 9:a156d3de5647 699 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
hudakz 9:a156d3de5647 700 wait_ms(50);
hudakz 9:a156d3de5647 701 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
hudakz 9:a156d3de5647 702 wait_ms(50);
hudakz 9:a156d3de5647 703 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
hudakz 9:a156d3de5647 704 }
hudakz 9:a156d3de5647 705
hudakz 9:a156d3de5647 706 /**
hudakz 9:a156d3de5647 707 * @brief
hudakz 9:a156d3de5647 708 * @note
hudakz 9:a156d3de5647 709 * @param
hudakz 9:a156d3de5647 710 * @retval
hudakz 9:a156d3de5647 711 */
hudakz 9:a156d3de5647 712 void Enc28j60Phy::powerOn()
hudakz 9:a156d3de5647 713 {
hudakz 9:a156d3de5647 714 writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
hudakz 9:a156d3de5647 715 wait_ms(50);
hudakz 9:a156d3de5647 716 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
hudakz 9:a156d3de5647 717 wait_ms(50);
hudakz 9:a156d3de5647 718 }
hudakz 9:a156d3de5647 719
hudakz 9:a156d3de5647 720 /**
hudakz 9:a156d3de5647 721 * @brief
hudakz 9:a156d3de5647 722 * @note
hudakz 9:a156d3de5647 723 * @param
hudakz 9:a156d3de5647 724 * @retval
hudakz 9:a156d3de5647 725 */
hudakz 9:a156d3de5647 726 bool Enc28j60Phy::linkStatus()
hudakz 9:a156d3de5647 727 {
hudakz 9:a156d3de5647 728 return(phyRead(PHSTAT2) & 0x0400) > 0;
hudakz 9:a156d3de5647 729 }