void Enc28J60Network::init(uint8_t* macaddr) { // initialize I/O // ss as output: pinMode(ENC28J60_CONTROL_CS, OUTPUT); CSPASSIVE; // ss=0 // pinMode(SPI_MOSI, OUTPUT); pinMode(SPI_SCK, OUTPUT); pinMode(SPI_MISO, INPUT); digitalWrite(SPI_MOSI, LOW); digitalWrite(SPI_SCK, LOW); /*DDRB |= 1<<PB3 | 1<<PB5; // mosi, sck output cbi(DDRB,PINB4); // MISO is input // cbi(PORTB,PB3); // MOSI low cbi(PORTB,PB5); // SCK low */ // // initialize SPI interface // master mode and Fosc/2 clock: SPCR = (1<<SPE)|(1<<MSTR); SPSR |= (1<<SPI2X); // perform system reset writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); delay(50); // check CLKRDY bit to see if reset is complete // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); // do bank 0 stuff // initialize receive buffer // 16-bit transfers, must write low byte first // set receive buffer start address nextPacketPtr = RXSTART_INIT; // Rx start writeRegPair(ERXSTL, RXSTART_INIT); // set receive pointer address writeRegPair(ERXRDPTL, RXSTART_INIT); // RX end writeRegPair(ERXNDL, RXSTOP_INIT); // TX start //writeRegPair(ETXSTL, TXSTART_INIT); // TX end //writeRegPair(ETXNDL, TXSTOP_INIT); // do bank 1 stuff, packet filter: // For broadcast packets we allow only ARP packtets // All other packets should be unicast only for our mac (MAADR) // // The pattern to match on is therefore // Type ETH.DST // ARP BROADCAST // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 // in binary these poitions are:11 0000 0011 1111 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); writeRegPair(EPMM0, 0x303f); writeRegPair(EPMCSL, 0xf7f9); // // // do bank 2 stuff // enable MAC receive // and bring MAC out of reset (writes 0x00 to MACON2) writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); // enable automatic padding to 60bytes and CRC operations writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); // set inter-frame gap (non-back-to-back) writeRegPair(MAIPGL, 0x0C12); // set inter-frame gap (back-to-back) writeReg(MABBIPG, 0x12); // Set the maximum packet size which the controller will accept // Do not send packets longer than MAX_FRAMELEN: writeRegPair(MAMXFLL, MAX_FRAMELEN); // do bank 3 stuff // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward writeReg(MAADR5, macaddr[0]); writeReg(MAADR4, macaddr[1]); writeReg(MAADR3, macaddr[2]); writeReg(MAADR2, macaddr[3]); writeReg(MAADR1, macaddr[4]); writeReg(MAADR0, macaddr[5]); // no loopback of transmitted frames phyWrite(PHCON2, PHCON2_HDLDIS); // switch to bank 0 setBank(ECON1); // enable interrutps writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); // enable packet reception writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); //Configure leds phyWrite(PHLCON,0x476); }
void Enc28J60Network::init(uint8_t* macaddr) { MemoryPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte // initialize I/O // ss as output: pinMode(ENC28J60_CONTROL_CS, OUTPUT); CSPASSIVE; // ss=0 // #ifdef ENC28J60DEBUG Serial.println("ENC28J60::initialize / before initSPI()"); #endif SPI.begin(); SPI.setBitOrder(MSBFIRST); // SPI.setDataMode(SPI_MODE0); // SPI.setClockDivider(SPI_CLOCK_DIV16); #ifdef ENC28J60DEBUG Serial.println("ENC28J60::initialize / after initSPI()"); Serial.print("ENC28J60::initialize / csPin = "); Serial.println(SPI.nssPin()); Serial.print("ENC28J60::initialize / miso = "); Serial.println(SPI.misoPin()); Serial.print("ENC28J60::initialize / mosi = "); Serial.println(SPI.mosiPin()); Serial.print("ENC28J60::initialize / sck = "); Serial.println(SPI.sckPin()); #endif selectPin = ENC28J60_CONTROL_CS; pinMode(selectPin, OUTPUT); digitalWrite(selectPin, HIGH); // perform system reset writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); delay(2); // errata B7/2 delay(50); // check CLKRDY bit to see if reset is complete // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); // do bank 0 stuff // initialize receive buffer // 16-bit transfers, must write low byte first // set receive buffer start address #ifdef ENC28J60DEBUG Serial.println("ENC28J60::initialize / before readOp(ENC28J60_READ_CTRL_REG, ESTAT)"); #endif while (!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY) ; #ifdef ENC28J60DEBUG Serial.println("ENC28J60::initialize / after readOp(ENC28J60_READ_CTRL_REG, ESTAT)"); #endif nextPacketPtr = RXSTART_INIT; // Rx start writeRegPair(ERXSTL, RXSTART_INIT); // set receive pointer address writeRegPair(ERXRDPTL, RXSTART_INIT); // RX end writeRegPair(ERXNDL, RXSTOP_INIT); // TX start //-------------writeRegPair(ETXSTL, TXSTART_INIT); // TX end //-------------writeRegPair(ETXNDL, TXSTOP_INIT); // do bank 1 stuff, packet filter: // For broadcast packets we allow only ARP packtets // All other packets should be unicast only for our mac (MAADR) // // The pattern to match on is therefore // Type ETH.DST // ARP BROADCAST // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 // in binary these poitions are:11 0000 0011 1111 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! // enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); writeRegPair(EPMM0, 0x303f); writeRegPair(EPMCSL, 0xf7f9); // // // do bank 2 stuff // enable MAC receive // and bring MAC out of reset (writes 0x00 to MACON2) writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); //----------------writeRegPair(MACON2, 0x00); // enable automatic padding to 60bytes and CRC operations writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); // set inter-frame gap (non-back-to-back) writeRegPair(MAIPGL, 0x0C12); // set inter-frame gap (back-to-back) writeReg(MABBIPG, 0x12); // Set the maximum packet size which the controller will accept // Do not send packets longer than MAX_FRAMELEN: writeRegPair(MAMXFLL, MAX_FRAMELEN); // do bank 3 stuff // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward writeReg(MAADR5, macaddr[0]); writeReg(MAADR4, macaddr[1]); writeReg(MAADR3, macaddr[2]); writeReg(MAADR2, macaddr[3]); writeReg(MAADR1, macaddr[4]); writeReg(MAADR0, macaddr[5]); // no loopback of transmitted frames phyWrite(PHCON2, PHCON2_HDLDIS); // switch to bank 0 setBank(ECON1); // enable interrutps writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); // enable packet reception writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); //Configure leds phyWrite(PHLCON,0x476); byte rev = readReg(EREVID); // microchip forgot to step the number on the silcon when they // released the revision B7. 6 is now rev B7. We still have // to see what they do when they release B8. At the moment // there is no B8 out yet if (rev > 5) ++rev; #ifdef ENC28J60DEBUG Serial.print("ENC28J60::initialize returns "); Serial.println(rev); #endif // return rev; }