/* Ethernet shield test program Copyright (C) 2018 Andreas Mieke Copyright (C) 2010 Arduino LLC This program 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. This program 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 this program. If not, see . */ #include "w5100.h" uint16_t ETH_SBASE[ETH_SOCKETS]; // Tx buffer base address uint16_t ETH_RBASE[ETH_SOCKETS]; // Rx buffer base address #define TX_RX_MAX_BUF_SIZE 2048 #define TX_BUF 0x1100 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) #define ETH_TXBUF_BASE 0x4000 #define ETH_RXBUF_BASE 0x6000 void SPI_SetSS(void) { GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET); } void SPI_ResetSS(void) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET); GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET); } uint8_t SPI_WriteRead(uint8_t write) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI1->DR = write; while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); return SPI1->DR; } void ETH_init(void) { // Port init stuff // PA5 -> SCK // PA6 -> MISO // PA7 -> MOSI // PC8 -> /SS // Set RCC Registers for GPIOA/C RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // Init gpio structure to default values GPIO_InitTypeDef gpio; GPIO_StructInit(&gpio); // Set PA5 to alternate function PushPull gpio.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Pin = GPIO_Pin_5; GPIO_Init(GPIOA, &gpio); // Set PA7 to alternate function push pull gpio.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &gpio); // Set PC8 to push pull gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOC, &gpio); GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET); // Set PA6 to input floating gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; gpio.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOA, &gpio); // Init SPI engine // Init struct to default values SPI_InitTypeDef spi; SPI_StructInit(&spi); // We are master spi.SPI_Mode = SPI_Mode_Master; spi.SPI_NSS = SPI_NSS_Soft; //spi.SPI_CPHA = SPI_CPHA_2Edge; spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // Write the registers SPI_Init(SPI1, &spi); // Enable SPI1 SPI_Cmd(SPI1, ENABLE); for(uint16_t i = 0; i < 65535; i++); ETH_writeMR(ETH_MR_RST); ETH_writeRMSR(0x55); ETH_writeTMSR(0x55); for (int i=0; i> 8); SPI_WriteRead(addr & 0xFF); SPI_WriteRead(data); SPI_ResetSS(); return 8; } uint16_t ETH_write_n(uint16_t addr, const uint8_t *buf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { SPI_SetSS(); SPI_WriteRead(0xF0); SPI_WriteRead(addr >> 8); SPI_WriteRead(addr & 0xFF); addr++; SPI_WriteRead(buf[i]); SPI_ResetSS(); } return len; } uint8_t ETH_read_8(uint16_t addr) { uint8_t data; SPI_SetSS(); SPI_WriteRead(0x0F); SPI_WriteRead(addr >> 8); SPI_WriteRead(addr & 0xFF); data = SPI_WriteRead(0x00); SPI_ResetSS(); return data; } uint16_t ETH_read_n(uint16_t addr, uint8_t *buf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { SPI_SetSS(); SPI_WriteRead(0x0F); SPI_WriteRead(addr >> 8); SPI_WriteRead(addr & 0xFF); addr++; buf[i] = SPI_WriteRead(0x00); SPI_ResetSS(); } return len; } uint16_t ETH_get_TX_free_size(SOCKET s) { uint16_t val=0, val1=0; do { val1 = ETH_readSnTX_FSR(s); if (val1 != 0) val = ETH_readSnTX_FSR(s); } while (val != val1); return val; } uint16_t ETH_get_RX_received_size(SOCKET s) { uint16_t val=0,val1=0; do { val1 = ETH_readSnRX_RSR(s); if (val1 != 0) val = ETH_readSnRX_RSR(s); } while (val != val1); return val; } void ETH_read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len) { uint16_t size; uint16_t src_mask; uint16_t src_ptr; src_mask = src & ETH_RMASK; src_ptr = ETH_RBASE[s] + src_mask; if( (src_mask + len) > ETH_RSIZE ) { size = ETH_RSIZE - src_mask; ETH_read_n(src_ptr, (uint8_t *)dst, size); dst += size; ETH_read_n(ETH_RBASE[s], (uint8_t *) dst, len - size); } else ETH_read_n(src_ptr, (uint8_t *) dst, len); } void ETH_send_data_processing(SOCKET s, const uint8_t *data, uint16_t len) { ETH_send_data_processing_offset(s, 0, data, len); } void ETH_send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len) { uint16_t ptr = ETH_readSnTX_WR(s); ptr += data_offset; uint16_t offset = ptr & ETH_SMASK; uint16_t dstAddr = offset + ETH_SBASE[s]; if (offset + len > ETH_SSIZE) { uint16_t size = ETH_SSIZE - offset; ETH_write_n(dstAddr, data, size); ETH_write_n(ETH_SBASE[s], data + size, len - size); } else { ETH_write_n(dstAddr, data, len); } ptr += len; ETH_writeSnTX_WR(s, ptr); } void ETH_recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) { uint16_t ptr; ptr = ETH_readSnRX_RD(s); ETH_read_data(s, ptr, data, len); if (!peek) { ptr += len; ETH_writeSnRX_RD(s, ptr); } } void ETH_exec_socket_cmd(SOCKET s, uint8_t cmd) { ETH_writeSnCR(s, cmd); while(ETH_readSnCR(s)) { // Wait for command to be executed } }