/** * Reset and initialize the ENC28J60 and starts packet transmission/reception. * * \param[in] mac A pointer to a 6-byte buffer containing the MAC address. * \returns \c true on success, \c false on failure. */ bool enc28j60_init(const uint8_t* mac) { #if 0 /* init i/o */ enc28j60_io_init(); #endif /* reset device */ enc28j60_reset(); /* configure rx/tx buffers */ enc28j60_write(ERXSTL, RX_START & 0xff); enc28j60_write(ERXSTH, RX_START >> 8); enc28j60_write(ERXNDL, RX_END & 0xff); enc28j60_write(ERXNDH, RX_END >> 8); enc28j60_write(ERXWRPTL, RX_START & 0xff); enc28j60_write(ERXWRPTH, RX_START >> 8); enc28j60_write(ERXRDPTL, RX_START & 0xff); enc28j60_write(ERXRDPTH, RX_START >> 8); /* configure frame filters */ enc28j60_write(ERXFCON, (1 << ERXFCON_UCEN) | /* accept unicast packets */ (1 << ERXFCON_CRCEN) | /* accept packets with valid CRC only */ (0 << ERXFCON_PMEN) | /* no pattern matching */ (0 << ERXFCON_MPEN) | /* ignore magic packets */ (0 << ERXFCON_HTEN) | /* disable hash table filter */ (0 << ERXFCON_MCEN) | /* ignore multicast packets */ (1 << ERXFCON_BCEN) | /* accept broadcast packets */ (0 << ERXFCON_ANDOR) /* packets must meet at least one criteria */ ); /* configure MAC */ enc28j60_clear_bits(MACON2, (1 << MACON2_MARST)); enc28j60_write(MACON1, (0 << MACON1_LOOPBK) | #if ENC28J60_FULL_DUPLEX (1 << MACON1_TXPAUS) | (1 << MACON1_RXPAUS) | #else (0 << MACON1_TXPAUS) | (0 << MACON1_RXPAUS) | #endif (0 << MACON1_PASSALL) | (1 << MACON1_MARXEN) ); enc28j60_write(MACON3, (1 << MACON3_PADCFG2) | (1 << MACON3_PADCFG1) | (1 << MACON3_PADCFG0) | (1 << MACON3_TXCRCEN) | (0 << MACON3_PHDRLEN) | (0 << MACON3_HFRMEN) | (1 << MACON3_FRMLNEN) | #if ENC28J60_FULL_DUPLEX (1 << MACON3_FULDPX) #else (0 << MACON3_FULDPX) #endif ); enc28j60_write(MAMXFLL, 0xee); enc28j60_write(MAMXFLH, 0x05); #if ENC28J60_FULL_DUPLEX enc28j60_write(MABBIPG, 0x15); #else enc28j60_write(MABBIPG, 0x12); #endif enc28j60_write(MAIPGL, 0x12); #if !ENC28J60_FULL_DUPLEX enc28j60_write(MAIPGH, 0x0c); #endif enc28j60_write(MAADR0, mac[5]); enc28j60_write(MAADR1, mac[4]); enc28j60_write(MAADR2, mac[3]); enc28j60_write(MAADR3, mac[2]); enc28j60_write(MAADR4, mac[1]); enc28j60_write(MAADR5, mac[0]); if(enc28j60_read(MAADR5)== mac[0]){ ENC28J60_INIT_DEBUG(("MAADR5 = 0x%x\n", enc28j60_read(MAADR5))); ENC28J60_INIT_DEBUG(("MAADR4 = 0x%x\n", enc28j60_read(MAADR4))); ENC28J60_INIT_DEBUG(("MAADR3 = 0x%x\n", enc28j60_read(MAADR3))); ENC28J60_INIT_DEBUG(("MAADR2 = 0x%x\n", enc28j60_read(MAADR2))); ENC28J60_INIT_DEBUG(("MAADR1 = 0x%x\n", enc28j60_read(MAADR1))); ENC28J60_INIT_DEBUG(("MAADR0 = 0x%x\n", enc28j60_read(MAADR0))); } /* * configure PHY */ /* leda -- green led, ledb -- orange led */ #if 0 enc28j60_write_phy(PHLCON, (1 << PHLCON_LACFG3) | (1 << PHLCON_LACFG2) | (0 << PHLCON_LACFG1) | (1 << PHLCON_LACFG0) | (0 << PHLCON_LBCFG3) | (1 << PHLCON_LBCFG2) | (0 << PHLCON_LBCFG1) | (1 << PHLCON_LBCFG0) | (0 << PHLCON_LFRQ1) | (0 << PHLCON_LFRQ0) | (1 << PHLCON_STRCH) ); #else enc28j60_write_phy(PHLCON, (0 << PHLCON_LACFG3) | (1 << PHLCON_LACFG2) | (0 << PHLCON_LACFG1) | (0 << PHLCON_LACFG0) | (0 << PHLCON_LBCFG3) | (1 << PHLCON_LBCFG2) | (1 << PHLCON_LBCFG1) | (1 << PHLCON_LBCFG0) | (0 << PHLCON_LFRQ1) | (0 << PHLCON_LFRQ0) | (1 << PHLCON_STRCH) ); #endif enc28j60_write_phy(PHCON1, (0 << PHCON1_PRST) | (0 << PHCON1_PLOOPBK) | (0 << PHCON1_PPWRSV) | #if ENC28J60_FULL_DUPLEX (1 << PHCON1_PDPXMD) #else (0 << PHCON1_PDPXMD) #endif ); enc28j60_write_phy(PHCON2, (0 << PHCON2_FRCLNK) | (0 << PHCON2_TXDIS) | (0 << PHCON2_JABBER) | (1 << PHCON2_HDLDIS) ); /* start receiving packets */ enc28j60_set_bits(ECON2, (1 << ECON2_AUTOINC)); #if 0 enc28j60_set_bits(ECON1, (1 << ECON1_RXEN)); ENC28J60_INIT_DEBUG(("line:%d, EIE = 0x%x\n", __LINE__, enc28j60_read(EIE))); /* enable interrupt, David */ enc28j60_set_bits(EIE, (1 << EIE_INTIE) | (1<<EIE_PKTIE) | (1<<EIE_TXIE)); ENC28J60_INIT_DEBUG(("line:%d, EIE = 0x%x\n", __LINE__, enc28j60_read(EIE))); #endif return true; }
//initialise spi & enc28j60 void enc28j60_init(void) { unsigned char i; unsigned int timeout=0; //set bank to invalid value -> bank set will update in any case: enc28j60_current_bank = 0xFF; //set up port directions: ENC28J60_DDR |= (1<<ENC28J60_PIN_CS); //RoBue: //PORTB0 + B3 als zusaetzliche Ausgabe ENC28J60_DDR |= (1<<PB0) | (1<<PB3); //deselect enc28j60: ENC28J60_CS_HI(); //SPI init // initialize I/O PORTB |= (1<<ENC28J60_PIN_SCK); //sck = hi //spi = output DDRB |= (1<<ENC28J60_PIN_SS)|(1<<ENC28J60_PIN_CS)|(1<<ENC28J60_PIN_MOSI)|(1<<ENC28J60_PIN_SCK); //SS,MOSI,SCK = OUT DDRB &= ~(1<<ENC28J60_PIN_MISO); //MISO = IN //SPI init: // - master mode // - positive clock phase // - msb first // - maximum SPI speed (fosc/2) // - enable spi SPCR = (0<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0); SPSR = (1<<SPI2X); delay(200000); enc28j60_spi_write_word (ENC28J60_SOFT_RESET, ENC28J60_SOFT_RESET); // check CLKRDY bit to see if reset is complete delay(200000); //wait for ready flag while((!(enc28j60_read_address(ENC28J60_REG_ESTAT) & 0x01)) && (timeout<65000)){timeout++;}; if(timeout>=65000){timeout=0;} //set up rx pointer: enc28j60_next_packet_ptr = ENC28J60_RX_BUFFER_START; //enc28j60_next_packet_ptr = 0x0602; //copy config from progmem to enc28j60: for(i=0; i<2*22; i+=2){ enc28j60_write_address(pgm_read_byte(&enc28j60_config[i+0]),pgm_read_byte(&enc28j60_config[i+1])); } //setup phy: enc28j60_write_phy(ENC28J60_PHY_PHCON2, (1<<ENC28J60_BIT_HDLDIS)); //=no loopback of transmitted frames //enable interrups enc28j60_write_address(ENC28J60_REG_EIE, (1<<ENC28J60_EIE_INTIE)|(1<<ENC28J60_EIE_PKTIE)); //enable rx //enc28j60_write_address(ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN)); enc28j60_spi_write_word(ENC28J60_OP_BFS|ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN)); //set up leds: LEDB: link status, LEDA: RX&TX activity, stretch 40ms, stretch enable enc28j60_write_phy(ENC28J60_PHY_PHLCON, 0x374A); //cave: Table3-3: reset value is 0x3422, do not modify the reserved "3"!! //RevA Datasheet page 9: write as '0000', see RevB Datasheet: write 0011! //read silicon revision //was geht hier vor?? Trotzdem die Bank 2 ist (0x40), gibt er beim Lesen //der RevID keine neue Bank aus, trotzdem kommt der Wert 05. //Vielleicht ist es gar keine Rev05?? enc28j60_revision = enc28j60_read_address(ENC28J60_REG_ECON1); //um die aktuelle Banknummer zu sehen enc28j60_revision = enc28j60_read_address(ENC28J60_REG_EREVID); }