mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Committer:
pilotak
Date:
Sun Aug 06 16:01:26 2017 +0000
Revision:
9:e55652bed36c
Parent:
8:4acb22344932
mBed OS5

Who changed what in which revision?

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