NPR70/NPR_14/source/W5500.cpp
Vlastimil Slinták 16140fd383 Initial commit with the original FW
This FW for the New Packet Radio project was taken from the Hackaday
project https://hackaday.io/project/164092-npr-new-packet-radio

The source code is original without any modifications, ver. 2020_06_29.
2025-03-11 23:20:01 +01:00

425 lines
No EOL
16 KiB
C++

// 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 <http://www.gnu.org/licenses/>
#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;
}