// This file is part of "NPR70 modem firmware" software // (A GMSK data modem for ham radio 430-440MHz, at several hundreds of kbps) // Copyright (c) 2017-2020 Guillaume F. F4HDK (amateur radio callsign) // // "NPR70 modem firmware" is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // "NPR70 modem firmware" is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with "NPR70 modem firmware". If not, see #include "W5500.h" #include "mbed.h" #include "global_variables.h" #include "Eth_IPv4.h" void W5500_read_long(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr, unsigned char* RX_data, int RX_size) { unsigned char W5_command[20]; unsigned char trash[20]; W5_command[0] = W5500_addr / 256; W5_command[1] = W5500_addr & 0xFF; W5_command[2] = (bloc_addr * 0x08); *(SPI_p_loc->cs)=0; RX_data[0]=0; SPI_p_loc->spi_port->transfer_2 (W5_command, 3, trash, 3); SPI_p_loc->spi_port->transfer_2 (trash, RX_size, RX_data, RX_size); wait_us(1); *(SPI_p_loc->cs)=1; wait_us(2); } void W5500_write_long(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr, unsigned char* TX_data, int TX_size) { unsigned char W5_command[4]; static unsigned char trash[1600]; W5_command[0] = W5500_addr / 256; W5_command[1] = W5500_addr & 0xFF; W5_command[2] = (bloc_addr * 0x08) + 4; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (W5_command, 3, trash, 3); //wait_us(10); SPI_p_loc->spi_port->transfer_2 (TX_data, TX_size, trash, 0); wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); } void W5500_read_short(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr, unsigned char* RX_data_ext, int RX_size) { unsigned char TX_data_loc[20]; unsigned char RX_data_loc[20]; int i; TX_data_loc[0] = W5500_addr / 256; TX_data_loc[1] = W5500_addr & 0xFF; TX_data_loc[2] = (bloc_addr * 0x08) ; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (TX_data_loc, RX_size+3, RX_data_loc, RX_size+3); for (i=0; i < RX_size; i++) { RX_data_ext[i] = RX_data_loc[i+3]; } wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); } void W5500_write_short(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr, unsigned char* TX_data_ext, int TX_size) { unsigned char TX_data_loc[10]; unsigned char trash[10]; int i; TX_data_loc[0] = W5500_addr / 256; TX_data_loc[1] = W5500_addr & 0xFF; TX_data_loc[2] = (bloc_addr * 0x08) + 4; for (i=0; i < TX_size; i++) { TX_data_loc[i+3] = TX_data_ext[i]; } SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (TX_data_loc, TX_size+3, trash, 0); wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); } unsigned char W5500_read_byte(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr) { unsigned char TX_data_loc[20]; unsigned char RX_data_loc[20]; unsigned char data_out; TX_data_loc[0] = W5500_addr / 256; TX_data_loc[1] = W5500_addr & 0xFF; TX_data_loc[2] = (bloc_addr * 0x08) ; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (TX_data_loc, 4, RX_data_loc, 4); wait_us(1); SPI_p_loc->cs->write(1); data_out = RX_data_loc[3]; return data_out; wait_us(2); } void W5500_write_byte(W5500_chip* SPI_p_loc, unsigned int W5500_addr, unsigned char bloc_addr, unsigned char data) { unsigned char TX_data_loc[10]; unsigned char trash[10]; TX_data_loc[0] = W5500_addr / 256; TX_data_loc[1] = W5500_addr & 0xFF; TX_data_loc[2] = (bloc_addr * 0x08) + 4; TX_data_loc[3] = data; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (TX_data_loc, 4, trash, 0); wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); } void W5500_Phy_off_2sec(W5500_chip* SPI_p_loc) { //unsigned char phy_config[1]; W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0x70); wait(5); W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xF8); } int W5500_read_received_size(W5500_chip* SPI_p_loc, int sock_nb) { int size=9999, previous_size=9999; unsigned char data[10]; do { previous_size = size; W5500_read_short(SPI_p_loc, 0x0026, (sock_nb*4)+1, data, 2); size = data[1] + data[0]*256; } while (previous_size != size); //printf("size:%d\r\n", size); return size; } int W5500_read_TX_free_size(W5500_chip* SPI_p_loc, int sock_nb) { int size=9999, previous_size=9999; unsigned char data[10]; do { previous_size = size; W5500_read_short(SPI_p_loc, 0x0020, (sock_nb*4)+1, data, 2); size = data[1] + data[0]*256; } while (previous_size != size); //printf("size:%d\r\n", size); return size; } void W5500_read_RX_buffer(W5500_chip* SPI_p_loc, int sock_nb, unsigned char* data, int size) { unsigned char read_pointer_raw[10]; unsigned short read_pointer; W5500_read_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); read_pointer = read_pointer_raw[1] + read_pointer_raw[0] * 256; W5500_read_long(SPI_p_loc, read_pointer, (sock_nb*4)+3, data, size); read_pointer = read_pointer + size ; read_pointer_raw[0] = read_pointer / 256; read_pointer_raw[1] = read_pointer & 0xFF; W5500_write_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); W5500_write_byte(SPI_p_loc, 0x0001, (sock_nb*4)+1, 0x40); } int W5500_read_UDP_pckt (W5500_chip* SPI_p_loc, int sock_nb, unsigned char* data) { int size=0; unsigned char read_pointer_raw[10]; unsigned char trash[20]; unsigned short read_pointer; unsigned char W5_command[20]; W5500_read_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); read_pointer = read_pointer_raw[1] + read_pointer_raw[0] * 256; // read first 8 bytes W5_command[0] = read_pointer_raw[0]; W5_command[1] = read_pointer_raw[1]; W5_command[2] = ((sock_nb*4)+3) * 0x08; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (W5_command, 3, trash, 3); SPI_p_loc->spi_port->transfer_2 (trash, 8, data, 8); size = data [7] + 256 * data[6]; SPI_p_loc->spi_port->transfer_2 (trash, size, data+8, size); size = size + 8; wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); //printf ("size UDP:%d\r\n", size); read_pointer = read_pointer + size ; read_pointer_raw[0] = read_pointer / 256; read_pointer_raw[1] = read_pointer & 0xFF; W5500_write_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); W5500_write_byte(SPI_p_loc, 0x0001, (sock_nb*4)+1, 0x40);//command receive return size; } int W5500_read_MAC_pckt (W5500_chip* SPI_p_loc, int sock_nb, unsigned char* data) { int size=0; unsigned char read_pointer_raw[10]; unsigned char trash[20]; unsigned short read_pointer; unsigned char W5_command[20]; W5500_read_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); read_pointer = read_pointer_raw[1] + read_pointer_raw[0] * 256; // read first 8 bytes W5_command[0] = read_pointer_raw[0]; W5_command[1] = read_pointer_raw[1]; W5_command[2] = ((sock_nb*4)+3) * 0x08; SPI_p_loc->cs->write(0); SPI_p_loc->spi_port->transfer_2 (W5_command, 3, trash, 3); SPI_p_loc->spi_port->transfer_2 (trash, 2, data, 2); size = data [1] + 256 * data[0]; SPI_p_loc->spi_port->transfer_2 (trash, size-2, data+2, size-2); wait_us(1); SPI_p_loc->cs->write(1); wait_us(2); //printf ("size UDP:%d\r\n", size); read_pointer = read_pointer + size ; read_pointer_raw[0] = read_pointer / 256; read_pointer_raw[1] = read_pointer & 0xFF; W5500_write_short(SPI_p_loc, 0x0028, (sock_nb*4)+1, read_pointer_raw, 2); W5500_write_byte(SPI_p_loc, 0x0001, (sock_nb*4)+1, 0x40); return size; } void W5500_write_TX_buffer(W5500_chip* SPI_p_loc, int sock_nb, unsigned char* data, int size, int send_mac) { unsigned char write_pointer_raw[10]; unsigned short write_pointer; W5500_read_short(SPI_p_loc, 0x0024, (sock_nb*4)+1, write_pointer_raw, 2); write_pointer = write_pointer_raw[1] + write_pointer_raw[0] * 256; W5500_write_long(SPI_p_loc, write_pointer, (sock_nb*4)+2, data, size); write_pointer = write_pointer + size ; write_pointer_raw[0] = write_pointer / 256; write_pointer_raw[1] = write_pointer & 0xFF; W5500_write_short(SPI_p_loc, 0x0024, (sock_nb*4)+1, write_pointer_raw, 2); if (send_mac == 1) { W5500_write_byte(SPI_p_loc, 0x0001, (sock_nb*4)+1, 0x21); } else { W5500_write_byte(SPI_p_loc, 0x0001, (sock_nb*4)+1, 0x20); } } static int W5500_configured = 0; // 0 not yet configured // 1 configured // 2 waiting reconfigure // 3 waiting reboot after reconfigure void W5500_re_configure (void) { W5500_configured = 2; } void W5500_re_configure_gateway(W5500_chip* SPI_p_loc) { unsigned char data[10]; if ( (LAN_conf_applied.LAN_def_route_activ) && (is_telnet_routed) && (is_TDMA_master) ) { IP_int2char (LAN_conf_applied.LAN_def_route, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); // gateway } else { IP_int2char (0x01010101, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); } } void W5500_re_configure_periodic_call(W5500_chip* SPI_p_loc) { unsigned char data[10]; if (W5500_configured == 4) { // reboot //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xF8);//!!! 0xC8 0xF8 W5500_write_byte(SPI_p_loc, 0x002E, 0x00, (CONF_Eth_mode << 3) + 0xC0);//!!! 0xC8 0xF8 W5500_configured = 1; //configured } if (W5500_configured == 3) { //wait W5500_configured = 4; } if (W5500_configured == 2) { //reconfigure IP_int2char (LAN_conf_applied.LAN_modem_IP, data); W5500_write_long(SPI_p_loc, 0x000F, 0x00, data, 4); // modem IP IP_int2char (LAN_conf_applied.LAN_subnet_mask, data); W5500_write_long(SPI_p_loc, 0x0005, 0x00, data, 4); // net mask if ( (LAN_conf_applied.LAN_def_route_activ) && (is_telnet_routed) && (is_TDMA_master) ) { IP_int2char (LAN_conf_applied.LAN_def_route, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); // gateway } else { IP_int2char (0x01010101, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); } //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0x78); // 0x48 0x78 W5500_write_byte(SPI_p_loc, 0x002E, 0x00, (CONF_Eth_mode << 3) + 0x40); // 0x48 0x78 W5500_configured = 3; //waiting reboot } } void W5500_initial_configure(W5500_chip* SPI_p_loc) { // reset W5500_write_byte(SPI_p_loc, 0x0000, 0x00, 0x80);//0x90 wait_ms(500); W5500_write_byte(SPI_p_loc, 0x0000, 0x00, 0x00);//0x10 //wait_ms(1600); //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xC8); //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0x78);//48 78 for 10MB full duplex / 40 half duplex !!! W5500_write_byte(SPI_p_loc, 0x002E, 0x00, (CONF_Eth_mode << 3) + 0x40);//48 78 for 10MB full duplex / 40 half duplex !!! wait_ms(1600); //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xF8);//c8 F8 for 10MB full duplex / c0 half duplexc8 !!! W5500_write_byte(SPI_p_loc, 0x002E, 0x00, (CONF_Eth_mode << 3) + 0xC0);//c8 F8 for 10MB full duplex / c0 half duplexc8 !!! //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xC8); //wait_ms(1600); //W5500_write_byte(SPI_p_loc, 0x002E, 0x00, 0xC0); //IP & MAC config //unsigned char data[20]={0x00,0x2E,0x00,4,5,6, 10,151,20,254}; //unsigned char data[20]={0x00,0x2E,0x00,4,5,6, 192,168,0,254}; unsigned char data[20]={0x00,0x2E,0x00,4,5,6}; //W5500_write_long(SPI_p_loc, 0x0009, 0x00, data, 6); // modem MAC //W5500_write_long(SPI_p_loc, 0x0009, 0x00, LAN_conf_applied.modem_MAC, 6); // modem MAC W5500_write_long(SPI_p_loc, 0x0009, 0x00, CONF_modem_MAC, 6); // modem MAC IP_int2char (LAN_conf_applied.LAN_modem_IP, data); W5500_write_long(SPI_p_loc, 0x000F, 0x00, data, 4); // modem IP if ( (is_telnet_routed) && (is_TDMA_master) ) { IP_int2char (LAN_conf_applied.LAN_def_route, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); // gateway } else { IP_int2char (0, data); W5500_write_long(SPI_p_loc, 0x0001, 0x00, data, 4); } IP_int2char (LAN_conf_applied.LAN_subnet_mask, data); W5500_write_long(SPI_p_loc, 0x0005, 0x00, data, 4); // net mask W5500_write_byte(SPI_p_loc, 0x0018, 0x00, 0x01);//sock interrupt mask // Socket Read buffer size W5500_write_byte(SPI_p_loc, 0x001E, 0x01, 0x08); //0 macraw 08 W5500_write_byte(SPI_p_loc, 0x001E, 0x05, 0x02); //1 telnet 02 W5500_write_byte(SPI_p_loc, 0x001E, 0x09, 0x04); //2 RTP 04 W5500_write_byte(SPI_p_loc, 0x001E, 0x0D, 0x02); //3 DHCP 02 W5500_write_byte(SPI_p_loc, 0x001E, 0x11, 0x00); //4 W5500_write_byte(SPI_p_loc, 0x001E, 0x15, 0x00); //5 W5500_write_byte(SPI_p_loc, 0x001E, 0x19, 0x00); //6 W5500_write_byte(SPI_p_loc, 0x001E, 0x1D, 0x00); //7 // Socket Write buffer size W5500_write_byte(SPI_p_loc, 0x001F, 0x01, 0x04); //0 macraw W5500_write_byte(SPI_p_loc, 0x001F, 0x05, 0x02); //1 telnet W5500_write_byte(SPI_p_loc, 0x001F, 0x09, 0x04); //2 RTP W5500_write_byte(SPI_p_loc, 0x001F, 0x0D, 0x02); //3 DHCP W5500_write_byte(SPI_p_loc, 0x001F, 0x11, 0x02); //4 UDP_FDD W5500_write_byte(SPI_p_loc, 0x001F, 0x15, 0x00); //5 W5500_write_byte(SPI_p_loc, 0x001F, 0x19, 0x00); //6 W5500_write_byte(SPI_p_loc, 0x001F, 0x1D, 0x00); //7 // Socket 0 MAC RAW for packet switching W5500_write_byte(SPI_p_loc, 0x0000, 0x01, 0x34); //config B4 for classic W5500_write_byte(SPI_p_loc, 0x002C, 0x01, 0x04); //Interrupt mask : RECV wait_ms(10); W5500_write_byte(SPI_p_loc, 0x0001, 0x01, 0x01); //open // Socket 1 telnet W5500_write_byte(SPI_p_loc, 0x0000, 0x05, 0x01); //config wait_ms(10); data[0]=0x00; //port 0d23 data[1]=0x17; W5500_write_short(SPI_p_loc, 0x0004, 0x05, data, 2); //port 23 (0x17) //W5500_write_byte(SPI_p_loc, 0x002C, 0x05, 0x00); //interrupt mask // Socket 2 RTP port 1519 W5500_write_byte(SPI_p_loc, 0x0000, 0x09, 0x42); //config wait_ms(10); data[0]=0x05; //port 0d1519 data[1]=0xEF; W5500_write_short(SPI_p_loc, 0x0004, 0x09, data, 2); //port rx 1519 data[0]=0x05; //port 0d1516 data[1]=0xEC; W5500_write_short(SPI_p_loc, 0x0010, 0x09, data, 2); //port tx 1516 W5500_write_byte(SPI_p_loc, 0x0001, 0x09, 0x01); // open data[0]=10; data[1]=151; data[2]=0; data[3]=60; W5500_write_short(SPI_p_loc, 0x000C, 0x09, data, 4); //IP destination 10.151.0.21 // Socket 3 DHCP server W5500_write_byte(SPI_p_loc, 0x0000, 0x0D, 0x02); //config wait_ms(10); data[0]=0x00; //port 0d67 data[1]=0x43; W5500_write_short(SPI_p_loc, 0x0004, 0x0D, data, 2); //port rx 67 data[0]=0x00; //port 0d68 data[1]=0x44; W5500_write_short(SPI_p_loc, 0x0010, 0x0D, data, 2); //port tx 68 W5500_write_byte(SPI_p_loc, 0x0001, 0x0D, 0x01); // open data[0]=255; data[1]=255; data[2]=255; data[3]=255; data[4]=255; data[5]=255; W5500_write_short(SPI_p_loc, 0x000C, 0x0D, data, 4); //IP destination 255.255.255.255 W5500_write_short(SPI_p_loc, 0x0006, 0x0D, data, 6); // Socket 4 UDP_FDD W5500_write_byte(SPI_p_loc, 0x0000, 0x11, 0x42); //config wait_ms(10); data[0]=0x1A; //port TX 0d6716 = 0x1A3E data[1]=0x3E; W5500_write_short(SPI_p_loc, 0x0004, 0x11, data, 2); data[0]=0x1A; //port RX 0d6718 = 0x1A3C data[1]=0x3C; W5500_write_short(SPI_p_loc, 0x0010, 0x11, data, 2); W5500_write_byte(SPI_p_loc, 0x0001, 0x11, 0x01); // open IP_int2char (CONF_master_down_IP, data); W5500_write_short(SPI_p_loc, 0x000C, 0x11, data, 4); // Socket 5 // Socket 6 // Socket 7 W5500_configured = 1; }