//----------------------------------------------------------------------------- #include "w5100_spi_interface.h" #include "spi_master.h" //#include "usart.h" volatile BOOL sock0_connection_established = false; volatile U08 eth_read_buffer[ETH_READ_BUFFER_SIZE]; volatile U08 eth_write_buffer[ETH_WRITE_BUFFER_SIZE]; U08 eth_write_index; //----------------------------------------------------------------------------- // INTERFACE CONTROL VARS bool w5100_needs_init = true; bool w5100_ready = false; U16 last_samurai = 0x0000; U08 w5100_caretaker() { U08 socket_status; socket_status = w5100_sock_status(); //usart_write_str((pU08)"ss:"); //usart_write_U08_hex(socket_status); //usart_write_char(' '); if (socket_status == SR_SOCK_ESTABLISHED) { w5100_ready = true; // everything is fine... } else if (socket_status == SR_SOCK_LISTEN) { w5100_ready = false; // wait for connection } else { socket_status = w5100_sock_status(); //usart_write_str((pU08)"ss2:"); //usart_write_U08_hex(socket_status); //usart_write_char(' '); if (socket_status == SR_SOCK_ESTABLISHED) { w5100_ready = true; // everything is fine... } else if (socket_status == SR_SOCK_LISTEN) { w5100_ready = false; // wait for connection } else { // this should never happen w5100_ready = false; w5100_reset(); w5100_init(); } } //usart_write_crlf(); return socket_status; } void w5100_reset() { PORTB &= ~(1< W5100 is in reset ... _delay_ms(50); //reset PORTB |= 1< W5100 is active _delay_ms(5); // give it 5ms to accomodate. } void w5100_write( U16 addr, U08 data) { // setup the SPI interface according to W5100 specs. // This is needed, because AD7719 has different SPI specs. spi_setup_w5100(); spi_write_buffer[0]=0xF0; spi_write_buffer[1]=(U08)(addr>>8); spi_write_buffer[2]=(U08)(addr); spi_write_buffer[3]=data; spi_transfer_w5100(4); // spi_read_buffer should contain 0x00 0x01 0x02 and 0x03 ... nice check! } U08 w5100_read( U16 addr) { // setup the SPI interface according to W5100 specs. // This is needed, because AD7719 has different SPI specs. spi_setup_w5100(); spi_write_buffer[0]=0x0F; spi_write_buffer[1]=(U08)(addr>>8); spi_write_buffer[2]=(U08)(addr); spi_write_buffer[3]=0x00; spi_transfer_w5100(4); return spi_read_buffer[3]; // spi_read_buffer should contain 0x00 0x01 0x02 and data ... nice check! } U08 w5100_init (void) { U08 sock0_status = 0x00; // set FSCs MAC Address to value defined in w5100_spi_interface.h w5100_write( CM_SHAR0, FSC_MAC_ADDRESS0 ); w5100_write( CM_SHAR1, FSC_MAC_ADDRESS1 ); w5100_write( CM_SHAR2, FSC_MAC_ADDRESS2 ); w5100_write( CM_SHAR3, FSC_MAC_ADDRESS3 ); w5100_write( CM_SHAR4, FSC_MAC_ADDRESS4 ); w5100_write( CM_SHAR5, FSC_MAC_ADDRESS5 ); //set IP w5100_write( CM_SIPR0, FSC_IP_ADDRESS0 ); w5100_write( CM_SIPR1, FSC_IP_ADDRESS1 ); w5100_write( CM_SIPR2, FSC_IP_ADDRESS2 ); w5100_write( CM_SIPR3, FSC_IP_ADDRESS3 ); // set subnet mask w5100_write( CM_SUBR0, FSC_SUBNET_MASK0 ); w5100_write( CM_SUBR1, FSC_SUBNET_MASK1 ); w5100_write( CM_SUBR2, FSC_SUBNET_MASK2 ); w5100_write( CM_SUBR3, FSC_SUBNET_MASK3 ); // set IP of Gateway used by FSC w5100_write( CM_GAR0, FSC_GATEWAY_ADDRESS0 ); w5100_write( CM_GAR1, FSC_GATEWAY_ADDRESS1 ); w5100_write( CM_GAR2, FSC_GATEWAY_ADDRESS2 ); w5100_write( CM_GAR3, FSC_GATEWAY_ADDRESS3 ); //set socket read and write fifo sizes w5100_write( CM_RMSR, 0x0A); // --> 4k for socket 0 and 1 w5100_write( CM_TMSR, 0x0A); // --> 4k for socket 0 and 1 w5100_write ( S0_MR, 0x01); // set Socket 0 as TCP w5100_write ( S0_PORT0, 0x13 ); // Port 5000 -> 0x1388 w5100_write ( S0_PORT1, 0x88 ); w5100_write ( S0_CR, CR_OPEN ); // issue Socket open command while (sock0_status != SR_SOCK_INIT) { sock0_status = w5100_read(S0_SR); // request socket 0 status } w5100_write ( S0_CR, CR_LISTEN ); // issue Socket listen command while (sock0_status != SR_SOCK_LISTEN) { sock0_status = w5100_read(S0_SR); // request socket 0 status } return sock0_status; } BOOL w5100_is_established() { if ( w5100_read(S0_SR) == SR_SOCK_ESTABLISHED ) { sock0_connection_established = true; } else { sock0_connection_established = false; } return sock0_connection_established; } U08 w5100_sock_status() { return w5100_read(S0_SR); } // getters of TX and RX registers // S0_TX_FSR // Contains Socket free size in bytes U16 get_S0_TX_FSR() { U16 freesize; freesize=w5100_read(S0_TX_FSR0); // datasheet: user should read upper byte first, and lower byte later freesize = freesize << 8; // to get correct value freesize += w5100_read(S0_TX_FSR1); return freesize; } // S0_TX_RD U16 get_S0_TX_RD() { U16 readpointer; readpointer=w5100_read(S0_TX_RD0); readpointer = readpointer << 8; readpointer += w5100_read(S0_TX_RD1); return readpointer; } // S0_TX_WR U16 get_S0_TX_WR() { U16 writepointer; writepointer=w5100_read(S0_TX_WR0); writepointer = writepointer << 8; writepointer += w5100_read(S0_TX_WR1); return writepointer; } // S0_RX_RSR U16 get_S0_RX_RSR() { U16 received_size; U08 highbyte, lowbyte; highbyte = w5100_read(S0_RX_RSR0); lowbyte = w5100_read(S0_RX_RSR1); received_size = (highbyte<<8) | lowbyte; // usart_write_str((pU08)"hi:"); // usart_write_U08_hex(highbyte); // usart_write_crlf(); // // usart_write_str((pU08)"lo:"); // usart_write_U08_hex(lowbyte); // usart_write_crlf(); // // usart_write_str((pU08)"total:"); // usart_write_U16_hex(received_size); // usart_write_crlf(); // _delay_ms(200); return received_size; } // S0_RX_RD U16 get_S0_RX_RD() { U16 readpointer; readpointer=w5100_read(S0_RX_RD0); readpointer = readpointer << 8; readpointer += w5100_read(S0_RX_RD1); return readpointer; } // setters for some RX and TX registers // S0_TX_WR void set_S0_TX_WR(U16 value) { U08 high_byte = (value>>8); U08 low_byte = value&0x00FF; w5100_write(S0_TX_WR0, high_byte); w5100_write(S0_TX_WR1, low_byte); } // S0_TX_RD void set_S0_RX_RD(U16 value) { U08 high_byte = (value>>8); U08 low_byte = value&0x00FF; w5100_write(S0_RX_RD0, high_byte); w5100_write(S0_RX_RD1, low_byte); } U08 w5100_get_RX(U08 NumBytes, BOOL send_ACK) { U16 size = get_S0_RX_RSR(); U16 upper_size, lower_size; if (NumBytes > ETH_READ_BUFFER_SIZE) { NumBytes = ETH_READ_BUFFER_SIZE; } if (size == 0) { return 0; } else if ( size < NumBytes ) { NumBytes = size; } // now calculate the offset address // calculated according to W5100 datasheet page: 43 U16 last_RX_read_pointer = get_S0_RX_RD(); U16 offset = last_RX_read_pointer & S0_RX_MASK; U16 start_address = S0_RX_BASE + offset; //usart_write_str((pU08)"lrp:"); //usart_write_U16_hex(last_RX_read_pointer); //usart_write_crlf(); //usart_write_str((pU08)"off:"); //usart_write_U16_hex(offset); //usart_write_crlf(); //usart_write_str((pU08)"sad:"); //usart_write_U16_hex(start_address); //usart_write_crlf(); if ((offset + NumBytes) > (S0_RX_MASK + 1) ) // if data is turned over in RX-mem { upper_size = (S0_RX_MASK + 1) - offset; lower_size = NumBytes - upper_size; for (U08 i = 0; i < upper_size; ++i) { eth_read_buffer[i] = w5100_read(start_address + i); } for (U08 i = 0; i < lower_size; ++i) { eth_read_buffer[upper_size + i] = w5100_read(S0_RX_BASE + i); } } else // if not data turn over in RX-mem { for (U08 i = 0; i < NumBytes; ++i) { eth_read_buffer[i] = w5100_read(start_address + i); } } // inform W5100 about how much data was read out. U16 new_read_pointer = last_RX_read_pointer + NumBytes; //usart_write_str((pU08)"nrp:"); //usart_write_U16_hex(new_read_pointer); //usart_write_crlf(); set_S0_RX_RD(new_read_pointer); w5100_write ( S0_CR, CR_RECV ); /* usart_write_U16_hex(get_S0_TX_FSR()); usart_write_char('\t'); usart_write_char('|'); usart_write_U16_hex(get_S0_TX_RD()); usart_write_char('\t'); usart_write_char('|'); usart_write_U16_hex(get_S0_TX_WR()); usart_write_char('\t'); usart_write_char('|'); usart_write_U16_hex(get_S0_RX_RSR()); usart_write_char('\t'); usart_write_char('|'); usart_write_U16_hex(get_S0_RX_RD()); usart_write_char('\t'); usart_write_char('|'); */ // if user wishes, W5100 may inform peer about receiption. // this should be done quickly, otherwise timeout may occur on // peer side, and peer retransmitts or so ... // // maybe it is necessary to acknowledge receiption very early. // I think there is an option in Socket mode register for this. if (send_ACK) { //w5100_write ( S0_CR, CR_RECV ); } return NumBytes; } // returns number of bytes, transmitted into TX - buffer. U16 w5100_set_TX(U08* string, U16 NumBytes) { U08 repetitions; U16 freesize; U16 last_TX_write_pointer; freesize = get_S0_TX_FSR(); for (repetitions=0 ; repetitions < 3; ) { // increase is *inside the loop* if ( freesize != get_S0_TX_FSR()) { freesize = get_S0_TX_FSR(); } else { repetitions++; } } if (freesize == 0) { return 0; } last_TX_write_pointer = get_S0_TX_WR(); for (repetitions=0 ; repetitions < 3; ) { // increase is *inside the loop* if ( last_TX_write_pointer != get_S0_TX_WR()) { last_TX_write_pointer = get_S0_TX_WR(); } else { repetitions++; } } U16 offset = last_TX_write_pointer & S0_TX_MASK; U16 start_address = S0_TX_BASE + offset; U16 upper_size; U16 lower_size; if ( freesize < NumBytes ) { NumBytes = freesize; } // now calculate the offset address // calculated according to W5100 datasheet page: 44 if ((offset + NumBytes) > (S0_RX_MASK + 1) ) { // if data is turned over in RX-mem upper_size = (S0_RX_MASK + 1) - offset; lower_size = NumBytes - upper_size; for (U16 i = 0; i < upper_size; ++i) { w5100_write(start_address + i, string[i]); } for (U16 i = 0; i < lower_size; ++i) { w5100_write(S0_RX_BASE + i, string[upper_size+i]); } } else { // if not data turn over in RX-mem for (U16 i = 0; i < NumBytes; ++i) { w5100_write(start_address + i, string[i]); } } // inform W5100 about how much data was written. U16 new_write_pointer = last_TX_write_pointer + NumBytes; set_S0_TX_WR(new_write_pointer); // tell it to send now the data away w5100_write( S0_CR, CR_SEND); return NumBytes; } void eth_write_str( U08* str ){ while (*str) { if (eth_write_index < ETH_WRITE_BUFFER_SIZE) { eth_write_buffer[eth_write_index++] = *str++; } } w5100_set_TX(eth_write_buffer, eth_write_index); eth_write_index = 0; } void eth_writeln_str( U08* str ){ while (*str) { if (eth_write_index < ETH_WRITE_BUFFER_SIZE) { eth_write_buffer[eth_write_index++] = *str++; } } if (eth_write_index < ETH_WRITE_BUFFER_SIZE) { eth_write_buffer[eth_write_index++] = '\n'; } w5100_set_TX(eth_write_buffer, eth_write_index); eth_write_index = 0; } void eth_write_lf(void) { if (eth_write_index < ETH_WRITE_BUFFER_SIZE) { eth_write_buffer[eth_write_index++] = '\n'; } w5100_set_TX(eth_write_buffer, eth_write_index); eth_write_index = 0; }