/**
 * 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;
}
Example #2
0
//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);
}