diff --git a/ARM/syscalls.c b/ARM/syscalls.c new file mode 100644 index 0000000..475caad --- /dev/null +++ b/ARM/syscalls.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2020-2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +/*int _stat(char *file, struct stat *st) +{ + (void)file; + //st->st_mode = S_IFCHR; + return 0; +}*/ + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/HAL/FLASH/eeprom.c b/HAL/FLASH/eeprom.c index 7ef6b95..9f66c70 100644 --- a/HAL/FLASH/eeprom.c +++ b/HAL/FLASH/eeprom.c @@ -31,15 +31,15 @@ uint8_t EE_ReadByteArray(uint8_t *DataOut, uint16_t VirtAddress, uint16_t size) *(DataOut++) = data; } - data = EE_ReadByte(VirtAddress); - if(data == checksum) { - return 1; - } + /*data = EE_ReadByte(VirtAddress); + if(data != checksum) { + return 0; + }*/ - return 0; + return 1; } -void EE_WriteByteArray(uint16_t VirtAddress, uint8_t *DataIn, uint16_t size) +void EE_WriteByteArray(uint16_t VirtAddress, const uint8_t *DataIn, uint16_t size) { unsigned char checksum = 0; @@ -49,7 +49,7 @@ void EE_WriteByteArray(uint16_t VirtAddress, uint8_t *DataIn, uint16_t size) EE_WriteByte(VirtAddress++, *(DataIn++)); } - EE_WriteByte(VirtAddress, checksum); + //EE_WriteByte(VirtAddress, checksum); } void EE_Program(void) diff --git a/HAL/FLASH/eeprom.h b/HAL/FLASH/eeprom.h index 5b29dc8..75187d0 100644 --- a/HAL/FLASH/eeprom.h +++ b/HAL/FLASH/eeprom.h @@ -23,8 +23,8 @@ #include "stm32f4xx.h" -#ifdef USE_EXT_EEPROM - #define EEPROM_SIZE 1 +#if (USE_EXT_EEPROM) + #define EEPROM_SIZE 1 #else #define EEPROM_SIZE 1024 #endif @@ -44,7 +44,7 @@ uint8_t EE_ReadByte(uint16_t VirtAddress); void EE_WriteByte(uint16_t VirtAddress, uint8_t Data); uint8_t EE_ReadByteArray(uint8_t *DataOut, uint16_t VirtAddress, uint16_t size); -void EE_WriteByteArray(uint16_t VirtAddress, uint8_t *DataIn, uint16_t size); +void EE_WriteByteArray(uint16_t VirtAddress, const uint8_t *DataIn, uint16_t size); void EE_Program(void); void EE_Erase(void); diff --git a/HAL/GPIO/GPIO.c b/HAL/GPIO/GPIO.c index 507f1dc..15dab4b 100644 --- a/HAL/GPIO/GPIO.c +++ b/HAL/GPIO/GPIO.c @@ -11,8 +11,8 @@ * D11: SPINDLE_PWM: PA7 * D12: Z_LIMIT_BIT: PA6 * D13: SPINDLE_DIRECTION_BIT: PA5 - * D14: SPINDLE_ENABLE_BIT: PB7 - * D15: SAFETY_DOOR_ENABLE_BIT: PC2 + * ???: SPINDLE_ENABLE_BIT: PB13 + * ???: SAFETY_DOOR_ENABLE_BIT: PC2 * * A0: CONTROL_RESET_BIT: PA0 * A1: CONTROL_FEED_HOLD_BIT: PA1 @@ -23,6 +23,8 @@ */ #include "GPIO.h" #include "Platform.h" +#include "Config.h" +#include "defaults.h" static void GPIO_InitStepper(void); @@ -112,14 +114,12 @@ static void GPIO_InitSpindle(void) GPIO_Init(GPIOA, &GPIO_InitStructure); /* GPIO Configuration: */ -#if !defined(LATHE_MODE) - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); -#endif /* GPIO Configuration: PWM */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; @@ -140,12 +140,13 @@ static void GPIO_InitLimit(void) GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - /* GPIO Configuration: */ -#if !defined(LATHE_MODE) - // Y1 - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; - GPIO_Init(GPIOB, &GPIO_InitStructure); -#endif + /* GPIO Configuration: */ + if (DEFAULT_LATHE_MODE) + { + // Y1 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; + GPIO_Init(GPIOB, &GPIO_InitStructure); + } // X1 X2 Y2 Z2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_5 | GPIO_Pin_6; @@ -176,7 +177,7 @@ static void GPIO_InitSystem(void) { GPIO_InitTypeDef GPIO_InitStructure; -#ifdef ETH_IF +#if (USE_ETH_IF) // W5500 Reset Pin GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; diff --git a/HAL/GPIO/GPIO.h b/HAL/GPIO/GPIO.h index 78c1d82..51a7cc9 100644 --- a/HAL/GPIO/GPIO.h +++ b/HAL/GPIO/GPIO.h @@ -64,7 +64,7 @@ #define GPIO_SPINDLE_DIR_PORT GPIOA #define GPIO_SPINDLE_DIR_PIN GPIO_Pin_5 #define GPIO_SPINDLE_ENA_PORT GPIOB -#define GPIO_SPINDLE_ENA_PIN GPIO_Pin_7 +#define GPIO_SPINDLE_ENA_PIN GPIO_Pin_13 // Safety door #define GPIO_DOOR_PORT GPIOC diff --git a/HAL/SPI/SPI.c b/HAL/SPI/SPI.c index b506fb4..9871c0b 100644 --- a/HAL/SPI/SPI.c +++ b/HAL/SPI/SPI.c @@ -172,7 +172,10 @@ uint8_t Spi_WriteByte(SPI_TypeDef *SPIx, uint8_t _data) // Loop while DR register is not empty while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); - // Send byte through the SPIx peripheral + // Clear rx register + SPI_I2S_ReceiveData(SPIx); + + // Send byte through the SPIx peripheral SPI_I2S_SendData(SPIx, _data); while((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET) && timeout--); @@ -182,17 +185,20 @@ uint8_t Spi_WriteByte(SPI_TypeDef *SPIx, uint8_t _data) } -void Spi_ReadByteArray(SPI_TypeDef *SPIx, uint8_t *_buffer, uint8_t _len) +void Spi_ReadByteArray(SPI_TypeDef *SPIx, uint8_t *_buffer, uint16_t _len) { - uint8_t i = 0; - uint16_t timeout = 0xFFF; + uint16_t i = 0; + uint16_t timeout = 0xFFF; + + // Clear rx register + SPI_I2S_ReceiveData(SPIx); - for(i = 0; i < _len; ++i) + for(i = 0; i < _len; ++i) { // Loop while DR register is not empty while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); - // Send byte through the SPIx peripheral + // Send byte through the SPIx peripheral SPI_I2S_SendData(SPIx, 0xFF); while((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET) && timeout--); @@ -201,11 +207,11 @@ void Spi_ReadByteArray(SPI_TypeDef *SPIx, uint8_t *_buffer, uint8_t _len) } } -void Spi_WriteDataArray(SPI_TypeDef *SPIx, uint8_t *_data, uint8_t _len) +void Spi_WriteDataArray(SPI_TypeDef *SPIx, uint8_t *_data, uint16_t _len) { - uint8_t i = 0; + uint16_t i = 0; - for(i = 0; i < _len; ++i) + for(i = 0; i < _len; ++i) { // Loop while DR register is not empty while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); @@ -213,6 +219,10 @@ void Spi_WriteDataArray(SPI_TypeDef *SPIx, uint8_t *_data, uint8_t _len) // Send byte through the SPIx peripheral SPI_I2S_SendData(SPIx, _data[i]); } + while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); + + // Clear rx register + SPI_I2S_ReceiveData(SPIx); } diff --git a/HAL/SPI/SPI.h b/HAL/SPI/SPI.h index 10a382c..df9ab9c 100644 --- a/HAL/SPI/SPI.h +++ b/HAL/SPI/SPI.h @@ -49,8 +49,8 @@ void Spi_Init(SPI_TypeDef *SPIx, SPI_Mode mode); uint8_t Spi_ReadByte(SPI_TypeDef *SPIx); uint8_t Spi_WriteByte(SPI_TypeDef *SPIx, uint8_t _data); -void Spi_ReadByteArray(SPI_TypeDef *SPIx, uint8_t *_buffer, uint8_t _len); -void Spi_WriteDataArray(SPI_TypeDef *SPIx, uint8_t *_data, uint8_t _len); +void Spi_ReadByteArray(SPI_TypeDef *SPIx, uint8_t *_buffer, uint16_t _len); +void Spi_WriteDataArray(SPI_TypeDef *SPIx, uint8_t *_data, uint16_t _len); void Spi_SetPrescaler(SPI_TypeDef *SPIx, uint16_t prescaler); void Spi_ChipSelect(SPI_TypeDef *SPIx, bool select); diff --git a/HAL/STM32/stm32f4xx_it.c b/HAL/STM32/stm32f4xx_it.c index 6e1b912..1044908 100644 --- a/HAL/STM32/stm32f4xx_it.c +++ b/HAL/STM32/stm32f4xx_it.c @@ -66,9 +66,9 @@ extern void System_PinChangeISR(void); static volatile uint32_t gMillis = 0; uint32_t spindle_rpm = 0; -uint16_t tim4_cnt_prev = 0; -uint32_t rpm_arr[RPM_FILTER_NUM] = {0}; -uint8_t rpm_idx = 0; +static uint16_t tim4_cnt_prev = 0; +static uint32_t rpm_arr[RPM_FILTER_NUM] = {0}; +static uint8_t rpm_idx = 0; /******************************************************************************/ @@ -120,9 +120,12 @@ void ProcessReceive(char c) case CMD_SPINDLE_OVR_FINE_MINUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_FINE_MINUS); break; case CMD_SPINDLE_OVR_STOP: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_STOP); break; case CMD_COOLANT_FLOOD_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; -#ifdef ENABLE_M7 - case CMD_COOLANT_MIST_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; -#endif + case CMD_COOLANT_MIST_OVR_TOGGLE: + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) + { + System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_MIST_OVR_TOGGLE); + } + break; } // Throw away any unfound extended-ASCII character by not passing it to the serial buffer. } @@ -299,7 +302,7 @@ void SysTick_Handler(void) } // Calculate RPM and smooth it - float rpm = ((cnt_diff * 31.25) / PULSES_PER_REV) * 60.0; + float rpm = ((cnt_diff * 31.25) / settings.enc_ppr) * 60.0; rpm_arr[rpm_idx++] = (uint32_t)rpm; if(rpm_idx > (RPM_FILTER_NUM-1)) { diff --git a/HAL/System32.c b/HAL/System32.c index e36d704..c666223 100644 --- a/HAL/System32.c +++ b/HAL/System32.c @@ -31,7 +31,7 @@ void SysTick_Init(void) // for 100 MHz STM32F411 -#define COUNTS_PER_MICROSECOND 33 +#define COUNTS_PER_MICROSECOND 50 void Delay_us(volatile uint32_t us) { volatile uint32_t count = us * COUNTS_PER_MICROSECOND - 2; diff --git a/Libraries/EEPROM/M24C0X.c b/Libraries/EEPROM/M24C0X.c index 78cbaae..b7eda32 100644 --- a/Libraries/EEPROM/M24C0X.c +++ b/Libraries/EEPROM/M24C0X.c @@ -141,11 +141,11 @@ uint8_t M24C0X_WriteByteArray(uint16_t addr, uint8_t *pData, uint16_t len) // If eeprom is busy (write takes up to 5ms), try again until success or timeout while((ret = I2C_WriteByteArray(M24C0X_I2C, slave_adr, addr, &pData[bytesWritten], bytes2write)) && (timeout < 4)) { - Delay_ms(2); + Delay_ms(1); timeout++; } - if(timeout >= 4) + if(timeout >= 7) { // Failed to write return 1; diff --git a/Libraries/Encoder/Encoder.c b/Libraries/Encoder/Encoder.c index 4741578..5fac3cb 100644 --- a/Libraries/Encoder/Encoder.c +++ b/Libraries/Encoder/Encoder.c @@ -22,20 +22,17 @@ #include "TIM.h" -#ifndef PULSES_PER_REV - #define PULSES_PER_REV 360 - #pragma message("Using 360 pulses/rev for encoder") -#endif - - static uint32_t OvfCnt = 0; static uint32_t CntValue = 0; +static uint16_t PulsesPerRev = 360; -void Encoder_Init(void) + +void Encoder_Init(uint16_t ppr) { - TIM4_Init(PULSES_PER_REV); + TIM4_Init(ppr); Encoder_Reset(); + PulsesPerRev = ppr; } @@ -46,6 +43,12 @@ void Encoder_Reset(void) } +void Encoder_SetPulsesPerRev(uint16_t ppr) +{ + Encoder_Init(ppr); +} + + uint32_t Encoder_GetValue(void) { return CntValue + TIM4_CNT(); @@ -61,5 +64,5 @@ void Encoder_SetValue(uint32_t val) void Encoder_OvfISR(void) { OvfCnt++; - CntValue += PULSES_PER_REV; + CntValue += PulsesPerRev; } diff --git a/Libraries/Encoder/Encoder.h b/Libraries/Encoder/Encoder.h index 51ffa46..02705b9 100644 --- a/Libraries/Encoder/Encoder.h +++ b/Libraries/Encoder/Encoder.h @@ -10,9 +10,11 @@ extern "C" { #endif -void Encoder_Init(void); +void Encoder_Init(uint16_t ppr); void Encoder_Reset(void); +void Encoder_SetPulsesPerRev(uint16_t ppr); + uint32_t Encoder_GetValue(void); void Encoder_SetValue(uint32_t val); diff --git a/Libraries/Ethernet/Ethernet.c b/Libraries/Ethernet/Ethernet.c deleted file mode 100644 index 5791c34..0000000 --- a/Libraries/Ethernet/Ethernet.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) -*/ -#include "Ethernet.h" -#include "W5500.h" - - -IPAddress_t _dnsServerAddress = {{0, 0, 0, 0}}; - - -void Ethernet_Init(uint8_t *mac, IPAddress_t *local_ip, IPAddress_t *dns_server, IPAddress_t *gateway, IPAddress_t *subnet) -{ - W5500_Init(); - W5500_SetMACAddress(mac); - W5500_SetIPAddress(local_ip->IP); - W5500_SetGatewayIp(gateway->IP); - W5500_SetSubnetMask(subnet->IP); - - _dnsServerAddress = *dns_server; -} - - -IPAddress_t Ethernet_LocalIP(void) -{ - IPAddress_t ret; - - W5500_GetIPAddress(ret.IP); - - return ret; -} - - -IPAddress_t Ethernet_SubnetMask(void) -{ - IPAddress_t ret; - - W5500_GetSubnetMask(ret.IP); - - return ret; -} - - -IPAddress_t Ethernet_GatewayIP(void) -{ - IPAddress_t ret; - - W5500_GetGatewayIp(ret.IP); - - return ret; -} - - -IPAddress_t Ethernet_DnsServerIP(void) -{ - return _dnsServerAddress; -} - - -uint8_t Ethernet_LinkStatus(void) -{ - return (W5500_GetPHYCFGR() & 0x01); -} diff --git a/Libraries/Ethernet/Ethernet.h b/Libraries/Ethernet/Ethernet.h deleted file mode 100644 index 394bae7..0000000 --- a/Libraries/Ethernet/Ethernet.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) -*/ -#ifndef ETHERNET_H_INLUDED -#define ETHERNET_H_INLUDED - - -#include -#include "util2.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -void Ethernet_Init(uint8_t *mac_address, IPAddress_t *local_ip, IPAddress_t *dns_server, IPAddress_t *gateway, IPAddress_t *subnet); - -IPAddress_t Ethernet_LocalIP(void); -IPAddress_t Ethernet_SubnetMask(void); -IPAddress_t Ethernet_GatewayIP(void); -IPAddress_t Ethernet_DnsServerIP(void); - -uint8_t Ethernet_LinkStatus(void); - - -#ifdef __cplusplus -} -#endif - - -#endif // ETHERNET_H_INLUDED diff --git a/Libraries/Ethernet/ServerTCP.c b/Libraries/Ethernet/ServerTCP.c index 32a7099..e0d7132 100644 --- a/Libraries/Ethernet/ServerTCP.c +++ b/Libraries/Ethernet/ServerTCP.c @@ -5,32 +5,94 @@ * Author: PatrickVM */ #include "ServerTCP.h" -#include "W5500.h" +#include "wizchip_conf.h" +#include "SPI.h" #include "socket.h" #include "System32.h" +#include "Platform.h" +#include "Print.h" + + +// Debug output +//#define _LOOPBACK_DEBUG_ + +#define ETH_MAX_BUF_SIZE 32 + + +static int32_t loopback_tcp_server(uint8_t sn, uint8_t *buf, uint16_t port); +static void PrintNetworkInfo(void); static uint8_t mSock = 0; static uint16_t mPort = 0; -uint8_t ServerTCP_Init(uint8_t sock, uint16_t port) + +static uint8_t wiznet_memsize[2][8] = {{4, 2, 2, 2, 2, 2, 1, 1}, {4, 2, 2, 2, 2, 2, 1, 1}}; + +static uint8_t ethBuf0[ETH_MAX_BUF_SIZE]; +static wiz_NetInfo gWIZNETINFO = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x22, 0x33}, + .ip = {192, 168, 1, 20}, + .sn = {255, 255, 255, 0}, + .gw = {192, 168, 1, 1}, + .dns = {8, 8, 8, 8}, + .dhcp = NETINFO_STATIC}; + + +bool ServerTCP_Init(uint8_t sock, uint16_t port) { mSock = sock; mPort = port; - // Check if socket is available - if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) == SnSR_CLOSED) - { - // Set socket to TCP listen mode - socket(sock, SnMR_TCP, port, 0); - listen(sock); + Spi_Init(SPI_W5500, SPI_MODE0); - // OK - return 0; - } + // Set clock to 21 Mhz (W5500 should support up to about 80 Mhz) + Spi_SetPrescaler(SPI_W5500, SPI_PRESCALER_2); + + // Hard reset + GPIO_ResetBits(GPIOA, GPIO_Pin_15); + Delay_ms(40); + GPIO_SetBits(GPIOA, GPIO_Pin_15); + Delay_ms(40); + + //wizchip_sw_reset(); + reg_wizchip_spi_cbfunc(0, 0); + reg_wizchip_spiburst_cbfunc(0, 0); + reg_wizchip_cs_cbfunc(0, 0); + + if (ctlwizchip(CW_INIT_WIZCHIP, (void*)wiznet_memsize) == -1) + { +#ifdef _LOOPBACK_DEBUG_ + Printf("WIZchip memory initialization failed\r\n"); + Printf_Flush(); +#endif + return false; + } + + ctlnetwork(CN_SET_NETINFO, (void *)&gWIZNETINFO); - // Socket occupied - return 1; + // Uncomment if phy cant establish a link + //wiz_PhyConf conf = {PHY_CONFBY_SW, PHY_MODE_MANUAL, PHY_SPEED_10, PHY_DUPLEX_FULL}; + //wizphy_setphyconf(&conf); + + /*uint8_t tmp; + do + { + if (ctlwizchip(CW_GET_PHYLINK, (void *)&tmp) == -1) + { +#ifdef _LOOPBACK_DEBUG_ + Printf("Unknown PHY Link status.\r\n"); + Printf_Flush(); +#endif + return false; + } + } while (tmp == PHY_LINK_OFF);*/ + +#ifdef _LOOPBACK_DEBUG_ + Printf("version:%.2X\r\n", getVERSIONR()); + Printf_Flush(); +#endif + + return true; } @@ -42,68 +104,231 @@ void ServerTCP_DeInit(uint8_t sock) Delay_ms(5); // Check if socket is released - if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) != SnSR_CLOSED) - { + if (getSn_SR(sock) != SOCK_CLOSED) + { // Force release close(sock); } } -uint8_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len) +int32_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len) { - // Check if socket available - if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) == SnSR_ESTABLISHED) - { - // Send data - if(send(sock, data, len) <= 0) - { - return 1; - } - - // OK - return 0; - } + int32_t ret = send(sock, data, len); + + if (ret < 0) + { +#if defined(_LOOPBACK_DEBUG_) + Printf("%d: send() error: %ld\r\n", sock, ret); + Printf_Flush(); +#endif + close(sock); + } - return 2; + return ret; } int32_t ServerTCP_Receive(uint8_t sock, uint8_t *data, uint16_t len) { - // Check if data is available - if(W5500_GetRXReceivedSize(sock)) - { - // Read data - return recv(sock, data, len); - } + int32_t ret = 0; + uint16_t size = ServerTCP_DataAvailable(sock); + + if (size) + { + ret = recv(sock, data, len); + + if (ret != size) + { + if (ret == SOCK_BUSY) + { + return 0; + } + if (ret < 0) + { +#if defined(_LOOPBACK_DEBUG_) + Printf("%d: recv() error: %ld\r\n", sock, ret); + Printf_Flush(); +#endif + close(sock); + } + } + return ret; + } // No data available - return -1; + return 0; } uint16_t ServerTCP_DataAvailable(uint8_t sock) { - return W5500_GetRXReceivedSize(sock); + return getSn_RX_RSR(sock); } void ServerTCP_Update(void) { - // If socket is closed, reinitalize it. - uint8_t ret = 0; + loopback_tcp_server(mSock, ethBuf0, mPort); +} - ret = W5500_READ_SOCK_REG8(mSock, REG8_SnSR); - if(ret == SnSR_CLOSE_WAIT) - { - ServerTCP_DeInit(mSock); - ServerTCP_Init(mSock, mPort); - } +static int32_t loopback_tcp_server(uint8_t sn, uint8_t *buf, uint16_t port) +{ + int32_t ret; + uint8_t tmp; + + (void)buf; + +#ifdef _LOOPBACK_DEBUG_ + uint8_t destip[4]; + uint16_t destport; +#endif - if(ret == SnSR_CLOSED) + if (ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1) { - ServerTCP_Init(mSock, mPort); + // Error + return -1; + } + else + { + if (tmp == PHY_LINK_OFF) + { + // No active link + return 0; + } + } + + switch (getSn_SR(sn)) + { + case SOCK_ESTABLISHED: + if (getSn_IR(sn) & Sn_IR_CON) + { +#ifdef _LOOPBACK_DEBUG_ + getSn_DIPR(sn, destip); + destport = getSn_DPORT(sn); + + Printf("%d:Connected - %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport); +#endif + setSn_IR(sn, Sn_IR_CON); + } + + // Don't need to check SOCKERR_BUSY because it doesn't not occur. + /*uint16_t size = 0; + uint16_t sentsize = 0; + + if ((size = getSn_RX_RSR(sn)) > 0) + { + if (size > DATA_BUF_SIZE) + { + size = DATA_BUF_SIZE; + } + ret = recv(sn, buf, size); + + if (ret <= 0) + { + // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY. + return ret; + } + size = (uint16_t)ret; + sentsize = 0; + + while (size != sentsize) + { + ret = send(sn, buf + sentsize, size - sentsize); + if (ret < 0) + { + close(sn); + return ret; + } + // Don't care SOCKERR_BUSY, because it is zero. + sentsize += ret; + } + }*/ + break; + + case SOCK_CLOSE_WAIT: +#ifdef _LOOPBACK_DEBUG_ + Printf("%d:CloseWait\r\n", sn); + Printf_Flush(); +#endif + if ((ret = disconnect(sn)) != SOCK_OK) + { + return ret; + } +#ifdef _LOOPBACK_DEBUG_ + Printf("%d:Socket Closed\r\n", sn); +#endif + break; + + case SOCK_INIT: +#ifdef _LOOPBACK_DEBUG_ + Printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port); + Printf_Flush(); +#endif + if ((ret = listen(sn)) != SOCK_OK) + { + return ret; + } + break; + + case SOCK_CLOSED: +#ifdef _LOOPBACK_DEBUG_ + Printf("%d:TCP server loopback start\r\n", sn); +#endif + if ((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) + { + return ret; + } +#ifdef _LOOPBACK_DEBUG_ + Printf("%d:Socket opened\r\n", sn); +#endif + break; + + default: + break; } + +#ifdef _LOOPBACK_DEBUG_ + Printf_Flush(); +#endif + + return 1; +} + + +__attribute__((unused)) +static void PrintNetworkInfo(void) +{ + wiz_NetInfo defaultNetInfo; + + wizchip_getnetinfo(&defaultNetInfo); + Printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n\r", + defaultNetInfo.mac[0], + defaultNetInfo.mac[1], + defaultNetInfo.mac[2], + defaultNetInfo.mac[3], + defaultNetInfo.mac[4], + defaultNetInfo.mac[5]); + Printf("IP address : %d.%d.%d.%d\n\r", + defaultNetInfo.ip[0], + defaultNetInfo.ip[1], + defaultNetInfo.ip[2], + defaultNetInfo.ip[3]); + Printf("SM Mask : %d.%d.%d.%d\n\r", + defaultNetInfo.sn[0], + defaultNetInfo.sn[1], + defaultNetInfo.sn[2], + defaultNetInfo.sn[3]); + Printf("Gate way : %d.%d.%d.%d\n\r", + defaultNetInfo.gw[0], + defaultNetInfo.gw[1], + defaultNetInfo.gw[2], + defaultNetInfo.gw[3]); + Printf("DNS Server : %d.%d.%d.%d\n\r", + defaultNetInfo.dns[0], + defaultNetInfo.dns[1], + defaultNetInfo.dns[2], + defaultNetInfo.dns[3]); + Printf_Flush(); } diff --git a/Libraries/Ethernet/ServerTCP.h b/Libraries/Ethernet/ServerTCP.h index 12c6f40..5118c55 100644 --- a/Libraries/Ethernet/ServerTCP.h +++ b/Libraries/Ethernet/ServerTCP.h @@ -9,12 +9,21 @@ #include +#include -uint8_t ServerTCP_Init(uint8_t sock, uint16_t port); +#define htons(x) ((uint16_t)(((x) << 8) | (((x) >> 8) & 0xFF))) +#define ntohs(x) htons(x) + +#define htonl(x) \ + (((x) << 24 & 0xFF000000UL) | ((x) << 8 & 0x00FF0000UL) | ((x) >> 8 & 0x0000FF00UL) | ((x) >> 24 & 0x000000FFUL)) +#define ntohl(x) htonl(x) + + +bool ServerTCP_Init(uint8_t sock, uint16_t port); void ServerTCP_DeInit(uint8_t sock); -uint8_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len); +int32_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len); int32_t ServerTCP_Receive(uint8_t sock, uint8_t *data, uint16_t len); uint16_t ServerTCP_DataAvailable(uint8_t sock); diff --git a/Libraries/Ethernet/Socket_APIs_V3.0.3.chm b/Libraries/Ethernet/Socket_APIs_V3.0.3.chm new file mode 100644 index 0000000..35ed512 Binary files /dev/null and b/Libraries/Ethernet/Socket_APIs_V3.0.3.chm differ diff --git a/Libraries/Ethernet/W5100/w5100.c b/Libraries/Ethernet/W5100/w5100.c new file mode 100644 index 0000000..ab3ebf8 --- /dev/null +++ b/Libraries/Ethernet/W5100/w5100.c @@ -0,0 +1,386 @@ +//***************************************************************************** +// +//! \file w5100.c +//! \brief W5100 HAL Interface. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include "w5100.h" + +#if (_WIZCHIP_ == 5100) +/** +@brief This function writes the data into W5100 registers. +*/ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) +{ + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte(0xF0); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data) +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + //WIZCHIP.IF.BUS._write_byte(AddrSel,wb); + WIZCHIP.IF.BUS._write_data(AddrSel,wb); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with ioLibrary + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + WIZCHIP.IF.BUS._write_data(IDM_DR,wb); +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} +/** +@brief This function reads the value from W5100 registers. +*/ +uint8_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint8_t ret; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte(0x0F); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + ret = WIZCHIP.IF.SPI._read_byte(); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + //ret = WIZCHIP.IF.BUS._read_byte(AddrSel); + ret = WIZCHIP.IF.BUS._read_data(AddrSel); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with ioLibrary + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + ret = WIZCHIP.IF.BUS._read_data(IDM_DR); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + + +/** +@brief This function writes into W5100 memory(Buffer) +*/ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint16_t i = 0; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); //M20150601 : Moved here. + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + for(i = 0; i < len; i++) + { + //M20160715 : Depricated "M20150601 : Remove _select() to top-side" + // CS should be controlled every SPI frames + WIZCHIP.CS._select(); + WIZCHIP.IF.SPI._write_byte(0xF0); + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data) + //M20160715 : Depricated "M20150601 : Remove _select() to top-side" + WIZCHIP.CS._deselect(); + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + for(i = 0; i < len; i++) + //M20150601 : Rename the function for integrating with ioLibrary + // WIZCHIP.IF.BUS._write_byte(AddrSel+i,pBuf[i]); + WIZCHIP.IF.BUS._write_data(AddrSel+i,pBuf[i]); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + /* + WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR()|MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]); + setMR(getMR() & ~MR_AI); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!" +#endif + + WIZCHIP.CS._deselect(); //M20150601 : Moved here. + WIZCHIP_CRITICAL_EXIT(); +} + +/** +@brief This function reads into W5100 memory(Buffer) +*/ + +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint16_t i = 0; + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); //M20150601 : Moved here. + + #if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + for(i = 0; i < len; i++) + { + //M20160715 : Depricated "M20150601 : Remove _select() to top-side" + // CS should be controlled every SPI frames + WIZCHIP.CS._select(); + WIZCHIP.IF.SPI._write_byte(0x0F); + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0); + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + //M20160715 : Depricated "M20150601 : Remove _select() to top-side" + WIZCHIP.CS._deselect(); + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + for(i = 0 ; i < len; i++) + //M20150601 : Rename the function for integrating with ioLibrary + // pBuf[i] = WIZCHIP.IF.BUS._read_byte(AddrSel+i); + pBuf[i] = WIZCHIP.IF.BUS._read_data(AddrSel+i); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + /* + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR() | MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR); + setMR(getMR() & ~MR_AI); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!" +#endif + + WIZCHIP.CS._deselect(); //M20150601 : Moved Here. + WIZCHIP_CRITICAL_EXIT(); +} + +/////////////////////////////////// +// Socket N regsiter IO function // +/////////////////////////////////// + +uint16_t getSn_TX_FSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_TX_FSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + } + }while (val != val1); + return val; +} + + +uint16_t getSn_RX_RSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_RX_RSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + } + }while (val != val1); + return val; +} + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +uint32_t getSn_RxBASE(uint8_t sn) +{ + int8_t i; +#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + uint32_t rxbase = _W5100_IO_BASE_ + _WIZCHIP_IO_RXBUF_; +#else + uint32_t rxbase = _WIZCHIP_IO_RXBUF_; +#endif + for(i = 0; i < sn; i++) + rxbase += getSn_RxMAX(i); + + return rxbase; +} + +uint32_t getSn_TxBASE(uint8_t sn) +{ + int8_t i; +#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + uint32_t txbase = _W5100_IO_BASE_ + _WIZCHIP_IO_TXBUF_; +#else + uint32_t txbase = _WIZCHIP_IO_TXBUF_; +#endif + for(i = 0; i < sn; i++) + txbase += getSn_TxMAX(i); + return txbase; +} + +/** +@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip. + +This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer +register. User should read upper byte first and lower byte later to get proper value. +And this function is being used for copy the data form application buffer to Transmite +buffer of the chip. It calculate the actual physical address where one has to write +the data in transmite buffer. Here also take care of the condition while it exceed +the Tx memory uper-bound of socket. + +*/ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr; + uint16_t size; + uint16_t dst_mask; + uint16_t dst_ptr; + + ptr = getSn_TX_WR(sn); + + dst_mask = ptr & getSn_TxMASK(sn); + dst_ptr = getSn_TxBASE(sn) + dst_mask; + + if (dst_mask + len > getSn_TxMAX(sn)) + { + size = getSn_TxMAX(sn) - dst_mask; + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size); + wizdata += size; + size = len - size; + dst_ptr = getSn_TxBASE(sn); + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size); + } + else + { + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len); + } + + ptr += len; + + setSn_TX_WR(sn, ptr); +} + + +/** +@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer. + +This function read the Rx read pointer register +and after copy the data from receive buffer update the Rx write pointer register. +User should read upper byte first and lower byte later to get proper value. +It calculate the actual physical address where one has to read +the data from Receive buffer. Here also take care of the condition while it exceed +the Rx memory uper-bound of socket. +*/ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr; + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + ptr = getSn_RX_RD(sn); + + src_mask = (uint32_t)ptr & getSn_RxMASK(sn); + src_ptr = (getSn_RxBASE(sn) + src_mask); + + + if( (src_mask + len) > getSn_RxMAX(sn) ) + { + size = getSn_RxMAX(sn) - src_mask; + WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size); + wizdata += size; + size = len - size; + src_ptr = getSn_RxBASE(sn); + WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size); + } + else + { + WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len); + } + + ptr += len; + + setSn_RX_RD(sn, ptr); +} + +void wiz_recv_ignore(uint8_t sn, uint16_t len) +{ + uint16_t ptr; + + ptr = getSn_RX_RD(sn); + + ptr += len; + setSn_RX_RD(sn,ptr); +} + +#endif diff --git a/Libraries/Ethernet/W5100/w5100.h b/Libraries/Ethernet/W5100/w5100.h new file mode 100644 index 0000000..3396955 --- /dev/null +++ b/Libraries/Ethernet/W5100/w5100.h @@ -0,0 +1,1865 @@ +//* **************************************************************************** +//! \file w5100.h +//! \brief W5100 HAL Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef _W5100_H_ +#define _W5100_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "wizchip_conf.h" + +/// \cond DOXY_APPLY_CODE +#if (_WIZCHIP_ == 5100) +/// \endcond + +#define _WIZCHIP_SN_BASE_ (0x0400) +#define _WIZCHIP_SN_SIZE_ (0x0100) +#define _WIZCHIP_IO_TXBUF_ (0x4000) /* Internal Tx buffer address of the iinchip */ +#define _WIZCHIP_IO_RXBUF_ (0x6000) /* Internal Rx buffer address of the iinchip */ + + +#define WIZCHIP_CREG_BLOCK 0x00 ///< Common register block +#define WIZCHIP_SREG_BLOCK(N) (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + N) ///< Increase offset address + +#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + #define _W5100_IO_BASE_ _WIZCHIP_IO_BASE_ +#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) + #define IDM_OR ((_WIZCHIP_IO_BASE + 0x0000)) + #define IDM_AR0 ((_WIZCHIP_IO_BASE_ + 0x0001)) + #define IDM_AR1 ((_WIZCHIP_IO_BASE_ + 0x0002)) + #define IDM_DR ((_WIZCHIP_IO_BASE_ + 0x0003)) + #define _W5100_IO_BASE_ 0x0000 +#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define _W5100_IO_BASE_ 0x0000 +#endif + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + + +//----------- defgroup -------------------------------- + +/** + * @defgroup W5100 W5100 + * @brief WHIZCHIP register defines and I/O functions of @b W5100. + * + * - @ref WIZCHIP_register_W5100 : @ref Common_register_group_W5100 and @ref Socket_register_group_W5100 + * - @ref WIZCHIP_IO_Functions_W5100 : @ref Basic_IO_function_W5100, @ref Common_register_access_function_W5100 and @ref Socket_register_group_W5100 + */ + + /** + * @defgroup WIZCHIP_register_W5100 WIZCHIP register + * @ingroup W5100 + * @brief WIZCHIP register defines register group of W5100 . + * + * - \ref Common_register_group_W5100 : Common register group W5100 + * - \ref Socket_register_group_W5100 : \c SOCKET n register group W5100 + */ + + +/** + * @defgroup WIZCHIP_IO_Functions_W5100 WIZCHIP I/O functions + * @ingroup W5100 + * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5100. + * + * - Basic I/O function \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n + * + * - \ref Common_register_group_W5100 access functions \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), + * -# Network Information \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC() + * + * - \ref Socket_register_group_W5100 access functions \n + * -# SOCKET control \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IR(), setSn_IR() + * -# SOCKET information \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# SOCKET communication \n + * getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR() + * -# IP header field \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + +/** + * @defgroup Common_register_group_W5100 Common register + * @ingroup WIZCHIP_register_W5100 + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa IR, Sn_IR, _IMR_ : Interrupt. + * @sa _RTR_, _RCR_ : Data retransmission. + * @sa PTIMER, PMAGIC : PPPoE. + */ + + + /** + * @defgroup Socket_register_group_W5100 Socket register + * @ingroup WIZCHIP_register_W5100 + * @brief Socket register group\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAG : Internet protocol. + * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + /** + * @defgroup Basic_IO_function_W5100 Basic I/O function + * @ingroup WIZCHIP_IO_Functions_W5100 + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function_W5100 Common register access functions + * @ingroup WIZCHIP_IO_Functions_W5100 + * @brief These are functions to access common registers. + */ + +/** + * @defgroup Socket_register_access_function_W5100 Socket register access functions + * @ingroup WIZCHIP_IO_Functions_W5100 + * @brief These are functions to access socket registers. + */ + + //----------------------------------------------------------------------------------- + +//----------------------------- W5100 Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group_W5100 + * @brief Mode Register address(R/W)\n + * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of \ref MR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved AI IND
+ * - \ref MR_RST : Reset + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_AI : Address Auto-Increment in Indirect Bus Interface + * - \ref MR_IND : Indirect Bus Interface mode + */ +#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_ + #define MR (_WIZCHIP_IO_BASE_ + (0x0000)) // Mode +#else + #define MR (_W5100_IO_BASE_ + (0x0000)) // Mode +#endif + +/** + * @ingroup Common_register_group_W5100 + * @brief Gateway IP Register address(R/W) + * @details \ref GAR configures the default gateway address. + */ +#define GAR (_W5100_IO_BASE_ + (0x0001)) // GW Address + +/** + * @ingroup Common_register_group_W5100 + * @brief Subnet mask Register address(R/W) + * @details \ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5100_IO_BASE_ + (0x0005)) // SN Mask Address + +/** + * @ingroup Common_register_group_W5100 + * @brief Source MAC Register address(R/W) + * @details \ref SHAR configures the source hardware address. + */ +#define SHAR (_W5100_IO_BASE_ + (0x0009)) // Source Hardware Address + +/** + * @ingroup Common_register_group_W5100 + * @brief Source IP Register address(R/W) + * @details \ref SIPR configures the source IP address. + */ +#define SIPR (_W5100_IO_BASE_ + (0x000F)) // Source IP Address + +// Reserved (_W5100_IO_BASE_ + (0x0013)) +// Reserved (_W5100_IO_BASE_ + (0x0014)) + +/** + * @ingroup Common_register_group_W5100 + * @brief Interrupt Register(R/W) + * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host. + * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of \ref IR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE Reserved S3_INT S2_INT S1_INT S0_INT
+ * - \ref IR_CONFLICT : IP conflict + * - \ref IR_UNREACH : Destination unreachable + * - \ref IR_PPPoE : PPPoE connection close + * - \ref IR_SOCK(3) : SOCKET 3 Interrupt + * - \ref IR_SOCK(2) : SOCKET 2 Interrupt + * - \ref IR_SOCK(1) : SOCKET 1 Interrupt + * - \ref IR_SOCK(0) : SOCKET 0 Interrupt + */ +#define IR (_W5100_IO_BASE_ + (0x0015)) // Interrupt + +/** + * @ingroup Common_register_group_W5100 + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR. + * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR is set, Interrupt will be issued. + */ +#define _IMR_ (_W5100_IO_BASE_ + (0x0016)) // Socket Interrupt Mask + +/** + * @ingroup Common_register_group_W5100 + * @brief Timeout register address( 1 is 100us )(R/W) + * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0or 000 + * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5100 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the \ref _RTR_ time, W5100 retransmits the packet or issues timeout. + */ +#define _RTR_ (_W5100_IO_BASE_ + (0x0017)) // Retry Time + +/** + * @ingroup Common_register_group_W5100 + * @brief Retry count register(R/W) + * @details \ref _RCR_ configures the number of time of retransmission. + * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1'). + */ +#define _RCR_ (_W5100_IO_BASE_ + (0x0019)) // Retry Count +#define RMSR (_W5100_IO_BASE_ + (0x001A)) // Receicve Memory Size +#define TMSR (_W5100_IO_BASE_ + (0x001B)) // Trnasmit Memory Size + + +/** + * @ingroup Common_register_group_W5100 + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PATR notifies authentication method that has been agreed at the connection with + * PPPoE Server. W5100 supports two types of Authentication method - PAP and CHAP. + */ +#define PATR (_W5100_IO_BASE_ + (0x001C)) + + +/** + * @ingroup Common_register_group_W5100 + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER (_W5100_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer + +/** + * @ingroup Common_register_group_W5100 + * @brief PPP LCP Magic number register in PPPoE mode(R) + * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC (_W5100_IO_BASE_ + (0x0029)) // PPP LCP Magic number + +#define UIPR0 (_W5100_IO_BASE_ + (0x002A)) +#define UPORT0 (_W5100_IO_BASE + (0x002E)) + + + +//----------------------------- W5100 Socket Registers ----------------------------- + +//--------------------------- For Backward Compatibility --------------------------- + +/** + * @ingroup Socket_register_group_W5100 + * @brief socket Mode register(R/W) + * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of \ref Sn_MR defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
MULTI MF ND/MC Reserved Protocol[3] Protocol[2] Protocol[1] Protocol[0]
+ * - \ref Sn_MR_MULTI : Support UDP Multicasting + * - \ref Sn_MR_MF : Support MACRAW + * - \ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - \ref Sn_MR_MC : IGMP version used in UDP mulitcasting + * - Protocol + * + * + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
+ * - In case of Socket 0 + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 1 0 0 MACRAW
0 1 0 1 PPPoE
+ * - \ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - \ref Sn_MR_UDP : UDP + * - \ref Sn_MR_TCP : TCP + * - \ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5100 accepts the command, the \ref Sn_CR register is automatically cleared to 0x00. + * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR. + * - \ref Sn_CR_OPEN : Initialize or open socket. + * - \ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) + * - \ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) + * - \ref Sn_CR_DISCON : Send closing request in TCP mode. + * - \ref Sn_CR_CLOSE : Close socket. + * - \ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - \ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - \ref Sn_CR_SEND_KEEP : Send keep alive message. + * - \ref Sn_CR_RECV : Update RX buffer pointer and receive data. + * - In case of S0_MR(P3:P0) = S0_MR_PPPoE + * + * + * + * + * + * + * + *
Value Symbol Description
0x23 PCON PPPoE connection begins by transmitting PPPoE discovery packet
0x24 PDISCON Closes PPPoE connection
0x25 PCR In each phase, it transmits REQ message.
0x26 PCN In each phase, it transmits NAK message.
0x27 PCJ In each phase, it transmits REJECT message.
+ */ +#define Sn_CR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Socket interrupt register(R) + * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit \ref IR_SOCK(N) in \ref _IMR_ are set, \ref IR_SOCK(N) in \ref IR becomes '1'.\n + * In order to clear the \ref Sn_IR bit, the host should write the bit to \n + * + * + * + *
7 6 5 4 3 2 1 0
PRECV PFAIL PNEXT SEND_OK TIMEOUT RECV DISCON CON
+ * - \ref Sn_IR_PRECV : PPP Receive Interrupt + * - \ref Sn_IR_PFAIL : PPP Fail Interrupt + * - \ref Sn_IR_PNEXT : PPP Next Phase Interrupt + * - \ref Sn_IR_SENDOK : SEND_OK Interrupt + * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt + * - \ref Sn_IR_RECV : RECV Interrupt + * - \ref Sn_IR_DISCON : DISCON Interrupt + * - \ref Sn_IR_CON : CON Interrupt + */ +#define Sn_IR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Socket status register(R) + * @details \ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - \ref SOCK_CLOSED : Closed + * - \ref SOCK_INIT : Initiate state + * - \ref SOCK_LISTEN : Listen state + * - \ref SOCK_ESTABLISHED : Success to connect + * - \ref SOCK_CLOSE_WAIT : Closing state + * - \ref SOCK_UDP : UDP socket + * - \ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - \ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - \ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - \ref SOCK_FIN_WAIT : Connection state + * - \ref SOCK_CLOSING : Closing state + * - \ref SOCK_TIME_WAIT : Closing state + * - \ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register + +/** + * @ingroup Socket_register_group_W5100 + * @brief source port register(R/W) + * @details \ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered. +*/ +#define Sn_PORT(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Peer MAC register address(R/W) + * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief Peer IP register address(R/W) + * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of TCP server before CONNECT command. + * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief Peer port register address(R/W) + * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command. + * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief IP Protocol(PROTO) Register(R/W) + * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is + * valid only in IPRAW mode, and ignored in other modes. + */ +#define Sn_PROTO(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode + +/** + * @ingroup Socket_register_group_W5100 + * @brief IP Type of Service(TOS) Register(R/W) + * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register + +/** + * @ingroup Socket_register_group_W5100 + * @brief IP Time to live(TTL) Register(R/W) + * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register + +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C)) +// Reserved (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D)) + +/** + * @ingroup Socket_register_group_W5100 + * @brief Transmit free memory size register(R) + * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE. + * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Transmit memory read pointer register address(R) + * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief Transmit memory write pointer register address(R/W) + * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address + +/** + * @ingroup Socket_register_group_W5100 + * @brief Received data size register(R) + * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between + * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD) + */ +#define Sn_RX_RSR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register + +/** + * @ingroup Socket_register_group_W5100 + * @brief Read point of Receive memory(R/W) + * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5100. + */ +#define Sn_RX_RD(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory + +/** + * @ingroup Socket_register_group_W5100 + * @brief Write point of Receive memory(R) + * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(sn) (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory + + +//----------------------------- W5100 Register values ----------------------------- + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 ///< reset + + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 ///< ping block + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be '1'. + */ +#define MR_PPPOE 0x08 ///< enable pppoe + +/** + * @brief Address Auto-Increment in Indirect Bus Interface + * @details 0 : Disable auto-increment \n + * 1 : Enable auto-incremente \n + * At the Indirect Bus Interface mode, if this bit is set as ��1��, the address will + * be automatically increased by 1 whenever read and write are performed. + */ +#define MR_AI 0x02 ///< auto-increment in indirect mode + +/** + * @brief Indirect Bus Interface mode + * @details 0 : Disable Indirect bus Interface mode \n + * 1 : Enable Indirect bus Interface mode \n + * If this bit is set as ��1��, Indirect Bus Interface mode is set. + */ +#define MR_IND 0x01 ///< enable indirect mode + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 ///< check ip confict + +/** + * @brief Get the destination unreachable message in UDP sending. + * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as + * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. + */ +#define IR_UNREACH 0x40 ///< check destination unreachable + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 ///< get the PPPoE close message + +#define IR_SOCK(sn) (0x01 << sn) ///< check socket interrupt + + +// Sn_MR values +/* Sn_MR Default values */ +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 ///< unused socket + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 ///< TCP + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 ///< UDP +#define Sn_MR_IPRAW 0x03 ///< IP LAYER RAW SOCK + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 ///< MAC LAYER RAW SOCK + +/** + * @brief PPPoE + * @details This configures the protocol mode of Socket n. + * @note PPPoE mode should be only used in Socket 0. + */ +#define Sn_MR_PPPoE 0x05 ///< PPPoE + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001).\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_. + */ +#define Sn_MR_ND 0x20 ///< No Delayed Ack(TCP) flag + +/** + * @brief Support UDP Multicasting + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1') + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MC Sn_MR_ND ///< Select IGMP version 1(0) or 2(1) + +/** + * @brief MAC filter enable in @ref Sn_MR_MACRAW mode + * @details 0 : disable MAC Filtering\n + * 1 : enable MAC Filtering\n + * This bit is applied only during MACRAW mode(P[3:0] = 100.\n + * When set as W5100 can only receive broadcasting packet or packet sent to itself. + * When this bit is W5100 can receive all packets on Ethernet. + * If user wants to implement Hybrid TCP/IP stack, + * it is recommended that this bit is set as for reducing host overhead to process the all received packets. + */ +#define Sn_MR_MF 0x40 ///< Use MAC filter +#define Sn_MR_MFEN Sn_MR_MF + + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010).\n + * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of \ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 ///< support multicating + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n + * + * + * + * + * + * + * + * + *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000) --
Sn_MR_TCP (001) SOCK_INIT (0x13)
Sn_MR_UDP (010) SOCK_UDP (0x22)
S0_MR_IPRAW (011) SOCK_IPRAW (0x32)
S0_MR_MACRAW (100) SOCK_MACRAW (0x42)
S0_MR_PPPoE (101) SOCK_PPPoE (0x5F)
+ */ +#define Sn_CR_OPEN 0x01 ///< initialize or open socket + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).// + * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.// + * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.// + * When a 'TCP client' connection request is successfully established, + * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes + * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 ///< wait connection request in tcp mode(Server mode) + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to TCP serverconfigured by \ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as TCP client + */ +#define Sn_CR_CONNECT 0x04 ///< send connection request in tcp mode(Client mode) + +/** + * @brief Send closing request in TCP mode + * @details Regardless of TCP serveror TCP client the DISCON command processes the disconnect-process (Active closeor Passive close.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 ///< send closing reqeuset in tcp mode + +/** + * @brief Close socket + * @details Sn_SR is changed to \ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (\ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/** + * @brief PPPoE connection + * @details PPPoE connection begins by transmitting PPPoE discovery packet + */ +#define Sn_CR_PCON 0x23 + +/** + * @brief Closes PPPoE connection + * @details Closes PPPoE connection + */ +#define Sn_CR_PDISCON 0x24 + +/** + * @brief REQ message transmission + * @details In each phase, it transmits REQ message. + */ +#define Sn_CR_PCR 0x25 + +/** + * @brief NAK massage transmission + * @details In each phase, it transmits NAK message. + */ +#define Sn_CR_PCN 0x26 + +/** + * @brief REJECT message transmission + * @details In each phase, it transmits REJECT message. + */ +#define Sn_CR_PCJ 0x27 + +/* Sn_IR values */ +/** + * @brief PPP Receive Interrupt + * @details PPP Receive Interrupts when the option which is not supported is received. + */ +#define Sn_IR_PRECV 0x80 + +/** + * @brief PPP Fail Interrupt + * @details PPP Fail Interrupts when PAP Authentication is failed. + */ +#define Sn_IR_PFAIL 0x40 + +/** + * @brief PPP Next Phase Interrupt + * @details PPP Next Phase Interrupts when the phase is changed during ADSL connection process. + */ +#define Sn_IR_PNEXT 0x20 + +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 ///< complete sending + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 ///< assert timeout + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 ///< closed + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\n + * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n + * After \ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 ///< init state + +/** + * @brief Listen state + * @details This indicates Socket n is operating as TCP servermode and waiting for connection-request (SYN packet) from a peer (TCP client).\n + * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1'). + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to \ref SOCK_ESTABLISHED. \n + * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to \ref SOCK_ESTABLISHED when the TCP SERVERprocessed the SYN packet from the TCP CLIENTduring \ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n + * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and @ref Sn_CR_OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 ///< udp socket + +/** + * @brief IP raw mode socket + * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is + * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n + * IP Packet can be transferred without a connection similar to the UDP mode. +*/ +#define SOCK_IPRAW 0x32 ///< ip raw mode socket + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n=0) and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0]) = '100' and @ref Sn_CR_OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 ///< mac raw mode socket + +/** + * @brief PPPoE mode socket + * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR + * (P3:P0)=S0_MR_PPPoE.\n + * It is temporarily used at the PPPoE +connection. + */ +#define SOCK_PPPOE 0x5F ///< pppoe socket + +// IP PROTOCOL +#define IPPROTO_IP 0 ///< Dummy for IP +#define IPPROTO_ICMP 1 ///< Control message protocol +#define IPPROTO_IGMP 2 ///< Internet group management protocol +#define IPPROTO_GGP 3 ///< GW^2 (deprecated) +#define IPPROTO_TCP 6 ///< TCP +#define IPPROTO_PUP 12 ///< PUP +#define IPPROTO_UDP 17 ///< UDP +#define IPPROTO_IDP 22 ///< XNS idp +#define IPPROTO_ND 77 ///< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 ///< Raw IP packet + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +#ifdef _exit +#undef _exit +#endif + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + + +//////////////////////// +// Basic I/O Function // +//////////////////////// +// +//M20150601 : uint16_t AddrSel --> uint32_t AddrSel +// +/** + * @ingroup Basic_IO_function_W5100 + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function_W5100 + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function_W5100 + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100 + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + + +///////////////////////////////// +// Common Register IO function // +///////////////////////////////// + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define setMR(mr) WIZCHIP_WRITE(MR,mr) +#else + #define setMR(mr) (*((uint8_t*)MR) = mr) +#endif + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get @ref MR. + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define getMR() WIZCHIP_READ(MR) +#else + #define getMR() (*(uint8_t*)MR) +#endif + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set @ref GAR. + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get @ref GAR. + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set @ref SUBR. + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @note If subr is null pointer, set the backup subnet to SUBR. \n + * If subr is 0.0.0.0, back up SUBR and clear it. \n + * Otherwize, set subr to SUBR + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR,subr,4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get @ref SUBR. + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set @ref SHAR. + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get @ref SHAR. + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() +*/ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref IR register + * @param (uint8_t)ir Value to set \ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xA0)) +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref IR register + * @return uint8_t. Value of \ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xA0) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref _IMR_ register + * @param (uint8_t)imr Value to set @ref _IMR_ register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(_IMR_, imr) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref _IMR_ register + * @return uint8_t. Value of @ref _IMR_ register. + * @sa setIMR() + */ +#define getIMR() \ + WIZCHIP_READ(_IMR_) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref _RTR_ register + * @param (uint16_t)rtr Value to set @ref _RTR_ register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(_RTR_, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref _RTR_ register + * @return uint16_t. Value of @ref _RTR_ register. + * @sa setRTR() + */ +#define getRTR() \ + (((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1))) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref _RCR_ register + * @param (uint8_t)rcr Value to set @ref _RCR_ register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(_RCR_, rcr) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref _RCR_ register + * @return uint8_t. Value of @ref _RCR_ register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(_RCR_) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref RMSR register + * @sa getRMSR() + */ +#define setRMSR(rmsr) \ + WIZCHIP_WRITE(RMSR) // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref RMSR register + * @return uint8_t. Value of @ref RMSR register. + * @sa setRMSR() + */ + #define getRMSR() \ + WIZCHIP_READ() // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref TMSR register + * @sa getTMSR() + */ +#define setTMSR(rmsr) \ + WIZCHIP_WRITE(TMSR) // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref TMSR register + * @return uint8_t. Value of @ref TMSR register. + * @sa setTMSR() + */ + + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref PATR register + * @return uint16_t. Value to set \ref PATR register + */ +#define getPATR() \ + (((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1))) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref PPPALGO register + * @return uint8_t. Value to set \ref PPPALGO register + */ +#define getPPPALGO() \ + WIZCHIP_READ(PPPALGO) + + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref PTIMER register + * @param (uint8_t)ptimer Value to set \ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Set \ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function_W5100 + * @brief Get \ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @param mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @return Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), ir) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + WIZCHIP_READ(Sn_IR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +#define getSn_PORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa SetSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +#define getSn_DPORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)proto Value to set \ref Sn_PROTO + * @sa getSn_PROTO() + */ +#define setSn_PROTO(sn, proto) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_PROTO. + * @sa setSn_PROTO() + */ +#define getSn_PROTO(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE + * @sa getSn_RXMEM_SIZE() + */ +#define setSn_RXMEM_SIZE(sn, rxmemsize) \ + WIZCHIP_WRITE(RMSR, (WIZCHIP_READ(RMSR) & ~(0x03 << (2*sn))) | (rxmemsize << (2*sn))) +#define setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_RXMEM. + * @sa setSn_RXMEM_SIZE() + */ +#define getSn_RXMEM_SIZE(sn) \ + ((WIZCHIP_READ(RMSR) & (0x03 << (2*sn))) >> (2*sn)) +#define getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE + * @sa getSn_TXMEM_SIZE() + */ +#define setSn_TXMEM_SIZE(sn, txmemsize) \ + WIZCHIP_WRITE(TMSR, (WIZCHIP_READ(TMSR) & ~(0x03 << (2*sn))) | (txmemsize << (2*sn))) +#define setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_TXMEM_SIZE. + * @sa setSn_TXMEM_SIZE() + */ +#define getSn_TXMEM_SIZE(sn) \ + ((WIZCHIP_READ(TMSR) & (0x03 << (2*sn))) >> (2*sn)) +#define getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +#define getSn_TX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +#define getSn_TX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @regurn uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +#define getSn_RX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR + * @sa getSn_RX_WR() + */ +#define setSn_RX_WR(sn, rxwr) { \ + WIZCHIP_WRITE(Sn_RX_WR(sn), (uint8_t)(rxwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \ + } + + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +#define getSn_RX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Set @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)frag Value to set \ref Sn_FRAG + * @sa getSn_FRAG() + */ +#define setSn_FRAG(sn, frag) { \ + WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ + } + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_FRAG. + * @sa setSn_FRAG() + */ +#define getSn_FRAG(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the max RX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_RxMAX(sn) \ + ((uint16_t)(1 << getSn_RXMEM_SIZE(sn)) << 10) + + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the max TX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_TxMAX(sn) \ + ((uint16_t)(1 << getSn_TXMEM_SIZE(sn)) << 10) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the mask of socket sn RX buffer. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_RxMASK(sn) \ + (getSn_RxMAX(sn) - 1) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the mask of socket sn TX buffer + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_TxMASK(sn) \ + (getSn_TxMAX(sn) - 1) + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the base address of socket sn RX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n RX buffer base address. + */ +uint32_t getSn_RxBASE(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100 + * @brief Get the base address of socket sn TX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n TX buffer base address. + */ +uint32_t getSn_TxBASE(uint8_t sn); + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @ingroup Basic_IO_function_W5100 + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100 + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to wizdata(pointer variable) of the length of len(variable) bytes. + * This function is being called by recv() also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100 + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of len(variable) bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +/// @cond DOXY_APPLY_CODE +#endif +/// @endcond + +#ifdef __cplusplus +} +#endif + +#endif //_W5100_H_ + + + diff --git a/Libraries/Ethernet/W5100S/w5100s.c b/Libraries/Ethernet/W5100S/w5100s.c new file mode 100644 index 0000000..8583eb1 --- /dev/null +++ b/Libraries/Ethernet/W5100S/w5100s.c @@ -0,0 +1,514 @@ +//***************************************************************************** +// +//! \file w5100S.c +//! \brief W5100S HAL Interface. +//! \version 1.0.0 +//! \date 2018/03/29 +//! \par Revision history +//! <2018/03/29> 1st Release +//! \author Peter +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include "w5100s.h" + +#if (_WIZCHIP_ == W5100S) +/** +@brief This function writes the data into W5100S registers. +*/ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) +{ + uint8_t spi_data[4]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_)) + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte(0xF0); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data) + } + else // burst operation + { + spi_data[0] = 0xF0; + spi_data[1] = (AddrSel & 0xFF00) >> 8; + spi_data[2] = (AddrSel & 0x00FF) >> 0; + spi_data[3] = wb; + WIZCHIP.IF.SPI._write_burst(spi_data, 4); + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) ) + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(0xF0); + WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data) + } + else // burst operation + { + spi_data[0] = (AddrSel & 0xFF00) >> 8; + spi_data[1] = (AddrSel & 0x00FF) >> 0; + spi_data[2] = 0xF0; + spi_data[3] = wb; + WIZCHIP.IF.SPI._write_burst(spi_data, 4); + + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with ioLibrary + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + WIZCHIP.IF.BUS._write_data(IDM_DR,wb); +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} +/** +@brief This function reads the value from W5100S registers. +*/ +uint8_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint8_t ret; + uint8_t spi_data[3]; + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_)) + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte(0x0F); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + } + else + { + spi_data[0] = 0x0F; + spi_data[1] = (AddrSel & 0xFF00) >> 8; + spi_data[2] = (AddrSel & 0x00FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + } + ret = WIZCHIP.IF.SPI._read_byte(); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) ) + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // burst operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(0x0F); + } + else + { + spi_data[0] = (AddrSel & 0xFF00) >> 8; + spi_data[1] = (AddrSel & 0x00FF) >> 0; + spi_data[2] = 0x0F + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + } + ret = WIZCHIP.IF.SPI._read_byte(); +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with ioLibrary + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + ret = WIZCHIP.IF.BUS._read_data(IDM_DR); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + + +/** +@brief This function writes into W5100S memory(Buffer) +*/ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + uint16_t i = 0; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); //M20150601 : Moved here. + +#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_)) + + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte(0xF0); + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0); + + for(i = 0; i < len; i++) + { + WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data) + } + } + else // burst operation + { + spi_data[0] = 0xF0; + spi_data[1] = (((uint16_t)(AddrSel+i)) & 0xFF00) >> 8; + spi_data[2] = (((uint16_t)(AddrSel+i)) & 0x00FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._write_burst(pBuf, len); + } + +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) ) + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(0xF0); + + for(i = 0; i < len; i++) + { + WIZCHIP.IF.SPI._write_byte(pBuf[i]); // Data write (write 1byte data) + } + } + else // burst operation + { + spi_data[0] = (((uint16_t)(AddrSel+i)) & 0xFF00) >> 8; + spi_data[1] = (((uint16_t)(AddrSel+i)) & 0x00FF) >> 0; + spi_data[2] = 0xF0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._write_burst(pBuf, len); + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + /* + WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR()|MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]); + setMR(getMR() & ~MR_AI); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!" +#endif + + WIZCHIP.CS._deselect(); //M20150601 : Moved here. + WIZCHIP_CRITICAL_EXIT(); +} + +/** +@brief This function reads into W5100S memory(Buffer) +*/ + +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + uint16_t i = 0; + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); //M20150601 : Moved here. + +#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_) ) + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte(0x0F); + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0); + + for(i = 0; i < len; i++) + { + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + } + } + else // burst operation + { + spi_data[0] = 0x0F; + spi_data[1] = (uint16_t)((AddrSel+i) & 0xFF00) >> 8; + spi_data[2] = (uint16_t)((AddrSel+i) & 0x00FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._read_burst(pBuf, len); + + } +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) ) + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >> 8); + WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >> 0); + WIZCHIP.IF.SPI._write_byte(0x0F); + + for(i = 0; i < len; i++) + { + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + } + } + else // burst operation + { + spi_data[0] = (uint16_t)((AddrSel+i) & 0xFF00) >> 8; + spi_data[1] = (uint16_t)((AddrSel+i) & 0x00FF) >> 0; + spi_data[2] = 0x0F; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._read_burst(pBuf, len); + } + + +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + //M20150601 : Rename the function for integrating with ioLibrary + /* + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR() | MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR); + setMR(getMR() & ~MR_AI); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!" +#endif + + WIZCHIP.CS._deselect(); //M20150601 : Moved Here. + WIZCHIP_CRITICAL_EXIT(); +} + +/////////////////////////////////// +// Socket N regsiter IO function // +/////////////////////////////////// + +uint16_t getSn_TX_FSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_TX_FSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + } + }while (val != val1); + return val; +} + + +uint16_t getSn_RX_RSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_RX_RSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + } + }while (val != val1); + return val; +} + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +uint32_t getSn_RxBASE(uint8_t sn) +{ + int8_t i; +#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + uint32_t rxbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_RXBUF_; +#else + uint32_t rxbase = _WIZCHIP_IO_RXBUF_; +#endif + for(i = 0; i < sn; i++) + rxbase += getSn_RxMAX(i); + + return rxbase; +} + +uint32_t getSn_TxBASE(uint8_t sn) +{ + int8_t i; +#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + uint32_t txbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_TXBUF_; +#else + uint32_t txbase = _WIZCHIP_IO_TXBUF_; +#endif + for(i = 0; i < sn; i++) + txbase += getSn_TxMAX(i); + return txbase; +} + +/** +@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip. + +This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer +register. User should read upper byte first and lower byte later to get proper value. +And this function is being used for copy the data form application buffer to Transmite +buffer of the chip. It calculate the actual physical address where one has to write +the data in transmite buffer. Here also take care of the condition while it exceed +the Tx memory uper-bound of socket. + +*/ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr; + uint16_t size; + uint16_t dst_mask; + uint16_t dst_ptr; + + ptr = getSn_TX_WR(sn); + + dst_mask = ptr & getSn_TxMASK(sn); + dst_ptr = getSn_TxBASE(sn) + dst_mask; + + if (dst_mask + len > getSn_TxMAX(sn)) + { + size = getSn_TxMAX(sn) - dst_mask; + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size); + wizdata += size; + size = len - size; + dst_ptr = getSn_TxBASE(sn); + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size); + } + else + { + WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len); + } + + ptr += len; + + setSn_TX_WR(sn, ptr); +} + + +/** +@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer. + +This function read the Rx read pointer register +and after copy the data from receive buffer update the Rx write pointer register. +User should read upper byte first and lower byte later to get proper value. +It calculate the actual physical address where one has to read +the data from Receive buffer. Here also take care of the condition while it exceed +the Rx memory uper-bound of socket. +*/ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr; + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + ptr = getSn_RX_RD(sn); + + src_mask = (uint32_t)ptr & getSn_RxMASK(sn); + src_ptr = (getSn_RxBASE(sn) + src_mask); + + + if( (src_mask + len) > getSn_RxMAX(sn) ) + { + size = getSn_RxMAX(sn) - src_mask; + WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size); + wizdata += size; + size = len - size; + src_ptr = getSn_RxBASE(sn); + WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size); + } + else + { + WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len); + } + + ptr += len; + + setSn_RX_RD(sn, ptr); +} + +void wiz_recv_ignore(uint8_t sn, uint16_t len) +{ + uint16_t ptr; + + ptr = getSn_RX_RD(sn); + + ptr += len; + setSn_RX_RD(sn,ptr); +} + +void wiz_mdio_write(uint8_t PHYMDIO_regadr, uint16_t var) +{ + WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr); + WIZCHIP_WRITE(PHYDIR, (uint8_t)(var >> 8)); + WIZCHIP_WRITE(PHYDIR+1, (uint8_t)(var)); + WIZCHIP_WRITE(PHYACR, PHYACR_WRITE); + while(WIZCHIP_READ(PHYACR)); //wait for command complete +} + +uint16_t wiz_mdio_read(uint8_t PHYMDIO_regadr) +{ + WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr); + WIZCHIP_WRITE(PHYACR, PHYACR_READ); + while(WIZCHIP_READ(PHYACR)); //wait for command complete + return ((uint16_t)WIZCHIP_READ(PHYDOR) << 8) | WIZCHIP_READ(PHYDOR+1); +} + +void wiz_delay_ms(uint32_t milliseconds) +{ + uint32_t i; + for(i = 0 ; i < milliseconds ; i++) + { + //Write any values to clear the TCNTCLKR register + setTCNTCLKR(0xff); + + // Wait until counter register value reaches 10.(10 = 1ms : TCNTR is 100us tick counter register) + while(getTCNTR() < 0x0a){} + } +} + +#endif diff --git a/Libraries/Ethernet/W5100S/w5100s.h b/Libraries/Ethernet/W5100S/w5100s.h new file mode 100644 index 0000000..3daa8b4 --- /dev/null +++ b/Libraries/Ethernet/W5100S/w5100s.h @@ -0,0 +1,3322 @@ +//* **************************************************************************** +//! \file w5100S.h +//! \brief W5100S HAL Header File. +//! \version 1.0.0 +//! \date 2018/03/29 +//! \par Revision history +//! <2018/03/29> 1st Release +//! \author Peter +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + + +#ifndef _W5100S_H_ +#define _W5100S_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "wizchip_conf.h" + +/// \cond DOXY_APPLY_CODE +#if (_WIZCHIP_ == W5100S) +/// \endcond + +#define _WIZCHIP_SN_BASE_ (0x0400) +#define _WIZCHIP_SN_SIZE_ (0x0100) +#define _WIZCHIP_IO_TXBUF_ (0x4000) /* Internal Tx buffer address of the iinchip */ +#define _WIZCHIP_IO_RXBUF_ (0x6000) /* Internal Rx buffer address of the iinchip */ + + +#define WIZCHIP_CREG_BLOCK 0x00 ///< Common register block +#define WIZCHIP_SREG_BLOCK(N) (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + N) ///< Increase offset address + +#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + #define _W5100S_IO_BASE_ _WIZCHIP_IO_BASE_ +#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) + #define IDM_OR ((_WIZCHIP_IO_BASE + 0x0000)) + #define IDM_AR0 ((_WIZCHIP_IO_BASE_ + 0x0001)) + #define IDM_AR1 ((_WIZCHIP_IO_BASE_ + 0x0002)) + #define IDM_DR ((_WIZCHIP_IO_BASE_ + 0x0003)) + #define _W5100S_IO_BASE_ 0x0000 +#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define _W5100S_IO_BASE_ 0x0000 +#endif + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + + +//----------- defgroup -------------------------------- + +/** + * @defgroup W5100S W5100S + * @brief WHIZCHIP register defines and I/O functions of @b W5100S. + * + * - @ref WIZCHIP_register_W5100S: @ref Common_register_group_W5100S and @ref Socket_register_group_W5100S + * - @ref WIZCHIP_IO_Functions_W5100S: @ref Basic_IO_function_W5100S, @ref Common_register_access_function_W5100S and @ref Special_function_W5100S + */ + + /** + * @defgroup WIZCHIP_register_W5100S WIZCHIP register + * @ingroup W5100S + * @brief WIZCHIP register defines register group of W5100S . + * + * - \ref Common_register_group_W5100S : Common register group W5100S + * - \ref Socket_register_group_W5100S : \c SOCKET n register group W5100S + */ + + +/** + * @defgroup WIZCHIP_IO_Functions_W5100S WIZCHIP I/O functions + * @ingroup W5100S + * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5100S. + * + * - Basic I/O function \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF(), wiz_recv_data(), wiz_recv_ignore(), wiz_send_data() \n\n + * + * - \ref Common_register_group_W5100S access functions \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), + * -# Network Information \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC() + * + * - \ref Socket_register_group_W5100S access functions \n + * -# SOCKET control \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IR(), setSn_IR() + * -# SOCKET information \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# SOCKET communication \n + * getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR() + * -# IP header field \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + +/** + * @defgroup Common_register_group_W5100S Common register + * @ingroup WIZCHIP_register_W5100S + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa IR, Sn_IR, _IMR_ : Interrupt. + * @sa _RTR_, _RCR_ : Data retransmission. + * @sa PTIMER, PMAGIC : PPPoE. + */ + + + /** + * @defgroup Socket_register_group_W5100S Socket register + * @ingroup WIZCHIP_register_W5100S + * @brief Socket register group\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAGR : Internet protocol. + * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + /** + * @defgroup Basic_IO_function_W5100S Basic I/O function + * @ingroup WIZCHIP_IO_Functions_W5100S + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function_W5100S Common register access functions + * @ingroup WIZCHIP_IO_Functions_W5100S + * @brief These are functions to access common registers. + */ + +/** + * @defgroup Socket_register_access_function_W5100S Socket register access functions + * @ingroup WIZCHIP_IO_Functions_W5100S + * @brief These are functions to access socket registers. + */ + + /** + * @defgroup Special_function_W5100S Special functions + * @ingroup WIZCHIP_IO_Functions_W5100S + * @brief These are special functions to access to the PHY + */ + + //----------------------------------------------------------------------------------- + +//----------------------------- W5100S Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group_W5100S + * @brief Mode Register address(R/W)\n + * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of \ref MR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved AI IND
+ * - \ref MR_RST : Reset + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_AI : Address Auto-Increment in Indirect Bus Interface + * - \ref MR_IND : Indirect Bus Interface mode + */ +#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_ + #define MR (_WIZCHIP_IO_BASE_ + (0x0000)) // Mode +#else + #define MR (_W5100S_IO_BASE_ + (0x0000)) // Mode +#endif + +/** + * @ingroup Common_register_group_W5100S + * @brief Gateway IP Register address(R/W) + * @details \ref GAR configures the default gateway address. + */ +#define GAR (_W5100S_IO_BASE_ + (0x0001)) // GW Address + +/** + * @ingroup Common_register_group_W5100S + * @brief Subnet mask Register address(R/W) + * @details \ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5100S_IO_BASE_ + (0x0005)) // SN Mask Address + +/** + * @ingroup Common_register_group_W5100S + * @brief Source MAC Register address(R/W) + * @details \ref SHAR configures the source hardware address. + */ +#define SHAR (_W5100S_IO_BASE_ + (0x0009)) // Source Hardware Address + +/** + * @ingroup Common_register_group_W5100S + * @brief Source IP Register address(R/W) + * @details \ref SIPR configures the source IP address. + */ +#define SIPR (_W5100S_IO_BASE_ + (0x000F)) // Source IP Address + +// Reserved (_W5100S_IO_BASE_ + (0x0013)) +// Reserved (_W5100S_IO_BASE_ + (0x0014)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Interrupt Register(R/W) + * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host. + * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of \ref IR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE Reserved S3_INT S2_INT S1_INT S0_INT
+ * - \ref IR_CONFLICT : IP conflict + * - \ref IR_UNREACH : Destination unreachable + * - \ref IR_PPPoE : PPPoE connection close + * - \ref IR_SOCK(3) : SOCKET 3 Interrupt + * - \ref IR_SOCK(2) : SOCKET 2 Interrupt + * - \ref IR_SOCK(1) : SOCKET 1 Interrupt + * - \ref IR_SOCK(0) : SOCKET 0 Interrupt + */ +#define IR (_W5100S_IO_BASE_ + (0x0015)) // Interrupt + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR. + * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR is set, Interrupt will be issued. + */ +#define _IMR_ (_W5100S_IO_BASE_ + (0x0016)) // Socket Interrupt Mask + +/** + * @ingroup Common_register_group_W5100S + * @brief Timeout register address( 1 is 100us )(R/W) + * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0or 000 + * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5100S waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the \ref _RTR_ time, W5100S retransmits the packet or issues timeout. + */ +#define _RTR_ (_W5100S_IO_BASE_ + (0x0017)) // Retry Time + +/** + * @ingroup Common_register_group_W5100S + * @brief Retry count register(R/W) + * @details \ref _RCR_ configures the number of time of retransmission. + * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1'). + */ +#define _RCR_ (_W5100S_IO_BASE_ + (0x0019)) // Retry Count + +/** + * @ingroup Common_register_group_W5100S + * @brief Receive Memory Size Register + * @details \ref RMSR register configures RX bufffer Size of the SOCKET + * The sum of the RX buffers can not exceed 8kB. + * + * + * + *
7 6 5 4 3 2 1 0
S3-1 S3-0 S2-1 S2-0 S1-1 S1-0 S0-1 S0-0
+ * + * + * + * + * + * + *
Memory SizeSn-1Sn-0
1KB00
2KB01
4KB10
8KB11
+ */ +#define RMSR (_W5100S_IO_BASE_ + (0x001A)) // Receive Memory Size + +/** + * @ingroup Common_register_group_W5100S + * @brief Transmit Memory Size Register + * @details \ref TMSR register configures TX bufffer Size of the SOCKET + * The sum of the TX buffers can not exceed 8kB. + * + * + * + *
7 6 5 4 3 2 1 0
S3-1 S3-0 S2-1 S2-0 S1-1 S1-0 S0-1 S0-0
+ * + * + * + * + * + * + *
Memory SizeSn-1Sn-0
1KB00
2KB01
4KB10
8KB11
+ */ +#define TMSR (_W5100S_IO_BASE_ + (0x001B)) // Transmit Memory Size + +/** + * @ingroup Common_register_group_W5100S + * @brief Interrupt register 2 + * @details \ref IR2 indicates the interrupt status. + * Each bit of IR2 will be still until the bit will be written to by the host. + * + * + * + *
7:1 0
Reserved WOL
+ * - \ref IR2_WOL : WOL MAGIC PACKET Interrupt Mask + */ +#define IR2 (_W5100S_IO_BASE_ + (0x0020)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Interrupt mask register 2 + * @details \ref IMR2 Each bit of IMR2 corresponds to each bit of IR2. + * When a bit of IMR2 is and the corresponding bit of IR2 is set, Interrupt will be issued. + */ +#define IMR2 (_W5100S_IO_BASE_ + (0x0021)) + + +/** + * @ingroup Common_register_group_W5100S + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER (_W5100S_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer + +/** + * @ingroup Common_register_group_W5100S + * @brief PPP LCP Magic number register in PPPoE mode(R) + * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC (_W5100S_IO_BASE_ + (0x0029)) // PPP LCP Magic number + +/** + * @ingroup Common_register_group_W5100S + * @brief Unreachable IP address register + * @details \ref + */ +#define UIPR (_W5100S_IO_BASE_ + (0x002A)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Unreachable Port register + * @details \ref + */ +#define UPORTR (_W5100S_IO_BASE_ + (0x002E)) + +/* register for W5100S only */ + +/*------------------------------------------ Common registers ------------------------------------------*/ + +/** + * @ingroup Common_register_group_W5100S + * @brief MR2 Mode register 2 + * @details \reg + */ +#define MR2 (_W5100S_IO_BASE_ + (0x0030)) + + +/** + * @ingroup Common_register_group_W5100S + * @brief Destination Hardware address in PPPoE + * @details \reg + */ +#define PHAR (_W5100S_IO_BASE_ + (0x0032)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Session ID in PPPoE + * @details \reg + */ +#define PSIDR (_W5100S_IO_BASE_ + (0x0038)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Maximum receive Unit in PPPoE + * @details \reg + */ +#define PMRUR (_W5100S_IO_BASE_ + (0x003A)) + + +/*------------------------------------------ PHY registers ------------------------------------------*/ + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY status register + * @details \reg + */ +#define PHYSR (_W5100S_IO_BASE_ + (0x003C)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY status register(hidden) + * @details \reg + */ +#define PHYSR1 (_W5100S_IO_BASE_ + (0x003D)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Address value + * @details \reg + */ +#define PHYAR (_W5100S_IO_BASE_ + (0x003E)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Register address + * @details \reg + */ +#define PHYRAR (_W5100S_IO_BASE_ + (0x003F)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Data input register + * @details \reg + */ +#define PHYDIR (_W5100S_IO_BASE_ + (0x0040)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY data output register + * @details \reg + */ +#define PHYDOR (_W5100S_IO_BASE_ + (0x0042)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Action register + * @details \reg + */ +#define PHYACR (_W5100S_IO_BASE_ + (0x0044)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Division register + * @details \reg + */ +#define PHYDIVR (_W5100S_IO_BASE_ + (0x0045)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Control register 0 + * @details \reg + */ +#define PHYCR0 (_W5100S_IO_BASE_ + (0x0046)) +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Control register 1 + * @details \reg + */ +#define PHYCR1 (_W5100S_IO_BASE_ + (0x0047)) + +/*------------------------------------------ Socket Less registers ------------------------------------------*/ + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less control register + * @details \reg + */ +#define SLCR (_W5100S_IO_BASE_ + (0x004C)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less retry time register + * @details \reg + */ +#define SLRTR (_W5100S_IO_BASE_ + (0x004D)) + + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less retry count register + * @details \reg + */ +#define SLRCR (_W5100S_IO_BASE_ + (0x004F)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less peer IP address register + * @details \reg + */ +#define SLPIPR (_W5100S_IO_BASE_ + (0x0050)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less peer hardware address register + * @details \reg + */ +#define SLPHAR (_W5100S_IO_BASE_ + (0x0054)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Ping sequence number register + * @details \reg + */ +#define PINGSEQR (_W5100S_IO_BASE_ + (0x005A)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Ping ID register + * @details \reg + */ +#define PINGIDR (_W5100S_IO_BASE_ + (0x005C)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less interrupt mask register + * @details \reg + */ +#define SLIMR (_W5100S_IO_BASE_ + (0x005E)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Socket-less interrupt register + * @details \reg + */ +#define SLIR (_W5100S_IO_BASE_ + (0x005F)) + +/** + * @ingroup Common_register_group_W5100S + * @brief DBGOUT(hidden) + * @details \reg + */ +#define DBGOUT (_W5100S_IO_BASE_ + (0x0060)) + +/** + * @ingroup Common_register_group_W5100S + * @brief NICMAXCOLR(hidden) + * @details \reg + */ +#define NICMAXCOLR (_W5100S_IO_BASE_ + (0x0063)) +/*------------------------------------------ CFG registers ------------------------------------------*/ + +/** + * @ingroup Common_register_group_W5100S + * @brief Chip Configuration locking register + * @details \reg + */ +#define CHIPLCKR (_W5100S_IO_BASE_ + (0x0070)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Network Configuration locking register + * @details \reg + */ +#define NETLCKR (_W5100S_IO_BASE_ + (0x0071)) + +/** + * @ingroup Common_register_group_W5100S + * @brief PHY Configuration locking register + * @details \reg + */ +#define PHYLCKR (_W5100S_IO_BASE_ + (0x0072)) + +/** + * @ingroup Common_register_group_W5100S + * @brief version register + * @details \reg + */ +#define VERR (_W5100S_IO_BASE_ + (0x0080)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Core 100us Counter register + * @details \reg + */ +#define TCNTR (_W5100S_IO_BASE_ + (0x0082)) + +/** + * @ingroup Common_register_group_W5100S + * @brief Core 100us Counter clear register + * @details \reg + */ +#define TCNTCLKR (_W5100S_IO_BASE_ + (0x0088)) + +//----------------------------- W5100S Socket Registers ----------------------------- + +//--------------------------- For Backward Compatibility --------------------------- + +/** + * @ingroup Socket_register_group_W5100S + * @brief socket Mode register(R/W) + * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of \ref Sn_MR defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
MULTI MF ND/MC Reserved Protocol[3] Protocol[2] Protocol[1] Protocol[0]
+ * - \ref Sn_MR_MULTI : Support UDP Multicasting + * - \ref Sn_MR_MF : Support MACRAW + * - \ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - \ref Sn_MR_MC : IGMP version used in UDP mulitcasting + * - Protocol + * + * + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
+ * - In case of Socket 0 + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 1 0 0 MACRAW
0 1 0 1 PPPoE
+ * - \ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - \ref Sn_MR_UDP : UDP + * - \ref Sn_MR_TCP : TCP + * - \ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5100S accepts the command, the \ref Sn_CR register is automatically cleared to 0x00. + * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR. + * - \ref Sn_CR_OPEN : Initialize or open socket. + * - \ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) + * - \ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) + * - \ref Sn_CR_DISCON : Send closing request in TCP mode. + * - \ref Sn_CR_CLOSE : Close socket. + * - \ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - \ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - \ref Sn_CR_SEND_KEEP : Send keep alive message. + * - \ref Sn_CR_RECV : Update RX buffer pointer and receive data. + * - In case of S0_MR(P3:P0) = S0_MR_PPPoE + * + * + * + * + * + * + * + *
Value Symbol Description
0x23 PCON PPPoE connection begins by transmitting PPPoE discovery packet
0x24 PDISCON Closes PPPoE connection
0x25 PCR In each phase, it transmits REQ message.
0x26 PCN In each phase, it transmits NAK message.
0x27 PCJ In each phase, it transmits REJECT message.
+ */ +#define Sn_CR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket interrupt register(R) + * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit \ref IR_SOCK(N) in \ref _IMR_ are set, \ref IR_SOCK(N) in \ref IR becomes '1'.\n + * In order to clear the \ref Sn_IR bit, the host should write the bit to \n + * + * + * + *
7 6 5 4 3 2 1 0
PRECV PFAIL PNEXT SEND_OK TIMEOUT RECV DISCON CON
+ * - \ref Sn_IR_PRECV : PPP Receive Interrupt + * - \ref Sn_IR_PFAIL : PPP Fail Interrupt + * - \ref Sn_IR_PNEXT : PPP Next Phase Interrupt + * - \ref Sn_IR_SENDOK : SEND_OK Interrupt + * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt + * - \ref Sn_IR_RECV : RECV Interrupt + * - \ref Sn_IR_DISCON : DISCON Interrupt + * - \ref Sn_IR_CON : CON Interrupt + */ +#define Sn_IR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket status register(R) + * @details \ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - \ref SOCK_CLOSED : Closed + * - \ref SOCK_INIT : Initiate state + * - \ref SOCK_LISTEN : Listen state + * - \ref SOCK_ESTABLISHED : Success to connect + * - \ref SOCK_CLOSE_WAIT : Closing state + * - \ref SOCK_UDP : UDP socket + * - \ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - \ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - \ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - \ref SOCK_FIN_WAIT : Connection state + * - \ref SOCK_CLOSING : Closing state + * - \ref SOCK_TIME_WAIT : Closing state + * - \ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register + +/** + * @ingroup Socket_register_group_W5100S + * @brief source port register(R/W) + * @details \ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered. +*/ +#define Sn_PORT(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Peer MAC register address(R/W) + * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief Peer IP register address(R/W) + * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of TCP server before CONNECT command. + * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief Peer port register address(R/W) + * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command. + * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief IP Protocol(PROTO) Register(R/W) + * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is + * valid only in IPRAW mode, and ignored in other modes. + */ +#define Sn_PROTO(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode + +/** + * @ingroup Socket_register_group_W5100S + * @brief IP Type of Service(TOS) Register(R/W) + * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register + +/** + * @ingroup Socket_register_group_W5100S + * @brief IP Time to live(TTL) Register(R/W) + * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register + +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C)) +// Reserved (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D)) + + + +/** + * @ingroup Socket_register_group_W5100S + * @brief Receive memory size register(R/W) + * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. + * Socket n RX Buffer Block size can be configured with 1,2,4 and 8Kbytes. + * If a different size is configured, the data cannot be normally received from a peer. + * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, + * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 8Kbytes. + * When exceeded, the data reception error is occurred. + */ +#define Sn_RXBUF_SIZE(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001E)) + +/** + * @ingroup Socket_register_group_W5100S + * @brief Transmit memory size register(R/W) + * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4 and 8Kbytes. + * If a different size is configured, the data cannot be normally transmitted to a peer. + * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, + * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 8Kbytes. + * When exceeded, the data transmission error is occurred. + */ +#define Sn_TXBUF_SIZE(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001F)) + + +/** + * @ingroup Socket_register_group_W5100S + * @brief Transmit free memory size register(R) + * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE. + * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Transmit memory read pointer register address(R) + * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief Transmit memory write pointer register address(R/W) + * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address + +/** + * @ingroup Socket_register_group_W5100S + * @brief Received data size register(R) + * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between + * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD) + */ +#define Sn_RX_RSR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register + +/** + * @ingroup Socket_register_group_W5100S + * @brief Read point of Receive memory(R/W) + * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5100S. + */ +#define Sn_RX_RD(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory + +/** + * @ingroup Socket_register_group_W5100S + * @brief Write point of Receive memory(R) + * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory + + +//todo +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket interrupt mask register + * @details Register address to configure the interrupt mask of the socket + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * + */ +#define Sn_IMR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002C)) + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket fragment field register + * @details Register to configure the Fragment field of IP Header + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +#define Sn_FRAGR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002D)) // and +1 + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket Mode register 2 + * @details Register to set mode 2 + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +#define Sn_MR2(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002F)) + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket n Keep Alive Timer Register + * @details Register to set the transmission period of keep alive packet. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +#define Sn_KPALVTR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0030)) + +/** todo delete + * @ingroup Socket_register_group_W5100S + * @brief Socket n Timer Status Register + * @details + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +//#define Sn_TSR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0031)) + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket n Retry Time-value Register + * @details Register to set the retry time value + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +#define Sn_RTR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0032)) + +/** + * @ingroup Socket_register_group_W5100S + * @brief Socket n Retry Count-value Register + * @details Register to set the retry count value + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + */ +#define Sn_RCR(sn) (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0034)) + + +/*----------------------------- W5100S Register values -----------------------------*/ + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 ///< reset + + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 ///< ping block + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be '1'. + */ +#define MR_PPPOE 0x08 ///< enable pppoe + +/** + * @brief Address Auto-Increment in Indirect Bus Interface + * @details 0 : Disable auto-increment \n + * 1 : Enable auto-incremente \n + * At the Indirect Bus Interface mode, if this bit is set as the address will + * be automatically increased by 1 whenever read and write are performed. + */ +#define MR_AI 0x02 ///< auto-increment in indirect mode + +/** + * @brief Indirect Bus Interface mode + * @details 0 : Disable Indirect bus Interface mode \n + * 1 : Enable Indirect bus Interface mode \n + * If this bit is set as Indirect Bus Interface mode is set. + */ +#define MR_IND 0x01 ///< enable indirect mode + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 ///< check ip confict + +/** + * @brief Get the destination unreachable message in UDP sending. + * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as + * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. + */ +#define IR_UNREACH 0x40 ///< check destination unreachable + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 ///< get the PPPoE close message + +/** + * @brief Socket interrupt bit + * @details Indicates whether each socket interrupt has occured. + */ +#define IR_SOCK(sn) (0x01 << sn) ///< check socket interrupt + +/** + * @brief IP conflict interrupt mask bit + * @details If this bit is set, IP conflict interrupt is enabled. + */ +#define IMR_CONFLICT 0x80 + +/** + * @brief Destination port unreachable interrupt mask bit + * @details If this bit is set, destination port unreachable interrupt is enabled. + */ +#define IMR_UNREACH 0x40 + +/** + * @brief PADT/LCPT interrupt mask bit(PPPoE) + * @details If this bit is set, PADT/LCPT interrupt is enabled. + */ +#define IMR_PPPoE 0x20 + +/** + * @brief Socket interrupt mask bit + * @details If this bit is set, each socket interrupt is enabled. + */ +#define IMR_SOCK(sn) (0x01 << sn) + +/** + * @brief Socket-less command register bit + * @details ARP command + */ +#define SLCMD_ARP (1<<1) + +/** + * @brief Socket-less command register bit + * @details ARP command + */ +#define SLCMD_PING (1<<0) + +/** + * @brief Socket-less command interrupt and interrupt mask register bit + * @details Request command time out interrupt and interrupt mask + */ +#define SLIR_TIMEOUT (1<<2) + +/** +* @brief Socket less command interrupt and interrupt mask register bit +* @details Socket less command ARP interrupt and interrupt mask +*/ +#define SLIR_ARP (1<<1) + +/** +* @brief Socket less command interrupt and interrupt mask register bit +* @details Socket less command PING interrupt and interruptmask +*/ +#define SLIR_PING (1<<0) + + + +// Sn_MR values +/* Sn_MR Default values */ +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 ///< unused socket + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 ///< TCP + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 ///< UDP +#define Sn_MR_IPRAW 0x03 ///< IP LAYER RAW SOCK + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 ///< MAC LAYER RAW SOCK + +/** + * @brief PPPoE + * @details This configures the protocol mode of Socket n. + * @note PPPoE mode should be only used in Socket 0. + */ +#define Sn_MR_PPPoE 0x05 ///< PPPoE + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001).\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_. + */ +#define Sn_MR_ND 0x20 ///< No Delayed Ack(TCP) flag + +/** + * @brief Support UDP Multicasting + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1') + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MC Sn_MR_ND ///< Select IGMP version 1(0) or 2(1) + +/** + * @brief MAC filter enable in @ref Sn_MR_MACRAW mode + * @details 0 : disable MAC Filtering\n + * 1 : enable MAC Filtering\n + * This bit is applied only during MACRAW mode(P[3:0] = 100.\n + * When set as W5100S can only receive broadcasting packet or packet sent to itself. + * When this bit is W5100S can receive all packets on Ethernet. + * If user wants to implement Hybrid TCP/IP stack, + * it is recommended that this bit is set as for reducing host overhead to process the all received packets. + */ +#define Sn_MR_MF 0x40 ///< Use MAC filter +#define Sn_MR_MFEN Sn_MR_MF + + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010).\n + * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of \ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 ///< support multicating + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n + * + * + * + * + * + * + * + * + *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000) --
Sn_MR_TCP (001) SOCK_INIT (0x13)
Sn_MR_UDP (010) SOCK_UDP (0x22)
S0_MR_IPRAW (011) SOCK_IPRAW (0x32)
S0_MR_MACRAW (100) SOCK_MACRAW (0x42)
S0_MR_PPPoE (101) SOCK_PPPoE (0x5F)
+ */ +#define Sn_CR_OPEN 0x01 ///< initialize or open socket + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).// + * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.// + * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.// + * When a 'TCP client' connection request is successfully established, + * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes + * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 ///< wait connection request in tcp mode(Server mode) + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to TCP serverconfigured by \ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as TCP client + */ +#define Sn_CR_CONNECT 0x04 ///< send connection request in tcp mode(Client mode) + +/** + * @brief Send closing request in TCP mode + * @details Regardless of TCP serveror TCP client the DISCON command processes the disconnect-process (Active closeor Passive close.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 ///< send closing reqeuset in tcp mode + +/** + * @brief Close socket + * @details Sn_SR is changed to \ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (\ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/** + * @brief + * @details + */ +#define Sn_CR_IGMP_JOIN 0x23 + +/** + * @brief + * @details + */ +#define Sn_CR_IGMP_LEAVE 0x24 + + +/* Sn_IR values */ + +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 ///< complete sending + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 ///< assert timeout + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 ///< closed + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\n + * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n + * After \ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 ///< init state + +/** + * @brief Listen state + * @details This indicates Socket n is operating as TCP servermode and waiting for connection-request (SYN packet) from a peer (TCP client).\n + * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1'). + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to \ref SOCK_ESTABLISHED. \n + * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to \ref SOCK_ESTABLISHED when the TCP SERVERprocessed the SYN packet from the TCP CLIENTduring \ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n + * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and @ref Sn_CR_OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 ///< udp socket + +/** + * @brief IP raw mode socket + * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is + * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n + * IP Packet can be transferred without a connection similar to the UDP mode. +*/ +#define SOCK_IPRAW 0x32 ///< ip raw mode socket + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n=0) and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0]) = '100' and @ref Sn_CR_OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 ///< mac raw mode socket + +/** + * @brief PPPoE mode socket + * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR + * (P3:P0)=S0_MR_PPPoE.\n + * It is temporarily used at the PPPoE +connection. + */ +#define SOCK_PPPOE 0x5F ///< pppoe socket + +// IP PROTOCOL +#define IPPROTO_IP 0 ///< Dummy for IP +#define IPPROTO_ICMP 1 ///< Control message protocol +#define IPPROTO_IGMP 2 ///< Internet group management protocol +#define IPPROTO_GGP 3 ///< GW^2 (deprecated) +#define IPPROTO_TCP 6 ///< TCP +#define IPPROTO_PUP 12 ///< PUP +#define IPPROTO_UDP 17 ///< UDP +#define IPPROTO_IDP 22 ///< XNS idp +#define IPPROTO_ND 77 ///< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 ///< Raw IP packet + + + +/*----------------------------- W5100S !!Only!! Register values -----------------------------*/ + +//todo +/* MODE2 register values */ + +/** + * @brief Clock select bit + * @details With this bit, system clock can be selected to be 25Mhz or 100Mhz + * 1: 25Mhz + * 0: 100Mhz (default) + */ +#define MR2_CLKSEL (1<<7) + +/** + * @brief Interrupt pin enable bit + * @details This bit enables interrupt. + * 1: Enable interrupt + * 0: Disable interrupt + */ +#define MR2_G_IEN (1<<6) + + +/** + * @brief No TCP Reset Packet send + * @details This bit prevents sending reset packet. + * 1: Block TCP reset packet send + * 0: TCP Reset packet send + */ +#define MR2_NOTCPRST (1<<5) + +/** + * @brief Unreachable Packet Send Block bit + * @details This bit prevents sending Destination Port Unreachable Packet. + * 1: Block Destination Port Unreachable Packet Send + * 0: Destination Port Unreachable Packet Send + */ +#define MR2_UDPURB (1<<4) + +/** + * @brief Wake On LAN + * @details This bit enables WOL packet to be received. + * 1: WOL packet can be received. + * 0: WOL packet cannot be received. + */ +#define MR2_WOL (1<<3) + +/**todo + * @brief MACRAW No Size Check + * @details + */ +#define MR2_MNOSCHK (1<<2) + +/** + * @brief UDP force ARP + * @details This bit can enables to force ARP for each send command. + * 1: UDP Force ARP Enable + * 0: UDP Force ARP Disable. + * + */ +#define MR2_UDPFARP (1<<1) + +/**todo + * @brief Skip SRC Hardware Address + * @details This bit can enables to receive without checking the hardware address of the peer. + * 1: + */ +#define MR2_SSRCHA (1<<0) + + + +/* Common interrupt register 2 values */ + +/**todo + * @brief magic packet + * @details + */ +#define IR2_MGC (1<<1) + +/**todo + * @brief Magic packet interrupt mask bit + * @details If this bit is set, each socket interrupt is enabled. + */ +#define IMR2_MGC (1<<1) + +/**todo + * @brief + * @details + */ +//#define IR2_MGD (1<<1) /* Reserved */ + + +/* PHY status register 0 values */ + +/**todo + * @brief Ethernet CABLE OFF Signal + * @details + */ +#define PHYSR_CABOFF (1<<7) + +/**todo + * @brief + * @details + */ +#define PHYSR_MD2 (1<<5) + +/**todo + * @brief + * @details + */ +#define PHYSR_MD1 (1<<4) + +/**todo + * @brief + * @details + */ +#define PHYSR_MD0 (1<<3) + +/**todo + * @brief + * @details + */ +#define PHYSR_DUP (1<<2) + +/**todo + * @brief + * @details + */ +#define PHYSR_SPD (1<<1) + +/**todo + * @brief LINKDONE register + * @details If 1 Linked successfully, if 0 no link + */ +#define PHYSR_LNK (1<<0) + + +/* PHY status register 10 values */ + +/** + * @brieftodo + * @details + */ +#define PHYSR1_RXPG (1<<2) + +/** + * @brieftodo + * @details + */ +#define PHYSR1_LPI (1<<1) + +/** + * @brieftodo + * @details + */ +#define PHYSR1_CLDN (1<<0) + +#define PHYCR_AUTONEGO_ENABLE (0<<2) +#define PHYCR_AUTONEGO_DISABLE (1<<2) + +#define PHYCR_SPD_10 (1<<1) +#define PHYCR_SPD_100 (0<<1) + +#define PHYCR_HALF_DUP (1<<0) +#define PHYCR_FULL_DUP (0<<0) + +#define PHYCR1_RST (0<<0) + +#define PHYCR1_PWDN_ENABLE (1<<5) +#define PHYCR1_PWDN_DISABLE (0<<5) + + +/* Socket n MODE register 2 values */ + +/** + * @brief Broadcast Blocking bit in MACRAW mode + * @details In MACRAW mode, this bit is set to ????to block the broadcast packet. + */ +#define Sn_MR2_MBBLK (1<<6) + +/** + * @brief Multicast Blocking bit in MACRAW mode + * @details In MACRAW mode, this bit is set to ????to block the multicast packet. + */ +#define Sn_MR2_MMBLK (1<<5) + +/** + * @brief IPv6 packet Blocking bit in MACRAW mode + * @details In MACRAW mode, this bit is set to ????to block the IPv6 packet. + */ +#define Sn_MR2_IPV6BLK (1<<4) + + +/** + * @brief Broadcast Blocking bit in UDP mode + * @details In UDP mode, this bit is set to ????to block the broadcast packet. + */ +#define Sn_MR2_UBBLK (1<<1) + + +/** + * @brief TCP Force PSH bit + * @details When the SOCKET transmits data in TCP mode, PSH Flag is set to all packets. + */ +#define Sn_MR2_FPSH Sn_MR2_UBBLK + +/** + * @brief Unicast Blocking bit in UDP mode + * @details In UDP mode, this bit is set to ????to block the Unicast packet. + */ +#define Sn_MR2_UUBLK (1<<0) + +/*----------------------------For PHY Control-------------------------------*/ + +/********************/ +/* Register Address */ +/********************/ + +//Basic mode control register, basic register +#define PHYMDIO_BMCR 0x00 + +//Basic mode status register, basic register +#define PHYMDIO_BMSR 0x01 + +//--------------------------------------Not used-------------------------------------------// +////PHY identifier register 1, extended register +//#define PHY_IDR1 0x02 //not used +// +////PHY identifier register 2, extended register +//#define PHY_IDR2 0x03 //not used +// +////Auto-negotiation advertisement register, extended register +//#define PHY_ANAR 0x04 //not used +// +////Auto-negotiation link partner ability register, extended register +//#define PHY_ANLPAR 0x05 //not used +// +////Auto-negotiation expansion register, extended register +//#define PHY_ANER 0x06 //not used +// +////Auto-negotiation next page transmit +//#define PHY_ANNP 0x07 //not used +// +////Auto-negotiation link partner of the next page receive +//#define PHY_ANLPNP 0x08 //not used +// +////MMD access control register +//#define PHY_REGCR 0x09 //not used +// +////MMD access address data register +//#define PHY_ADDAR 0x0e //not used +//--------------------------------------Not used-------------------------------------------// + +/********************/ +/* Bit definitions */ +/********************/ + +//For BMCR register +#define BMCR_RESET (1<<15) +#define BMCR_MLOOPBACK (1<<14) +#define BMCR_SPEED (1<<13) +#define BMCR_AUTONEGO (1<<12) +#define BMCR_PWDN (1<<11) +#define BMCR_ISOLATE (1<<10) +#define BMCR_RSTNEGO (1<<9) +#define BMCR_DUP (1<<8) +#define BMCR_COLTEST (1<<7) + +//For BMSR register +#define BMSR_AUTONEGO_COMPL (1<<5) +#define BMSR_REMOTE_FAULT (1<<4) +#define BMSR_LINK_STATUS (1<<2) +#define BMSR_JAB_DETECT (1<<1) +#define EXTENDED_CAPA (1<<0) + +//--------------------------------------Not used-------------------------------------------// +////For ANAR register +//#define ANAR_NP (1<<15) +//#define ANAR_ACK (1<<14) +//#define ANAR_RF (1<<13) +//#define ANAR_ASM (3<<10) +//#define ANAR_T4 (1<<9) +//#define ANAR_TX_FD (1<<8) +//#define ANAR_TX_HD (1<<7) +//#define ANAR_10_FD (1<<6) +//#define ANAR_10_HD (1<<5) +//#define ANAR_SELECTOR (0x1F<<0) +// +////For ANAR register +//#define ANLPAR_NP (1<<15) +//#define ANLPAR_ACK (1<<14) +//#define ANLPAR_RF (1<<13) +//#define ANLPAR_LP_DIR (1<<11) +//#define ANLPAR_PAUSE (1<<10) +//#define ANLPAR_T4 (1<<9) +//#define ANLPAR_TX_FD (1<<8) +//#define ANLPAR_TX_HD (1<<7) +//#define ANLPAR_10_FD (1<<6) +//#define ANLPAR_10_HD (1<<5) +//#define ANLPAR_SELECTOR (0x1F<<0) + +/**/ +/* MDIO register*/ +//PCS_CTL_1 | PCS control 1 register +//PCS_STS_1 | PCS status 1 register +//EEE_ABILITY | EEE capability register +//WAKE_ER_CNTR | EEE wake error counter +//EEE_ADVR | EEE Advertisement register +//EEE_LPAR | EEE link partner ability register + +//--------------------------------------Not used-------------------------------------------// + +/********************/ +/*Functions for PHY */ +/********************/ +//todo move this definition to bit area +#define PHYACR_READ 0x02 +#define PHYACR_WRITE 0x01 + + + + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +#ifdef _exit +#undef _exit +#endif + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + + +//////////////////////// +// Basic I/O Function // +//////////////////////// +// +//M20150601 : uint16_t AddrSel --> uint32_t AddrSel +// +/** + * @ingroup Basic_IO_function_W5100S + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function_W5100S + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function_W5100S + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100S + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + + +///////////////////////////////// +// Common Register IO function // +///////////////////////////////// + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define setMR(mr) WIZCHIP_WRITE(MR,mr) +#else + #define setMR(mr) (*((uint8_t*)MR) = mr) +#endif + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get @ref MR. + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define getMR() WIZCHIP_READ(MR) +#else + #define getMR() (*(uint8_t*)MR) +#endif + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set @ref GAR. + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get @ref GAR. + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set @ref SUBR. + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @note If subr is null pointer, set the backup subnet to SUBR. \n + * If subr is 0.0.0.0, back up SUBR and clear it. \n + * Otherwize, set subr to SUBR + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR,subr,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get @ref SUBR. + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set @ref SHAR. + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get @ref SHAR. + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() +*/ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref IR register + * @param (uint8_t)ir Value to set \ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xE0)) //peter 2016.11.07 unreachable interrupt bit added + //WIZCHIP_WRITE(IR, (ir & 0xA0)) +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref IR register + * @return uint8_t. Value of \ref IR register. + * @sa setIR() + */ +#define getIR() \ + WIZCHIP_READ(IR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref _IMR_ register + * @param (uint8_t)imr Value to set @ref _IMR_ register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(_IMR_, imr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref _IMR_ register + * @return uint8_t. Value of @ref _IMR_ register. + * @sa setIMR() + */ +#define getIMR() \ + WIZCHIP_READ(_IMR_) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref _RTR_ register + * @param (uint16_t)rtr Value to set @ref _RTR_ register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(_RTR_, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref _RTR_ register + * @return uint16_t. Value of @ref _RTR_ register. + * @sa setRTR() + */ +#define getRTR() \ + (((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1))) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref _RCR_ register + * @param (uint8_t)rcr Value to set @ref _RCR_ register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(_RCR_, rcr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref _RCR_ register + * @return uint8_t. Value of @ref _RCR_ register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(_RCR_) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref RMSR register + * @sa getRMSR() + */ +#define setRMSR(rmsr) \ + WIZCHIP_WRITE(RMSR,rmsr) // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref RMSR register + * @return uint8_t. Value of @ref RMSR register. + * @sa setRMSR() + */ + #define getRMSR() \ + WIZCHIP_READ(RMSR) // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref TMSR register + * @sa getTMSR() + */ +#define setTMSR(tmsr) \ + WIZCHIP_WRITE(TMSR,tmsr) // Receicve Memory Size + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref TMSR register + * @return uint8_t. Value of @ref TMSR register. + * @sa setTMSR() + */ +#define getTMSR() \ + WIZCHIP_READ(TMSR) + + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PATR register + * @return uint16_t. Value to set \ref PATR register + */ +#define getPATR() \ + (((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1))) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PPPALGO register + * @return uint8_t. Value to set \ref PPPALGO register + */ +#define getPPPALGO() \ + WIZCHIP_READ(PPPALGO) + + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PTIMER register + * @param (uint8_t)ptimer Value to set \ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + + +//todo Functions for W5100S + +/*----------------------------------------------------------------------*/ +/* W5100S only */ +/*----------------------------------------------------------------------*/ + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref IR2 register + * @param (uint8_t)ir2 Value to set @ref IR2 register. + * @sa getIR2() + */ +#define setIR2(ir2) \ + WIZCHIP_WRITE(IR2, ir2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref IR2 register + * @return uint8_t. Value of @ref IR2 register. + * @sa setIR2() + */ +#define getIR2() \ + WIZCHIP_READ(IR2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref IMR2 register + * @param (uint8_t)imr2 Value to set @ref IMR2 register. + * @sa setIMR2() + */ +#define setIMR2(imr2) \ + WIZCHIP_WRITE(IMR2,imr2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref IMR2 register + * @return uint8_t. Value of @ref IMR2 register. + * @sa getIMR2() + */ +#define getIMR2() \ + WIZCHIP_READ(IMR2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref UIPR(Unreachable IP Address Register) registers + * @param (uint8_t*)uipr Value to set @ref UIPR registers. + * @sa setUIPR() + */ +#define setUIPR(uipr) \ + WIZCHIP_WRITE_BUF(UIPR,uipr,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref UIPR(Unreachable IP Address Register) registers + * @param (uint8_t*)uipr Value to get @ref UIPR registers + * @sa setUIPR() + */ +#define getUIPR(uipr) \ + WIZCHIP_READ_BUF(UIPR,uipr,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref UPORTR(Unreachable Port Address Register) register + * @param (uint16_t)uportr Value to set @ref UPORTR register. + * @sa getUPORTR() + */ +#define setUPORTR(uportr) {\ + WIZCHIP_WRITE(UPORTR, (uint8_t)(uportr >> 8)); \ + WIZCHIP_WRITE(UPORTR+1, (uint8_t) uportr); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref UPORTR(Unreachable Port Address Register) register + * @return uint16_t. Value of @ref UPORTR register. + * @sa setUPORTR() + */ +#define getUPORTR() \ + (((uint16_t)WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(UPORTR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref MR2 register + * @param (uint8_t)mr2 Value to set @ref MR2 registers. + * @sa getMR2() + */ +#define setMR2(mr2) \ + WIZCHIP_WRITE(MR2,mr2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref MR2 register + * @return uint8_t. Value of @ref MR2 register. + * @sa setMR2() + */ +#define getMR2() \ + WIZCHIP_READ(MR2) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHAR registers + * @param (uint8_t*)phar Value to set @ref PHAR registers. + * @sa getPHAR() + */ +#define setPHAR(phar) \ + WIZCHIP_WRITE_BUF(PHAR,phar,6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHAR registers + * @param (uint8_t*)phar Pointer variable to get @ref PHAR registers. + * @sa setPHAR() + */ +#define getPHAR(phar) \ + WIZCHIP_READ_BUF(PHAR,phar,6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PSIDR register + * @param (uint16_t)psidr Value to set @ref PSIDR register. + * @sa getPSIDR() + */ +#define setPSIDR(psidr) {\ + WIZCHIP_WRITE(PSIDR, (uint8_t)(psidr >> 8)); \ + WIZCHIP_WRITE(PSIDR+1, (uint8_t) psidr); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PSIDR register + * @return uint16_t. Value of @ref PSIDR register. + * @sa setPSIDR() + */ +#define getPSIDR() \ + (((uint16_t)WIZCHIP_READ(PSIDR) << 8) + WIZCHIP_READ(PSIDR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PMRUR register + * @param (uint16_t)pmrur Value to set @ref PMRUR register. + * @sa getPMRUR() + */ +#define setPMRUR(pmrur) {\ + WIZCHIP_WRITE(PMRUR, (uint8_t)(pmrur >> 8)); \ + WIZCHIP_WRITE(PMRUR+1, (uint8_t) pmrur); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PMRUR register + * @return uint16_t. Value of @ref PMRUR register. + * @sa setPMRUR() + */ +#define getPMRUR() \ + (((uint16_t)WIZCHIP_READ(PMRUR) << 8) + WIZCHIP_READ(PMRUR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYSR register + * @return uint8_t. Value of @ref PHYSR register. + * @sa setPHYSR() + */ +#define getPHYSR() \ + WIZCHIP_READ(PHYSR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYSR1 register + * @return uint8_t. Value of @ref PHYSR1 register. + * @sa setPHYSR1() + */ +#define getPHYSR1() \ + WIZCHIP_READ(PHYSR1) + +/** + * For internal uses + * The address of the PHY is fixed as "0x0A". + */ +#define getPHYAR() \ + WIZCHIP_READ(PHYAR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYRAR register + * @return uint8_t. Value of @ref PHYRAR register. + * @sa setPHYRAR() + */ +#define getPHYRAR() \ + WIZCHIP_READ(PHYRAR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYRR register + * @param (uint8_t)phyrar Value to set @ref PHYRR register. + * @sa getPHYRR() + */ +#define setPHYRR(phyrar) \ + WIZCHIP_WRITE(PHYRAR, phyrar) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYDIR register + * @return uint16_t. Value of @ref PHYDIR register. + * @sa setPHYRAR() + */ +//read the value of the phy data input register +#define getPHYDIR() \ + (((uint16_t)WIZCHIP_READ(PHYDIR+1) << 8) + WIZCHIP_READ(PHYDIR)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYDIR register + * @param (uint16_t)phydir Value to set @ref PHYDIR register. + * @sa getPHYDIR() + */ +//write the value of the phy data input register +#define setPHYDIR(phydir) {\ + WIZCHIP_WRITE(PHYDIR+1, (uint8_t)(phydir >> 8)); \ + WIZCHIP_WRITE(PHYDIR, (uint8_t) phydir); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYDOR register + * @return uint16_t. Value of @ref PHYDOR register. + * @sa setPHYDOR() + */ +//read the value of the phy data output register +#define getPHYDOR() \ + (((uint16_t)WIZCHIP_READ(PHYDOR+1) << 8) + WIZCHIP_READ(PHYDOR)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYDOR register + * @param (uint16_t)phydor Value to set @ref PHYDOR register. + * @sa getPHYDOR() + */ +//write the value of the phy data output register +#define setPHYDOR(phydor) {\ + WIZCHIP_WRITE(PHYDOR, (uint8_t)(phydor >> 8)); \ + WIZCHIP_WRITE(PHYDOR+1, (uint8_t) phydor); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYACR register + * @return uint8_t. Value of @ref PHYACR register. + * @sa setPHYACR() + */ +//read the value of the phy action register ***This register will be cleared automatically*** +#define getPHYACR() \ + WIZCHIP_READ(PHYACR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYACR register + * @param (uint8_t)phyacr Value to set @ref PHYACR register. + * @sa getPHYACR() + */ +//write the value of the phy action register +#define setPHYACR(phyacr) \ + WIZCHIP_WRITE(PHYACR,phyacr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYDIVR register + * @param (uint8_t)phydivr Value to set @ref PHYDIVR register. + * @sa getPHYDIVR() + */ +#define setPHYDIVR(phydivr) \ + WIZCHIP_WRITE(PHYDIVR, phydivr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYDIVR register + * @return uint8_t. Value of @ref PHYDIVR register. + * @sa setPHYDIVR() + */ +#define getPHYDIVR() \ + WIZCHIP_READ(PHYDIVR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYCR0 register + * @param (uint8_t)phych0 Value to set @ref PHYCR0 register. + * @sa getPHYCR0() + */ +#define setPHYCR0(phych0) \ + WIZCHIP_WRITE(PHYCR0,phych0) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYCR0 register + * @return uint8_t. Value of @ref PHYCR0 register. + * @sa setPHYCR0() + */ +#define getPHYCR0() \ + WIZCHIP_READ(PHYCR0) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PHYCR1 register + * @param (uint8_t)phycr1 Value to set @ref PHYCR1 register. + * @sa getPHYCR1() + */ +#define setPHYCR1(phycr1) \ + WIZCHIP_WRITE(PHYCR1,phycr1) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PHYCR1 register + * @return uint8_t. Value of @ref PHYCR1 register. + * @sa setPHYCR1() + */ +#define getPHYCR1() \ + WIZCHIP_READ(PHYCR1) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLCR register + * @param (uint8_t)rqcr Value to set @ref SLCR register. + * @sa getSLCR() + */ +#define setSLCR(rqcr) \ + WIZCHIP_WRITE(SLCR, rqcr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLCR register + * @return uint8_t. Value of @ref SLCR register. + * @sa setSLCR() + */ +#define getSLCR() \ + WIZCHIP_READ(SLCR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLRTR register + * @param (uint16_t)slrtr Value to set @ref SLRTR register. + * @sa getSLRTR() + */ +#define setSLRTR(slrtr) \ + WIZCHIP_WRITE(SLRTR, (uint8_t)(slrtr >> 8)); \ + WIZCHIP_WRITE(SLRTR+1, (uint8_t) slrtr); \ + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLRTR register + * @return uint16_t. Value of @ref SLRTR register. + * @sa setSLRTR() + */ +#define getSLRTR() \ + (((uint16_t)WIZCHIP_READ(SLRTR) << 8) + WIZCHIP_READ(SLRTR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLRCR register + * @param (uint8_t)slrcr Value to set @ref SLRCR register. + * @sa getSLRCR() + */ +#define setSLRCR(slrcr) \ + WIZCHIP_WRITE(SLRCR,slrcr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLRCR register + * @return uint8_t. Value of @ref SLRCR register. + * @sa setSLRCR() + */ +#define getSLRCR() \ + WIZCHIP_READ(SLRCR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLPIPR registers + * @param (uint8_t*)slpipr Values to set @ref SLPIPR registers. + * @sa getSLPIPR() + */ +#define setSLPIPR(slpipr) \ + WIZCHIP_WRITE_BUF(SLPIPR,slpipr,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLPIPR registers + * @param (uint8_t*)slpipr Values to get @ref SLPIPR registers. + * @sa getSLPIPR() + */ +#define getSLPIPR(slpipr) \ + WIZCHIP_READ_BUF(SLPIPR,slpipr,4) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLPHAR registers + * @param (uint8_t*)slphar Values to set @ref SLPHAR registers. + * @sa getSLPHAR() + */ +#define setSLPHAR(slphar) \ + WIZCHIP_WRITE_BUF(SLPHAR,slphar,6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLPHAR registers + * @param (uint8_t*)slphar Values to get @ref SLPHAR registers. + * @sa getSLPHAR() + */ +#define getSLPHAR(slphar) \ + WIZCHIP_READ_BUF(SLPHAR,slphar,6) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PINGSEQR register + * @param (uint16_t)pingseqr Value to set @ref PINGSEQR register. + * @sa getPINGSEQR() + */ +#define setPINGSEQR(pingseqr) {\ + WIZCHIP_WRITE(PINGSEQR, (uint8_t)(pingseqr >> 8)); \ + WIZCHIP_WRITE(PINGSEQR+1, (uint8_t) pingseqr); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PINGSEQR register + * @return uint16_t. Value of @ref PINGSEQR register. + * @sa setPINGSEQR() + */ +#define getPINGSEQR() \ + (((uint16_t)WIZCHIP_READ(PINGSEQR) << 8) + WIZCHIP_READ(PINGSEQR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref PINGIDR register + * @param (uint16_t)pingidr Value to set @ref PINGIDR register. + * @sa getPINGIDR() + */ +#define setPINGIDR(pingidr) {\ + WIZCHIP_WRITE(PINGIDR, (uint8_t)(pingidr >> 8)); \ + WIZCHIP_WRITE(PINGIDR+1, (uint8_t) pingidr); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref PINGIDR register + * @return uint16_t. Value of @ref PINGIDR register. + * @sa setPINGIDR() + */ +#define getPINGIDR() \ + (((uint16_t)WIZCHIP_READ(PINGIDR) << 8) + WIZCHIP_READ(PINGIDR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLIMR register + * @param (uint8_t)slimr Value to set @ref SLIMR register. + * @sa getSLIMR() + */ +#define setSLIMR(slimr) \ + WIZCHIP_WRITE(SLIMR, slimr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLIMR register + * @return uint8_t. Value of @ref SLIMR register. + * @sa setSLIMR() + */ +#define getSLIMR() \ + WIZCHIP_READ(SLIMR) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref SLIR register + * @param (uint8_t)slir Value to set @ref SLIR register. + * @sa getSLIMR() + */ +#define setSLIR(slir) \ + WIZCHIP_WRITE(SLIR, slir) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref SLIMR register + * @return uint8_t. Value of @ref SLIMR register. + * @sa setSLIMR() + */ +#define getSLIR() \ + WIZCHIP_READ(SLIR) + +/*Hidden functions for W5100S*/ +#define setDBGOUT(dbgout) {\ + WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout >> 16)); \ + WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout >> 8)); \ + WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout)); \ + } + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref NICMAXCOLR register + * @param (uint8_t)nicmaxcolr Value to set @ref NICMAXCOLR register. + * @sa getNICMAXCOLR() + */ +#define setNICMAXCOLR(nicmaxcolr) \ + WIZCHIP_WRITE(NICMAXCOLR,nicmaxcolr) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref NICMAXCOLR register + * @return uint8_t. Value of @ref NICMAXCOLR register. + * @sa setNICMAXCOLR() + */ +#define getNICMAXCOLR() \ + WIZCHIP_READ(NICMAXCOLR) + +/*Clock lock/unlock*/ + +/** + * @ingroup Common_register_access_function_W5100S + * @brief LOCK Chip Information + * @sa CHIPULLOCK() + */ +#define CHIPLOCK() \ + WIZCHIP_WRITE(CHIPLCKR,0xff) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Unlock Chip Information + * @sa CHIPLOCK() + */ +#define CHIPUNLOCK() \ + WIZCHIP_WRITE(CHIPLCKR,0xCE) + + +/** + * @ingroup Common_register_access_function_W5100S + * @brief LOCK Chip Information + * @sa CHIPULLOCK() + */ +/*Network information lock/unlock*/ +#define NETLOCK() \ + WIZCHIP_WRITE(NETLCKR,0x3A) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Unlock Chip Information + * @sa CHIPLOCK() + */ +#define NETUNLOCK() \ + WIZCHIP_WRITE(NETLCKR,0xC5) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Lock PHYCR0,CR1 Information + * @sa CHIPULLOCK() + */ +/*PHY CR0,CR1 lock/unlock*/ +#define PHYLOCK() \ + WIZCHIP_WRITE(PHYLCKR,0xff) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Lock PHYCR0,CR1 Information + * @sa CHIPULLOCK() + */ +#define PHYUNLOCK() \ + WIZCHIP_WRITE(PHYLCKR,0x53) + +/** + * @ingroup Version register_access_function_W5100SS + * @brief Get version information. + * @return uint16_t. It must be "0x51" + */ +#define getVER() \ + (WIZCHIP_READ(VERR)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Get \ref TCNTR register + * @return uint16_t. Value of @ref TCNTR register. + * @sa setNTCNTR() + */ +/*Get 100us internal counter*/ +#define getTCNTR() \ + (((uint16_t)WIZCHIP_READ(TCNTR) << 8) + WIZCHIP_READ(TCNTR+1)) + +/** + * @ingroup Common_register_access_function_W5100S + * @brief Set \ref TCNTR register + * @param (uint8_t) + Value to set @ref TCNTR register. + * @sa getTCNTCLKR() + */ +/*Reset 100us internal counter(TCNTR)*/ +#define setTCNTCLKR(var) \ + WIZCHIP_WRITE(TCNTCLKR, var) + +/*w5100s only end*/ + + + + + +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @param mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @return Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), ir) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + WIZCHIP_READ(Sn_IR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +#define getSn_PORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa SetSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +#define getSn_DPORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)proto Value to set \ref Sn_PROTO + * @sa getSn_PROTO() + */ +#define setSn_PROTO(sn, proto) \ + WIZCHIP_WRITE(Sn_PROTO(sn), proto) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_PROTO. + * @sa setSn_PROTO() + */ +#define getSn_PROTO(sn) \ + WIZCHIP_READ(Sn_PROTO(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE + * @sa getSn_RXMEM_SIZE() + */ +#define setSn_RXMEM_SIZE(sn, rxmemsize) \ + WIZCHIP_WRITE(RMSR, (WIZCHIP_READ(RMSR) & ~(0x03 << (2*sn))) | (rxmemsize << (2*sn))) +#define setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize) +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_RXMEM. + * @sa setSn_RXMEM_SIZE() + */ +#define getSn_RXMEM_SIZE(sn) \ + ((WIZCHIP_READ(RMSR) & (0x03 << (2*sn))) >> (2*sn)) +#define getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE + * @sa getSn_TXMEM_SIZE() + */ +#define setSn_TXMEM_SIZE(sn, txmemsize) \ + WIZCHIP_WRITE(TMSR, (WIZCHIP_READ(TMSR) & ~(0x03 << (2*sn))) | (txmemsize << (2*sn))) +#define setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_TXMEM_SIZE. + * @sa setSn_TXMEM_SIZE() + */ +#define getSn_TXMEM_SIZE(sn) \ + ((WIZCHIP_READ(TMSR) & (0x03 << (2*sn))) >> (2*sn)) +#define getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +#define getSn_TX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +#define getSn_TX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @regurn uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +#define getSn_RX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR + * @sa getSn_RX_WR() + */ +#define setSn_RX_WR(sn, rxwr) { \ + WIZCHIP_WRITE(Sn_RX_WR(sn), (uint8_t)(rxwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \ + } + + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +#define getSn_RX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set @ref Sn_FRAGR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)frag Value to set \ref Sn_FRAGR + * @sa getSn_FRAG() + */ +#define setSn_FRAGR(sn, fragr) { \ + WIZCHIP_WRITE(Sn_FRAGR(sn), (uint8_t)(fragr >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAGR(sn),1), (uint8_t) fragr); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get @ref Sn_FRAGR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_FRAGR. + * @sa setSn_FRAG() + */ +#define getSn_FRAGR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_FRAGR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAGR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the max RX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_RxMAX(sn) \ + ((uint16_t)(0x0001 << getSn_RXMEM_SIZE(sn)) << 10) + + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the max TX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_TxMAX(sn) \ + ((uint16_t)(0x0001 << getSn_TXMEM_SIZE(sn)) << 10) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the mask of socket sn RX buffer. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_RxMASK(sn) \ + (getSn_RxMAX(sn) - 1) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the mask of socket sn TX buffer + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_TxMASK(sn) \ + (getSn_TxMAX(sn) - 1) + + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the base address of socket sn RX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n RX buffer base address. + */ +uint32_t getSn_RxBASE(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the base address of socket sn TX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n TX buffer base address. + */ +uint32_t getSn_TxBASE(uint8_t sn); + + +/*socket register W5100S only*/ + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set the interrupt mask register of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)imr Value to set \ref Sn_IMR + * @sa getSn_IMR(sn) + */ +#define setSn_IMR(sn,imr) \ + WIZCHIP_WRITE(Sn_IMR(sn),imr) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the interrupt mask register of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n interrupt mask register. + */ +#define getSn_IMR(sn) \ + WIZCHIP_READ(Sn_IMR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set the Sn_MR2 value of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param mr2 Value of Sn_MR2 register to set. + */ +#define setSn_MR2(sn,mr2) \ + WIZCHIP_WRITE(Sn_MR2(sn), mr2) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the Sn_MR2 value of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n Sn_MR2 register. + */ +#define getSn_MR2(sn) \ + WIZCHIP_READ(Sn_MR2(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set the Sn_KPALVTR value of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param kpalvtr Value of the Sn_KPALVTR register to set. + */ +#define setSn_KPALVTR(sn,kpalvtr) \ + WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvtr) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the Sn_KPALVTR value of socket sn + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of the Sn_KPALVTR register. + */ +#define getSn_KPALVTR(sn) \ + WIZCHIP_READ(Sn_KPALVTR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the Sn_TSR register of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of the Socket n Sn_TSR register. + */ +#define getSn_TSR(sn) \ + WIZCHIP_READ(Sn_TSR(sn)) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set the Sn_RTR register of socket sn. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rtr Value of the Socket n Sn_RTR register to set. + */ +#define setSn_RTR(sn,rtr) { \ + WIZCHIP_WRITE(Sn_RTR(sn), (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RTR(sn),1), (uint8_t) rtr); \ + } + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the Sn_RTR register of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of the Socket n Sn_RTR register. + */ +#define getSn_RTR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RTR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RTR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Set the Sn_RCR register of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of the Socket n Sn_RCR register to set. + */ +#define setSn_RCR(sn,rcr) \ + WIZCHIP_WRITE(Sn_RCR(sn),rcr) + +/** + * @ingroup Socket_register_access_function_W5100S + * @brief Get the Sn_RCR of socket sn. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of the Socket n Sn_RCR. + */ +#define getSn_RCR(sn) \ + WIZCHIP_READ(Sn_RCR(sn)) + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @ingroup Basic_IO_function_W5100S + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100S + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to wizdata(pointer variable) of the length of len(variable) bytes. + * This function is being called by recv() also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5100S + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of len(variable) bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +/** + * @ingroup Special_function_W5100S + * @brief Write data to the PHY via MDC/MDIO interface. + * @details Write command data to the PHY via MDC/MDIO interface. + * @param (uint8_t)PHYMDIO_regadr Address of the PHY register. It should be PHYMDIO_BMCR or PHYMDIO_BMSR. + * @param (uint16_t)var Data to write to the PHY register. Please refer to the bit definitions of the BMCR and BMSR register. + */ +void wiz_mdio_write(uint8_t PHYMDIO_regadr, uint16_t var); + +/** + * @ingroup Special_function_W5100S + * @brief Read data from the PHY via MDC/MDIO interface. + * @details Read command or status data from the PHY via MDC/MDIO interface. + * @param (uint8_t)PHYMDIO_regadr Address of the PHY register. It should be PHYMDIO_BMCR or PHYMDIO_BMSR. + * @return The value of the PHY register + */ +uint16_t wiz_mdio_read(uint8_t PHYMDIO_regadr); + +/** + * @ingroup Special_function_W5100S + * @brief Delay function + * @details Delay function using internal 100us timer of the W5100S + * @param (uint32_t)ms Time to delay in milliseconds. + */ +void wiz_delay_ms(uint32_t ms); + +/// @cond DOXY_APPLY_CODE +#endif +/// @endcond + +#ifdef __cplusplus +} +#endif + +#endif //_W5100S_H_ + + + diff --git a/Libraries/Ethernet/W5200/w5200.c b/Libraries/Ethernet/W5200/w5200.c new file mode 100644 index 0000000..52bd5f5 --- /dev/null +++ b/Libraries/Ethernet/W5200/w5200.c @@ -0,0 +1,353 @@ +//***************************************************************************** +// +//! \file w5200.c +//! \brief W5200 HAL Interface. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include "w5200.h" + +#if (_WIZCHIP_ == 5200) +/** +@brief This function writes the data into W5200 registers. +*/ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) +{ + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_); // Data write command and Write data length upper + WIZCHIP.IF.SPI._write_byte(0x01); // Write data length lower + WIZCHIP.IF.SPI._write_byte(wb); // Data write (write 1byte data) + +#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with W5300 + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF)); + //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF)); + WIZCHIP.IF.BUS._write_data(IDM_DR,wb); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} +/** +@brief This function reads the value from W5200 registers. +*/ +uint8_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint8_t ret; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + WIZCHIP.IF.SPI._write_byte(_W5200_SPI_READ_); // Read data length upper + WIZCHIP.IF.SPI._write_byte(0x01); // Data length lower + ret = WIZCHIP.IF.SPI._read_byte(); + +#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) ) + + //add indirect bus + //M20150601 : Rename the function for integrating with W5300 + //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF)); + //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF)); + ret = WIZCHIP.IF.BUS._read_data(IDM_DR); + +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + + +/** +@brief This function writes into W5200 memory(Buffer) +*/ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint16_t i = 0; + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_ | ((len & 0x7F00) >> 8)); // Write data op code and length upper + WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0); // length lower + for(i = 0; i < len; i++) + WIZCHIP.IF.SPI._write_byte(pBuf[i]); + +#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) ) + //M20150601 : Rename the function for integrating with W5300 + /* + WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR() | MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF)); + for(i = 0 ; i < len; i++) + WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +/** +@brief This function reads into W5200 memory(Buffer) +*/ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint16_t i = 0; + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + WIZCHIP.IF.SPI._write_byte( _W5200_SPI_READ_ | ((len & 0x7F00) >> 8)); // Write data op code and length upper + WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0); // length lower + for(i = 0; i < len; i++) + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + +#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) ) + //M20150601 : Rename the function for integrating with W5300 + /* + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI); + WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_byte(IDM_DR); + WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); + */ + setMR(getMR() | MR_AI); + WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF)); + for(i = 0 ; i < len; i++) + pBuf[i] = WIZCHIP.IF.BUS._read_data(IDM_DR); + setMR(getMR() & ~MR_AI); +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +/////////////////////////////////// +// Socket N regsiter IO function // +/////////////////////////////////// + +uint16_t getSn_TX_FSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_TX_FSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + } + }while (val != val1); + return val; +} + + +uint16_t getSn_RX_RSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + do + { + val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_RX_RSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + } + }while (val != val1); + return val; +} + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// + +uint16_t getSn_RxBASE(uint8_t sn) +{ + int8_t i; + uint16_t rxbase = _WIZCHIP_IO_RXBUF_; + for(i = 0; i < sn; i++) + rxbase += getSn_RxMAX(i); + return rxbase; +} + +uint16_t getSn_TxBASE(uint8_t sn) +{ + int8_t i; + uint16_t txbase = _WIZCHIP_IO_TXBUF_; + for(i = 0; i < sn; i++) + txbase += getSn_TxMAX(i); + return txbase; +} + +/** +@brief This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip. + +This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer +register. User should read upper byte first and lower byte later to get proper value. +And this function is being used for copy the data form application buffer to Transmite +buffer of the chip. It calculate the actual physical address where one has to write +the data in transmite buffer. Here also take care of the condition while it exceed +the Tx memory uper-bound of socket. + +*/ + +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + + uint16_t ptr; + uint16_t size; + uint16_t dst_mask; + uint8_t * dst_ptr; + + ptr = getSn_TX_WR(sn); + + + dst_mask = (uint32_t)ptr & getSn_TxMASK(sn); + dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn) + dst_mask); + + if (dst_mask + len > getSn_TxMAX(sn)) + { + size = getSn_TxMAX(sn) - dst_mask; + WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size); + wizdata += size; + size = len - size; + dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn)); + WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size); + } + else + { + WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, len); + } + + ptr += len; + + setSn_TX_WR(sn, ptr); +} + + +/** +@brief This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer. + +This function read the Rx read pointer register +and after copy the data from receive buffer update the Rx write pointer register. +User should read upper byte first and lower byte later to get proper value. +It calculate the actual physical address where one has to read +the data from Receive buffer. Here also take care of the condition while it exceed +the Rx memory uper-bound of socket. +*/ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr; + uint16_t size; + uint16_t src_mask; + uint8_t * src_ptr; + + ptr = getSn_RX_RD(sn); + + src_mask = (uint32_t)ptr & getSn_RxMASK(sn); + src_ptr = (uint8_t *)((uint32_t)getSn_RxBASE(sn) + src_mask); + + if( (src_mask + len) > getSn_RxMAX(sn) ) + { + size = getSn_RxMAX(sn) - src_mask; + WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size); + wizdata += size; + size = len - size; + src_ptr = (uint8_t*)((uint32_t)getSn_RxBASE(sn)); + WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size); + } + else + { + WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, len); + } + + ptr += len; + + setSn_RX_RD(sn, ptr); +} + +void wiz_recv_ignore(uint8_t sn, uint16_t len) +{ + uint16_t ptr; + + ptr = getSn_RX_RD(sn); + + ptr += len; + setSn_RX_RD(sn,ptr); +} + +#endif diff --git a/Libraries/Ethernet/W5200/w5200.h b/Libraries/Ethernet/W5200/w5200.h new file mode 100644 index 0000000..0fcfe3e --- /dev/null +++ b/Libraries/Ethernet/W5200/w5200.h @@ -0,0 +1,2110 @@ +//* **************************************************************************** +//! \file w5200.h +//! \brief W5200 HAL Header File. +//! \version 1.0.0 +//! \date 2015/03/23 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef _W5200_H +#define _W5200_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "wizchip_conf.h" + +/// \cond DOXY_APPLY_CODE +#if (_WIZCHIP_ == 5200) +/// \endcond + +#define _WIZCHIP_SN_BASE_ (0x4000) +#define _WIZCHIP_SN_SIZE_ (0x0100) +#define _WIZCHIP_IO_TXBUF_ (0x8000) /* Internal Tx buffer address of the iinchip */ +#define _WIZCHIP_IO_RXBUF_ (0xC000) /* Internal Rx buffer address of the iinchip */ + +#define _W5200_SPI_READ_ (0x00 << 7) ///< SPI interface Read operation in Control Phase +#define _W5200_SPI_WRITE_ (0x01 << 7) ///< SPI interface Write operation in Control Phase + +#define WIZCHIP_CREG_BLOCK 0x00 ///< Common register block +#define WIZCHIP_SREG_BLOCK(N) (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + N) ///< Increase offset address + +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) + #define IDM_AR0 ((_WIZCHIP_IO_BASE_ + 0x0001)) + #define IDM_AR1 ((_WIZCHIP_IO_BASE_ + 0x0002)) + #define IDM_DR ((_WIZCHIP_IO_BASE_ + 0x0003)) + #define _W5200_IO_BASE_ 0x0000 +#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define _W5200_IO_BASE_ 0x0000 +#endif + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + + +//----------- defgroup -------------------------------- + +/** + * @defgroup W5200 W5200 + * @brief WHIZCHIP register defines and I/O functions of @b W5200. + * + * - @ref WIZCHIP_register_W5200 : @ref Common_register_group_W5200 and @ref Socket_register_group_W5200 + * - @ref WIZCHIP_IO_Functions_W5200 : @ref Basic_IO_function_W5200, @ref Common_register_access_function_W5200 and @ref Socket_register_group_W5200 + */ + + /** + * @defgroup WIZCHIP_register_W5200 WIZCHIP register + * @ingroup W5200 + * @brief WIZCHIP register defines register group of W5200 . + * + * - \ref Common_register_group_W5200 : Common register group w5200 + * - \ref Socket_register_group_W5200 : \c SOCKET n register group w5200 + */ + + +/** + * @defgroup WIZCHIP_IO_Functions_W5200 WIZCHIP I/O functions + * @ingroup W5200 + * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5200. + * + * - Basic I/O function \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n + * + * - \ref Common_register_group_W5200 access functions \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), getIR2(), setIR2(), getIMR2(), setIMR2(), getINTLEVEL(), setINTLEVEL() + * -# Network Information \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC() + * -# @b etc. \n + * getPHYSTATUS(), getVERSIONR() \n\n + * + * - \ref Socket_register_group_W5200 access functions \n + * -# SOCKET control \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() + * -# SOCKET information \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# SOCKET communication \n + * getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR() + * -# IP header field \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + +/** + * @defgroup Common_register_group_W5200 Common register + * @ingroup WIZCHIP_register_W5200 + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa INTLEVEL, IR, _IMR_, IR2, IMR2 : Interrupt. + * @sa _RTR_, _RCR_ : Data retransmission. + * @sa PTIMER, PMAGIC : PPPoE. + * @sa PHYSTATUS, VERSIONR : etc. + */ + + + /** + * @defgroup Socket_register_group_W5200 Socket register + * @ingroup WIZCHIP_register_W5200 + * @brief Socket register group\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAG : Internet protocol. + * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + /** + * @defgroup Basic_IO_function_W5200 Basic I/O function + * @ingroup WIZCHIP_IO_Functions_W5200 + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function_W5200 Common register access functions + * @ingroup WIZCHIP_IO_Functions_W5200 + * @brief These are functions to access common registers. + */ + +/** + * @defgroup Socket_register_access_function_W5200 Socket register access functions + * @ingroup WIZCHIP_IO_Functions_W5200 + * @brief These are functions to access socket registers. + */ + + //----------------------------------------------------------------------------------- + +//----------------------------- W5200 Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group_W5200 + * @brief Mode Register address(R/W)\n + * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of \ref MR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved AI IND
+ * - \ref MR_RST : Reset + * - \ref MR_WOL : Wake on LAN + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_AI : Address Auto-Increment in Indirect Bus Interface + * - \ref MR_IND : Indirect Bus Interface mode + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) + #define MR (_WIZCHIP_IO_BASE_ + (0x0000)) // Mode +#else + #define MR (_W5200_IO_BASE_ + (0x0000)) // Mode +#endif + +/** + * @ingroup Common_register_group_W5200 + * @brief Gateway IP Register address(R/W) + * @details \ref GAR configures the default gateway address. + */ +#define GAR (_W5200_IO_BASE_ + (0x0001)) // GW Address + +/** + * @ingroup Common_register_group_W5200 + * @brief Subnet mask Register address(R/W) + * @details \ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5200_IO_BASE_ + (0x0005)) // SN Mask Address + +/** + * @ingroup Common_register_group_W5200 + * @brief Source MAC Register address(R/W) + * @details \ref SHAR configures the source hardware address. + */ +#define SHAR (_W5200_IO_BASE_ + (0x0009)) // Source Hardware Address + +/** + * @ingroup Common_register_group_W5200 + * @brief Source IP Register address(R/W) + * @details \ref SIPR configures the source IP address. + */ +#define SIPR (_W5200_IO_BASE_ + (0x000F)) // Source IP Address + +// Reserved (_W5200_IO_BASE_ + (0x0013)) +// Reserved (_W5200_IO_BASE_ + (0x0014)) + +/** + * @ingroup Common_register_group_W5200 + * @brief Interrupt Register(R/W) + * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host. + * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of \ref IR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
CONFLICT Reserved PPPoE Reserved Reserved Reserved Reserved Reserved
+ * - \ref IR_CONFLICT : IP conflict + * - \ref IR_PPPoE : PPPoE connection close + */ +#define IR (_W5200_IO_BASE_ + (0x0015)) // Interrupt + +/** + * @ingroup Common_register_group_W5200 + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR2. + * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR2 is Interrupt will be issued. + * In other words, if a bit of \ref _IMR_, an interrupt will be not issued even if the corresponding bit of \ref IR2 is set + * @note This Register is same operated as SMIR of W5100, W5300 and W5550.\n + * So, \ref setSIMR() set a value to _IMR_ for integrating with ioLibrary + */ +#define _IMR_ (_W5200_IO_BASE_ + (0x0016)) // Socket Interrupt Mask + +/** + * @ingroup Common_register_group_W5200 + * @brief Timeout register address( 1 is 100us )(R/W) + * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0. + * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5200 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the \ref _RTR_ time, W5200 retransmits the packet or issues timeout. + */ +#define _RTR_ (_W5200_IO_BASE_ + (0x0017)) // Retry Time + +/** + * @ingroup Common_register_group_W5200 + * @brief Retry count register(R/W) + * @details \ref _RCR_ configures the number of time of retransmission. + * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1'). + */ +#define _RCR_ (_W5200_IO_BASE_ + (0x0019)) // Retry Count + +// Reserved (_W5200_IO_BASE_ + (0x001A)) +// Reserved (_W5200_IO_BASE_ + (0x001B)) + +/** + * @ingroup Common_register_group_W5200 + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PATR notifies authentication method that has been agreed at the connection with + * PPPoE Server. W5200 supports two types of Authentication method - PAP and CHAP. + */ +#define PATR (_W5200_IO_BASE_ + (0x001C)) + +/** + * @ingroup Common_register_group_W5200 + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PPPALGO notifies authentication algorithm in PPPoE mode. For detailed information, + * please refer to PPPoE application note. + */ +#define PPPALGO (_W5200_IO_BASE_ + (0x001E)) // Authentication Algorithm in PPPoE + +/** + * @ingroup Common_register_group_W5200 + * @brief chip version register address(R) + * @details \ref VERSIONR always indicates the W5200 version as @b 0x03. + */ +#define VERSIONR (_W5200_IO_BASE_ + (0x001F)) // Chip version + +// Reserved (_W5200_IO_BASE_ + (0x0020)) +// Reserved (_W5200_IO_BASE_ + (0x0021)) +// Reserved (_W5200_IO_BASE_ + (0x0022)) +// Reserved (_W5200_IO_BASE_ + (0x0023)) +// Reserved (_W5200_IO_BASE_ + (0x0024)) +// Reserved (_W5200_IO_BASE_ + (0x0025)) +// Reserved (_W5200_IO_BASE_ + (0x0026)) +// Reserved (_W5200_IO_BASE_ + (0x0027)) + +/** + * @ingroup Common_register_group_W5200 + * @brief PPP LCP Request Timer register in PPPoE mode(R) + * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER (_W5200_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer + +/** + * @ingroup Common_register_group_W5200 + * @brief PPP LCP Magic number register in PPPoE mode(R) + * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC (_W5200_IO_BASE_ + (0x0029)) // PPP LCP Magic number + +// Reserved (_W5200_IO_BASE_ + (0x002A)) +// Reserved (_W5200_IO_BASE_ + (0x002B)) +// Reserved (_W5200_IO_BASE_ + (0x002C)) +// Reserved (_W5200_IO_BASE_ + (0x002D)) +// Reserved (_W5200_IO_BASE_ + (0x002E)) +// Reserved (_W5200_IO_BASE_ + (0x002F)) + +/** + * @ingroup Common_register_group_W5200 + * @brief Set Interrupt low level timer register address(R/W) + * @details \ref INTLEVEL configures the Interrupt Assert Time. + */ +#define INTLEVEL (_W5200_IO_BASE_ + (0x0030)) // Interrupt Low Level Timer + +// Reserved (_W5200_IO_BASE_ + (0x0032)) +// Reserved (_W5200_IO_BASE_ + (0x0033)) + +/** + * @ingroup Common_register_group_W5200 + * @brief Socket Interrupt Register(R/W) + * @details \ref IR2 indicates the interrupt status of Socket.\n + * Each bit of \ref IR2 be still until \ref Sn_IR is cleared by the host.\n + * If \ref Sn_IR is not equal to x00 the n-th bit of \ref IR2 is and INTn PIN is asserted until \ref IR2 is x00 */ +#define IR2 (_W5200_IO_BASE_ + (0x0034)) // Socket Interrupt + +/** + * @ingroup Common_register_group_W5200 + * @brief PHYSTATUS(R/W) + * @details \ref PHYSTATUS is the Register to indicate W5200 status of PHY. + * + * + * + *
7 6 5 4 3 2 1 0
Reserved Reserved LINK POWERSAVE POWERDOWN Reserved Reserved Reserved
+ * - \ref PHYSTATUS_LINK : Link Status Register[Read Only] + * - \ref PHYSTATUS_POWERSAVE : Power save mode of PHY[R/W] + * - \ref PHYSTATUS_POWERDOWN : Power down mode of PHY[R/W] + */ +#define PHYSTATUS (_W5200_IO_BASE_ + (0x0035)) // PHY Status + +/** + * @ingroup Common_register_group_W5200 + * @brief Interrupt mask register(R/W) + * @details \ref IMR2 is used to mask interrupts. Each bit of \ref _IMR_ corresponds to each bit of \ref IR. + * When a bit of \ref IMR2 is and the corresponding bit of \ref IR is an interrupt will be issued. In other words, + * if a bit of \ref IMR2 is an interrupt will not be issued even if the corresponding bit of \ref IR is \n\n + * Each bit of \ref IMR2 defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
IM_IR7 Reserved IM_IR5 Reserved Reserved Reserved Reserved Reserved
+ * - \ref IM_IR7 : IP Conflict Interrupt Mask + * - \ref IM_IR5 : PPPoE Close Interrupt Mask + * @note This Register is same operated as _IMR_ of W5100, W5300 and W5550.\n + * So, \ref setIMR() set a value to IMR2 for integrating with ioLibrary + */ +#define IMR2 (_W5200_IO_BASE_ + (0x0036)) // Interrupt Mask + + +//----------------------------- W5200 Socket Registers ----------------------------- + +//--------------------------- For Backward Compatibility --------------------------- + +/** + * @ingroup Socket_register_group_W5200 + * @brief socket Mode register(R/W) + * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of \ref Sn_MR defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
MULTI MF ND/MC Reserved Protocol[3] Protocol[2] Protocol[1] Protocol[0]
+ * - \ref Sn_MR_MULTI : Support UDP Multicasting + * - \ref Sn_MR_MF : Support MACRAW + * - \ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - \ref Sn_MR_MC : IGMP version used in UDP mulitcasting + * - Protocol + * + * + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
+ * - In case of Socket 0 + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 1 0 0 MACRAW
0 1 0 1 PPPoE
+ * - \ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - \ref Sn_MR_UDP : UDP + * - \ref Sn_MR_TCP : TCP + * - \ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5200 accepts the command, the \ref Sn_CR register is automatically cleared to 0x00. + * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR. + * - \ref Sn_CR_OPEN : Initialize or open socket. + * - \ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) + * - \ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) + * - \ref Sn_CR_DISCON : Send closing request in TCP mode. + * - \ref Sn_CR_CLOSE : Close socket. + * - \ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - \ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - \ref Sn_CR_SEND_KEEP : Send keep alive message. + * - \ref Sn_CR_RECV : Update RX buffer pointer and receive data. + * - In case of S0_MR(P3:P0) = S0_MR_PPPoE + * + * + * + * + * + * + * + *
Value Symbol Description
0x23 PCON PPPoE connection begins by transmitting PPPoE discovery packet
0x24 PDISCON Closes PPPoE connection
0x25 PCR In each phase, it transmits REQ message.
0x26 PCN In each phase, it transmits NAK message.
0x27 PCJ In each phase, it transmits REJECT message.
+ */ +#define Sn_CR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Socket interrupt register(R) + * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit of \ref Sn_IMR is the corresponding bit of \ref Sn_IR becomes \n + * In order to clear the \ref Sn_IR bit, the host should write the bit to \n + * + * + * + *
7 6 5 4 3 2 1 0
PRECV PFAIL PNEXT SEND_OK TIMEOUT RECV DISCON CON
+ * - \ref Sn_IR_PRECV : PPP Receive Interrupt + * - \ref Sn_IR_PFAIL : PPP Fail Interrupt + * - \ref Sn_IR_PNEXT : PPP Next Phase Interrupt + * - \ref Sn_IR_SENDOK : SEND_OK Interrupt + * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt + * - \ref Sn_IR_RECV : RECV Interrupt + * - \ref Sn_IR_DISCON : DISCON Interrupt + * - \ref Sn_IR_CON : CON Interrupt + */ +#define Sn_IR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Socket status register(R) + * @details \ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - \ref SOCK_CLOSED : Closed + * - \ref SOCK_INIT : Initiate state + * - \ref SOCK_LISTEN : Listen state + * - \ref SOCK_ESTABLISHED : Success to connect + * - \ref SOCK_CLOSE_WAIT : Closing state + * - \ref SOCK_UDP : UDP socket + * - \ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - \ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - \ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - \ref SOCK_FIN_WAIT : Connection state + * - \ref SOCK_CLOSING : Closing state + * - \ref SOCK_TIME_WAIT : Closing state + * - \ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register + +/** + * @ingroup Socket_register_group_W5200 + * @brief source port register(R/W) + * @details \ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered. +*/ +#define Sn_PORT(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Peer MAC register address(R/W) + * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief Peer IP register address(R/W) + * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of TCP server before CONNECT command. + * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief Peer port register address(R/W) + * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command. + * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief IP Protocol(PROTO) Register(R/W) + * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is + * valid only in IPRAW mode, and ignored in other modes. + */ +#define Sn_PROTO(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode + +/** + * @ingroup Socket_register_group_W5200 + * @brief IP Type of Service(TOS) Register(R/W) + * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(sn) (WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register + +/** + * @ingroup Socket_register_group_W5200 + * @brief IP Time to live(TTL) Register(R/W) + * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register + +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C)) +// Reserved (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D)) + +/** + * @ingroup Socket_register_group_W5200 + * @brief Receive memory size register(R/W) + * @details \ref Sn_RXMEM_SIZE configures the RX buffer block size of Socket n. + * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data cannot be normally received from a peer. + * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, + * user can re-configure its size using \ref Sn_RXMEM_SIZE. The total sum of \ref Sn_RXMEM_SIZE can not be exceed 16Kbytes. + * When exceeded, the data reception error is occurred. + */ +#define Sn_RXMEM_SIZE(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001E)) // Receive memory size reigster + +/** + * @ingroup Socket_register_group_W5200 + * @brief Transmit memory size register(R/W) + * @details \ref Sn_TXMEM_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data can't be normally transmitted to a peer. + * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, + * user can be re-configure its size using \ref Sn_TXMEM_SIZE. The total sum of \ref Sn_TXMEM_SIZE can not be exceed 16Kbytes. + * When exceeded, the data transmission error is occurred. + */ +#define Sn_TXMEM_SIZE(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001F)) // Transmit memory size reigster + +/** + * @ingroup Socket_register_group_W5200 + * @brief Transmit free memory size register(R) + * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE. + * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Transmit memory read pointer register address(R) + * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief Transmit memory write pointer register address(R/W) + * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address + +/** + * @ingroup Socket_register_group_W5200 + * @brief Received data size register(R) + * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between + * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD) + */ +#define Sn_RX_RSR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Read point of Receive memory(R/W) + * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5200. + */ +#define Sn_RX_RD(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory + +/** + * @ingroup Socket_register_group_W5200 + * @brief Write point of Receive memory(R) + * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory + +/** + * @ingroup Socket_register_group_W5200 + * @brief socket interrupt mask register(R) + * @details \ref Sn_IMR masks the interrupt of Socket n. + * Each bit corresponds to each bit of \ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of \ref Sn_IMR is + * the corresponding bit of \ref Sn_IR becomes When both the corresponding bit of \ref Sn_IMR and \ref Sn_IR are and the n-th bit of \ref IR is + * Host is interrupted by asserted INTn PIN to low. + */ +#define Sn_IMR(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002C)) // socket interrupt mask register + +/** + * @ingroup Socket_register_group_W5200 + * @brief Fragment field value in IP header register(R/W) + * @details \ref Sn_FRAG configures the FRAG(Fragment field in IP header). + */ +#define Sn_FRAG(sn) (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002D)) // frag field value in IP header register + + +//----------------------------- W5200 Register values ----------------------------- + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 ///< reset + +/** + * @brief Wake on LAN + * @details 0 : Disable WOL mode\n + * 1 : Enable WOL mode\n + * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. + * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (\ref Sn_MR) for opening Socket.) + * @note The magic packet over UDP supported by W5200 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and + * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. + */ +#define MR_WOL 0x20 ///< Wake on Lan + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 ///< ping block + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be '1'. + */ +#define MR_PPPOE 0x08 ///< enable pppoe + +/** + * @brief Address Auto-Increment in Indirect Bus Interface + * @details 0 : Disable auto-increment \n + * 1 : Enable auto-incremente \n + * At the Indirect Bus Interface mode, if this bit is set as ��1��, the address will + * be automatically increased by 1 whenever read and write are performed. + */ +#define MR_AI 0x02 ///< auto-increment in indirect mode + +/** + * @brief Indirect Bus Interface mode + * @details 0 : Disable Indirect bus Interface mode \n + * 1 : Enable Indirect bus Interface mode \n + * If this bit is set as ��1��, Indirect Bus Interface mode is set. + */ +#define MR_IND 0x01 ///< enable indirect mode + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 ///< check ip confict + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 ///< get the PPPoE close message + +/** + * @brief Link Status [Read Only] + * @details 0: Link down \n 1: Link up \n + */ +#define PHYSTATUS_LINK 0x20 + +/** + * @brief Power save mode of PHY + * @details 0: Disable Power save mode \n 1: Enable Power save mode \n + */ +#define PHYSTATUS_POWERSAVE 0x10 + +/** + * @brief Power down mode of PHY + * @details 0: Disable Power down mode \n 1: Enable Power down mode\n + */ +#define PHYSTATUS_POWERDOWN 0x08 + +// Sn_MR values +/* Sn_MR Default values */ +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 ///< unused socket + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 ///< TCP + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 ///< UDP +#define Sn_MR_IPRAW 0x03 ///< IP LAYER RAW SOCK + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 ///< MAC LAYER RAW SOCK + +/** + * @brief PPPoE + * @details This configures the protocol mode of Socket n. + * @note PPPoE mode should be only used in Socket 0. + */ +#define Sn_MR_PPPOE 0x05 ///< PPPoE + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001).\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_. + */ +#define Sn_MR_ND 0x20 ///< No Delayed Ack(TCP) flag + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010).\n + * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of \ref Sn_CR. + */ +#define Sn_MR_MC Sn_MR_ND ///< Select IGMP version 1(0) or 2(1) + +/** + * @brief Multicast Blocking in \ref Sn_MR_MACRAW mode + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1') + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MF 0x40 ///< Use MAC filter +#define Sn_MR_MFEN Sn_MR_MF + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010).\n + * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of \ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 ///< support multicating + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n + * + * + * + * + * + * + * + * + *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000) --
Sn_MR_TCP (001) SOCK_INIT (0x13)
Sn_MR_UDP (010) SOCK_UDP (0x22)
S0_MR_IPRAW (011) SOCK_IPRAW (0x32)
S0_MR_MACRAW (100) SOCK_MACRAW (0x42)
S0_MR_PPPoE (101) SOCK_PPPoE (0x5F)
+ */ +#define Sn_CR_OPEN 0x01 ///< initialize or open socket + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).// + * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.// + * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.// + * When a 'TCP client' connection request is successfully established, + * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes + * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 ///< wait connection request in tcp mode(Server mode) + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to TCP serverconfigured by \ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as TCP client + */ +#define Sn_CR_CONNECT 0x04 ///< send connection request in tcp mode(Client mode) + +/** + * @brief Send closing request in TCP mode + * @details Regardless of TCP serveror TCP client the DISCON command processes the disconnect-process (Active closeor Passive close.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 ///< send closing reqeuset in tcp mode + +/** + * @brief Close socket + * @details Sn_SR is changed to \ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (\ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/** + * @brief PPPoE connection + * @details PPPoE connection begins by transmitting PPPoE discovery packet + */ +#define Sn_CR_PCON 0x23 + +/** + * @brief Closes PPPoE connection + * @details Closes PPPoE connection + */ +#define Sn_CR_PDISCON 0x24 + +/** + * @brief REQ message transmission + * @details In each phase, it transmits REQ message. + */ +#define Sn_CR_PCR 0x25 + +/** + * @brief NAK massage transmission + * @details In each phase, it transmits NAK message. + */ +#define Sn_CR_PCN 0x26 + +/** + * @brief REJECT message transmission + * @details In each phase, it transmits REJECT message. + */ +#define Sn_CR_PCJ 0x27 + +/* Sn_IR values */ +/** + * @brief PPP Receive Interrupt + * @details PPP Receive Interrupts when the option which is not supported is received. + */ +#define Sn_IR_PRECV 0x80 + +/** + * @brief PPP Fail Interrupt + * @details PPP Fail Interrupts when PAP Authentication is failed. + */ +#define Sn_IR_PFAIL 0x40 + +/** + * @brief PPP Next Phase Interrupt + * @details PPP Next Phase Interrupts when the phase is changed during ADSL connection process. + */ +#define Sn_IR_PNEXT 0x20 + +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 ///< complete sending + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 ///< assert timeout + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 ///< closed + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\n + * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n + * After \ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 ///< init state + +/** + * @brief Listen state + * @details This indicates Socket n is operating as TCP servermode and waiting for connection-request (SYN packet) from a peer (TCP client).\n + * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1'). + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to \ref SOCK_ESTABLISHED. \n + * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to \ref SOCK_ESTABLISHED when the TCP SERVERprocessed the SYN packet from the TCP CLIENTduring \ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (\ref Sn_IR[TIMEOUT] = '1'). + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n + * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 ///< udp socket + +/** +* @brief IP raw mode socket + * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when Sn_MR (P3:P0) is + * Sn_MR_IPRAW and OPEN command is used.\n + * IP Packet can be transferred without a connection similar to the UDP mode. +*/ +#define SOCK_IPRAW 0x32 ///< ip raw mode socket + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100)and OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 ///< mac raw mode socket + +/** + * @brief PPPoE mode socket + * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR + * (P3:P0)=S0_MR_PPPoE.\n + * It is temporarily used at the PPPoE +connection. + */ +#define SOCK_PPPOE 0x5F ///< pppoe socket + +// IP PROTOCOL +#define IPPROTO_IP 0 ///< Dummy for IP +#define IPPROTO_ICMP 1 ///< Control message protocol +#define IPPROTO_IGMP 2 ///< Internet group management protocol +#define IPPROTO_GGP 3 ///< GW^2 (deprecated) +#define IPPROTO_TCP 6 ///< TCP +#define IPPROTO_PUP 12 ///< PUP +#define IPPROTO_UDP 17 ///< UDP +#define IPPROTO_IDP 22 ///< XNS idp +#define IPPROTO_ND 77 ///< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 ///< Raw IP packet + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +#ifdef _exit +#undef _exit +#endif + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + + +//////////////////////// +// Basic I/O Function // +//////////////////////// +/** + * @ingroup Basic_IO_function_W5200 + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function_W5200 + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function_W5200 + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5200 + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + + +///////////////////////////////// +// Common Register IO function // +///////////////////////////////// + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define setMR(mr) WIZCHIP_WRITE(MR,mr) +#else + #define setMR(mr) (*((uint8_t*)MR) = mr) +#endif + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref MR. + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #define getMR() WIZCHIP_READ(MR) +#else + #define getMR() (*(uint8_t*)MR) +#endif + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set @ref GAR. + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref GAR. + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set @ref SUBR. + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @note If subr is null pointer, set the backup subnet to SUBR. \n + * If subr is 0.0.0.0, back up SUBR and clear it. \n + * Otherwize, set subr to SUBR + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR, subr,4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref SUBR. + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set @ref SHAR. + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref SHAR. + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() +*/ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref SIPR. + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref IR register + * @param (uint8_t)ir Value to set \ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xA0)) +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref IR register + * @return uint8_t. Value of \ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xA0) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref IMR2 register + * @param (uint8_t)imr Value to set @ref IMR2 register. + * @sa getIMR() + */ +//M20150410 : Replace _IMR_ with IMR2 for integrating with ioLibrary +/* +#define setIMR(imr) \ + WIZCHIP_WRITE(_IMR_, imr) +*/ +#define setIMR(imr) \ + WIZCHIP_WRITE(IMR2, imr & 0xA0) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref IMR2 register + * @return uint8_t. Value of @ref IMR2 register. + * @sa setIMR() + */ +//M20150410 : Replace _IMR_ with IMR2 for integrating with ioLibrary +/* +#define getIMR() \ + WIZCHIP_READ(_IMR_) +*/ +#define getIMR() \ + (WIZCHIP_READ(IMR2) & 0xA0) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref _RTR_ register + * @param (uint16_t)rtr Value to set @ref _RTR_ register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(_RTR_, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref _RTR_ register + * @return uint16_t. Value of @ref _RTR_ register. + * @sa setRTR() + */ +#define getRTR() \ + (((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1))) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref _RCR_ register + * @param (uint8_t)rcr Value to set @ref _RCR_ register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(_RCR_, rcr) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref _RCR_ register + * @return uint8_t. Value of @ref _RCR_ register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(_RCR_) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref PATR register + * @return uint16_t. Value to set \ref PATR register + */ +#define getPATR() \ + (((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1))) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref PPPALGO register + * @return uint8_t. Value to set \ref PPPALGO register + */ +#define getPPPALGO() \ + WIZCHIP_READ(PPPALGO) + + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref VERSIONR register + * @return uint8_t. Value to set \ref VERSIONR register + */ +#define getVERSIONR() \ + WIZCHIP_READ(VERSIONR) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref PTIMER register + * @param (uint8_t)ptimer Value to set \ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set @ref INTLEVEL register + * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. + * @sa getINTLEVEL() + */ +#define setINTLEVEL(intlevel) {\ + WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ + } +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get @ref INTLEVEL register + * @return uint16_t. Value of @ref INTLEVEL register. + * @sa setINTLEVEL() + */ +#define getINTLEVEL() \ + (((uint16_t)WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref IR2 register + * @param (uint8_t)ir2 Value to set \ref IR2 register. + * @sa getIR2() + */ +#define setIR2(ir2) \ + WIZCHIP_WRITE(IR2, ir2) +#define setSIR(ir2) setIR2(ir2) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref IR2 register + * @return uint8_t. Value of \ref IR2 register. + * @sa setIR2() + */ +#define getIR2() \ + WIZCHIP_READ(IR2) +#define getSIR() getIR2() + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref PHYSTATUS register + * @return uint8_t. Value to set \ref PHYSTATUS register. + */ +#define getPHYSTATUS() \ + WIZCHIP_READ(PHYSTATUS) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Set \ref _IMR_ register + * @param (uint8_t)imr2 Value to set \ref IMR2 register. + * @sa getIMR2() + * @note If possible, Don't use this function. Instead, Use setSIMR() for compatible with ioLibrary. + */ + //M20150410 : Replace IMR2 with _IMR_ for integrating with ioLibrary +/* +#define setIMR2(imr2) \ + WIZCHIP_WRITE(IMR2, (imr2 & 0xA0)) +*/ +#define setIMR2(imr2) \ + WIZCHIP_WRITE(_IMR_, imr2) +#define setSIMR(imr2) setIMR2(imr2) + +/** + * @ingroup Common_register_access_function_W5200 + * @brief Get \ref _IMR_ register + * @return uint8_t. Value of \ref IMR2 register. + * @sa setIMR2() + */ + //M20150410 : Replace IMR2 with _IMR_ for integrating with ioLibrary +/* +#define getIMR2() \ + (WIZCHIP_READ(IMR2) & 0xA0) +*/ +#define getIMR2() \ + WIZCHIP_READ(_IMR_) +#define getSIMR() getIMR2() +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @param mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_MR register + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ expect bit 4. + * @return Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), ir) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + WIZCHIP_READ(Sn_IR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)imr Value to set @ref Sn_IMR + * @sa getSn_IMR() +*/ +#define setSn_IMR(sn, imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), imr) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +#define getSn_IMR(sn) \ + WIZCHIP_READ(Sn_IMR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +#define getSn_PORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa SetSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +#define getSn_DPORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)proto Value to set \ref Sn_PROTO + * @sa getSn_PROTO() + */ +//M20150601 : Fixed Wrong Register address +/* +#define setSn_PROTO(sn, proto) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) +*/ +#define setSn_PROTO(sn, proto) \ + WIZCHIP_WRITE(Sn_PROTO(sn), proto) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_PROTO register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_PROTO. + * @sa setSn_PROTO() + */ +//M20150601 : Fixed Wrong Register address +/* +#define getSn_PROTO(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) +*/ +#define getSn_PROTO(sn) \ + WIZCHIP_READ(Sn_PROTO(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE + * @sa getSn_RXMEM_SIZE() + */ +#define setSn_RXMEM_SIZE(sn, rxmemsize) \ + WIZCHIP_WRITE(Sn_RXMEM_SIZE(sn),rxmemsize) + +#define setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_RXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_RXMEM. + * @sa setSn_RXMEM_SIZE() + */ +#define getSn_RXMEM_SIZE(sn) \ + WIZCHIP_READ(Sn_RXMEM_SIZE(sn)) + +#define getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE + * @sa getSn_TXMEM_SIZE() + */ +#define setSn_TXMEM_SIZE(sn, txmemsize) \ + WIZCHIP_WRITE(Sn_TXMEM_SIZE(sn), txmemsize) + +#define setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TXMEM_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_TXMEM_SIZE. + * @sa setSn_TXMEM_SIZE() + */ +#define getSn_TXMEM_SIZE(sn) \ + WIZCHIP_READ(Sn_TXMEM_SIZE(sn)) + +#define getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +#define getSn_TX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +#define getSn_TX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +#define getSn_RX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR + * @sa getSn_RX_WR() + */ +#define setSn_RX_WR(sn, rxwr) { \ + WIZCHIP_WRITE(Sn_RX_WR(sn), (uint8_t)(rxwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \ + } + + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +#define getSn_RX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)imr Value to set \ref Sn_IMR + * @sa getSn_IMR() + */ +#define setSn_IMR(sn ,imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), imr) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +#define getSn_IMR(sn) \ + WIZCHIP_READ(Sn_IMR(sn)) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Set @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint16_t)frag Value to set \ref Sn_FRAG + * @sa getSn_FRAG() + */ +#define setSn_FRAG(sn, frag) { \ + WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ + } + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of @ref Sn_FRAG. + * @sa setSn_FRAG() + */ +#define getSn_FRAG(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the max RX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_RxMAX(sn) \ + ((uint16_t)getSn_RXMEM_SIZE(sn) << 10) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the max TX buffer size of socket sn + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Max buffer size + */ +#define getSn_TxMAX(sn) \ + ((uint16_t)getSn_TXMEM_SIZE(sn) << 10) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the mask of socket sn RX buffer. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_RxMASK(sn) \ + ((uint16_t)getSn_RxMAX(sn) - 1) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the mask of socket sn TX buffer + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Mask value + */ +#define getSn_TxMASK(sn) \ + ((uint16_t)getSn_TxMAX(sn) - 1) + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the base address of socket sn RX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n RX buffer base address. + */ +uint16_t getSn_RxBASE(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5200 + * @brief Get the base address of socket sn TX buffer. + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint16_t. Value of Socket n TX buffer base address. + */ +uint16_t getSn_TxBASE(uint8_t sn); + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @ingroup Basic_IO_function_W5200 + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5200 + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to wizdata(pointer variable) of the length of len(variable) bytes. + * This function is being called by recv() also. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function_W5200 + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of len(variable) bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +/// \cond DOXY_APPLY_CODE +#endif +/// \endcond + +#ifdef __cplusplus +} +#endif + +#endif //_W5200_H_ + + + diff --git a/Libraries/Ethernet/W5300/w5300.c b/Libraries/Ethernet/W5300/w5300.c new file mode 100644 index 0000000..4b5e60b --- /dev/null +++ b/Libraries/Ethernet/W5300/w5300.c @@ -0,0 +1,225 @@ +//***************************************************************************** +// +//! \file w5300.h +//! \brief W5300 HAL implement File. +//! \version 1.0.0 +//! \date 2015/05/01 +//! \par Revision history +//! <2015/05/01> 1st Released for integrating with ioLibrary +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2015, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include +#include "wizchip_conf.h" + +#if _WIZCHIP_ == 5300 + + extern uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_]; + extern uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_]; + + +/*********************** + * Basic I/O Function * + ***********************/ + +void WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb ) +{ + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + #if(_WIZCHIP_IO_BUS_WIDTH_ == 8) + WIZCHIP.IF.BUS._write_data(AddrSel, (uint8_t)(wb>>8)); + WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(AddrSel,1),(uint8_t)wb); + #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16) + WIZCHIP.IF.BUS._write_data(AddrSel, wb); + #else + #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16" + #endif +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + #if(_WIZCHIP_IO_BUS_WIDTH_ == 8) + WIZCHIP.IF.BUS._write_data(IDM_AR, (uint8_t)(AddrSel >> 8)); + WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel); + WIZCHIP.IF.BUS._write_data(IDM_DR,(uint8_t)(wb>>8)); + WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_DR,1),(uint8_t)wb); + #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16) + WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel); + WIZCHIP.IF.BUS._write_data(IDM_DR, wb); + #else + #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16" + #endif +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +uint16_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint16_t ret; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + +#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) ) + #if (_WIZCHIP_IO_BUS_WIDTH_ == 8) + ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(AddrSel)) << 8) | + (((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(AddrSel,1))) & 0x00FF) ; + #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16) + ret = WIZCHIP.IF.BUS._read_data(AddrSel); + #else + #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16" + #endif +#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) + #if(_WIZCHIP_IO_BUS_WIDTH_ == 8) + WIZCHIP.IF.BUS._write_data(IDM_AR, (uint8_t)(AddrSel >> 8)); + WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel); + ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(IDM_DR)) << 8) | + (((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(IDM_DR,1))) & 0x00FF); + #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16) + WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel); + ret = WIZCHIP.IF.BUS._read_data(IDM_DR); + #else + #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16" + #endif +#else + #error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!" +#endif + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + + +void setTMSR(uint8_t sn,uint8_t tmsr) +{ + uint16_t tmem; + tmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))); + if(sn & 0x01) tmem = (tmem & 0xFF00) | (((uint16_t)tmsr ) & 0x00FF) ; + else tmem = (tmem & 0x00FF) | (((uint16_t)tmsr) << 8) ; + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE)),tmem); +} + +uint8_t getTMSR(uint8_t sn) +{ + if(sn & 0x01) + return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) & 0x00FF); + return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) >> 8); +} + +void setRMSR(uint8_t sn,uint8_t rmsr) +{ + uint16_t rmem; + rmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))); + if(sn & 0x01) rmem = (rmem & 0xFF00) | (((uint16_t)rmsr ) & 0x00FF) ; + else rmem = (rmem & 0x00FF) | (((uint16_t)rmsr) << 8) ; + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE)),rmem); +} + +uint8_t getRMSR(uint8_t sn) +{ + if(sn & 0x01) + return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) & 0x00FF); + return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) >> 8); +} + +uint32_t getSn_TX_FSR(uint8_t sn) +{ + uint32_t free_tx_size=0; + uint32_t free_tx_size1=1; + while(1) + { + free_tx_size = (((uint32_t)WIZCHIP_READ(Sn_TX_FSR(sn))) << 16) | + (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),2))) & 0x0000FFFF); // read + if(free_tx_size == free_tx_size1) break; // if first == sencond, Sn_TX_FSR value is valid. + free_tx_size1 = free_tx_size; // save second value into first + } + return free_tx_size; +} + +uint32_t getSn_RX_RSR(uint8_t sn) +{ + uint32_t received_rx_size=0; + uint32_t received_rx_size1=1; + while(1) + { + received_rx_size = (((uint32_t)WIZCHIP_READ(Sn_RX_RSR(sn))) << 16) | + (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),2))) & 0x0000FFFF); + if(received_rx_size == received_rx_size1) break; + received_rx_size1 = received_rx_size; // if first == sencond, Sn_RX_RSR value is valid. + } // save second value into first + return received_rx_size + (uint32_t)((sock_pack_info[sn] & 0x02) ? 1 : 0); +} + + +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint32_t len) +{ + uint32_t i = 0; + if(len == 0) return; + + for(i = 0; i < len ; i += 2) + setSn_TX_FIFOR(sn, (((uint16_t)wizdata[i]) << 8) | (((uint16_t)wizdata[i+1]) & 0x00FF)) +} + +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint32_t len) +{ + uint16_t rd = 0; + uint32_t i = 0; + + if(len == 0) return; + + for(i = 0; i < len; i++) + { + if((i & 0x01)==0) + { + rd = getSn_RX_FIFOR(sn); + wizdata[i] = (uint8_t)(rd >> 8); + } + else wizdata[i] = (uint8_t)rd; // For checking the memory access violation + } + sock_remained_byte[sn] = (uint8_t)rd; // back up the remaind fifo byte. +} + +void wiz_recv_ignore(uint8_t sn, uint32_t len) +{ + uint32_t i = 0; + for(i = 0; i < len ; i += 2) getSn_RX_FIFOR(sn); +} + + +#endif diff --git a/Libraries/Ethernet/W5300/w5300.h b/Libraries/Ethernet/W5300/w5300.h new file mode 100644 index 0000000..a8bcd18 --- /dev/null +++ b/Libraries/Ethernet/W5300/w5300.h @@ -0,0 +1,2336 @@ +#ifndef _W5300_H_ +#define _W5300_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//***************************************************************************** +// +//! \file w5300.h +//! \brief W5300 HAL Header File. +//! \version 1.0.0 +//! \date 2015/05/01 +//! \par Revision history +//! <2015/05/01> 1st Released for integrating with ioLibrary +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2015, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include +#include "wizchip_conf.h" + +/// \cond DOXY_APPLY_CODE +#if (_WIZCHIP_ == 5300) +/// \endcond + +#define _WIZCHIP_SN_BASE_ (0x0200) +#define _WIZCHIP_SN_SIZE_ (0x0040) + + +#define WIZCHIP_CREG_BLOCK 0x00 ///< Common register block +#define WIZCHIP_SREG_BLOCK(N) (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + N) ///< Increase offset address + +#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) + #define _W5300_IO_BASE_ _WIZCHIP_IO_BASE_ +#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) + #define IDM_AR ((_WIZCHIP_IO_BASE_ + 0x0002)) ///< Indirect mode address register + #define IDM_DR ((_WIZCHIP_IO_BASE_ + 0x0004)) ///< Indirect mode data register + #define _W5300_IO_BASE_ 0x0000 +#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) + #error "Unkonw _WIZCHIP_IO_MODE_" +#endif + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +//#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +//#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + +//-------------------------- defgroup --------------------------------- +/** + * @defgroup W5300 W5300 + * + * @brief WHIZCHIP register defines and I/O functions of @b W5300. + * + * - @ref WIZCHIP_register_W5300 : @ref Common_register_group_W5300 and @ref Socket_register_group_W5300 + * - @ref WIZCHIP_IO_Functions_W5300 : @ref Basic_IO_function_W5300, @ref Common_register_access_function_W5300 and @ref Socket_register_access_function_W5300 + */ + + +/** + * @defgroup WIZCHIP_register_W5300 WIZCHIP register + * @ingroup W5300 + * + * @brief WHIZCHIP register defines register group of @b W5300. + * + * - @ref Common_register_group_W5300 : Common register group + * - @ref Socket_register_group_W5300 : \c SOCKET n register group + */ + + +/** + * @defgroup WIZCHIP_IO_Functions_W5300 WIZCHIP I/O functions + * @ingroup W5300 + * + * @brief This supports the basic I/O functions for @ref WIZCHIP_register_W5300. + * + * - Basic I/O function \n + * WIZCHIP_READ(), WIZCHIP_WRITE() \n\n + * + * - @ref Common_register_group_W5300 access functions \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR() + * -# Network Information \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() + * -# ICMP packet \n + * getUIPR(), getUPORTR() + * -# @b Socket Memory \n + * getMTYPER(), setMTYPER() \n + * getTMS01R(), getTMS23R(), getTMS45R(), getTMS67R(), setTMS01R(), setTMS23R(), setTMS45R(), setTMS67R() \n + * getRMS01R(), getRMS23R(), getRMS45R(), getRMS67R(), setRMS01R(), setRMS23R(), setRMS45R(), setRMS67R() \n + * -# @b etc. \n + * getPn_BRDYR(), setPn_BRDYR(), getPn_BDPTHR(), setPn_BDPTHR(), getIDR() \n\n + * + * - \ref Socket_register_group_W5300 access functions \n + * -# SOCKET control \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() + * -# SOCKET information \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# SOCKET communication \n + * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() + * -# IP header field \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + + +/** + * @defgroup Common_register_group_W5300 Common register + * @ingroup WIZCHIP_register_W5300 + * + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR : Network Configuration + * @sa IR, _IMR_ : Interrupt. + * @sa MTYPER, TMS01R,TMS23R, TMS45R, TMS67R,RMS01R,RMS23R, RMS45R, RMS67R : Socket TX/RX memory + * @sa _RTR_, _RCR_ : Data retransmission. + * @sa PTIMER, PMAGIC, PSID, PDHAR : PPPoE. + * @sa UIPR, UPORTR, FMTUR : ICMP message. + * @sa Pn_BRDYR, Pn_BDPTHR, IDR : etc. + */ + + +/** + * @defgroup Socket_register_group_W5300 Socket register + * @ingroup WIZCHIP_register_W5300 + * + * @brief Socket register group.\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. + * @sa Sn_TX_WRSR, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR, Sn_TX_FIFOR, Sn_RX_FIFOR : Data communication + */ + + + /** + * @defgroup Basic_IO_function_W5300 Basic I/O function + * @ingroup WIZCHIP_IO_Functions_W5300 + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function_W5300 Common register access functions + * @ingroup WIZCHIP_IO_Functions_W5300 + * @brief These are functions to access common registers. + */ + +/** + * @defgroup Socket_register_access_function_W5300 Socket register access functions + * @ingroup WIZCHIP_IO_Functions_W5300 + * @brief These are functions to access socket registers. + */ + +//------------------------------- defgroup end -------------------------------------------- + +//----------------------------- W5300 Common Registers ----------------------------- +/** + * @ingroup Common_register_group_W5300 + * @brief Mode Register address(R/W)\n + * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of @ref MR defined as follows. + * + * + * + * + * + *
15 14 13 12 11 10 9 8
DBW MPF WDFRDF Reserved FS
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
+ * - \ref MR_DBW : Data bus width (0 : 8 Bit, 1 : 16 Bit), Read Only + * - \ref MR_MPF : Received a Pause Frame from MAC layer (0 : Normal Frame, 1 : Pause Frame), Read Only + * - \ref MR_WDF : Write Data Fetch time (When CS signal is low, W5300 Fetch a written data by Host after PLL_CLK * MR_WDF) + * - \ref MR_RDH : Read Data Hold time (0 : No use data hold time, 1 : Use data hold time, 2 PLL_CLK) + * - \ref MR_FS : FIFO Swap (0 : Disable Swap, 1 : Enable Swap) + * - \ref MR_RST : Reset + * - \ref MR_WOL : Wake on LAN + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_FARP : Force ARP mode + */ +#define MR (_WIZCHIP_IO_BASE_) + +/** + * @ingroup Common_register_group_W5300 + * @brief Interrupt Register(R/W) + * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host. + * If \ref IR is not equal to 0x0000 INTn PIN is asserted to low until it is 0x0000\n\n + * Each bit of \ref IR defined as follows. + * + * + * + * + * + *
15 14 13 12 11 10 9 8
IPCF DPUR PPPT FMTU Reserved Reserved Reserved Reserved
7 6 5 4 3 2 1 0
S7_INT S6_INT S5_INT S4_INT S3_INT S2_INT S1_INT S0_INT
+ * - \ref IR_IPCF : IP conflict + * - \ref IR_DPUR : Destination Port Unreachable + * - \ref IR_PPPT : PPPoE Termination + * - \ref IR_FMTU : Fragmented MTU + * - \ref IR_SnINT(n) : Interrupted from SOCKETn + * + * @note : In W5300, IR is operated same as IR and SIR in other WIZCHIP(5100,5200,W5500) + */ +#define IR (_W5300_IO_BASE_ + 0x02) + +/** + * @ingroup Common_register_group_W5300 + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR. + * When a bit of _IMR_ is and the corresponding bit of \ref IR is Interrupt will be issued. + * In other words, if a bit of _IMR_, an interrupt will be not issued even if the corresponding bit of \ref IR is set + * @note : In W5300, _IMR_ is operated same as _IMR_ and SIMR in other WIZCHIP(5100,5200,W5500) + */ +#define _IMR_ (_W5300_IO_BASE_ + 0x04) + + +//#define ICFGR (_W5300_IO_BASE_ + 0x06) +//#define INTLEVEL ICFGR + +/** + * @ingroup Common_register_group_W5300 + * @brief Source MAC Register address(R/W) + * @details @ref SHAR configures the source hardware address. + */ +#define SHAR (_W5300_IO_BASE_ + 0x08) + + +/** + * @ingroup Common_register_group_W5300 + * @brief Gateway IP Register address(R/W) + * @details @ref GAR configures the default gateway address. + */ + #define GAR (_W5300_IO_BASE_ + 0x10) + +/** + * @ingroup Common_register_group_W5300 + * @brief Subnet mask Register address(R/W) + * @details @ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5300_IO_BASE_ + 0x14) + +/** + * @ingroup Common_register_group_W5300 + * @brief Source IP Register address(R/W) + * @details @ref SIPR configures the source IP address. + */ +#define SIPR (_W5300_IO_BASE_ + 0x18) + +/** + * @ingroup Common_register_group_W5300 + * @brief Timeout register address( 1 is 100us )(R/W) + * @details @ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref _RTR_ is x07D0. + * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref _RTR_, W5300 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the @ref _RTR_ time, W5300 retransmits the packet or issues timeout. + */ + #define _RTR_ (_W5300_IO_BASE_ + 0x1C) + +/** + * @ingroup Common_register_group_W5300 + * @brief Retry count register(R/W) + * @details @ref _RCR_ configures the number of time of retransmission. + * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (@ref Sn_IR_TIMEOUT = '1'). + */ +#define _RCR_ (_W5300_IO_BASE_ + 0x1E) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 0 & 1 + * @details TMS01R configures the TX buffer block size of \c SOCKET 0 & 1. The default value is configured with 8KB and can be configure from 0 to 64KB with unit 1KB. + * But the sum of all SOCKET TX buffer size should be multiple of 8 and the sum of all SOCKET TX and RX memory size can't exceed 128KB. + * When exceeded nor multiple of 8, the data transmittion is invalid. + */ +#define TMS01R (_W5300_IO_BASE_ + 0x20) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 2 & 3 + * @details refer to \ref TMS01R + */ +#define TMS23R (TMS01R + 2) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 4 & 5 + * @details refer to \ref TMS01R + */ +#define TMS45R (TMS01R + 4) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 6 & 7 + * @details refer to \ref TMS01R + */ +#define TMS67R (TMS01R + 6) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 0. + * @details refer to \ref TMS01R + */ +#define TMSR0 TMS01R + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 1. + * @details refer to \ref TMS01R + */ +#define TMSR1 (TMSR0 + 1) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 2. + * @details refer to \ref TMS01R + */ +#define TMSR2 (TMSR0 + 2) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 3. + * @details refer to \ref TMS01R + */ +#define TMSR3 (TMSR0 + 3) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 4. + * @details refer to \ref TMS01R + */ +#define TMSR4 (TMSR0 + 4) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 5. + * @details refer to \ref TMS01R + */ +#define TMSR5 (TMSR0 + 5) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 6. + * @details refer to \ref TMS01R + */ +#define TMSR6 (TMSR0 + 6) + +/** + * @ingroup Common_register_group_W5300 + * @brief TX memory size of \c SOCKET 7. + * @details refer to \ref TMS01R + */ +#define TMSR7 (TMSR0 + 7) + + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 0 & 1 + * @details RMS01R configures the RX buffer block size of \c SOCKET 0 & 1. The default value is configured with 8KB and can be configure from 0 to 64KB with unit 1KB. + * But the sum of all SOCKET RX buffer size should be multiple of 8 and the sum of all SOCKET RX and TX memory size can't exceed 128KB. + * When exceeded nor multiple of 8, the data reception is invalid. + */ +#define RMS01R (_W5300_IO_BASE_ + 0x28) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 2 & 3 + * @details Refer to \ref RMS01R + */ +#define RMS23R (RMS01R + 2) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 4 & 5 + * @details Refer to \ref RMS01R + */ +#define RMS45R (RMS01R + 4) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 6 & 7 + * @details Refer to \ref RMS01R + */ +#define RMS67R (RMS01R + 6) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 0. + * @details refer to \ref RMS01R + */ +#define RMSR0 RMS01R + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 1. + * @details refer to \ref RMS01R + */ +#define RMSR1 (RMSR0 + 1) + +/** + * @ingroup Common_register_group_5300 + * @brief RX memory size of \c SOCKET 2. + * @details refer to \ref RMS01R + */ +#define RMSR2 (RMSR0 + 2) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 3. + * @details refer to \ref RMS01R + */ +#define RMSR3 (RMSR0 + 3) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 4. + * @details refer to \ref RMS01R + */ +#define RMSR4 (RMSR0 + 4) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 5. + * @details refer to \ref RMS01R + */ +#define RMSR5 (RMSR0 + 5) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 6. + * @details refer to \ref RMS01R + */ +#define RMSR6 (RMSR0 + 6) + +/** + * @ingroup Common_register_group_W5300 + * @brief RX memory size of \c SOCKET 7. + * @details refer to \ref RMS01R + */ +#define RMSR7 (RMSR0 + 7) + + + +/** + * @ingroup Common_register_group_W5300 + * @brief Memory Type Register + * @details W5300’s 128Kbytes data memory (Internal TX/RX memory) is composed of 16 memory blocks + * of 8Kbytes. MTYPER configures type of each 8KB memory block in order to select RX or TX memory. + * The type of 8KB memory block corresponds to each bit of MTYPER. When the bit is ‘1’, it is used as TX + * memory, and the bit is ‘0’, it is used as RX memory. MTYPER is configured as TX memory type + * from the lower bit. The rest of the bits not configured as TX memory, should be set as ‘0’. + */ +#define MTYPER (_W5300_IO_BASE_ + 0x30) + +/** + * @ingroup Common_register_group_W5300 + * @brief PPPoE Authentication Type register + * @details It notifies authentication method negotiated with PPPoE server. + * W5300 supports 2 types of authentication methods. + * - PAP : 0xC023 + * - CHAP : 0xC223 + */ +#define PATR (_W5300_IO_BASE_ + 0x32) + +//#define PPPALGOR (_W5300_IO_BASE_ + 0x34) + +/** + * @ingroup Common_register_group_W5300 + * @brief PPP Link Control Protocol Request Timer Register + * @details It configures transmitting timer of link control protocol (LCP) echo request. Value 1 is about 25ms. + */ +#define PTIMER (_W5300_IO_BASE_ + 0x36) + +/** + * @ingroup Common_register_group_W5300 + * @brief PPP LCP magic number register + * @details It configures byte value to be used for 4bytes “Magic Number” during LCP negotiation with PPPoE server. + */ +#define PMAGICR (_W5300_IO_BASE_ + 0x38) + +//#define PSTATER (_W5300_IO_BASE_ + 0x3A) + +/** + * @ingroup Common_register_group_W5300 + * @brief PPPoE session ID register + * @details It notifies PPP session ID to be used for communication with PPPoE server (acquired by PPPoE-process of W5300). + */ +#define PSIDR (_W5300_IO_BASE_ + 0x3C) + +/** + * @ingroup Common_register_group_W5300 + * @brief PPPoE destination hardware address register + * @details It notifies hardware address of PPPoE server (acquired by PPPoE-process of W5300). + */ +#define PDHAR (_W5300_IO_BASE_ + 0x40) + +/** + * @ingroup Common_register_group_W5300 + * @brief Unreachable IP address register + * @details When trying to transmit UDP data to destination port number which is not open, + * W5300 can receive ICMP (Destination port unreachable) packet. \n + * In this case, \ref IR_DPUR bit of \ref IR becomes '1'. + * And destination IP address and unreachable port number of ICMP packet can be acquired through UIPR and \ref UPORTR. + */ +#define UIPR (_W5300_IO_BASE_ + 0x48) + +/** + * @ingroup Common_register_group_W5300 + * @brief Unreachable port number register + * @details Refer to \ref UIPR. + */ +#define UPORTR (_W5300_IO_BASE_ + 0x4C) + +/** + * @ingroup Common_register_group_W5300 + * @brief Fragment MTU register + * @details When communicating with the peer having a different MTU, W5300 can receive an ICMP(Fragment MTU) packet. + * At this case, IR(FMTU) becomes ‘1’ and destination IP address and fragment MTU value of ICMP packet can be acquired through UIPR and FMTUR. + * In order to keep communicating with the peer having Fragment MTU, set the FMTUR first in Sn_MSSR of the SOCKETn, and try the next communication. + */ +#define FMTUR (_W5300_IO_BASE_ + 0x4E) + +//#define Sn_RTCR(n) (_W5300_IO_BASE_ + 0x50 + n*2) + +/** + * @ingroup Common_register_group_W5300 + * @brief PIN 'BRDYn' configure register + * @details It configures the PIN "BRDYn" which is monitoring TX/RX memory status of the specified SOCKET. + * If the free buffer size of TX memory is same or bigger than the buffer depth of \ref Pn_BDPTHR, + * or received buffer size of RX memory is same or bigger than the \ref Pn_BDPTHR, + * PIN "BRDYn" is signaled. + * + * + * + * + * + *
15 14 13 12 11 10 9 8
Reserved, Read as 0
7 6 5 4 3 2 1 0
PEN MT PPL Reserved SN
+ * + * - \ref Pn_PEN Enable PIN 'BRDYn' (0 : Disable, 1 : Enable) + * - \ref Pn_MT Monitoring Memory type (0 : RX memory, 1 : TX Memory) + * - \ref Pn_PPL PIN Polarity bit of Pn_BRDYR. (0 : Low sensitive, 1 : High sensitive) + * - \ref Pn_SN(n) Monitoring SOCKET number of Pn_BRDYR + */ +#define Pn_BRDYR(n) (_W5300_IO_BASE_ + 0x60 + n*4) + +/** + * @ingroup Common_register_group_W5300 + * @brief PIN 'BRDYn' buffer depth Register + * @details It configures buffer depth of PIN "BRDYn". + * When monitoring TX memory and \ref Sn_TX_FSR is same or bigger than Pn_BDPTHR, the PIN "BRDYn" is signaled. + * When monitoring RX memory and if \ref Sn_RX_RSR is same or bigger than Pn_BDPTHR, PIN "BRDYn" is signaled. + * The value for Pn_BDPTHR can't exceed TX/RX memory size allocated by TMSR or RMSR such like as \ref TMS01R or \ref RMS01R. + */ +#define Pn_BDPTHR(n) (_W5300_IO_BASE_ + 0x60 + n*4 + 2) + +/** + * @ingroup Common_register_group_W5300 + * @brief W5300 identification register. + * @details Read Only. 0x5300. + */ +#define IDR (_W5300_IO_BASE_ + 0xFE) +#define VERSIONR IDR + + +//----------------------------- W5300 SOCKET Registers ----------------------------- + +/** + * @ingroup Socket_register_group_W5300 + * @brief Socket Mode register(R/W) + * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of @ref Sn_MR defined as the following. + * + * + * + * + * + *
15 14 13 12 11 10 9 8
Reserved. Read as 0 ALIGN
7 6 5 4 3 2 1 0
MULTI MF ND/IGMPv Reserved PROTOCOL[3:0]
+ * - @ref Sn_MR_ALIGN : Alignment bit of Sn_MR, Only valid in \ref Sn_MR_TCP. (C0 : Include TCP PACK_INFO, 1 : Not include TCP PACK_INFO) + * - @ref Sn_MR_MULTI : Support UDP Multicasting + * - @ref Sn_MR_MF : Enable MAC Filter (0 : Disable, 1 - Enable), When enabled, W5300 can receive only both own and broadcast packet. + * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - @ref Sn_MR_IGMPv : IGMP version used in UDP mulitcasting. (0 : Version 2, 1 : Version 2) + * - PROTOCOL[3:0] + * + * + * + * + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 0 1 1 IPCRAW
0 1 0 0 MACRAW
0 1 0 1 PPPoE
+ * + * - @ref Sn_MR_PPPoE : PPPoE + * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK + * - @ref Sn_MR_IPRAW : IP LAYER RAW SOCK + * - @ref Sn_MR_UDP : UDP + * - @ref Sn_MR_TCP : TCP + * - @ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x00) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. + * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. + * - @ref Sn_CR_OPEN : Initialize or open socket. + * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) + * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) + * - @ref Sn_CR_DISCON : Send closing request in TCP mode. + * - @ref Sn_CR_CLOSE : Close socket. + * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - @ref Sn_CR_SEND_KEEP : Send keep alive message. + * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. + * - @ref Sn_CR_PCON : PPPoE connection begins by transmitting PPPoE discovery packet. + * - @ref Sn_CR_PDISCON : Closes PPPoE connection. + * - @ref Sn_CR_PCR : In each phase, it transmits REQ message. + * - @ref Sn_CR_PCN : In each phase, it transmits NAK message. + * - @ref Sn_CR_PCJ : In each phase, it transmits REJECT message. + */ +#define Sn_CR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x02) + +/** + * @ingroup Socket_register_group_W5300 + * @brief socket interrupt mask register(R) + * @details @ref Sn_IMR masks the interrupt of Socket n. + * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is + * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is + * Host is interrupted by asserted INTn PIN to low. + */ +#define Sn_IMR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x04) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Socket interrupt register(R) + * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n + * In order to clear the @ref Sn_IR bit, the host should write the bit to \n + * + * + * + * + * + *
15 14 13 12 11 10 9 8
Reserved. Read as 0
7 6 5 4 3 2 1 0
PRECV PFAIL PNEXT SENDOK TIMEOUT RECV DISCON CON
+ * - \ref Sn_IR_PRECV : PPP receive + * - \ref Sn_IR_PFAIL : PPP fail + * - \ref Sn_IR_PNEXT : PPP next phase + * - \ref Sn_IR_SENDOK : SENDOK + * - \ref Sn_IR_TIMEOUT : TIMEOUT + * - \ref Sn_IR_RECV : RECV + * - \ref Sn_IR_DISCON : DISCON + * - \ref Sn_IR_CON : CON + */ +#define Sn_IR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x06) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Socket status register(R) + * @details @ref Sn_SSR indicates the status of Socket n.\n + * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - @ref SOCK_CLOSED : Closed + * - @ref SOCK_INIT : Initiate state + * - @ref SOCK_LISTEN : Listen state + * - @ref SOCK_ESTABLISHED : Success to connect + * - @ref SOCK_CLOSE_WAIT : Closing state + * - @ref SOCK_UDP : UDP socket + * - @ref SOCK_IPRAW : IPRAW socket + * - @ref SOCK_MACRAW : MAC raw mode socket + * - @ref SOCK_PPPoE : PPPoE mode Socket + *@par Temporary status during changing the status of Socket n. + * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - @ref SOCK_FIN_WAIT : Connection state + * - @ref SOCK_CLOSING : Closing state + * - @ref SOCK_TIME_WAIT : Closing state + * - @ref SOCK_LAST_ACK : Closing state + * - @ref SOCK_ARP : ARP request state + */ +#define Sn_SSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x08) +#define Sn_SR(n) Sn_SSR(n) ///< For Compatible ioLibrary. Refer to @ref Sn_SSR(n) + +/** + * @ingroup Socket_register_group_W5300 + * @brief source port register(R/W) + * @details @ref Sn_PORTR configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. + */ +#define Sn_PORTR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0A) +#define Sn_PORT(n) Sn_PORTR(n) ///< For compatible ioLibrary. Refer to @ref Sn_PORTR(n). + +/** + * @ingroup Socket_register_group_W5300 + * @brief Peer MAC register address(R/W) + * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0C) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Peer port register address(R/W) + * @details @ref Sn_DPORTR configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP clientmode, it configures the listen port number of TCP serverbefore CONNECT command. + * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORTR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x12) +#define Sn_DPORT(n) Sn_DPORTR(n) ///< For compatible ioLibrary. Refer to \ref Sn_DPORTR. + + +/** + * @ingroup Socket_register_group_W5300 + * @brief Peer IP register address(R/W) + * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of TCP serverbefore CONNECT command. + * In TCP server mode, it indicates an IP address of TCP clientafter successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ + #define Sn_DIPR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x14) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x18) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Keep Alive Timer register(R/W) + * @details @ref Sn_KPALVTR configures the transmitting timer of KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, + * and ignored in other modes. The time unit is 5s. + * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. + * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). + * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, + * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). + * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. + */ +#define Sn_KPALVTR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1A) + +/** + * @ingroup Socket_register_group_W5300 + * @brief IP Protocol(PROTO) Register(R/W) + * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is + * valid only in IPRAW mode, and ignored in other modes. + */ +#define Sn_PROTOR(n) Sn_KPALVTR(n) + + +/** + * @ingroup Socket_register_group_W5300 + * @brief IP Type of Service(TOS) Register(R/W) + * @details @ref Sn_TOSR configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1C) +#define Sn_TOS(n) Sn_TOSR(n) ///< For compatible ioLibrary. Refer to Sn_TOSR + +/** + * @ingroup Socket_register_group_W5300 + * @brief IP Time to live(TTL) Register(R/W) + * @details @ref Sn_TTLR configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTLR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1E) +#define Sn_TTL(n) Sn_TTLR(n) ///< For compatible ioLibrary. Refer to Sn_TTLR + +/** + * @ingroup Socket_register_group_W5300 + * @brief SOCKETn TX write size register(R/W) + * @details It sets the byte size of the data written in internal TX memory through @ref Sn_TX_FIFOR. + * It is set before SEND or SEND_MAC command, and can't be bigger than internal TX memory + * size set by TMSR such as @ref TMS01R, TMS23R and etc. + */ +#define Sn_TX_WRSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x20) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Transmit free memory size register(R) + * @details Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by TMSR such as @ref TMS01SR. + * Data bigger than Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0024) + +/** + * @ingroup Socket_register_group_w5300 + * @brief Received data size register(R) + * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * @ref Sn_RX_RSR does not exceed the RMSR such as @ref RMS01SR and is calculated as the difference between + * ?Socket n RX Write Pointer (@ref Sn_RX_WR)and Socket n RX Read Pointer (@ref Sn_RX_RD) + */ +#define Sn_RX_RSR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0028) + +/** + * @ingroup Socket_register_group_W5300 + * @brief Fragment field value in IP header register(R/W) + * @details @ref Sn_FRAGR configures the FRAG(Fragment field in IP header). + */ +#define Sn_FRAGR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x002C) +#define Sn_FRAG(n) Sn_FRAGR(n) + +/** + * @ingroup Socket_register_group_W5300 + * @brief SOCKET n TX FIFO regsiter + * @details It indirectly accesses internal TX memory of SOCKETn. + * The internal TX memory can't be accessed directly by the host, but can be accessed through Sn_TX_FIFOR. + * If @ref MR(MT) = '0', only the Host-Write of internal TX memory is allowed through Sn_TX_FIFOR. + * But if @ref MR(MT) is '1', both of Host-Read and Host-Write are allowed. + */ +#define Sn_TX_FIFOR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x2E) + +/** + * @ingroup Socket_register_group_W5300 + * @brief SOCKET n RX FIFO register + * @details It indirectly accesses to internal RX memory of SOCKETn. + * The internal RX memory can't be directly accessed by the host, but can be accessed through Sn_RX_FIFOR. + * If MR(MT) = '0', only the Host-Read of internal RX memory is allowed through Sn_RX_FIFOR. + * But if MR(MT) is '1', both of Host-Read and Host-Write are allowed. + */ +#define Sn_RX_FIFOR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x30) + +//#define Sn_TX_SADR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x32) + +//#define Sn_RX_SADR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x34) + +//#define Sn_TX_RD(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x36) + +//#define Sn_TX_WR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x38) + +//#define Sn_TX_ACK(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3A) + +//#define Sn_RX_RD(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3C) + +//#define Sn_RX_WR(n) (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3E) + + +/************************************/ +/* The bit of MR regsiter defintion */ +/************************************/ +#define MR_DBW (1 << 15) /**< Data bus width bit of \ref MR. Read Only. (0 : 8Bit, 1 : 16Bit)*/ +#define MR_MPF (1 << 14) /**< Mac layer pause frame bit of \ref MR. (0 : Disable, 1 : Enable)*/ +#define MR_WDF(X) ((X & 0x07) << 11) /**< Write data fetch time bit of \ref MR. Fetch Data from DATA bus after PLL_CLK * MR_WDF[2:0]*/ +#define MR_RDH (1 << 10) /**< Read data hold time bit of \ref MR. Hold Data on DATA bus during 2 * PLL_CLK after CS high*/ +#define MR_FS (1 << 8) /**< FIFO swap bit of \ref MR. Swap MSB & LSB of \ref Sn_TX_FIFOR & Sn_RX_FIFOR (0 : No swap, 1 : Swap) */ +#define MR_RST (1 << 7) /**< S/W reset bit of \ref MR. (0 : Normal Operation, 1 : Reset (automatically clear after reset))*/ +#define MR_MT (1 << 5) /**< Memory test bit of \ref MR. (0 : Normal, 1 : Internal Socket memory write & read Test)*/ +#define MR_PB (1 << 4) /**< Ping block bit of \ref MR. (0 : Unblock, 1 : Block)*/ +#define MR_PPPoE (1 << 3) /**< PPPoE bit of \ref MR. (0 : No use PPPoE, 1: Use PPPoE)*/ +#define MR_DBS (1 << 2) /**< Data bus swap of \ref MR. Valid only 16bit mode (0 : No swap, 1 : Swap)*/ +#define MR_IND (1 << 0) /**< Indirect mode bit of \ref MR. (0 : Direct mode, 1 : Indirect mode) */ + + +/************************************/ +/* The bit of IR regsiter definition */ +/************************************/ +#define IR_IPCF (1 << 7) /**< IP conflict bit of \ref IR. To clear, Write the bit to '1'. */ +#define IR_DPUR (1 << 6) /**< Destination port unreachable bit of \ref IR. To clear, Write the bit to '1'. */ +#define IR_PPPT (1 << 5) /**< PPPoE terminate bit of \ref IR. To clear, Write the bit to '1'. */ +#define IR_FMTU (1 << 4) /**< Fragment MTU bit of IR. To clear, Write the bit to '1'. */ +#define IR_SnINT(n) (0x01 << n) /**< SOCKETn interrupt occurrence bit of \ref IR. To clear, Clear \ref Sn_IR*/ + +/*****************************************/ +/* The bit of Pn_BRDYR regsiter definition*/ +/*****************************************/ +#define Pn_PEN (1 << 7) /**< PIN 'BRDYn' enable bit of Pn_BRDYR. */ +#define Pn_MT (1 << 6) /**< PIN memory type bit of Pn_BRDYR. */ +#define Pn_PPL (1 << 5) /**< PIN Polarity bit of Pn_BRDYR. */ +#define Pn_SN(n) ((n & 0x07) << 0) /**< What socket to monitor. */ + + +/***************************************/ +/* The bit of Sn_MR regsiter definition */ +/***************************************/ +/** + * @brief Alignment bit of \ref Sn_MR. + * @details It is valid only in the TCP (\ref Sn_MR_TCP) with TCP communication, + * when every the received DATA packet size is of even number and set as '1', + * data receiving performance can be improved by removing PACKET-INFO(data size) that is attached to every the received DATA packet. + */ +#define Sn_MR_ALIGN (1 << 8) + +/** + * @brief Multicasting bit of \ref Sn_MR + * @details It is valid only in UDP (\ref Sn_MR_UDP). + * In order to implement multicasting, set the IP address and port number in @ref Sn_DIPR and @ref Sn_DPORTR respectively before "OPEN" command(@ref Sn_CR_OPEN).\n + * 0 : Disable, 1 : Enable + */ +#define Sn_MR_MULTI (1 << 7) + +/** + * @brief MAC filter bit of \ref Sn_MR + * @details It is valid in MACRAW(@ref Sn_MR_MACRAW). + * When this bit is set as ‘1’, W5300 can receive packet that is belong in itself or broadcasting. + * When this bit is set as ‘0’, W5300 can receive all packets on Ethernet. + * When using the hybrid TCP/IP stack, it is recommended to be set as ‘1’ for reducing the receiving overhead of host. \n + * 0 : Disable, 1 : Enable + */ +#define Sn_MR_MF (1 << 6) + +/** + * @brief IGMP version bit of \ref Sn_MR + * details It is valid in case of @ref Sn_MR_MULTI='1' and UDP(@ref Sn_MR_UDP). + * It configures IGMP version to send IGMP message such as Join/Leave/Report to multicast-group. \n + * 0 : IGMPv2, 1 : IGMPv1 + */ +#define Sn_MR_IGMPv (1 << 5) +#define Sn_MR_MC Sn_MR_IGMPv ///< For compatible ioLibrary + +/** + * @brief No delayed ack bit of \ref Sn_MR + * @details It is valid in TCP(@ref Sn_MR_TCP). + * In case that it is set as '1', ACK packet is transmitted right after receiving DATA packet from the peer. + * It is recommended to be set as '1' for TCP performance improvement. + * In case that it is set as '0', ACK packet is transmitted after the time set in @ref _RTR_ regardless of DATA packet receipt.\n + * 0 : No use, 1 : Use + */ +#define Sn_MR_ND (1 << 5) + +/** + * @brief No mode + * @details This configures the protocol mode of Socket n. + * @sa Sn_MR + */ +#define Sn_MR_CLOSE 0x00 + +/** + * @brief TCP mode + * @details This configures the protocol mode of Socket n. + * @sa Sn_MR + */ +#define Sn_MR_TCP 0x01 + +/** + * @brief UDP mode + * @details This configures the protocol mode of Socket n. + * @sa Sn_MR + */ +#define Sn_MR_UDP 0x02 /**< Protocol bits of \ref Sn_MR. */ + +/** + * @brief IP LAYER RAW mode + * @details This configures the protocol mode of Socket n. + * @sa Sn_MR + */ +#define Sn_MR_IPRAW 0x03 /**< Protocol bits of \ref Sn_MR. */ + +/** + * @brief MAC LAYER RAW mode + * @details This configures the protocol mode of Socket 0. + * @sa Sn_MR + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 + +/** + * @brief PPPoE mode + * @details This configures the protocol mode of Socket 0. + * @sa Sn_MR + * @note PPPoE mode should be only used in Socket 0. + */ +#define Sn_MR_PPPoE 0x05 /**< Protocol bits of \ref Sn_MR. */ + +#define SOCK_STREAM Sn_MR_TCP /**< For Berkeley Socket API, Refer to @ref Sn_MR_TCP */ +#define SOCK_DGRAM Sn_MR_UDP /**< For Berkeley Socket API, Refer to @ref Sn_MR_UDP */ + + + +/******************************/ +/* The values of CR definition */ +/******************************/ +/** + * @brief Initialize or open a socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n + * + * + * + * + * + * + * + * + *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000)
Sn_MR_TCP (001) SOCK_INIT (0x13)
Sn_MR_UDP (010) SOCK_UDP (0x22)
Sn_MR_IPRAW (010) SOCK_IPRAW (0x32)
Sn_MR_MACRAW (100) SOCK_MACRAW (0x42)
Sn_MR_PPPoE (101) SOCK_PPPoE (0x5F)
+ */ +#define Sn_CR_OPEN 0x01 + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (\ref Sn_MR(P3:P0) = \ref Sn_MR_TCP). + * In this mode, Socket n operates as a TCP serverand waits for connection-request (SYN packet) from any TCP client + * The @ref Sn_SR changes the state from \ref SOCK_INIT to \ref SOCKET_LISTEN. + * When a TCP clientconnection request is successfully established, + * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the @ref Sn_IR(0) becomes + * But when a TCP clientconnection request is failed, @ref Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as TCP client + */ +#define Sn_CR_CONNECT 0x04 + +/** + * @brief Send closing request in TCP mode + * @details Regardless of TCP serveror TCP client the DISCON command processes the disconnect-process (b>Active close
or Passive close.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n + * Otherwise, @b TCPTO occurs (\ref Sn_IR[3]='1') and then @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 + +/** + * @brief Close socket + * @details @ref Sn_SR is changed to @ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND command transmits all the data in the Socket n TX buffer thru @ref Sn_TX_FIFOR.\n + * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR) and Socket TX Write Size register (@ref Sn_TX_WRSR). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND command transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC command transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer thru @ref Sn_RX_FIFOR).\n + * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR) & @ref Sn_RX_FIFOR. + */ +#define Sn_CR_RECV 0x40 /**< RECV command value of \ref Sn_CR */ + +#define Sn_CR_PCON 0x23 /**< PPPoE connection begins by transmitting PPPoE discovery packet. Refer to \ref Sn_CR */ +#define Sn_CR_PDISCON 0x24 /**< Closes PPPoE connection. Refer to \ref Sn_CR */ +#define Sn_CR_PCR 0x25 /**< In each phase, it transmits REQ message. Refer to \ref Sn_CR */ +#define Sn_CR_PCN 0x26 /**< In each phase, it transmits NAK message. Refer to \ref Sn_CR */ +#define Sn_CR_PCJ 0x27 /**< In each phase, it transmits REJECT message. Refer to \ref Sn_CR */ + + +/*********************************/ +/* The values of Sn_IR definition */ +/*********************************/ +#define Sn_IR_PRECV 0x80 /**< It is set in the case that option data which is not supported is received. Refer to \ref Sn_IR */ +#define Sn_IR_PFAIL 0x40 /**< It is set in the case that PAP authentication is failed. Refer to \ref Sn_IR */ +#define Sn_IR_PNEXT 0x20 /**< It is set in the case that the phase is changed during PPPoE connection process. \ref Sn_IR */ +#define Sn_IR_SENDOK 0x10 /**< It is set when SEND command is completed. Refer to \ref Sn_IR */ +#define Sn_IR_TIMEOUT 0x08 /**< It is set when ARPTO or TCPTO is occured. Refer to \ref Sn_IR */ +#define Sn_IR_RECV 0x04 /**< It is set whenever data is received from a peer. Refer to \ref Sn_IR */ +#define Sn_IR_DISCON 0x02 /**< It is set when FIN or FIN/ACK packet is received from a peer. Refer to \ref Sn_IR */ +#define Sn_IR_CON 0x01 /**< It is set one time when the connection is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. */ + +/**********************************/ +/* The values of Sn_SSR definition */ +/**********************************/ +/** + * @brief The state of SOCKET intialized or closed + * @details This indicates that Socket n is released.\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 + +/** + * @brief The state of ARP process + * @details It is temporary state for getting a peer MAC address when TCP connect or UDP Data Send\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_ARP 0x01 /**< ARP-request is transmitted in order to acquire destination hardware address. */ + +/** + * @brief Initiate state in TCP. + * @details This indicates Socket n is opened with TCP mode.\n + * It is changed to @ref SOCK_INIT when \ref Sn_MR(P[3:0]) = '001' and OPEN command(\ref Sn_CR_OPEN) is ordered.\n + * After SOCK_INIT, user can use LISTEN(@ref Sn_CR_LISTEN)/CONNECT(@ref Sn_CR_CONNET) command. + */ +#define SOCK_INIT 0x13 + +/** + * @brief Listen state + * @details This indicates Socket n is operating as TCP servermode and waiting for connection-request (SYN packet) from a peer TCP client.\n + * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR_TIMEOUT = '1') is occurred. + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by @ref Sn_CR_CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR_TIMEOUT = '1') is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n + * If not, it changes to @ref SOCK_CLOSED after timeout (@ref Sn_IR_TIMEOUT = '1') is occurred. + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to @ref SOCK_ESTABLISHED when the TCP SERVERprocessed the SYN packet from the TCP CLIENTduring @ref SOCK_LISTEN, or + * when the @ref Sn_CR_CONNECT command is successful.\n + * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using @ref Sn_CR_SEND or @ref Sn_CR_RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout(@ref Sn_CR_TIMTEOUT = '1') is occurred, these change to @ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, @ref Sn_CR_DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout (@ref Sn_IR_TIMEOUT = '1') is occurred. + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(@ref Sn_MR(P[3:0]) = '010').\n + * It changes to SOCK_UDP when @ref Sn_MR(P[3:0]) = '010' and @ref Sn_CR_OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 + +/** + * @brief IP raw mode socket + * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is + * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n + * IP Packet can be transferred without a connection similar to the UDP mode. +*/ +#define SOCK_IPRAW 0x32 + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n = 0) and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0] = 100)and @ ref Sn_CR_OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 /**< SOCKET0 is open as MACRAW mode. */ + +/** + * @brief PPPoE mode socket + * @details It is the status that SOCKET0 is opened as PPPoE mode. + * It is changed to SOCK_PPPoE in case of @ref Sn_CR_OPEN command is ordered and @ref Sn_MR(P3:P0)= @ref Sn_MR_PPPoE\n + * It is temporarily used at the PPPoE connection. + */ +#define SOCK_PPPoE 0x5F /**< SOCKET0 is open as PPPoE mode. */ + +/* IP PROTOCOL */ +#define IPPROTO_IP 0 //< Dummy for IP +#define IPPROTO_ICMP 1 //< Control message protocol +#define IPPROTO_IGMP 2 //< Internet group management protocol +#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) +#define IPPROTO_TCP 6 //< TCP +#define IPPROTO_PUP 12 //< PUP +#define IPPROTO_UDP 17 //< UDP +#define IPPROTO_IDP 22 //< XNS idp +#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 //< Raw IP packet + + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +#ifdef _exit +#undef _exit +#endif + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + +//////////////////////// +// Basic I/O Function // +//////////////////////// + +/** + * @ingroup Basic_IO_function_W5300 + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint16_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function_W5300 + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb ); + +/*********************************** + * COMMON Register Access Function * + ***********************************/ + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set Mode Register + * @param (@ref iodata_t)mr The value to be set. + * @sa getMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) + #if (_WIZCHIP_IO_BUS_WIDTH_ == 8) + #define setMR(mr) \ + (*((uint8_t*)MR) = (uint8_t)((mr) >> 8)); (*((uint8_t*)WIZCHIP_OFFSET_INC(MR,1)) = (uint8_t)((mr) & 0xFF)) + #elif (_WIZCHIP_IO_BUS_WIDTH_ == 16) + #define setMR(mr) (*((uint16_t*)MR) = (uint16_t)((mr) & 0xFFFF)) + #else + #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. You should be define _WIZCHIP_IO_BUS_WIDTH as 8 or 16." + #endif +#else + #error "Unknown _WIZCHIP_IO_MODE_" +#endif + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref MR. + * @return @ref iodata_t. The value of Mode register. + * @sa setMR() + */ +#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) + #if (_WIZCHIP_IO_BUS_WIDTH_ == 8) + #define getMR() (((uint16_t)(*((uint8_t*)MR)) << 8) + (((uint16_t)(*((uint8_t*)WIZCHIP_OFFSET_INC(MR,1)))) & 0x00FF)) + #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16) + #define getMR() (*((uint16_t*)MR)) + #else + #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. You should be define _WIZCHIP_IO_BUS_WIDTH as 8 or 16." + #endif +#else + #error "Unknown _WIZCHIP_IO_MODE_" +#endif + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set \ref IR register + * @param (uint16_t)ir Value to set \ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, ir & 0xF0FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get \ref IR register + * @return uint8_t. Value of \ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xF0FF) + + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set \ref _IMR_ register + * @param (uint16_t)imr Value to set @ref _IMR_ register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(_IMR_, imr & 0xF0FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get \ref _IMR_ register + * @return uint16_t. Value of \ref IR register. + * @sa setIMR() + */ +#define getIMR() \ + (WIZCHIP_READ(_IMR_) & 0xF0FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set local MAC address + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) { \ + WIZCHIP_WRITE(SHAR, (((uint16_t)((shar)[0])) << 8) + (((uint16_t)((shar)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SHAR,2), (((uint16_t)((shar)[2])) << 8) + (((uint16_t)((shar)[3])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SHAR,4), (((uint16_t)((shar)[4])) << 8) + (((uint16_t)((shar)[5])) & 0x00FF)); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get local MAC address + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) { \ + (shar)[0] = (uint8_t)(WIZCHIP_READ(SHAR) >> 8); \ + (shar)[1] = (uint8_t)(WIZCHIP_READ(SHAR)); \ + (shar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,2)) >> 8); \ + (shar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,2))); \ + (shar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,4)) >> 8); \ + (shar)[5] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,4))); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set gateway IP address + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) { \ + WIZCHIP_WRITE(GAR, (((uint16_t)((gar)[0])) << 8) + (((uint16_t)((gar)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(GAR,2), (((uint16_t)((gar)[2])) << 8) + (((uint16_t)((gar)[3])) & 0x00FF)); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get gateway IP address + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) { \ + (gar)[0] = (uint8_t)(WIZCHIP_READ(GAR) >> 8); \ + (gar)[1] = (uint8_t)(WIZCHIP_READ(GAR)); \ + (gar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(GAR,2)) >> 8); \ + (gar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(GAR,2))); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set subnet mask address + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @sa getSUBR() + */ +#define setSUBR(subr) { \ + WIZCHIP_WRITE(SUBR, (((uint16_t)((subr)[0])) << 8) + (((uint16_t)((subr)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SUBR,2), (((uint16_t)((subr)[2])) << 8) + (((uint16_t)((subr)[3])) & 0x00FF)); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get subnet mask address + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) { \ + (subr)[0] = (uint8_t)(WIZCHIP_READ(SUBR) >> 8); \ + (subr)[1] = (uint8_t)(WIZCHIP_READ(SUBR)); \ + (subr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SUBR,2)) >> 8); \ + (subr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SUBR,2))); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set local IP address + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() + */ +#define setSIPR(sipr) { \ + WIZCHIP_WRITE(SIPR, (((uint16_t)((sipr)[0])) << 8) + (((uint16_t)((sipr)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SIPR,2), (((uint16_t)((sipr)[2])) << 8) + (((uint16_t)((sipr)[3])) & 0x00FF)); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get local IP address + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) { \ + (sipr)[0] = (uint8_t)(WIZCHIP_READ(SIPR) >> 8); \ + (sipr)[1] = (uint8_t)(WIZCHIP_READ(SIPR)); \ + (sipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SIPR,2)) >> 8); \ + (sipr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SIPR,2))); \ + } + + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref _RTR_ register + * @param (uint16_t)rtr Value to set @ref _RTR_ register. + * @sa getRTR() + */ +#define setRTR(rtr) \ + WIZCHIP_WRITE(_RTR_, rtr) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref _RTR_ register + * @return uint16_t. Value of @ref _RTR_ register. + * @sa setRTR() + */ +#define getRTR() \ + WIZCHIP_READ(_RTR_) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref _RCR_ register + * @param (uint8_t)rcr Value to set @ref _RCR_ register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(_RCR_, ((uint16_t)rcr)&0x00FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref _RCR_ register + * @return uint8_t. Value of @ref _RCR_ register. + * @sa setRCR() + */ +#define getRCR() \ + ((uint8_t)(WIZCHIP_READ(_RCR_) & 0x00FF)) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref TMS01R register + * @param (uint16_t)tms01r Value to set @ref TMS01R register. The lower socket memory size is located at MSB of tms01r. + * @sa getTMS01R() + */ +#define setTMS01R(tms01r) \ + WIZCHIP_WRITE(TMS01R,tms01r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref TMS01R register + * @return uint16_t. Value of @ref TMS01R register. + * @sa setTMS01R() + */ +#define getTMS01R() \ + WIZCHIP_READ(TMS01R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref TMS23R register + * @param (uint16_t)tms23r Value to set @ref TMS23R register. The lower socket memory size is located at MSB of tms01r. + * @sa getTMS23R() + */ +#define setTMS23R(tms23r) \ + WIZCHIP_WRITE(TMS23R,tms23r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref TMS23R register + * @return uint16_t. Value of @ref TMS23R register. + * @sa setTMS23R() + */ +#define getTMS23R() \ + WIZCHIP_READ(TMS23R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref TMS45R register + * @param (uint16_t)tms45r Value to set @ref TMS45R register. The lower socket memory size is located at MSB of tms45r. + * @sa getTMS45R() + */ +#define setTMS45R(tms45r) \ + WIZCHIP_WRITE(TMS45R,tms45r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref TMS45R register + * @return uint16_t. Value of @ref TMS45R register. + * @sa setTMS45R() + */ +#define getTMS45R() \ + WIZCHIP_READ(TMS45R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref TMS67R register + * @param (uint16_t)tms67r Value to set @ref TMS67R register. The lower socket memory size is located at MSB of tms67r. + * @sa getTMS67R() + */ +#define setTMS67R(tms67r) \ + WIZCHIP_WRITE(TMS67R,tms67r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref TMS67R register + * @return uint16_t. Value of @ref TMS67R register. + * @sa setTMS67R() + */ +#define getTMS67R() \ + WIZCHIP_READ(TMS67R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref TMSR0 ~ @ref TMSR7 register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)tmsr Value to set @ref TMSR0 ~@ref TMSR7 register. + * @sa getTMSR() + */ +void setTMSR(uint8_t sn,uint8_t tmsr); +#define setSn_TXBUF_SIZE(sn, tmsr) setTMSR(sn, tmsr) ///< For compatible ioLibrary + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref TMSR0 ~ @ref TMSR7 register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref TMSR0 ~ @ref TMSR7 + * @sa getTMSR() + */ +uint8_t getTMSR(uint8_t sn); +#define getSn_TXBUF_SIZE(sn) getTMSR(sn) ///< For compatible ioLibrary + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref RMS01R register + * @param (uint16_t)rms01r Value to set @ref RMS01R register. The lower socket memory size is located at MSB of rms01r. + * @sa getRMS01R() + */ +#define setRMS01R(rms01r) \ + WIZCHIP_WRITE(RMS01R,rms01r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RMS01R register + * @return uint16_t. Value of @ref RMS01R register. + * @sa setRMS01R() + */ +#define getRMS01R() \ + WIZCHIP_READ(RMS01R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref RMS23R register + * @param (uint16_t)rms23r Value to set @ref RMS23R register. The lower socket memory size is located at MSB of rms01r. + * @sa getRMS23R() + */ +#define setRMS23R(rms23r) \ + WIZCHIP_WRITE(RMS23R,rms23r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RMS23R register + * @return uint16_t. Value of @ref RMS23R register. + * @sa setRMS23R() + */ +#define getRMS23R() \ + WIZCHIP_READ(RMS23R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref RMS45R register + * @param (uint16_t)rms45r Value to set @ref RMS45R register. The lower socket memory size is located at MSB of rms45r. + * @sa getRMS45R() + */ +#define setRMS45R(rms45r) \ + WIZCHIP_WRITE(RMS45R,rms45r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RMS45R register + * @return uint16_t. Value of @ref RMS45R register. + * @sa setRMS45R() + */ +#define getRMS45R() \ + WIZCHIP_READ(RMS45R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref RMS67R register + * @param (uint16_t)rms67r Value to set @ref RMS67R register. The lower socket memory size is located at MSB of rms67r. + * @sa getRMS67R() + */ +#define setRMS67R(rms67r) \ + WIZCHIP_WRITE(RMS67R,rms67r) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RMS67R register + * @return uint16_t. Value of @ref RMS67R register. + * @sa setRMS67R() + */ +#define getRMS67R() \ + WIZCHIP_READ(RMS67R) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref RMS01R ~ @ref RMS67R register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)rmsr Value to set @ref RMSR0 ~@ref RMSR7 register. + * @sa getTMSR() + */ +void setRMSR(uint8_t sn,uint8_t rmsr); +#define setSn_RXBUF_SIZE(sn,rmsr) setRMSR(sn, rmsr) ///< For compatible ioLibrary + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RMS01R ~ @ref RMS67R register + * @param (uint8_t)sn Socket number. It shoudl be 0 ~ 7. + * @return uint8_t. Value of @ref RMSR0 ~ @ref RMSR7 register. + * @sa setRMSR() + */ +uint8_t getRMSR(uint8_t sn); +#define getSn_RXBUF_SIZE(sn) getRMSR(sn) ///< For compatible ioLibrary + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref MTYPER register + * @param (uint16_t)mtyper Value to set @ref MTYPER register. + * @sa getMTYPER() + */ +#define setMTYPER(mtype) \ + WIZCHIP_WRITE(MTYPER, mtype) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref MTYPER register + * @return uint16_t. Value of @ref MTYPER register. + * @sa setMTYPER() + */ +#define getMTYPER() \ + WIZCHIP_READ(MTYPER) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref RATR register + * @return uint16_t. Value of @ref PATR register. + */ +#define getPATR() \ + WIZCHIP_READ(PATR) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref PTIMER register + * @param (uint8_t)ptimer Value to set @ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ((uint16_t)ptimer) & 0x00FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + ((uint8_t)(WIZCHIP_READ(PTIMER) & 0x00FF)) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, ((uint16_t)pmagic) & 0x00FF) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + ((uint8_t)(WIZCHIP_READ(PMAGIC) & 0x00FF)) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref PSID register + * @return uint16_t. Value of @ref PSID register. + */ +#define getPSIDR() \ + WIZCHIP_READ(PSIDR) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref PDHAR register + * @param (uint8_t*)pdhar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. + */ +#define getPDHAR(pdhar) { \ + (pdhar)[0] = (uint8_t)(WIZCHIP_READ(PDHAR) >> 8); \ + (pdhar)[1] = (uint8_t)(WIZCHIP_READ(PDHAR)); \ + (pdhar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,2)) >> 8); \ + (pdhar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,2))); \ + (pdhar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,4)) >> 8); \ + (pdhar)[5] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,4))); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get unreachable IP address. @ref UIPR + * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. + */ +#define getUIPR(uipr) { \ + (uipr)[0] = (uint8_t)(WIZCHIP_READ(UIPR) >> 8); \ + (uipr)[1] = (uint8_t)(WIZCHIP_READ(UIPR)); \ + (uipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(UIPR,2)) >> 8); \ + (uipr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(UIPR,2))); \ + } + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref UPORTR register + * @return uint16_t. Value of @ref UPORTR register. + */ +#define getUPORTR() \ + WIZCHIP_READ(UPORTR) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref FMTUR register + * @return uint16_t. Value of @ref FMTUR register. + */ +#define getFMTUR() \ + WIZCHIP_READ(FMTUR) + + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref Pn_BRDYR register + * @return uint8_t. Value of @ref Pn_BRDYR register. + */ +#define getPn_BRDYR(p) \ + ((uint8_t)(WIZCHIP_READ(Pn_BRDYR(p)) & 0x00FF)) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref Pn_BRDYR register + * @param p Pin number (p = 0,1,2,3) + * @param brdyr Set a value @ref Pn_BRDYR(p). + */ +#define setPn_BRDYR(p, brdyr) \ + WIZCHIP_WRITE(Pn_BRDYR(p), brdyr & 0x00E7) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref Pn_BDPTHR register + * @param p Pin number (p = 0,1,2,3) + * @return uint16_t. Value of @ref Pn_BDPTHR register. + */ +#define getPn_BDPTHR(p) \ + WIZCHIP_READ(Pn_BDPTHR(p)) + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Set @ref Pn_BDPTHR register + * @param p Pin number (p = 0,1,2,3) + * @param bdpthr Value of @ref Pn_BDPTHR + */ +#define setPn_BDPTHR(p, bdpthr) \ + WIZCHIP_WRITE(Pn_BDPTHR(p),bdpthr) + + +/** + * @ingroup Common_register_access_function_W5300 + * @brief Get @ref IDR register + * @return uint16_t. Always 0x5300. + */ +#define getIDR() \ + WIZCHIP_READ(IDR) + + +/*********************************** + * SOCKET Register Access Function * + ***********************************/ + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), ((uint16_t)cr) & 0x00FF) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_CR(sn))) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)imr Value to set @ref Sn_IMR + * @sa getSn_IMR() + */ +#define setSn_IMR(sn, imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), ((uint16_t)imr) & 0x00FF) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +#define getSn_IMR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_IMR(sn))) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), ((uint16_t)ir) & 0x00FF) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_IR(sn))) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SSR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_SR(sn))) +#define getSn_SR(sn) getSn_SSR(sn) ///< For compatible ioLibrary. Refer to getSn_SSR(). + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_PORTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)port Variable to set @ref Sn_PORTR. + * @sa getSn_PORTR() + */ +#define setSn_PORTR(sn, port) \ + WIZCHIP_WRITE(Sn_PORTR(sn), port) +#define setSn_PORT(sn, port) setSn_PORTR(sn, port) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_PORTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Variable of @ref Sn_PORTR. + * @sa setSn_PORTR() + */ +#define getSn_PORTR(sn) \ + WIZCHIP_READ(Sn_PORTR(sn)) +#define getSn_PORT(sn) getSn_PORTR(sn) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) { \ + WIZCHIP_WRITE(Sn_DHAR(sn), (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2), (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4), (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \ + } + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) { \ + (dhar)[0] = (uint8_t)(WIZCHIP_READ(Sn_DHAR(sn)) >> 8); \ + (dhar)[1] = (uint8_t) WIZCHIP_READ(Sn_DHAR(sn)); \ + (dhar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2)) >> 8); \ + (dhar)[3] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2)); \ + (dhar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4)) >> 8); \ + (dhar)[5] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4)); \ + } + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORTR(sn, dport) \ + WIZCHIP_WRITE(Sn_DPORTR(sn),dport) +#define setSn_DPORT(sn, dport) setSn_DPORTR(sn,dport) ///< For compatible ioLibrary. Refer to @ref Sn_DPORTR. + + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + * @note This function is not available because W5300 have a bug to read @ref Sn_DPORTR. \n + * Don't use this function. + */ +#define getSn_DPORTR(sn) \ + WIZCHIP_READ(Sn_DPORTR(sn)) +#define getSn_DPORT(sn) getSn_DPORTR(sn) ///< For compatible ioLibrary. Refer to @ref Sn_DPORTR. + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) { \ + WIZCHIP_WRITE(Sn_DIPR(sn), (((uint16_t)((dipr)[0])) << 8) + (((uint16_t)((dipr)[1])) & 0x00FF)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2), (((uint16_t)((dipr)[2])) << 8) + (((uint16_t)((dipr)[3])) & 0x00FF)); \ + } + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa setSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) { \ + (dipr)[0] = (uint8_t)(WIZCHIP_READ(Sn_DIPR(sn)) >> 8); \ + (dipr)[1] = (uint8_t) WIZCHIP_READ(Sn_DIPR(sn)); \ + (dipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2)) >> 8); \ + (dipr)[3] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2)); \ + } + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) \ + WIZCHIP_WRITE(Sn_MSSR(sn), mss) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + WIZCHIP_READ(Sn_MSSR(sn)) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR + * @sa getSn_KPALVTR() + */ +#define setSn_KPALVTR(sn, kpalvt) \ + WIZCHIP_WRITE(Sn_KPALVTR(sn), (WIZCHIP_READ(Sn_KPALVTR(sn)) & 0x00FF) | (((uint16_t)kpalvt)<<8)) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_KPALVTR. + * @sa setSn_KPALVTR() + */ +#define getSn_KPALVTR(sn) \ + ((uint8_t)(WIZCHIP_READ(Sn_KPALVTR(sn)) >> 8)) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_PROTOR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)proto Value to set \ref Sn_PROTOR + * @sa getSn_PROTOR() + */ +#define setSn_PROTOR(sn, proto) \ + WIZCHIP_WRITE(Sn_PROTOR(sn),(WIZCHIP_READ(Sn_PROTOR(sn)) & 0xFF00) | (((uint16_t)proto) & 0x00FF)) +#define setSn_PROTO(sn,proto) setSn_PROTOR(sn,proto) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_PROTOR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return uint8_t. Value of @ref Sn_PROTOR. + * @sa setSn_PROTOR() + */ +#define getSn_PROTOR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_PROTOR(sn))) +#define getSn_PROTO(sn) getSn_PROTOR(sn) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_TX_WRSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint32_t)txwrs Value to set @ref Sn_KPALVTR (It should be <= 0x00010000) + * @sa getSn_TX_WRSR() + */ +#define setSn_TX_WRSR(sn, txwrs) { \ + WIZCHIP_WRITE(Sn_TX_WRSR(sn), (uint16_t)(((uint32_t)txwrs) >> 16)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WRSR(sn),2), (uint16_t)txwrs); \ + } + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_TX_WRSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint32_t. Value of Sn_TX_WRSR. + * @sa setSn_TX_WRSR() + */ +#define getSn_TX_WRSR(sn) \ + ( (((uint32_t)WIZCHIP_READ(Sn_TX_WRSR(sn))) << 16) + (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WRSR(sn),1))) & 0x0000FFFF) ) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint32_t. Value of @ref Sn_TX_FSR. + */ +uint32_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint32_t. Value of @ref Sn_RX_RSR. + */ +uint32_t getSn_RX_RSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_TX_FIFOR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)txfifo. Value to set @ref Sn_TX_FIFOR. + */ +#define setSn_TX_FIFOR(sn, txfifo) \ + WIZCHIP_WRITE(Sn_TX_FIFOR(sn), txfifo); + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_RX_FIFOR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_RX_FIFOR. + */ +#define getSn_RX_FIFOR(sn) \ + WIZCHIP_READ(Sn_RX_FIFOR(sn)); + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_TOSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param (uint8_t)tos Value to set @ref Sn_TOSR + * @sa getSn_TOSR() + */ +#define setSn_TOSR(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), ((uint16_t)tos) & 0x00FF) +#define setSn_TOS(sn,tos) setSn_TOSR(sn,tos) ///< For compatible ioLibrar + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_TOSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_ . + * @return uint8_t. Value of Sn_TOSR. + * @sa setSn_TOSR() + */ +#define getSn_TOSR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_TOSR(sn))) +#define getSn_TOS(sn) getSn_TOSR(sn) ///< For compatible ioLibrar + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_TTLR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)ttl Value to set @ref Sn_TTLR + * @sa getSn_TTLR() + */ +#define setSn_TTLR(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTLR(sn), ((uint16_t)ttl) & 0x00FF) +#define setSn_TTL(sn,ttl) setSn_TTLR(sn,ttl) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_TTLR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_TTLR. + * @sa setSn_TTLR() + */ +#define getSn_TTLR(sn) \ + ((uint8_t)WIZCHIP_READ(Sn_TTL(sn))) +#define getSn_TTL(sn) getSn_TTLR(sn) ///< For compatible ioLibrary + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Set @ref Sn_FRAGR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)frag Value to set @ref Sn_FRAGR + * @sa getSn_FRAGR() + */ +#define setSn_FRAGR(sn, frag) \ + WIZCHIP_WRITE(Sn_FRAGR(sn), ((uint16_t)frag) & 0x00FF) +#define setSn_FRAG(sn,frag) setSn_FRAGR(sn,flag) + +/** + * @ingroup Socket_register_access_function_W5300 + * @brief Get @ref Sn_FRAGR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_FRAGR. + * @sa setSn_FRAGR() + */ +#define getSn_FRAGR(sn) \ + (WIZCHIP_READ(Sn_FRAG(sn))) +#define getSn_FRAG(sn) getSn_FRAGR(sn) + + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// + +/** + * @brief Socket_register_access_function_W5300 + * @brief Gets the max buffer size of socket sn passed as parameter. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint32_t. Value of Socket n RX max buffer size. + */ +#define getSn_RxMAX(sn) \ + (((uint32_t)getSn_RXBUF_SIZE(sn)) << 10) + +/** + * @brief Socket_register_access_function_W5300 + * @brief Gets the max buffer size of socket sn passed as parameters. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint32_t. Value of Socket n TX max buffer size. + */ +#define getSn_TxMAX(sn) \ + (((uint32_t)getSn_TXBUF_SIZE(sn)) << 10) + +/** + * @ingroup Basic_IO_function_W5300 + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint32_t len); + +/** + * @ingroup Basic_IO_function_W5300 + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to wizdata(pointer variable) of the length of len(variable) bytes. + * This function is being called by recv() also. + * + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint32_t len); + +/** + * @ingroup Basic_IO_function_W5300 + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of len(variable) bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint32_t len); + +/// \cond DOXY_APPLY_CODE +#endif +/// \endcond + +#ifdef __cplusplus +} +#endif + +#endif // _W5300_H_ diff --git a/Libraries/Ethernet/W5500/w5500.c b/Libraries/Ethernet/W5500/w5500.c new file mode 100644 index 0000000..161fac9 --- /dev/null +++ b/Libraries/Ethernet/W5500/w5500.c @@ -0,0 +1,267 @@ +//***************************************************************************** +// +//! \file w5500.c +//! \brief W5500 HAL Interface. +//! \version 1.0.2 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2014/05/01> V1.0.2 +//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 +//! Fixed the problem on porting into under 32bit MCU +//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh +//! Thank for your interesting and serious advices. +//! <2013/12/20> V1.0.1 +//! 1. Remove warning +//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ +//! for loop optimized(removed). refer to M20131220 +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +//#include +#include "w5500.h" + +#define _W5500_SPI_VDM_OP_ 0x00 +#define _W5500_SPI_FDM_OP_LEN1_ 0x01 +#define _W5500_SPI_FDM_OP_LEN2_ 0x02 +#define _W5500_SPI_FDM_OP_LEN4_ 0x03 + +#if (_WIZCHIP_ == 5500) +//////////////////////////////////////////////////// + +uint8_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint8_t ret; + uint8_t spi_data[3]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + } + else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + } + ret = WIZCHIP.IF.SPI._read_byte(); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) +{ + uint8_t spi_data[4]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + + //if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + WIZCHIP.IF.SPI._write_byte(wb); + } + else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + spi_data[3] = wb; + WIZCHIP.IF.SPI._write_burst(spi_data, 4); + } + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + + if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + for(i = 0; i < len; i++) + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + } + else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._read_burst(pBuf, len); + } + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + + if(!WIZCHIP.IF.SPI._write_burst) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + for(i = 0; i < len; i++) + WIZCHIP.IF.SPI._write_byte(pBuf[i]); + } + else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + WIZCHIP.IF.SPI._write_burst(spi_data, 3); + WIZCHIP.IF.SPI._write_burst(pBuf, len); + } + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + + +uint16_t getSn_TX_FSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + + do + { + val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_TX_FSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + } + }while (val != val1); + return val; +} + + +uint16_t getSn_RX_RSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + + do + { + val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_RX_RSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + } + }while (val != val1); + return val; +} + +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr = 0; + uint32_t addrsel = 0; + + if(len == 0) return; + ptr = getSn_TX_WR(sn); + //M20140501 : implict type casting -> explict type casting + //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + // + WIZCHIP_WRITE_BUF(addrsel,wizdata, len); + + ptr += len; + setSn_TX_WR(sn,ptr); +} + +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr = 0; + uint32_t addrsel = 0; + + if(len == 0) return; + ptr = getSn_RX_RD(sn); + //M20140501 : implict type casting -> explict type casting + //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + // + WIZCHIP_READ_BUF(addrsel, wizdata, len); + ptr += len; + + setSn_RX_RD(sn,ptr); +} + + +void wiz_recv_ignore(uint8_t sn, uint16_t len) +{ + uint16_t ptr = 0; + + ptr = getSn_RX_RD(sn); + ptr += len; + setSn_RX_RD(sn,ptr); +} + +#endif diff --git a/Libraries/Ethernet/W5500/w5500.h b/Libraries/Ethernet/W5500/w5500.h new file mode 100644 index 0000000..3afc16e --- /dev/null +++ b/Libraries/Ethernet/W5500/w5500.h @@ -0,0 +1,2163 @@ +//***************************************************************************** +// +//! \file w5500.h +//! \brief W5500 HAL Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +// + +#ifndef _W5500_H_ +#define _W5500_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "wizchip_conf.h" + +/// @cond DOXY_APPLY_CODE +#if (_WIZCHIP_ == 5500) +/// @endcond + +#define _W5500_IO_BASE_ 0x00000000 + +#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase +#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase + +#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block +#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block +#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block +#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address + + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + +////////////////////////////// +//-------------------------- defgroup --------------------------------- +/** + * @defgroup W5500 W5500 + * + * @brief WHIZCHIP register defines and I/O functions of @b W5500. + * + * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group + * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function + */ + + +/** + * @defgroup WIZCHIP_register WIZCHIP register + * @ingroup W5500 + * + * @brief WHIZCHIP register defines register group of @b W5500. + * + * - @ref Common_register_group : Common register group + * - @ref Socket_register_group : \c SOCKET n register group + */ + + +/** + * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions + * @ingroup W5500 + * + * @brief This supports the basic I/O functions for @ref WIZCHIP_register. + * + * - Basic I/O function \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n + * + * - @ref Common_register_group access functions \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() + * -# Network Information \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() + * -# ICMP packet \n + * getUIPR(), getUPORTR() + * -# @b etc. \n + * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n + * + * - \ref Socket_register_group access functions \n + * -# SOCKET control \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() + * -# SOCKET information \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# SOCKET communication \n + * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() + * -# IP header field \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + + + +/** + * @defgroup Common_register_group Common register + * @ingroup WIZCHIP_register + * + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. + * @sa _RTR_, _RCR_ : Data retransmission. + * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. + * @sa UIPR, UPORTR : ICMP message. + * @sa PHYCFGR, VERSIONR : etc. + */ + + + +/** + * @defgroup Socket_register_group Socket register + * @ingroup WIZCHIP_register + * + * @brief Socket register group.\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. + * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + + + /** + * @defgroup Basic_IO_function Basic I/O function + * @ingroup WIZCHIP_IO_Functions + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function Common register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access common registers. + */ + +/** + * @defgroup Socket_register_access_function Socket register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access socket registers. + */ + +//------------------------------- defgroup end -------------------------------------------- +//----------------------------- W5500 Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group + * @brief Mode Register address(R/W)\n + * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of @ref MR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
+ * - \ref MR_RST : Reset + * - \ref MR_WOL : Wake on LAN + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_FARP : Force ARP mode + */ +#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Gateway IP Register address(R/W) + * @details @ref GAR configures the default gateway address. + */ +#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Subnet mask Register address(R/W) + * @details @ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Source MAC Register address(R/W) + * @details @ref SHAR configures the source hardware address. + */ +#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Source IP Register address(R/W) + * @details @ref SIPR configures the source IP address. + */ +#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Set Interrupt low level timer register address(R/W) + * @details @ref INTLEVEL configures the Interrupt Assert Time. + */ +#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Interrupt Register(R/W) + * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. + * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of @ref IR defined as follows. + * + * + * + *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
+ * - \ref IR_CONFLICT : IP conflict + * - \ref IR_UNREACH : Destination unreachable + * - \ref IR_PPPoE : PPPoE connection close + * - \ref IR_MP : Magic packet + */ +#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Interrupt mask register(R/W) + * @details @ref _IMR_ is used to mask interrupts. Each bit of @ref _IMR_ corresponds to each bit of @ref IR. + * When a bit of @ref _IMR_ is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, + * if a bit of @ref _IMR_ is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n + * Each bit of @ref _IMR_ defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
+ * - \ref IM_IR7 : IP Conflict Interrupt Mask + * - \ref IM_IR6 : Destination unreachable Interrupt Mask + * - \ref IM_IR5 : PPPoE Close Interrupt Mask + * - \ref IM_IR4 : Magic Packet Interrupt Mask + */ +//M20150401 : Rename SYMBOE ( Re-define error in a compile) +//#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +#define _IMR_ (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Register(R/W) + * @details @ref SIR indicates the interrupt status of Socket.\n + * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n + * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ +#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. + * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. + * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is + */ +#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Timeout register address( 1 is 100us )(R/W) + * @details @ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref _RTR_ is x07D0. + * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref _RTR_, W5500 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the @ref _RTR_ time, W5500 retransmits the packet or issues timeout. + */ +//M20150401 : Rename SYMBOE ( Re-define error in a compile) +//#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +#define _RTR_ (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Retry count register(R/W) + * @details @ref _RCR_ configures the number of time of retransmission. + * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (@ref Sn_IR_TIMEOUT = '1'). + */ +//M20150401 : Rename SYMBOE ( Re-define error in a compile) +//#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) +#define _RCR_ (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Request Timer register in PPPoE mode(R/W) + * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Magic number register in PPPoE mode(R/W) + * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Destination MAC Register address(R/W) + * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. + */ +#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Session Identification Register(R/W) + * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. + */ +#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Maximum Segment Size(MSS) register(R/W) + * @details @ref PMRU configures the maximum receive unit of PPPoE. + */ +#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable IP register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates + * the destination IP address & port number respectively. + */ +#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable Port register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR + * indicates the destination IP address & port number respectively. + */ +#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PHY Status Register(R/W) + * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. + */ +#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief chip version register address(R) + * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. + */ +#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + + +//----------------------------- W5500 Socket Registers IOMAP ----------------------------- +/** + * @ingroup Socket_register_group + * @brief socket Mode register(R/W) + * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of @ref Sn_MR defined as the following. + * + * + * + *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
+ * - @ref Sn_MR_MULTI : Support UDP Multicasting + * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting + * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting + * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode + * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating + * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode + * - Protocol + * + * + * + * + * + * + *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
+ * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - @ref Sn_MR_UDP : UDP + * - @ref Sn_MR_TCP : TCP + * - @ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. + * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. + * - @ref Sn_CR_OPEN : Initialize or open socket. + * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) + * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) + * - @ref Sn_CR_DISCON : Send closing request in TCP mode. + * - @ref Sn_CR_CLOSE : Close socket. + * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - @ref Sn_CR_SEND_KEEP : Send keep alive message. + * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. + */ +#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket interrupt register(R) + * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n + * In order to clear the @ref Sn_IR bit, the host should write the bit to \n + * + * + * + *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
+ * - \ref Sn_IR_SENDOK : SEND_OK Interrupt + * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt + * - \ref Sn_IR_RECV : RECV Interrupt + * - \ref Sn_IR_DISCON : DISCON Interrupt + * - \ref Sn_IR_CON : CON Interrupt + */ +#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket status register(R) + * @details @ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - @ref SOCK_CLOSED : Closed + * - @ref SOCK_INIT : Initiate state + * - @ref SOCK_LISTEN : Listen state + * - @ref SOCK_ESTABLISHED : Success to connect + * - @ref SOCK_CLOSE_WAIT : Closing state + * - @ref SOCK_UDP : UDP socket + * - @ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - @ref SOCK_FIN_WAIT : Connection state + * - @ref SOCK_CLOSING : Closing state + * - @ref SOCK_TIME_WAIT : Closing state + * - @ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief source port register(R/W) + * @details @ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered. + */ +#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer MAC register address(R/W) + * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer IP register address(R/W) + * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of TCP serverbefore CONNECT command. + * In TCP server mode, it indicates an IP address of TCP clientafter successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer port register address(R/W) + * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP clientmode, it configures the listen port number of TCP serverbefore CONNECT command. + * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief IP Type of Service(TOS) Register(R/W) + * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +/** + * @ingroup Socket_register_group + * @brief IP Time to live(TTL) Register(R/W) + * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Receive memory size register(R/W) + * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. + * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data cannot be normally received from a peer. + * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, + * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data reception error is occurred. + */ +#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory size register(R/W) + * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data can�t be normally transmitted to a peer. + * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, + * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data transmission error is occurred. + */ +#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit free memory size register(R) + * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. + * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory read pointer register address(R) + * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory write pointer register address(R/W) + * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Received data size register(R) + * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between + * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) + */ +#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Read point of Receive memory(R/W) + * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. + */ +#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Write point of Receive memory(R) + * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief socket interrupt mask register(R) + * @details @ref Sn_IMR masks the interrupt of Socket n. + * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is + * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is + * Host is interrupted by asserted INTn PIN to low. + */ +#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Fragment field value in IP header register(R/W) + * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). + */ +#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Keep Alive Timer register(R/W) + * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, + * and ignored in other modes. The time unit is 5s. + * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. + * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). + * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, + * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). + * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. + */ +#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + + +//----------------------------- W5500 Register values ----------------------------- + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 + +/** + * @brief Wake on LAN + * @details 0 : Disable WOL mode\n + * 1 : Enable WOL mode\n + * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. + * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) + * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and + * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. + */ +#define MR_WOL 0x20 + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be + */ +#define MR_PPPOE 0x08 + +/** + * @brief Enable UDP_FORCE_ARP CHECHK + * @details 0 : Disable Force ARP mode\n + * 1 : Enable Force ARP mode\n + * In Force ARP mode, It forces on sending ARP Request whenever data is sent. + */ +#define MR_FARP 0x02 + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 + +/** + * @brief Get the destination unreachable message in UDP sending. + * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as + * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. + */ +#define IR_UNREACH 0x40 + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 + +/** + * @brief Get the magic packet interrupt. + * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. + */ +#define IR_MP 0x10 + + +/* PHYCFGR register value */ +#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. +#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value +#define PHYCFGR_OPMDC_ALLA (7<<3) +#define PHYCFGR_OPMDC_PDOWN (6<<3) +#define PHYCFGR_OPMDC_NA (5<<3) +#define PHYCFGR_OPMDC_100FA (4<<3) +#define PHYCFGR_OPMDC_100F (3<<3) +#define PHYCFGR_OPMDC_100H (2<<3) +#define PHYCFGR_OPMDC_10F (1<<3) +#define PHYCFGR_OPMDC_10H (0<<3) +#define PHYCFGR_DPX_FULL (1<<2) +#define PHYCFGR_DPX_HALF (0<<2) +#define PHYCFGR_SPD_100 (1<<1) +#define PHYCFGR_SPD_10 (0<<1) +#define PHYCFGR_LNK_ON (1<<0) +#define PHYCFGR_LNK_OFF (0<<0) + +/* IMR register values */ +/** + * @brief IP Conflict Interrupt Mask. + * @details 0: Disable IP Conflict Interrupt\n + * 1: Enable IP Conflict Interrupt + */ +#define IM_IR7 0x80 + +/** + * @brief Destination unreachable Interrupt Mask. + * @details 0: Disable Destination unreachable Interrupt\n + * 1: Enable Destination unreachable Interrupt + */ +#define IM_IR6 0x40 + +/** + * @brief PPPoE Close Interrupt Mask. + * @details 0: Disable PPPoE Close Interrupt\n + * 1: Enable PPPoE Close Interrupt + */ +#define IM_IR5 0x20 + +/** + * @brief Magic Packet Interrupt Mask. + * @details 0: Disable Magic Packet Interrupt\n + * 1: Enable Magic Packet Interrupt + */ +#define IM_IR4 0x10 + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010.\n + * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of @ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 + +/** + * @brief Broadcast block in UDP Multicasting. + * @details 0 : disable Broadcast Blocking\n + * 1 : enable Broadcast Blocking\n + * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m + * In addition, This bit does when MACRAW mode(P[3:0] = 100 + */ +#define Sn_MR_BCASTB 0x40 + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001.\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref _RTR_. + */ +#define Sn_MR_ND 0x20 + +/** + * @brief Unicast Block in UDP Multicasting + * @details 0 : disable Unicast Blocking\n + * 1 : enable Unicast Blocking\n + * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = + */ +#define Sn_MR_UCASTB 0x10 + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 + +#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 + +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 + +/* Sn_MR values used with Sn_MR_MACRAW */ +/** + * @brief MAC filter enable in @ref Sn_MR_MACRAW mode + * @details 0 : disable MAC Filtering\n + * 1 : enable MAC Filtering\n + * This bit is applied only during MACRAW mode(P[3:0] = 100.\n + * When set as W5500 can only receive broadcasting packet or packet sent to itself. + * When this bit is W5500 can receive all packets on Ethernet. + * If user wants to implement Hybrid TCP/IP stack, + * it is recommended that this bit is set as for reducing host overhead to process the all received packets. + */ +#define Sn_MR_MFEN Sn_MR_MULTI + +/** + * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MMB Sn_MR_ND + +/** + * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : disable IPv6 Blocking\n + * 1 : enable IPv6 Blocking\n + * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. + */ +#define Sn_MR_MIP6B Sn_MR_UCASTB + +/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ +/** + * @brief IGMP version used in UDP mulitcasting + * @details 0 : disable Multicast Blocking\n + * 1 : enable Multicast Blocking\n + * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. + */ +#define Sn_MR_MC Sn_MR_ND + +/* Sn_MR alternate values */ +/** + * @brief For Berkeley Socket API + */ +#define SOCK_STREAM Sn_MR_TCP + +/** + * @brief For Berkeley Socket API + */ +#define SOCK_DGRAM Sn_MR_UDP + + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n + * + * + * + * + * + * + *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000)
Sn_MR_TCP (001) SOCK_INIT (0x13)
Sn_MR_UDP (010) SOCK_UDP (0x22)
S0_MR_MACRAW (100) SOCK_MACRAW (0x02)
+ */ +#define Sn_CR_OPEN 0x01 + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (\ref Sn_MR(P3:P0) = \ref Sn_MR_TCP). + * In this mode, Socket n operates as a TCP serverand waits for connection-request (SYN packet) from any TCP client + * The @ref Sn_SR changes the state from \ref SOCK_INIT to \ref SOCKET_LISTEN. + * When a TCP clientconnection request is successfully established, + * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the @ref Sn_IR(0) becomes + * But when a TCP clientconnection request is failed, @ref Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as TCP client + */ +#define Sn_CR_CONNECT 0x04 + +/** + * @brief Send closing request in TCP mode + * @details Regardless of TCP serveror TCP client the DISCON command processes the disconnect-process (b>Active close
or Passive close.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (\ref Sn_IR(3)='1') and then @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 + +/** + * @brief Close socket + * @details Sn_SR is changed to @ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/* Sn_IR values */ +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\n + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\n + * It is changed to @ref SOCK_INIT when @ref Sn_MR(P[3:0]) = 001 and OPEN command is ordered.\n + * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 + +/** + * @brief Listen state + * @details This indicates Socket n is operating as TCP servermode and waiting for connection-request (SYN packet) from a peer TCP client.\n + * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to @ref SOCK_CLOSED after TCPTO @ref Sn_IR(TIMEOUT) = '1') is occurred. + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n + * If not, it changes to @ref SOCK_CLOSED after timeout (@ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to @ref SOCK_ESTABLISHED when the TCP SERVERprocessed the SYN packet from the TCP CLIENTduring @ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout(@ref Sn_IR[TIMEOUT] = '1') is occurred. + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(@ref Sn_MR(P[3:0]) = '010').\n + * It changes to SOCK_UDP when @ref Sn_MR(P[3:0]) = '010' and @ref Sn_CR_OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 + +#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 + +//#define SOCK_PPPOE 0x5F + +/* IP PROTOCOL */ +#define IPPROTO_IP 0 //< Dummy for IP +#define IPPROTO_ICMP 1 //< Control message protocol +#define IPPROTO_IGMP 2 //< Internet group management protocol +#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) +#define IPPROTO_TCP 6 //< TCP +#define IPPROTO_PUP 12 //< PUP +#define IPPROTO_UDP 17 //< UDP +#define IPPROTO_IDP 22 //< XNS idp +#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 //< Raw IP packet + + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +#ifdef _exit +#undef _exit +#endif + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + +//////////////////////// +// Basic I/O Function // +//////////////////////// + +/** + * @ingroup Basic_IO_function + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +///////////////////////////////// +// Common Register I/O function // +///////////////////////////////// +/** + * @ingroup Common_register_access_function + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#define setMR(mr) \ + WIZCHIP_WRITE(MR,mr) + + +/** + * @ingroup Common_register_access_function + * @brief Get Mode Register + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#define getMR() \ + WIZCHIP_READ(MR) + +/** + * @ingroup Common_register_access_function + * @brief Set gateway IP address + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Get gateway IP address + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Set subnet mask address + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR, subr,4) + + +/** + * @ingroup Common_register_access_function + * @brief Get subnet mask address + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set local MAC address + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get local MAC address + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set local IP address + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() + */ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Get local IP address + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set INTLEVEL register + * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. + * @sa getINTLEVEL() + */ +#define setINTLEVEL(intlevel) {\ + WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ + } + + +/** + * @ingroup Common_register_access_function + * @brief Get INTLEVEL register + * @return uint16_t. Value of @ref INTLEVEL register. + * @sa setINTLEVEL() + */ +//M20150401 : Type explict declaration +/* +#define getINTLEVEL() \ + ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) +*/ +#define getINTLEVEL() \ + (((uint16_t)WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref IR register + * @param (uint8_t)ir Value to set @ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xF0)) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref IR register + * @return uint8_t. Value of @ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xF0) +/** + * @ingroup Common_register_access_function + * @brief Set @ref _IMR_ register + * @param (uint8_t)imr Value to set @ref _IMR_ register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(_IMR_, imr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref _IMR_ register + * @return uint8_t. Value of @ref _IMR_ register. + * @sa setIMR() + */ +#define getIMR() \ + WIZCHIP_READ(_IMR_) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIR register + * @param (uint8_t)sir Value to set @ref SIR register. + * @sa getSIR() + */ +#define setSIR(sir) \ + WIZCHIP_WRITE(SIR, sir) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIR register + * @return uint8_t. Value of @ref SIR register. + * @sa setSIR() + */ +#define getSIR() \ + WIZCHIP_READ(SIR) +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIMR register + * @param (uint8_t)simr Value to set @ref SIMR register. + * @sa getSIMR() + */ +#define setSIMR(simr) \ + WIZCHIP_WRITE(SIMR, simr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIMR register + * @return uint8_t. Value of @ref SIMR register. + * @sa setSIMR() + */ +#define getSIMR() \ + WIZCHIP_READ(SIMR) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref _RTR_ register + * @param (uint16_t)rtr Value to set @ref _RTR_ register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(_RTR_, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref _RTR_ register + * @return uint16_t. Value of @ref _RTR_ register. + * @sa setRTR() + */ +//M20150401 : Type explict declaration +/* +#define getRTR() \ + ((WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1))) +*/ +#define getRTR() \ + (((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1))) + + +/** + * @ingroup Common_register_access_function + * @brief Set @ref _RCR_ register + * @param (uint8_t)rcr Value to set @ref _RCR_ register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(_RCR_, rcr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref _RCR_ register + * @return uint8_t. Value of @ref _RCR_ register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(_RCR_) + +//================================================== test done =========================================================== + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PTIMER register + * @param (uint8_t)ptimer Value to set @ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PHAR address + * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. + * @sa getPHAR() + */ +#define setPHAR(phar) \ + WIZCHIP_WRITE_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PHAR address + * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. + * @sa setPHAR() + */ +#define getPHAR(phar) \ + WIZCHIP_READ_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PSID register + * @param (uint16_t)psid Value to set @ref PSID register. + * @sa getPSID() + */ +#define setPSID(psid) {\ + WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PSID register + * @return uint16_t. Value of @ref PSID register. + * @sa setPSID() + */ +//uint16_t getPSID(void); +//M20150401 : Type explict declaration +/* +#define getPSID() \ + ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) +*/ +#define getPSID() \ + (((uint16_t)WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMRU register + * @param (uint16_t)pmru Value to set @ref PMRU register. + * @sa getPMRU() + */ +#define setPMRU(pmru) { \ + WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMRU register + * @return uint16_t. Value of @ref PMRU register. + * @sa setPMRU() + */ +//M20150401 : Type explict declaration +/* +#define getPMRU() \ + ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) +*/ +#define getPMRU() \ + (((uint16_t)WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) + +/** + * @ingroup Common_register_access_function + * @brief Get unreachable IP address + * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. + */ +//M20150401 : Size Error of UIPR (6 -> 4) +/* +#define getUIPR(uipr) \ + WIZCHIP_READ_BUF(UIPR,uipr,6) +*/ +#define getUIPR(uipr) \ + WIZCHIP_READ_BUF(UIPR,uipr,4) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref UPORTR register + * @return uint16_t. Value of @ref UPORTR register. + */ +//M20150401 : Type explict declaration +/* +#define getUPORTR() \ + ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) +*/ +#define getUPORTR() \ + (((uint16_t)WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PHYCFGR register + * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. + * @sa getPHYCFGR() + */ +#define setPHYCFGR(phycfgr) \ + WIZCHIP_WRITE(PHYCFGR, phycfgr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PHYCFGR register + * @return uint8_t. Value of @ref PHYCFGR register. + * @sa setPHYCFGR() + */ +#define getPHYCFGR() \ + WIZCHIP_READ(PHYCFGR) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref VERSIONR register + * @return uint8_t. Value of @ref VERSIONR register. + */ +#define getVERSIONR() \ + WIZCHIP_READ(VERSIONR) + +///////////////////////////////////// + +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)imr Value to set @ref Sn_IMR + * @sa getSn_IMR() + */ +#define setSn_IMR(sn, imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +#define getSn_IMR(sn) \ + (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +//M20150401 : Type explict declaration +/* +#define getSn_PORT(sn) \ + ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) +*/ +#define getSn_PORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa setSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +//M20150401 : Type explict declaration +/* +#define getSn_DPORT(sn) \ + ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) +*/ +#define getSn_DPORT(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +//M20150401 : Type explict declaration +/* +#define getSn_MSSR(sn) \ + ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) +*/ +#define getSn_MSSR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE + * @sa getSn_RXBUF_SIZE() + */ +#define setSn_RXBUF_SIZE(sn, rxbufsize) \ + WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. + * @sa setSn_RXBUF_SIZE() + */ +#define getSn_RXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE + * @sa getSn_TXBUF_SIZE() + */ +#define setSn_TXBUF_SIZE(sn, txbufsize) \ + WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. + * @sa setSn_TXBUF_SIZE() + */ +#define getSn_TXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +//M20150401 : Type explict declaration +/* +#define getSn_TX_RD(sn) \ + ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) +*/ +#define getSn_TX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +//M20150401 : Type explict declaration +/* +#define getSn_TX_WR(sn) \ + ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) +*/ +#define getSn_TX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +//M20150401 : Type explict declaration +/* +#define getSn_RX_RD(sn) \ + ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) +*/ +#define getSn_RX_RD(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +//M20150401 : Type explict declaration +/* +#define getSn_RX_WR(sn) \ + ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) +*/ +#define getSn_RX_WR(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint16_t)frag Value to set @ref Sn_FRAG + * @sa getSn_FRAD() + */ +#define setSn_FRAG(sn, frag) { \ + WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of @ref Sn_FRAG. + * @sa setSn_FRAG() + */ +//M20150401 : Type explict declaration +/* +#define getSn_FRAG(sn) \ + ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) +*/ +#define getSn_FRAG(sn) \ + (((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR + * @sa getSn_KPALVTR() + */ +#define setSn_KPALVTR(sn, kpalvt) \ + WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint8_t. Value of @ref Sn_KPALVTR. + * @sa setSn_KPALVTR() + */ +#define getSn_KPALVTR(sn) \ + WIZCHIP_READ(Sn_KPALVTR(sn)) + +////////////////////////////////////// + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @brief Socket_register_access_function + * @brief Gets the max buffer size of socket sn passed as parameter. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of Socket n RX max buffer size. + */ +//M20150401 : Type explict declaration +/* +#define getSn_RxMAX(sn) \ + (getSn_RXBUF_SIZE(sn) << 10) +*/ +#define getSn_RxMAX(sn) \ + (((uint16_t)getSn_RXBUF_SIZE(sn)) << 10) + +/** + * @brief Socket_register_access_function + * @brief Gets the max buffer size of socket sn passed as parameters. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @return uint16_t. Value of Socket n TX max buffer size. + */ +//M20150401 : Type explict declaration +/* +#define getSn_TxMAX(sn) \ + (getSn_TXBUF_SIZE(sn) << 10) +*/ +#define getSn_TxMAX(sn) \ + (((uint16_t)getSn_TXBUF_SIZE(sn)) << 10) + +/** + * @ingroup Basic_IO_function + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to wizdata(pointer variable) of the length of len(variable) bytes. + * This function is being called by recv() also. + * + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of len(variable) bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be 0 ~ 7. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +/// @cond DOXY_APPLY_CODE +#endif +/// @endcond + +#ifdef __cplusplus +} +#endif + +#endif // _W5500_H_ diff --git a/Libraries/Ethernet/socket.c b/Libraries/Ethernet/socket.c new file mode 100644 index 0000000..412a65d --- /dev/null +++ b/Libraries/Ethernet/socket.c @@ -0,0 +1,931 @@ +//***************************************************************************** +// +//! \file socket.c +//! \brief SOCKET APIs Implements file. +//! \details SOCKET APIs like as Berkeley Socket APIs. +//! \version 1.0.3 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2014/05/01> V1.0.3. Refer to M20140501 +//! 1. Implicit type casting -> Explicit type casting. +//! 2. replace 0x01 with PACK_REMAINED in recvfrom() +//! 3. Validation a destination ip in connect() & sendto(): +//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. +//! Copy 4 byte addr value into temporary uint32 variable and then compares it. +//! <2013/12/20> V1.0.2 Refer to M20131220 +//! Remove Warning. +//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". +//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +#include "socket.h" + +//M20150401 : Typing Error +//#define SOCK_ANY_PORT_NUM 0xC000; +#define SOCK_ANY_PORT_NUM 0xC000 + +static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; +static uint16_t sock_io_mode = 0; +static uint16_t sock_is_sending = 0; + +static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; + +//M20150601 : For extern decleation +//static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; +uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; +// + +#if _WIZCHIP_ == 5200 + static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; +#endif + +//A20150601 : For integrating with W5300 +#if _WIZCHIP_ == 5300 + uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_] = {0,}; // set by wiz_recv_data() +#endif + + +#define CHECK_SOCKNUM() \ + do{ \ + if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ + }while(0); \ + +#define CHECK_SOCKMODE(mode) \ + do{ \ + if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ + }while(0); \ + +#define CHECK_SOCKINIT() \ + do{ \ + if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ + }while(0); \ + +#define CHECK_SOCKDATA() \ + do{ \ + if(len == 0) return SOCKERR_DATALEN; \ + }while(0); \ + + + +int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) +{ + CHECK_SOCKNUM(); + switch(protocol) + { + case Sn_MR_TCP : + { + //M20150601 : Fixed the warning - taddr will never be NULL + /* + uint8_t taddr[4]; + getSIPR(taddr); + */ + uint32_t taddr; + getSIPR((uint8_t*)&taddr); + if(taddr == 0) return SOCKERR_SOCKINIT; + break; + } + case Sn_MR_UDP : + case Sn_MR_MACRAW : + case Sn_MR_IPRAW : + break; + #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_PPPoE : + break; + #endif + default : + return SOCKERR_SOCKMODE; + } + //M20150601 : For SF_TCP_ALIGN & W5300 + //if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; + if((flag & 0x04) != 0) return SOCKERR_SOCKFLAG; +#if _WIZCHIP_ == 5200 + if(flag & 0x10) return SOCKERR_SOCKFLAG; +#endif + + if(flag != 0) + { + switch(protocol) + { + case Sn_MR_TCP: + //M20150601 : For SF_TCP_ALIGN & W5300 + #if _WIZCHIP_ == 5300 + if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK|SF_TCP_ALIGN))==0) return SOCKERR_SOCKFLAG; + #else + if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; + #endif + + break; + case Sn_MR_UDP: + if(flag & SF_IGMP_VER2) + { + if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; + } + #if _WIZCHIP_ == 5500 + if(flag & SF_UNI_BLOCK) + { + if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; + } + #endif + break; + default: + break; + } + } + close(sn); + //M20150601 + #if _WIZCHIP_ == 5300 + setSn_MR(sn, ((uint16_t)(protocol | (flag & 0xF0))) | (((uint16_t)(flag & 0x02)) << 7) ); + #else + setSn_MR(sn, (protocol | (flag & 0xF0))); + #endif + if(!port) + { + port = sock_any_port++; + if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; + } + setSn_PORT(sn,port); + setSn_CR(sn,Sn_CR_OPEN); + while(getSn_CR(sn)); + //A20150401 : For release the previous sock_io_mode + sock_io_mode &= ~(1 < sn + //if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) != getSn_TxMAX(s)) ) + if( ((getSn_MR(sn)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(sn) != getSn_TxMAX(sn)) ) + { + uint8_t destip[4] = {0, 0, 0, 1}; + // TODO + // You can wait for completing to sending data; + // wait about 1 second; + // if you have completed to send data, skip the code of erratum 1 + // ex> wait_1s(); + // if (getSn_TX_FSR(s) == getSn_TxMAX(s)) continue; + // + //M20160503 : The socket() of close() calls close() itself again. It occures a infinite loop - close()->socket()->close()->socket()-> ~ + //socket(s,Sn_MR_UDP,0x3000,0); + //sendto(s,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1). + setSn_MR(sn,Sn_MR_UDP); + setSn_PORTR(sn, 0x3000); + setSn_CR(sn,Sn_CR_OPEN); + while(getSn_CR(sn) != 0); + while(getSn_SR(sn) != SOCK_UDP); + sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1). + }; +#endif + setSn_CR(sn,Sn_CR_CLOSE); + /* wait to process the command... */ + while( getSn_CR(sn) ); + /* clear all interrupt of the socket. */ + setSn_IR(sn, 0xFF); + //A20150401 : Release the sock_io_mode of socket n. + sock_io_mode &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. + while(1) + { + freesize = getSn_TX_FSR(sn); + tmp = getSn_SR(sn); + if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) + { + close(sn); + return SOCKERR_SOCKSTATUS; + } + if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; + if(len <= freesize) break; + } + wiz_send_data(sn, buf, len); + #if _WIZCHIP_ == 5200 + sock_next_rd[sn] = getSn_TX_RD(sn) + len; + #endif + + #if _WIZCHIP_ == 5300 + setSn_TX_WRSR(sn,len); + #endif + + setSn_CR(sn,Sn_CR_SEND); + /* wait to process the command... */ + while(getSn_CR(sn)); + sock_is_sending |= (1 << sn); + //M20150409 : Explicit Type Casting + //return len; + return (int32_t)len; +} + + +int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) +{ + uint8_t tmp = 0; + uint16_t recvsize = 0; +//A20150601 : For integarating with W5300 +#if _WIZCHIP_ == 5300 + uint8_t head[2]; + uint16_t mr; +#endif +// + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + CHECK_SOCKDATA(); + + recvsize = getSn_RxMAX(sn); + if(recvsize < len) len = recvsize; + +//A20150601 : For Integrating with W5300 +#if _WIZCHIP_ == 5300 + //sock_pack_info[sn] = PACK_COMPLETED; // for clear + if(sock_remained_size[sn] == 0) + { +#endif +// + while(1) + { + recvsize = getSn_RX_RSR(sn); + tmp = getSn_SR(sn); + if (tmp != SOCK_ESTABLISHED) + { + if(tmp == SOCK_CLOSE_WAIT) + { + if(recvsize != 0) break; + else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) + { + close(sn); + return SOCKERR_SOCKSTATUS; + } + } + else + { + close(sn); + return SOCKERR_SOCKSTATUS; + } + } + if((sock_io_mode & (1< sock_remained_size[sn]) len = sock_remained_size[sn]; + recvsize = len; + if(sock_pack_info[sn] & PACK_FIFOBYTE) + { + *buf = sock_remained_byte[sn]; + buf++; + sock_pack_info[sn] &= ~(PACK_FIFOBYTE); + recvsize -= 1; + sock_remained_size[sn] -= 1; + } + if(recvsize != 0) + { + wiz_recv_data(sn, buf, recvsize); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + } + sock_remained_size[sn] -= recvsize; + if(sock_remained_size[sn] != 0) + { + sock_pack_info[sn] |= PACK_REMAINED; + if(recvsize & 0x1) sock_pack_info[sn] |= PACK_FIFOBYTE; + } + else sock_pack_info[sn] = PACK_COMPLETED; + if(getSn_MR(sn) & Sn_MR_ALIGN) sock_remained_size[sn] = 0; + //len = recvsize; +#else + if(recvsize < len) len = recvsize; + wiz_recv_data(sn, buf, len); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); +#endif + + //M20150409 : Explicit Type Casting + //return len; + return (int32_t)len; +} + +int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) +{ + uint8_t tmp = 0; + uint16_t freesize = 0; + uint32_t taddr; + + CHECK_SOCKNUM(); + switch(getSn_MR(sn) & 0x0F) + { + case Sn_MR_UDP: + case Sn_MR_MACRAW: +// break; +// #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_IPRAW: + break; +// #endif + default: + return SOCKERR_SOCKMODE; + } + CHECK_SOCKDATA(); + //M20140501 : For avoiding fatal error on memory align mismatched + //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; + //{ + //uint32_t taddr; + taddr = ((uint32_t)addr[0]) & 0x000000FF; + taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); + taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); + taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); + //} + // + //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; + if((taddr == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_IPINVALID; + if((port == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_PORTZERO; + tmp = getSn_SR(sn); +//#if ( _WIZCHIP_ < 5200 ) + if((tmp != SOCK_MACRAW) && (tmp != SOCK_UDP) && (tmp != SOCK_IPRAW)) return SOCKERR_SOCKSTATUS; +//#else +// if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS; +//#endif + + setSn_DIPR(sn,addr); + setSn_DPORT(sn,port); + freesize = getSn_TxMAX(sn); + if (len > freesize) len = freesize; // check size not to exceed MAX size. + while(1) + { + freesize = getSn_TX_FSR(sn); + if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; + if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; + if(len <= freesize) break; + }; + wiz_send_data(sn, buf, len); + + #if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata) + getSIPR((uint8_t*)&taddr); + if(taddr == 0) + { + getSUBR((uint8_t*)&taddr); + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + } + else taddr = 0; + #endif + +//A20150601 : For W5300 +#if _WIZCHIP_ == 5300 + setSn_TX_WRSR(sn, len); +#endif +// + setSn_CR(sn,Sn_CR_SEND); + /* wait to process the command... */ + while(getSn_CR(sn)); + while(1) + { + tmp = getSn_IR(sn); + if(tmp & Sn_IR_SENDOK) + { + setSn_IR(sn, Sn_IR_SENDOK); + break; + } + //M:20131104 + //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; + else if(tmp & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + //M20150409 : Fixed the lost of sign bits by type casting. + //len = (uint16_t)SOCKERR_TIMEOUT; + //break; + #if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata) + if(taddr) setSUBR((uint8_t*)&taddr); + #endif + return SOCKERR_TIMEOUT; + } + //////////// + } + #if _WIZCHIP_ < 5500 //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata) + if(taddr) setSUBR((uint8_t*)&taddr); + #endif + //M20150409 : Explicit Type Casting + //return len; + return (int32_t)len; +} + + + +int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) +{ +//M20150601 : For W5300 +#if _WIZCHIP_ == 5300 + uint16_t mr; + uint16_t mr1; +#else + uint8_t mr; +#endif +// + uint8_t head[8]; + uint16_t pack_len=0; + + CHECK_SOCKNUM(); + //CHECK_SOCKMODE(Sn_MR_UDP); +//A20150601 +#if _WIZCHIP_ == 5300 + mr1 = getMR(); +#endif + + switch((mr=getSn_MR(sn)) & 0x0F) + { + case Sn_MR_UDP: + case Sn_MR_IPRAW: + case Sn_MR_MACRAW: + break; + #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_PPPoE: + break; + #endif + default: + return SOCKERR_SOCKMODE; + } + CHECK_SOCKDATA(); + if(sock_remained_size[sn] == 0) + { + while(1) + { + pack_len = getSn_RX_RSR(sn); + if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; + if( (sock_io_mode & (1< 1514) + { + close(sn); + return SOCKFATAL_PACKLEN; + } + sock_pack_info[sn] = PACK_FIRST; + } + if(len < sock_remained_size[sn]) pack_len = len; + else pack_len = sock_remained_size[sn]; + wiz_recv_data(sn,buf,pack_len); + break; + //#if ( _WIZCHIP_ < 5200 ) + case Sn_MR_IPRAW: + if(sock_remained_size[sn] == 0) + { + wiz_recv_data(sn, head, 6); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + sock_remained_size[sn] = head[4]; + //M20150401 : For Typing Error + //sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; + sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[5]; + sock_pack_info[sn] = PACK_FIRST; + } + // + // Need to packet length check + // + if(len < sock_remained_size[sn]) pack_len = len; + else pack_len = sock_remained_size[sn]; + wiz_recv_data(sn, buf, pack_len); // data copy. + break; + //#endif + default: + wiz_recv_ignore(sn, pack_len); // data copy. + sock_remained_size[sn] = pack_len; + break; + } + setSn_CR(sn,Sn_CR_RECV); + /* wait to process the command... */ + while(getSn_CR(sn)) ; + sock_remained_size[sn] -= pack_len; + //M20150601 : + //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; + if(sock_remained_size[sn] != 0) + { + sock_pack_info[sn] |= PACK_REMAINED; + #if _WIZCHIP_ == 5300 + if(pack_len & 0x01) sock_pack_info[sn] |= PACK_FIFOBYTE; + #endif + } + else sock_pack_info[sn] = PACK_COMPLETED; +#if _WIZCHIP_ == 5300 + pack_len = len; +#endif + // + //M20150409 : Explicit Type Casting + //return pack_len; + return (int32_t)pack_len; +} + + +int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) +{ + uint8_t tmp = 0; + CHECK_SOCKNUM(); + switch(cstype) + { + case CS_SET_IOMODE: + tmp = *((uint8_t*)arg); + if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting + //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; + *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); + // + break; + case CS_GET_MAXTXBUF: + *((uint16_t*)arg) = getSn_TxMAX(sn); + break; + case CS_GET_MAXRXBUF: + *((uint16_t*)arg) = getSn_RxMAX(sn); + break; + case CS_CLR_INTERRUPT: + if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; + setSn_IR(sn,*(uint8_t*)arg); + break; + case CS_GET_INTERRUPT: + *((uint8_t*)arg) = getSn_IR(sn); + break; + #if _WIZCHIP_ != 5100 + case CS_SET_INTMASK: + if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; + setSn_IMR(sn,*(uint8_t*)arg); + break; + case CS_GET_INTMASK: + *((uint8_t*)arg) = getSn_IMR(sn); + break; + #endif + default: + return SOCKERR_ARG; + } + return SOCK_OK; +} + +int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) +{ + // M20131220 : Remove warning + //uint8_t tmp; + CHECK_SOCKNUM(); + switch(sotype) + { + case SO_TTL: + setSn_TTL(sn,*(uint8_t*)arg); + break; + case SO_TOS: + setSn_TOS(sn,*(uint8_t*)arg); + break; + case SO_MSS: + setSn_MSSR(sn,*(uint16_t*)arg); + break; + case SO_DESTIP: + setSn_DIPR(sn, (uint8_t*)arg); + break; + case SO_DESTPORT: + setSn_DPORT(sn, *(uint16_t*)arg); + break; +#if _WIZCHIP_ != 5100 + case SO_KEEPALIVESEND: + CHECK_SOCKMODE(Sn_MR_TCP); + #if _WIZCHIP_ > 5200 + if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; + #endif + setSn_CR(sn,Sn_CR_SEND_KEEP); + while(getSn_CR(sn) != 0) + { + // M20131220 + //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) + if (getSn_IR(sn) & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + return SOCKERR_TIMEOUT; + } + } + break; + #if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) ) + case SO_KEEPALIVEAUTO: + CHECK_SOCKMODE(Sn_MR_TCP); + setSn_KPALVTR(sn,*(uint8_t*)arg); + break; + #endif +#endif + default: + return SOCKERR_ARG; + } + return SOCK_OK; +} + +int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) +{ + CHECK_SOCKNUM(); + switch(sotype) + { + case SO_FLAG: + *(uint8_t*)arg = getSn_MR(sn) & 0xF0; + break; + case SO_TTL: + *(uint8_t*) arg = getSn_TTL(sn); + break; + case SO_TOS: + *(uint8_t*) arg = getSn_TOS(sn); + break; + case SO_MSS: + *(uint16_t*) arg = getSn_MSSR(sn); + break; + case SO_DESTIP: + getSn_DIPR(sn, (uint8_t*)arg); + break; + case SO_DESTPORT: + *(uint16_t*) arg = getSn_DPORT(sn); + break; + #if _WIZCHIP_ > 5200 + case SO_KEEPALIVEAUTO: + CHECK_SOCKMODE(Sn_MR_TCP); + *(uint16_t*) arg = getSn_KPALVTR(sn); + break; + #endif + case SO_SENDBUF: + *(uint16_t*) arg = getSn_TX_FSR(sn); + break; + case SO_RECVBUF: + *(uint16_t*) arg = getSn_RX_RSR(sn); + break; + case SO_STATUS: + *(uint8_t*) arg = getSn_SR(sn); + break; + case SO_REMAINSIZE: + if(getSn_MR(sn) & Sn_MR_TCP) + *(uint16_t*)arg = getSn_RX_RSR(sn); + else + *(uint16_t*)arg = sock_remained_size[sn]; + break; + case SO_PACKINFO: + //CHECK_SOCKMODE(Sn_MR_TCP); +#if _WIZCHIP_ != 5300 + if((getSn_MR(sn) == Sn_MR_TCP)) + return SOCKERR_SOCKMODE; +#endif + *(uint8_t*)arg = sock_pack_info[sn]; + break; + default: + return SOCKERR_SOCKOPT; + } + return SOCK_OK; +} diff --git a/Libraries/Ethernet/socket.h b/Libraries/Ethernet/socket.h new file mode 100644 index 0000000..72469a7 --- /dev/null +++ b/Libraries/Ethernet/socket.h @@ -0,0 +1,489 @@ +//***************************************************************************** +// +//! \file socket.h +//! \brief SOCKET APIs Header file. +//! \details SOCKET APIs like as berkeley socket api. +//! \version 1.0.2 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2014/05/01> V1.0.2. Refer to M20140501 +//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED +//! 2. Add the comment as zero byte udp data reception in getsockopt(). +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +/** + * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs + * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. + * But there is a little bit of difference. + * @details + * Comparison between WIZnet and Berkeley SOCKET APIs + * + * + * + * + * + * + * + * + * + * + * + * + *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
+ * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, + * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, + * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n + * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. + * When the listen SOCKET accepts a connection request from a client, it keeps listening. + * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n + * Following figure shows network flow diagram by Berkeley SOCKET API. + * @image html Berkeley_SOCKET.jpg "" + * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n + * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, + * it is changed in order to communicate with the client. + * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n + * If there're many listen SOCKET with same listen port number and a client requests a connection, + * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n + * Following figure shows network flow diagram by WIZnet SOCKET API. + * @image html WIZnet_SOCKET.jpg "" + */ +#ifndef _SOCKET_H_ +#define _SOCKET_H_ +#ifdef __cplusplus + extern "C" { +#endif + +#include "wizchip_conf.h" + +#define SOCKET uint8_t ///< SOCKET type define for legacy driver + +#define SOCK_OK 1 ///< Result is OK about socket process. +#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. +#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. + +#define SOCK_ERROR 0 +#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number +#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option +#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP +#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. +#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. +#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag +#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. +#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. +#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero +#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address +#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred +#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. +#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. + +#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. + +/* + * SOCKET FLAG + */ +#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet +#define SF_IGMP_VER2 (Sn_MR_MC) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. +#define SF_TCP_NODELAY (Sn_MR_ND) ///< In @ref Sn_MR_TCP, Use to nodelayed ack. +#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In @ref Sn_MR_UDP, Enable multicast mode. + +#if _WIZCHIP_ == 5500 + #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In @ref Sn_MR_UDP or @ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 + #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In @ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 + #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In @ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 + #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 +#endif + +//A201505 : For W5300 +#if _WIZCHIP_ == 5300 + #define SF_TCP_ALIGN 0x02 ///< Valid only \ref Sn_MR_TCP and W5300, refer to \ref Sn_MR_ALIGN +#endif + +#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). + +/* + * UDP & MACRAW Packet Infomation + */ +#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. (When W5300, This flag can be applied) +#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. (When W5300, This flag can be applied) +#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. (When W5300, This flag can be applied) +//A20150601 : For Integrating with W5300 +#define PACK_FIFOBYTE 0x02 ///< Valid only W5300, It indicate to have read already the Sn_RX_FIFOR. +// + +/** + * @ingroup WIZnet_socket_APIs + * @brief Open a socket. + * @details Initializes the socket with 'sn' passed as parameter and open. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. + * @param port Port number to be bined. + * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n + * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. + * @sa Sn_MR + * + * @return @b Success : The socket number @b 'sn' passed as parameter\n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n + * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n + * @ref SOCKERR_SOCKFLAG - Invaild socket flag. + */ +int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Close a socket. + * @details It closes the socket with @b'sn' passed as parameter. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * + * @return @b Success : @ref SOCK_OK \n + * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number + */ +int8_t close(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Listen to a connection request from a client. + * @details It is listening to a connection request from a client. + * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n + * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. + */ +int8_t listen(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Try to connect a server. + * @details It requests connection to the server with destination IP address and port number passed as parameter.\n + * @note It is valid only in TCP client mode. + * In block io mode, it does not return until connection is completed. + * In Non-block io mode, it return @ref SOCK_BUSY immediately. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * @param port Destination port number. + * + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n + * @ref SOCKERR_SOCKMODE - Invalid socket mode\n + * @ref SOCKERR_SOCKINIT - Socket is not initialized\n + * @ref SOCKERR_IPINVALID - Wrong server IP address\n + * @ref SOCKERR_PORTZERO - Server port zero\n + * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n + * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n + */ +int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Try to disconnect a connection socket. + * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. + * @note It is valid only in TCP server or client mode. \n + * In block io mode, it does not return until disconnection is completed. \n + * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n + + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +int8_t disconnect(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Send data to the connected peer in TCP socket. + * @details It is used to send outgoing data to the connected socket. + * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n + * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n + * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param buf Pointer buffer containing data to be sent. + * @param len The byte length of data in buf. + * @return @b Success : The sent data size \n + * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t send(uint8_t sn, uint8_t * buf, uint16_t len); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Receive data from the connected peer. + * @details It is used to read incoming data from the connected socket.\n + * It waits for data as much as the application wants to receive. + * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n + * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n + * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param buf Pointer buffer to read incoming data. + * @param len The max data length of data in buf. + * @return @b Success : The real received data size \n + * @b Fail :\n + * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. + * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n + * Even if the connectionless socket has been previously connected to a specific address, + * the address and port number parameters override the destination address for that particular datagram only. + * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len. + * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param buf Pointer buffer to send outgoing data. + * @param len The byte length of data in buf. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * @param port Destination port number. + * + * @return @b Success : The sent data size \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCKERR_IPINVALID - Wrong server IP address\n + * @ref SOCKERR_PORTZERO - Server port zero\n + * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Receive datagram of UDP or MACRAW + * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n + * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. + * This function can divide to received the packet data. + * On the MACRAW SOCKET, the addr and port parameters are ignored. + * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer + * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. + * + * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. + * @param buf Pointer buffer to read incoming data. + * @param len The max data length of data in buf. + * When the received packet size <= len, receives data as packet sized. + * When others, receives data as len. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * It is valid only when the first call recvfrom for receiving the packet. + * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). + * @param port Pointer variable of destination port number. + * It is valid only when the first call recvform for receiving the packet. +* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). + * + * @return @b Success : This function return real received data size for success.\n + * @b Fail : @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKBUSY - Socket is busy. + */ +int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); + + +///////////////////////////// +// SOCKET CONTROL & OPTION // +///////////////////////////// +#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). +#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). + +/** + * @defgroup DATA_TYPE DATA TYPE + */ + +/** + * @ingroup DATA_TYPE + * @brief The kind of Socket Interrupt. + * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() + */ +typedef enum +{ + SIK_CONNECTED = (1 << 0), ///< connected + SIK_DISCONNECTED = (1 << 1), ///< disconnected + SIK_RECEIVED = (1 << 2), ///< data received + SIK_TIMEOUT = (1 << 3), ///< timeout occurred + SIK_SENT = (1 << 4), ///< send ok + //M20150410 : Remove the comma of last member + //SIK_ALL = 0x1F, ///< all interrupt + SIK_ALL = 0x1F ///< all interrupt +}sockint_kind; + +/** + * @ingroup DATA_TYPE + * @brief The type of @ref ctlsocket(). + */ +typedef enum +{ + CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK + CS_GET_IOMODE, ///< get socket IO mode + CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory + CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory + CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind + CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind +#if _WIZCHIP_ > 5100 + CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind, Not supported in W5100 + CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind, Not supported in W5100 +#endif +}ctlsock_type; + + +/** + * @ingroup DATA_TYPE + * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() + */ +typedef enum +{ + SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket(). + SO_TTL, ///< Set TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) + SO_TOS, ///< Set TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) + SO_MSS, ///< Set MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) + SO_DESTIP, ///< Set the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) + SO_DESTPORT, ///< Set the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) +#if _WIZCHIP_ != 5100 + SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode, Not supported in W5100 + #if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) ) + SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode, Not supported in W5100, W5200 + #endif +#endif + SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() + SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() + SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() + SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. + SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. +}sockopt_type; + +/** + * @ingroup WIZnet_socket_APIs + * @brief Control socket. + * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. + * Refer to @ref ctlsock_type. + * @param sn socket number + * @param cstype type of control socket. refer to @ref ctlsock_type. + * @param arg Data type and value is determined according to @ref ctlsock_type. \n + * + * + * + * + * + *
@b cstype @b data type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF uint16_t 0 ~ 16K
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
+ * @return @b Success @ref SOCK_OK \n + * @b fail @ref SOCKERR_ARG - Invalid argument\n + */ +int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); + +/** + * @ingroup WIZnet_socket_APIs + * @brief set socket options + * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. + * + * @param sn socket number + * @param sotype socket option type. refer to @ref sockopt_type + * @param arg Data type and value is determined according to sotype. \n + * + * + * + * + * + * + * + * + * + *
@b sotype @b data type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t 0 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
+ * @return + * - @b Success : @ref SOCK_OK \n + * - @b Fail + * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n + * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n + * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n + * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n + */ +int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); + +/** + * @ingroup WIZnet_socket_APIs + * @brief get socket options + * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type + * @param sn socket number + * @param sotype socket option type. refer to @ref sockopt_type + * @param arg Data type and value is determined according to sotype. \n + * + * + * + * + * + * + * + * + * + * + * + * + * + *
@b sotype @b data type@b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF uint16_t 0 ~ 65535
@ref SO_RECVBUF uint16_t 0 ~ 65535
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc..
@ref SO_REMAINSIZE uint16_t 0~ 65535
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc...
+ * @return + * - @b Success : @ref SOCK_OK \n + * - @b Fail + * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n + * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n + * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n + * @note + * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n + * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, + * This means the zero byte UDP data(UDP Header only) received. + */ +int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg); + +#ifdef __cplusplus + } +#endif + +#endif // _SOCKET_H_ diff --git a/Libraries/Ethernet/stdio_private.h b/Libraries/Ethernet/stdio_private.h new file mode 100644 index 0000000..f92a32f --- /dev/null +++ b/Libraries/Ethernet/stdio_private.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2002, Joerg Wunsch + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +/* $Id: stdio_private.h,v 1.6 2003/01/07 22:17:24 joerg_wunsch Exp $ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct __file { + char *buf; /* buffer pointer */ + unsigned char unget; /* ungetc() buffer */ + uint8_t flags; /* flags, see below */ +#define __SRD 0x0001 /* OK to read */ +#define __SWR 0x0002 /* OK to write */ +#define __SSTR 0x0004 /* this is an sprintf/snprintf string */ +#define __SPGM 0x0008 /* fmt string is in progmem */ +#define __SERR 0x0010 /* found error */ +#define __SEOF 0x0020 /* found EOF */ +#define __SUNGET 0x040 /* ungetc() happened */ +#if 0 +/* possible future extensions, will require uint16_t flags */ +#define __SRW 0x0080 /* open for reading & writing */ +#define __SLBF 0x0100 /* line buffered */ +#define __SNBF 0x0200 /* unbuffered */ +#define __SMBF 0x0400 /* buf is from malloc */ +#endif + int size; /* size of buffer */ + int len; /* characters read or written so far */ + int (*put)(char); /* function to write one char to device */ + int (*get)(void); /* function to read one char from device */ +}; + +/* values for PRINTF_LEVEL */ +#define PRINTF_MIN 1 +#define PRINTF_STD 2 +#define PRINTF_FLT 3 + +/* values for SCANF_LEVEL */ +#define SCANF_MIN 1 +#define SCANF_STD 2 +#define SCANF_FLT 3 + +#ifdef __cplusplus +} +#endif diff --git a/Libraries/Ethernet/utility/W5500.c b/Libraries/Ethernet/utility/W5500.c deleted file mode 100644 index 3437396..0000000 --- a/Libraries/Ethernet/utility/W5500.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - W5500.c - Driver for WIZnet W5500. - - Copyright (c) 2018 Patrick F. - - 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 program. If not, see . -*/ -#include "W5500.h" -#include "SPI.h" -#include "System32.h" - - -#ifndef SPI_W5500 - #define SPI_W5500 SPI3 -#endif - -#define RESET_BIT 7 - - -static inline void Write(uint16_t _addr, uint8_t _cb, uint8_t _data); -static inline uint16_t WriteArray(uint16_t addr, uint8_t _cb, const uint8_t *buf, uint16_t len); -static inline uint8_t Read(uint16_t addr, uint8_t _cb); -static inline uint16_t ReadArray(uint16_t addr, uint8_t _cb, uint8_t *buf, uint16_t len); - - -static inline uint8_t ReadSn(SOCKET _s, uint16_t _addr); -static inline void WriteSn(SOCKET _s, uint16_t _addr, uint8_t _data); -static inline uint16_t ReadSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); -static inline uint16_t WriteSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); - - -void W5500_Init(void) -{ - Spi_Init(SPI_W5500, SPI_MODE0); - - // Set clock to 21 Mhz (W5500 should support up to about 80 Mhz) - Spi_SetPrescaler(SPI_W5500, SPI_PRESCALER_2); - - GPIO_ResetBits(GPIOA, GPIO_Pin_15); - Delay_ms(40); - GPIO_SetBits(GPIOA, GPIO_Pin_15); - Delay_ms(40); - - W5500_SoftReset(); - Delay_ms(40); - - for(uint8_t i = 0; i < MAX_SOCK_NUM; i++) - { - uint8_t cntl_byte = (0x0C + (i<<5)); - - Write(0x1E, cntl_byte, 4); //0x1E - Sn_RXBUF_SIZE - 4k - Write(0x1F, cntl_byte, 2); //0x1F - Sn_TXBUF_SIZE - 2k - } -} - - -void W5500_SoftReset(void) -{ - uint8_t cnt = 0; - - // Write reset bit - W5500_WRITE_GP_REG8(REG8_MR, 1<> 8); - Spi_WriteByte(SPI_W5500, _addr & 0xFF); - Spi_WriteByte(SPI_W5500, _cb); - Spi_WriteByte(SPI_W5500, _data); - - Spi_ChipSelect(SPI_W5500, false); - __ASM("nop"); - __ASM("nop"); -} - - -static inline uint16_t WriteArray(uint16_t _addr, uint8_t _cb, const uint8_t *_buf, uint16_t _len) -{ - Spi_ChipSelect(SPI_W5500, true); - - Spi_WriteByte(SPI_W5500, _addr >> 8); - Spi_WriteByte(SPI_W5500, _addr & 0xFF); - Spi_WriteByte(SPI_W5500, _cb); - - for(uint16_t i = 0; i < _len; i++) - { - Spi_WriteByte(SPI_W5500, _buf[i]); - } - - Spi_ChipSelect(SPI_W5500, false); - __ASM("nop"); - __ASM("nop"); - - return _len; -} - - -static inline uint8_t Read(uint16_t _addr, uint8_t _cb) -{ - Spi_ChipSelect(SPI_W5500, true); - - Spi_WriteByte(SPI_W5500, _addr >> 8); - Spi_WriteByte(SPI_W5500, _addr & 0xFF); - Spi_WriteByte(SPI_W5500, _cb); - - uint8_t _data = Spi_ReadByte(SPI_W5500); - - Spi_ChipSelect(SPI_W5500, false); - __ASM("nop"); - __ASM("nop"); - - return _data; -} - - -static inline uint16_t ReadArray(uint16_t _addr, uint8_t _cb, uint8_t *_buf, uint16_t _len) -{ - Spi_ChipSelect(SPI_W5500, true); - - Spi_WriteByte(SPI_W5500, _addr >> 8); - Spi_WriteByte(SPI_W5500, _addr & 0xFF); - Spi_WriteByte(SPI_W5500, _cb); - - for(uint16_t i = 0; i < _len; i++) - { - _buf[i] = Spi_ReadByte(SPI_W5500); - } - - Spi_ChipSelect(SPI_W5500, false); - __ASM("nop"); - __ASM("nop"); - - return _len; -} - - -static inline uint8_t ReadSn(SOCKET _s, uint16_t _addr) -{ - uint8_t cntl_byte = (_s<<5) + 0x08; - - return Read(_addr, cntl_byte); -} - - -static inline void WriteSn(SOCKET _s, uint16_t _addr, uint8_t _data) -{ - uint8_t cntl_byte = (_s<<5) + 0x0C; - - Write(_addr, cntl_byte, _data); -} - - -static inline uint16_t ReadSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) -{ - uint8_t cntl_byte = (_s<<5) + 0x08; - - return ReadArray(_addr, cntl_byte, _buf, _len); -} - - -static inline uint16_t WriteSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) -{ - uint8_t cntl_byte = (_s<<5) + 0x0C; - - return WriteArray(_addr, cntl_byte, _buf, _len); -} - - -// W5500 Registers -// --------------- -void W5500_WRITE_GP_REG8(uint16_t address, uint8_t _data) -{ - Write(address, 0x04, _data); -} - - -uint8_t W5500_READ_GP_REG8(uint16_t address) -{ - return Read(address, 0x00); -} - - -void W5500_WRITE_GP_REG16(uint16_t address, uint16_t _data) -{ - Write(address, 0x04, _data >> 8); - Write(address + 1, 0x04, _data & 0xFF); -} - - -uint16_t W5500_READ_GP_REG16(uint16_t address) -{ - uint16_t res = Read(address, 0x00); - res = (res << 8) + Read(address + 1, 0x00); - - return res; -} - - -uint16_t W5500_WRITE_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size) -{ - return WriteArray(address, 0x04, _buff, size); -} - - -uint16_t W5500_READ_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size) -{ - return ReadArray(address, 0x00, _buff, size); -} - - -// W5500 Socket registers -// ---------------------- - -void W5500_WRITE_SOCK_REG8(SOCKET _s, uint16_t address, uint8_t _data) -{ - WriteSn(_s, address, _data); -} - - -uint8_t W5500_READ_SOCK_REG8(SOCKET _s, uint16_t address) -{ - return ReadSn(_s, address); -} - - -void W5500_WRITE_SOCK_REG16(SOCKET _s, uint16_t address, uint16_t _data) -{ - WriteSn(_s, address, _data >> 8); \ - WriteSn(_s, address+1, _data & 0xFF); -} - - -uint16_t W5500_READ_SOCK_REG16(SOCKET _s, uint16_t address) -{ - uint16_t res = ReadSn(_s, address); - uint16_t res2 = ReadSn(_s, address + 1); - - res = res << 8; - res2 = res2 & 0xFF; - res = res | res2; - - return res; -} - - -uint16_t W5500_WRITE_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size) -{ - return WriteSnArray(_s, address, _buff, size); -} - - -uint16_t W5500_READ_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size) -{ - return ReadSnArray(_s, address, _buff, size); -} diff --git a/Libraries/Ethernet/utility/W5500.h b/Libraries/Ethernet/utility/W5500.h deleted file mode 100644 index b70c831..0000000 --- a/Libraries/Ethernet/utility/W5500.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - W5500.h - Driver for WIZnet W5500. - - Copyright (c) 2018 Patrick F. - - 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 program. If not, see . -*/ -#ifndef W5500_H_INCLUDED -#define W5500_H_INCLUDED - - -#include "util2.h" - - -#define MAX_SOCK_NUM 4 // Max 8 - - -#define W5500_SSIZE 2048 // Max Tx buffer size -#define W5500_RSIZE 2048 // Max Rx buffer size - - -// W5500 Registers -#define REG8_MR 0x0000 // Mode -#define REGN_GAR_4 0x0001 // Gateway IP address -#define REGN_SUBR_4 0x0005 // Subnet mask address -#define REGN_SHAR_6 0x0009 // Source MAC address -#define REGN_SIPR_4 0x000F // Source IP address -#define REG8_IR 0x0015 // Interrupt -#define REG8_IMR 0x0016 // Interrupt Mask -#define REG16_RTR 0x0019 // Timeout address -#define REG8_RCR 0x001B // Retry count -#define REGN_UIPR_4 0x0028 // Unreachable IP address in UDP mode -#define REG16_UPORT 0x002C // Unreachable Port address in UDP mode -#define REG8_PHYCFGR 0x002E // PHY Configuration register, default value: 0b1011 1XXX - - -// W5500 Socket registers -#define REG8_SnMR 0x0000 // Mode -#define REG8_SnCR 0x0001 // Command -#define REG8_SnIR 0x0002 // Interrupt -#define REG8_SnSR 0x0003 // Status -#define REG16_SnPORT 0x0004 // Source Port -#define REGN_SnDHAR_6 0x0006 // Destination Hardw Addr -#define REGN_SnDIPR_4 0x000C // Destination IP Addr -#define REG16_SnDPORT 0x0010 // Destination Port -#define REG16_SnMSSR 0x0012 // Max Segment Size -#define REG8_SnPROTO 0x0014 // Protocol in IP RAW Mode -#define REG8_SnTOS 0x0015 // IP TOS -#define REG8_SnTTL 0x0016 // IP TTL -#define REG16_SnTX_FSR 0x0020 // TX Free Size -#define REG16_SnTX_RD 0x0022 // TX Read Pointer -#define REG16_SnTX_WR 0x0024 // TX Write Pointer -#define REG16_SnRX_RSR 0x0026 // RX Free Size -#define REG16_SnRX_RD 0x0028 // RX Read Pointer -#define REG16_SnRX_WR 0x002A // RX Write Pointer (supported?) - - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef enum -{ - SnMR_CLOSE = 0x00, - SnMR_TCP = 0x01, - SnMR_UDP = 0x02, - SnMR_IPRAW = 0x03, - SnMR_MACRAW = 0x04, - SnMR_PPPOE = 0x05, - SnMR_ND = 0x20, - SnMR_MULTI = 0x80 -} SnMR_e; - - -typedef enum -{ - Sock_OPEN = 0x01, - Sock_LISTEN = 0x02, - Sock_CONNECT = 0x04, - Sock_DISCON = 0x08, - Sock_CLOSE = 0x10, - Sock_SEND = 0x20, - Sock_SEND_MAC = 0x21, - Sock_SEND_KEEP = 0x22, - Sock_RECV = 0x40 -} SockCMD_e; - - -typedef enum -{ - SnIR_SEND_OK = 0x10, - SnIR_TIMEOUT = 0x08, - SnIR_RECV = 0x04, - SnIR_DISCON = 0x02, - SnIR_CON = 0x01 -} SnIR_e; - - -typedef enum SnSR -{ - SnSR_CLOSED = 0x00, - SnSR_INIT = 0x13, - SnSR_LISTEN = 0x14, - SnSR_SYNSENT = 0x15, - SnSR_SYNRECV = 0x16, - SnSR_ESTABLISHED = 0x17, - SnSR_FIN_WAIT = 0x18, - SnSR_CLOSING = 0x1A, - SnSR_TIME_WAIT = 0x1B, - SnSR_CLOSE_WAIT = 0x1C, - SnSR_LAST_ACK = 0x1D, - SnSR_UDP = 0x22, - SnSR_IPRAW = 0x32, - SnSR_MACRAW = 0x42, - SnSR_PPPOE = 0x5F -} SnSR_e; - - -typedef enum -{ - IPPROTO_IP = 0, - IPPROTO_ICMP = 1, - IPPROTO_IGMP = 2, - IPPROTO_GGP = 3, - IPPROTO_TCP = 6, - IPPROTO_PUP = 12, - IPPROTO_UDP = 17, - IPPROTO_IDP = 22, - IPPROTO_ND = 77, - IPPROTO_RAW = 255, -} IPPROTO_e; - - - -void W5500_Init(void); - -void W5500_SoftReset(void); - -/** - * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. - * - * It calculate the actual physical address where one has to read - * the data from Receive buffer. Here also take care of the condition while it exceed - * the Rx memory uper-bound of socket. - */ -void W5500_ReadData(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); - -/** - * @brief This function is being called by send() and sendto() function also. - * - * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer - * register. User should read upper byte first and lower byte later to get proper value. - */ -void W5500_SendDataProcessing(SOCKET s, const uint8_t *data, uint16_t len); - -/** - * @brief A copy of send_data_processing that uses the provided ptr for the - * write offset. Only needed for the "streaming" UDP API, where - * a single UDP packet is built up over a number of calls to - * send_data_processing_ptr, because TX_WR doesn't seem to get updated - * correctly in those scenarios - * @param ptr value to use in place of TX_WR. If 0, then the value is read - * in from TX_WR - * @return New value for ptr, to be used in the next call - */ -void W5500_SendDataProcessingOffset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); - -/** - * @brief This function is being called by recv() also. - * - * This function read the Rx read pointer register - * and after copy the data from receive buffer update the Rx write pointer register. - * User should read upper byte first and lower byte later to get proper value. - */ -void W5500_RecvDataProcessing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek); - -void W5500_SetGatewayIp(uint8_t *_addr); -void W5500_GetGatewayIp(uint8_t *_addr); - -void W5500_SetSubnetMask(uint8_t *_addr); -void W5500_GetSubnetMask(uint8_t *_addr); - -void W5500_SetMACAddress(uint8_t *_addr); -void W5500_GetMACAddress(uint8_t *_addr); - -void W5500_SetIPAddress(uint8_t *_addr); -void W5500_GetIPAddress(uint8_t *_addr); - -void W5500_SetRetransmissionTime(uint16_t timeout); -void W5500_SetRetransmissionCount(uint8_t _retry); - -void W5500_ExecCmdSn(SOCKET s, SockCMD_e _cmd); - -uint16_t W5500_GetTXFreeSize(SOCKET s); -uint16_t W5500_GetRXReceivedSize(SOCKET s); - -void W5500_SetPHYCFGR(uint8_t _val); -uint8_t W5500_GetPHYCFGR(void); - - -// W5500 Registers -// --------------- -void W5500_WRITE_GP_REG8(uint16_t address, uint8_t _data); -uint8_t W5500_READ_GP_REG8(uint16_t address); -void W5500_WRITE_GP_REG16(uint16_t address, uint16_t _data); -uint16_t W5500_READ_GP_REG16(uint16_t address); -uint16_t W5500_WRITE_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size); -uint16_t W5500_READ_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size); - - -// W5500 Socket registers -// ---------------------- -void W5500_WRITE_SOCK_REG8(SOCKET _s, uint16_t address, uint8_t _data); -uint8_t W5500_READ_SOCK_REG8(SOCKET _s, uint16_t address); -void W5500_WRITE_SOCK_REG16(SOCKET _s, uint16_t address, uint16_t _data); -uint16_t W5500_READ_SOCK_REG16(SOCKET _s, uint16_t address); -uint16_t W5500_WRITE_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size); -uint16_t W5500_READ_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/Libraries/Ethernet/utility/socket.c b/Libraries/Ethernet/utility/socket.c deleted file mode 100644 index 1c81018..0000000 --- a/Libraries/Ethernet/utility/socket.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - socket.c - SOCKET APIs like as berkeley socket api. - - Copyright (c) 2018 Patrick F. - - 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 program. If not, see . -*/ -#include "W5500.h" -#include "socket.h" - - -/** - * @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it. - * @return 1 for success else 0. - */ -int8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) -{ - if(s < MAX_SOCK_NUM) - { - if((protocol == SnMR_TCP) || (protocol == SnMR_UDP) || (protocol == SnMR_IPRAW) || (protocol == SnMR_MACRAW) || (protocol == SnMR_PPPOE)) - { - close(s); - - W5500_WRITE_SOCK_REG8(s, REG8_SnMR, protocol | flag); - - if(port) - { - W5500_WRITE_SOCK_REG16(s, REG16_SnPORT, port); - - W5500_ExecCmdSn(s, Sock_OPEN); - - return SOCK_OK; - } - else - { - return SOCKERR_PORTZERO; - } - } - else - { - return SOCKERR_SOCKMODE; - } - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function close the socket and parameter is "s" which represent the socket number - */ -int8_t close(SOCKET s) -{ - if(s < MAX_SOCK_NUM) - { - W5500_ExecCmdSn(s, Sock_CLOSE); - // Clear interrupts - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, 0xFF); - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. - * @return 1 for success else 0. - */ -int8_t listen(SOCKET s) -{ - if(s < MAX_SOCK_NUM) - { - if(W5500_READ_SOCK_REG8(s, REG8_SnSR) != (uint8_t)SnSR_INIT) - { - return SOCKERR_SOCKINIT; - } - - W5500_ExecCmdSn(s, Sock_LISTEN); - - return SOCK_OK; - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function established the connection for the channel in Active (client) mode. - * This function waits for the untill the connection is established. - * - * @return 1 for success else 0. - */ -int8_t connect(SOCKET s, uint8_t * addr, uint16_t port) -{ - if(s < MAX_SOCK_NUM) - { - if(((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || - ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || - (port == 0x00)) - { - return SOCKERR_IPINVALID; - } - - // Set destination IP - W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4); - W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port); - W5500_ExecCmdSn(s, Sock_CONNECT); - - return SOCK_OK; - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function used for disconnect the socket and parameter is "s" which represent the socket number - * @return 1 for success else 0. - */ -int8_t disconnect(SOCKET s) -{ - if(s < MAX_SOCK_NUM) - { - W5500_ExecCmdSn(s, Sock_DISCON); - - return SOCK_OK; - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function used to send the data in TCP mode - * @return 1 for success else 0. - */ -int32_t send(SOCKET s, const uint8_t * buf, uint16_t len) -{ - uint8_t status = 0; - uint16_t ret = 0; - uint16_t freesize = 0; - - - if(len > W5500_SSIZE) - ret = W5500_SSIZE; // check size not to exceed MAX size. - else - ret = len; - - if(s < MAX_SOCK_NUM) - { - // if freebuf is available, start. - do - { - freesize = W5500_GetTXFreeSize(s); - - status = W5500_READ_SOCK_REG8(s, REG8_SnSR); - if((status != SnSR_ESTABLISHED) && (status != SnSR_CLOSE_WAIT)) - { - ret = 0; - break; - } - } while(freesize < ret); - - // copy data - W5500_SendDataProcessing(s, (uint8_t *)buf, ret); - W5500_ExecCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK) - { - /* m2008.01 [bj] : reduce code */ - if(W5500_READ_SOCK_REG8(s, REG8_SnSR) == SnSR_CLOSED) - { - close(s); - - return SOCKERR_SOCKCLOSED; - } - } - - /* +2008.01 bj */ - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK); - } - - return ret; -} - - -/** - * @brief This function is an application I/F function which is used to receive the data in TCP mode. - * It continues to wait for data as much as the application wants to receive. - * - * @return received data size for success else -1. - */ -int32_t recv(SOCKET s, uint8_t *buf, int16_t len) -{ - uint16_t ret = 0; - - - if(s < MAX_SOCK_NUM) - { - // Check how much data is available - ret = W5500_GetRXReceivedSize(s); - if(ret == 0) - { - // No data available. - uint8_t status = W5500_READ_SOCK_REG8(s, REG8_SnSR); - if(status == SnSR_LISTEN || status == SnSR_CLOSED || status == SnSR_CLOSE_WAIT) - { - // The remote end has closed its side of the connection, so this is the eof state - ret = 0; - } - else - { - // The connection is still up, but there's no data waiting to be read - ret = -1; - } - } - else if(ret > len) - { - ret = len; - } - - if(ret > 0) - { - W5500_RecvDataProcessing(s, buf, ret, 0); - W5500_ExecCmdSn(s, Sock_RECV); - } - } - else - { - return SOCKERR_SOCKNUM; - } - - return ret; -} - - -/** - * @brief Returns the first byte in the receive queue (no checking) - * - * @return - */ -uint16_t peek(SOCKET s, uint8_t *buf) -{ - if(s < MAX_SOCK_NUM) - { - W5500_RecvDataProcessing(s, buf, 1, 1); - - return SOCK_OK; - } - - return SOCKERR_SOCKNUM; -} - - -/** - * @brief This function is an application I/F function which is used to send the data for other then TCP mode. - * Unlike TCP transmission, The peer's destination address and the port is needed. - * - * @return This function return send data size for success else -1. - */ -int32_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) -{ - uint16_t ret = 0; - - - if(len > W5500_SSIZE) - ret = W5500_SSIZE; // check size not to exceed MAX size. - else - ret = len; - - if(s < MAX_SOCK_NUM) - { - if(((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00)) || (ret == 0)) - { - /* +2008.01 [bj] : added return value */ - ret = 0; - } - else - { - W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4); - W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port); - - // copy data - W5500_SendDataProcessing(s, (uint8_t *)buf, ret); - W5500_ExecCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK) - { - if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT) - { - /* +2008.01 [bj]: clear interrupt */ - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, (SnIR_SEND_OK | SnIR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */ - - return 0; - } - } - - /* +2008.01 bj */ - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK); - } - } - - return ret; -} - - -/** - * @brief This function is an application I/F function which is used to receive the data in other then - * TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. - * - * @return This function return received data size for success else -1. - */ -int32_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) -{ - uint8_t head[8]; - uint16_t data_len = 0; - uint16_t ptr = 0; - - if((s < MAX_SOCK_NUM) && (len > 0)) - { - ptr = W5500_READ_SOCK_REG16(s, REG16_SnRX_RD); - - switch(W5500_READ_SOCK_REG8(s, REG8_SnMR) & 0x07) - { - case SnMR_UDP : - W5500_ReadData(s, ptr, head, 0x08); - ptr += 8; - // read peer's IP address, port number. - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - *port = head[4]; - *port = (*port << 8) + head[5]; - data_len = head[6]; - data_len = (data_len << 8) + head[7]; - - W5500_ReadData(s, ptr, buf, data_len); // data copy. - ptr += data_len; - - W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr); - break; - - case SnMR_IPRAW : - W5500_ReadData(s, ptr, head, 0x06); - ptr += 6; - - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - data_len = head[4]; - data_len = (data_len << 8) + head[5]; - - W5500_ReadData(s, ptr, buf, data_len); // data copy. - ptr += data_len; - - W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr); - break; - - case SnMR_MACRAW: - W5500_ReadData(s, ptr, head, 2); - ptr+=2; - data_len = head[0]; - data_len = (data_len<<8) + head[1] - 2; - - W5500_ReadData(s, ptr, buf, data_len); - ptr += data_len; - W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr); - break; - - default : - break; - } - - W5500_ExecCmdSn(s, Sock_RECV); - } - - return data_len; -} - - -/** - * @brief Wait for buffered transmission to complete. - */ -void flush(SOCKET s) -{ - if(s < MAX_SOCK_NUM) - { - // TODO - (void)s; - } -} - - -uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) -{ - //uint8_t status = 0; - uint16_t ret = 0; - - - if(len > W5500_SSIZE) - ret = W5500_SSIZE; // check size not to exceed MAX size. - else - ret = len; - - if(ret == 0) - return 0; - - - if(s < MAX_SOCK_NUM) - { - W5500_SendDataProcessing(s, (uint8_t *)buf, ret); - W5500_ExecCmdSn(s, Sock_SEND); - - while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK) - { - //status = W5100_READ_SOCK_REG8(s, REG8_SnSR); - W5500_READ_SOCK_REG8(s, REG8_SnSR); - - if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT) - { - /* in case of igmp, if send fails, then socket closed */ - /* if you want change, remove this code. */ - close(s); - - return 0; - } - } - - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK); - } - - return ret; -} - - -uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) -{ - uint16_t ret = 0; - - - if(len > W5500_GetTXFreeSize(s)) - { - ret = W5500_GetTXFreeSize(s); // check size not to exceed MAX size. - } - else - { - ret = len; - } - - W5500_SendDataProcessingOffset(s, offset, buf, ret); - - return ret; -} - - -int startUDP(SOCKET s, uint8_t* addr, uint16_t port) -{ - if(((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00))) - { - return 0; - } - else - { - W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4); - W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port); - - return 1; - } -} - - -int sendUDP(SOCKET s) -{ - W5500_ExecCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK ) - { - if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT) - { - /* +2008.01 [bj]: clear interrupt */ - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, (SnIR_SEND_OK | SnIR_TIMEOUT)); - - return 0; - } - } - - /* +2008.01 bj */ - W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK); - - /* Sent ok */ - return 1; -} diff --git a/Libraries/Ethernet/utility/socket.h b/Libraries/Ethernet/utility/socket.h deleted file mode 100644 index b1a885d..0000000 --- a/Libraries/Ethernet/utility/socket.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - socket.c - SOCKET APIs like as berkeley socket api. - - Copyright (c) 2018 Patrick F. - - 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 program. If not, see . -*/ -#ifndef _SOCKET_H_ -#define _SOCKET_H_ - - -#include -#include "util.h" - - -#define SOCK_OK 1 ///< Result is OK about socket process. -#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. -#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. - -#define SOCK_ERROR 0 -#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number -#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option -#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized -#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. -#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. -#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag -#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. -#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argrument. -#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero -#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address -#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred -#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. -#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. - -#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. - - -#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). - -/* - * UDP & MACRAW Packet Infomation - */ -#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. -#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. -#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. - - -#ifdef __cplusplus -extern "C" { -#endif - - -// Opens a socket(TCP or UDP or IP_RAW mode) -int8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); -// Close socket -int8_t close(SOCKET s); - -// Establish TCP connection (Active connection) -int8_t connect(SOCKET s, uint8_t * addr, uint16_t port); -// disconnect the connection -int8_t disconnect(SOCKET s); - -// Establish TCP connection (Passive connection) -int8_t listen(SOCKET s); - -// Send data (TCP) -int32_t send(SOCKET s, const uint8_t * buf, uint16_t len); -// Receive data (TCP) -int32_t recv(SOCKET s, uint8_t * buf, int16_t len); - -uint16_t peek(SOCKET s, uint8_t *buf); - -// Send data (UDP/IP RAW) -int32_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); -// Receive data (UDP/IP RAW) -int32_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); - -// Wait for transmission to complete -void flush(SOCKET s); - - - -uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); - -// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a -// number of calls before being sent -/* - @brief This function sets up a UDP datagram, the data for which will be provided by one - or more calls to bufferData and then finally sent with sendUDP. - @return 1 if the datagram was successfully set up, or 0 if there was an error -*/ -int startUDP(SOCKET s, uint8_t* addr, uint16_t port); -/* - @brief This function copies up to len bytes of data from buf into a UDP datagram to be - sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. - @return Number of bytes successfully buffered -*/ -uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len); -/* - @brief Send a UDP datagram built up from a sequence of startUDP followed by one or more - calls to bufferData. - @return 1 if the datagram was successfully sent, or 0 if there was an error -*/ -int sendUDP(SOCKET s); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _SOCKET_H_ */ diff --git a/Libraries/Ethernet/utility/util2.h b/Libraries/Ethernet/utility/util2.h deleted file mode 100644 index 1f19bc7..0000000 --- a/Libraries/Ethernet/utility/util2.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef UTIL2_H -#define UTIL2_H - - -#include -#include - - -#define htons(x) ((uint16_t)(((x)<<8) | (((x)>>8)&0xFF))) -#define ntohs(x) htons(x) - -#define htonl(x) (((x)<<24 & 0xFF000000UL) | ((x)<< 8 & 0x00FF0000UL) | ((x)>> 8 & 0x0000FF00UL) | ((x)>>24 & 0x000000FFUL)) -#define ntohl(x) htonl(x) - - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef uint8_t SOCKET; - - -typedef struct -{ - uint8_t IP[4]; -} IPAddress_t; - -static const IPAddress_t INADDR_NONE = {0}; - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/Libraries/Ethernet/wizchip_conf.c b/Libraries/Ethernet/wizchip_conf.c new file mode 100644 index 0000000..5822894 --- /dev/null +++ b/Libraries/Ethernet/wizchip_conf.c @@ -0,0 +1,926 @@ +//****************************************************************************/ +//! +//! \file wizchip_conf.c +//! \brief WIZCHIP Config Header File. +//! \version 1.0.1 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2014/05/01> V1.0.1 Refer to M20140501 +//! 1. Explicit type casting in wizchip_bus_readdata() & wizchip_bus_writedata() +// Issued by Mathias ClauBen. +//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* +//! For remove the warning when pointer type size is not 32bit. +//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//*****************************************************************************/ +//A20140501 : for use the type - ptrdiff_t +#include +// + +#include "wizchip_conf.h" +#include "SPI.h" + +///////////// +//M20150401 : Remove ; in the default callback function such as wizchip_cris_enter(), wizchip_cs_select() and etc. +///////////// + +/** + * @brief Default function to enable interrupt. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_cris_enter(void) {}; +void wizchip_cris_enter(void) {} + +/** + * @brief Default function to disable interrupt. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_cris_exit(void) {}; +void wizchip_cris_exit(void) {} + +/** + * @brief Default function to select chip. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_cs_select(void) {}; +void wizchip_cs_select(void) +{ + Spi_ChipSelect(SPI3, true); +} + +/** + * @brief Default function to deselect chip. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_cs_deselect(void) {}; +void wizchip_cs_deselect(void) +{ + Spi_ChipSelect(SPI3, false); +} + +/** + * @brief Default function to read in direct or indirect interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ + //M20150601 : Rename the function for integrating with W5300 +//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); } +iodata_t wizchip_bus_readdata(uint32_t AddrSel) { return * ((volatile iodata_t *)((ptrdiff_t) AddrSel)); } + +/** + * @brief Default function to write in direct or indirect interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//M20150601 : Rename the function for integrating with W5300 +//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; } +void wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb) { *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb; } + +/** + * @brief Default function to read in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//uint8_t wizchip_spi_readbyte(void) {return 0;}; +uint8_t wizchip_spi_readbyte(void) +{ + return Spi_ReadByte(SPI3); +} + +/** + * @brief Default function to write in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_spi_writebyte(uint8_t wb) {}; +void wizchip_spi_writebyte(uint8_t wb) +{ + Spi_WriteByte(SPI3, wb); +} + +/** + * @brief Default function to burst read in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) {}; +void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) +{ + Spi_ReadByteArray(SPI3, pBuf, len); +} + +/** + * @brief Default function to burst write in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +//void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {}; +void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) +{ + Spi_WriteDataArray(SPI3, pBuf, len); +} + +/** + * @\ref _WIZCHIP instance + */ +// +//M20150401 : For a compiler didnot support a member of structure +// Replace the assignment of struct members with the assingment of array +// +/* +_WIZCHIP WIZCHIP = + { + .id = _WIZCHIP_ID_, + .if_mode = _WIZCHIP_IO_MODE_, + .CRIS._enter = wizchip_cris_enter, + .CRIS._exit = wizchip_cris_exit, + .CS._select = wizchip_cs_select, + .CS._deselect = wizchip_cs_deselect, + .IF.BUS._read_byte = wizchip_bus_readbyte, + .IF.BUS._write_byte = wizchip_bus_writebyte +// .IF.SPI._read_byte = wizchip_spi_readbyte, +// .IF.SPI._write_byte = wizchip_spi_writebyte + }; +*/ +_WIZCHIP WIZCHIP = +{ + _WIZCHIP_IO_MODE_, + _WIZCHIP_ID_ , + { + wizchip_cris_enter, + wizchip_cris_exit + }, + { + wizchip_cs_select, + wizchip_cs_deselect + }, + { + { + //M20150601 : Rename the function + //wizchip_bus_readbyte, + //wizchip_bus_writebyte + wizchip_bus_readdata, + wizchip_bus_writedata + }, + + } +}; + + +static uint8_t _DNS_[4]; // DNS server ip address +static dhcp_mode _DHCP_; // DHCP mode + +void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) +{ + if(!cris_en || !cris_ex) + { + WIZCHIP.CRIS._enter = wizchip_cris_enter; + WIZCHIP.CRIS._exit = wizchip_cris_exit; + } + else + { + WIZCHIP.CRIS._enter = cris_en; + WIZCHIP.CRIS._exit = cris_ex; + } +} + +void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) +{ + if(!cs_sel || !cs_desel) + { + WIZCHIP.CS._select = wizchip_cs_select; + WIZCHIP.CS._deselect = wizchip_cs_deselect; + } + else + { + WIZCHIP.CS._select = cs_sel; + WIZCHIP.CS._deselect = cs_desel; + } +} + +//M20150515 : For integrating with W5300 +//void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) +void reg_wizchip_bus_cbfunc(iodata_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb)) +{ + while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); + //M20150601 : Rename call back function for integrating with W5300 + /* + if(!bus_rb || !bus_wb) + { + WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; + WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; + } + else + { + WIZCHIP.IF.BUS._read_byte = bus_rb; + WIZCHIP.IF.BUS._write_byte = bus_wb; + } + */ + if(!bus_rb || !bus_wb) + { + WIZCHIP.IF.BUS._read_data = wizchip_bus_readdata; + WIZCHIP.IF.BUS._write_data = wizchip_bus_writedata; + } + else + { + WIZCHIP.IF.BUS._read_data = bus_rb; + WIZCHIP.IF.BUS._write_data = bus_wb; + } +} + +void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb)) +{ + while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); + + if(!spi_rb || !spi_wb) + { + WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte; + WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte; + } + else + { + WIZCHIP.IF.SPI._read_byte = spi_rb; + WIZCHIP.IF.SPI._write_byte = spi_wb; + } +} + +// 20140626 Eric Added for SPI burst operations +void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len)) +{ + while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); + + if(!spi_rb || !spi_wb) + { + WIZCHIP.IF.SPI._read_burst = wizchip_spi_readburst; + WIZCHIP.IF.SPI._write_burst = wizchip_spi_writeburst; + } + else + { + WIZCHIP.IF.SPI._read_burst = spi_rb; + WIZCHIP.IF.SPI._write_burst = spi_wb; + } +} + +int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) +{ +#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500 + uint8_t tmp = 0; +#endif + uint8_t* ptmp[2] = {0,0}; + switch(cwtype) + { + case CW_RESET_WIZCHIP: + wizchip_sw_reset(); + break; + case CW_INIT_WIZCHIP: + if(arg != 0) + { + ptmp[0] = (uint8_t*)arg; + ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; + } + return wizchip_init(ptmp[0], ptmp[1]); + case CW_CLR_INTERRUPT: + wizchip_clrinterrupt(*((intr_kind*)arg)); + break; + case CW_GET_INTERRUPT: + *((intr_kind*)arg) = wizchip_getinterrupt(); + break; + case CW_SET_INTRMASK: + wizchip_setinterruptmask(*((intr_kind*)arg)); + break; + case CW_GET_INTRMASK: + *((intr_kind*)arg) = wizchip_getinterruptmask(); + break; + //M20150601 : This can be supported by W5200, W5500 + //#if _WIZCHIP_ > W5100 + #if (_WIZCHIP_ == W5200 || _WIZCHIP_ == W5500) + case CW_SET_INTRTIME: + setINTLEVEL(*(uint16_t*)arg); + break; + case CW_GET_INTRTIME: + *(uint16_t*)arg = getINTLEVEL(); + break; + #endif + case CW_GET_ID: + ((uint8_t*)arg)[0] = WIZCHIP.id[0]; + ((uint8_t*)arg)[1] = WIZCHIP.id[1]; + ((uint8_t*)arg)[2] = WIZCHIP.id[2]; + ((uint8_t*)arg)[3] = WIZCHIP.id[3]; + ((uint8_t*)arg)[4] = WIZCHIP.id[4]; + ((uint8_t*)arg)[5] = WIZCHIP.id[5]; + ((uint8_t*)arg)[6] = 0; + break; + #if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500 + case CW_RESET_PHY: + wizphy_reset(); + break; + case CW_SET_PHYCONF: + wizphy_setphyconf((wiz_PhyConf*)arg); + break; + case CW_GET_PHYCONF: + wizphy_getphyconf((wiz_PhyConf*)arg); + break; + case CW_GET_PHYSTATUS: + break; + case CW_SET_PHYPOWMODE: + return wizphy_setphypmode(*(uint8_t*)arg); + #endif + #if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500 + case CW_GET_PHYPOWMODE: + tmp = wizphy_getphypmode(); + if((int8_t)tmp == -1) return -1; + *(uint8_t*)arg = tmp; + break; + case CW_GET_PHYLINK: + tmp = wizphy_getphylink(); + if((int8_t)tmp == -1) return -1; + *(uint8_t*)arg = tmp; + break; + #endif + default: + return -1; + } + return 0; +} + + +int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) +{ + + switch(cntype) + { + case CN_SET_NETINFO: + wizchip_setnetinfo((wiz_NetInfo*)arg); + break; + case CN_GET_NETINFO: + wizchip_getnetinfo((wiz_NetInfo*)arg); + break; + case CN_SET_NETMODE: + return wizchip_setnetmode(*(netmode_type*)arg); + case CN_GET_NETMODE: + *(netmode_type*)arg = wizchip_getnetmode(); + break; + case CN_SET_TIMEOUT: + wizchip_settimeout((wiz_NetTimeout*)arg); + break; + case CN_GET_TIMEOUT: + wizchip_gettimeout((wiz_NetTimeout*)arg); + break; + default: + return -1; + } + return 0; +} + +void wizchip_sw_reset(void) +{ + uint8_t gw[4], sn[4], sip[4]; + uint8_t mac[6]; +//A20150601 +#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_ + uint16_t mr = (uint16_t)getMR(); + setMR(mr | MR_IND); +#endif +// + getSHAR(mac); + getGAR(gw); getSUBR(sn); getSIPR(sip); + setMR(MR_RST); + getMR(); // for delay +//A2015051 : For indirect bus mode +#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_ + setMR(mr | MR_IND); +#endif +// + setSHAR(mac); + setGAR(gw); + setSUBR(sn); + setSIPR(sip); +} + +int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) +{ + int8_t i; +#if _WIZCHIP_ < W5200 + int8_t j; +#endif + int8_t tmp = 0; + wizchip_sw_reset(); + if(txsize) + { + tmp = 0; +//M20150601 : For integrating with W5300 +#if _WIZCHIP_ == W5300 + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { + if(txsize[i] > 64) return -1; //No use 64KB even if W5300 support max 64KB memory allocation + tmp += txsize[i]; + if(tmp > 128) return -1; + } + if(tmp % 8) return -1; +#else + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { + tmp += txsize[i]; + +#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s + if(tmp > 8) return -1; +#else + if(tmp > 16) return -1; +#endif + } +#endif + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { +#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 + j = 0; + while((txsize[i] >> j != 1)&&(txsize[i] !=0)){j++;} + setSn_TXBUF_SIZE(i, j); +#else + setSn_TXBUF_SIZE(i, txsize[i]); +#endif + } + } + + if(rxsize) + { + tmp = 0; +#if _WIZCHIP_ == W5300 + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { + if(rxsize[i] > 64) return -1; //No use 64KB even if W5300 support max 64KB memory allocation + tmp += rxsize[i]; + if(tmp > 128) return -1; + } + if(tmp % 8) return -1; +#else + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { + tmp += rxsize[i]; +#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s + if(tmp > 8) return -1; +#else + if(tmp > 16) return -1; +#endif + } +#endif + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + { +#if _WIZCHIP_ < W5200 // add condition for w5100 + j = 0; + while((rxsize[i] >> j != 1)&&(txsize[i] !=0)){j++;} + setSn_RXBUF_SIZE(i, j); +#else + setSn_RXBUF_SIZE(i, rxsize[i]); +#endif + } + } + return 0; +} + +void wizchip_clrinterrupt(intr_kind intr) +{ + uint8_t ir = (uint8_t)intr; + uint8_t sir = (uint8_t)((uint16_t)intr >> 8); +#if _WIZCHIP_ < W5500 + ir |= (1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == W5200 + ir |= (1 << 6); +#endif + +#if _WIZCHIP_ < W5200 + sir &= 0x0F; +#endif + +#if _WIZCHIP_ <= W5100S + ir |= sir; + setIR(ir); +//A20150601 : For integrating with W5300 +#elif _WIZCHIP_ == W5300 + setIR( ((((uint16_t)ir) << 8) | (((uint16_t)sir) & 0x00FF)) ); +#else + setIR(ir); +//M20200227 : For clear + //setSIR(sir); + for(ir=0; ir<8; ir++){ + if(sir & (0x01 <> 8); + sir = (uint8_t)ret; +#else + ir = getIR(); + sir = getSIR(); +#endif + +//M20150601 : For Integrating with W5300 +//#if _WIZCHIP_ < W5500 +#if _WIZCHIP_ < W5200 + ir &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == W5200 + ir &= ~(1 << 6); +#endif + ret = sir; + ret = (ret << 8) + ir; + return (intr_kind)ret; +} + +void wizchip_setinterruptmask(intr_kind intr) +{ + uint8_t imr = (uint8_t)intr; + uint8_t simr = (uint8_t)((uint16_t)intr >> 8); +#if _WIZCHIP_ < W5500 + imr &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == W5200 + imr &= ~(1 << 6); +#endif + +#if _WIZCHIP_ < W5200 + simr &= 0x0F; + imr |= simr; + setIMR(imr); +//A20150601 : For integrating with W5300 +#elif _WIZCHIP_ == W5300 + setIMR( ((((uint16_t)imr) << 8) | (((uint16_t)simr) & 0x00FF)) ); +#else + setIMR(imr); + setSIMR(simr); +#endif +} + +intr_kind wizchip_getinterruptmask(void) +{ + uint8_t imr = 0; + uint8_t simr = 0; + uint16_t ret = 0; +#if _WIZCHIP_ < W5200 + imr = getIMR(); + simr = imr & 0x0F; +//A20150601 : For integrating with W5300 +#elif _WIZCHIP_ == W5300 + ret = getIMR(); + imr = (uint8_t)(ret >> 8); + simr = (uint8_t)ret; +#else + imr = getIMR(); + simr = getSIMR(); +#endif + +#if _WIZCHIP_ < W5500 + imr &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == W5200 + imr &= ~(1 << 6); // IK_DEST_UNREACH +#endif + ret = simr; + ret = (ret << 8) + imr; + return (intr_kind)ret; +} + +int8_t wizphy_getphylink(void) +{ + int8_t tmp = PHY_LINK_OFF; +#if _WIZCHIP_ == W5100S + if(getPHYSR() & PHYSR_LNK) + tmp = PHY_LINK_ON; +#elif _WIZCHIP_ == W5200 + if(getPHYSTATUS() & PHYSTATUS_LINK) + tmp = PHY_LINK_ON; +#elif _WIZCHIP_ == W5500 + if(getPHYCFGR() & PHYCFGR_LNK_ON) + tmp = PHY_LINK_ON; + +#else + tmp = -1; +#endif + return tmp; +} + +#if _WIZCHIP_ > W5100 + +int8_t wizphy_getphypmode(void) +{ + int8_t tmp = 0; + #if _WIZCHIP_ == W5200 + if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) + tmp = PHY_POWER_DOWN; + else + tmp = PHY_POWER_NORM; + #elif _WIZCHIP_ == 5500 + if((getPHYCFGR() & PHYCFGR_OPMDC_ALLA) == PHYCFGR_OPMDC_PDOWN) + tmp = PHY_POWER_DOWN; + else + tmp = PHY_POWER_NORM; + #else + tmp = -1; + #endif + return tmp; +} +#endif + +#if _WIZCHIP_ == W5100S +void wizphy_reset(void) +{ + uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR); + tmp |= BMCR_RESET; + wiz_mdio_write(PHYMDIO_BMCR, tmp); + while(wiz_mdio_read(PHYMDIO_BMCR)&BMCR_RESET){} +} + +void wizphy_setphyconf(wiz_PhyConf* phyconf) +{ + uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR); + if(phyconf->mode == PHY_MODE_AUTONEGO) + tmp |= BMCR_AUTONEGO; + else + { + tmp &= ~BMCR_AUTONEGO; + if(phyconf->duplex == PHY_DUPLEX_FULL) + { + tmp |= BMCR_DUP; + } + else + { + tmp &= ~BMCR_DUP; + } + if(phyconf->speed == PHY_SPEED_100) + { + tmp |= BMCR_SPEED; + } + else + { + tmp &= ~BMCR_SPEED; + } + } + wiz_mdio_write(PHYMDIO_BMCR, tmp); +} + +void wizphy_getphyconf(wiz_PhyConf* phyconf) +{ + uint16_t tmp = 0; + tmp = wiz_mdio_read(PHYMDIO_BMCR); + phyconf->by = PHY_CONFBY_SW; + if(tmp & BMCR_AUTONEGO) + { + phyconf->mode = PHY_MODE_AUTONEGO; + } + else + { + phyconf->mode = PHY_MODE_MANUAL; + if(tmp&BMCR_DUP) phyconf->duplex = PHY_DUPLEX_FULL; + else phyconf->duplex = PHY_DUPLEX_HALF; + if(tmp&BMCR_SPEED) phyconf->speed = PHY_SPEED_100; + else phyconf->speed = PHY_SPEED_10; + } +} + +int8_t wizphy_setphypmode(uint8_t pmode) +{ + uint16_t tmp = 0; + tmp = wiz_mdio_read(PHYMDIO_BMCR); + if( pmode == PHY_POWER_DOWN) + { + tmp |= BMCR_PWDN; + } + else + { + tmp &= ~BMCR_PWDN; + } + wiz_mdio_write(PHYMDIO_BMCR, tmp); + tmp = wiz_mdio_read(PHYMDIO_BMCR); + if( pmode == PHY_POWER_DOWN) + { + if(tmp & BMCR_PWDN) return 0; + } + else + { + if((tmp & BMCR_PWDN) != BMCR_PWDN) return 0; + } + return -1; +} + +#endif +#if _WIZCHIP_ == W5500 +void wizphy_reset(void) +{ + uint8_t tmp = getPHYCFGR(); + tmp &= PHYCFGR_RST; + setPHYCFGR(tmp); + tmp = getPHYCFGR(); + tmp |= ~PHYCFGR_RST; + setPHYCFGR(tmp); +} + +void wizphy_setphyconf(wiz_PhyConf* phyconf) +{ + uint8_t tmp = 0; + if(phyconf->by == PHY_CONFBY_SW) + tmp |= PHYCFGR_OPMD; + else + tmp &= ~PHYCFGR_OPMD; + if(phyconf->mode == PHY_MODE_AUTONEGO) + tmp |= PHYCFGR_OPMDC_ALLA; + else + { + if(phyconf->duplex == PHY_DUPLEX_FULL) + { + if(phyconf->speed == PHY_SPEED_100) + tmp |= PHYCFGR_OPMDC_100F; + else + tmp |= PHYCFGR_OPMDC_10F; + } + else + { + if(phyconf->speed == PHY_SPEED_100) + tmp |= PHYCFGR_OPMDC_100H; + else + tmp |= PHYCFGR_OPMDC_10H; + } + } + setPHYCFGR(tmp); + wizphy_reset(); +} + +void wizphy_getphyconf(wiz_PhyConf* phyconf) +{ + uint8_t tmp = 0; + tmp = getPHYCFGR(); + phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_ALLA: + case PHYCFGR_OPMDC_100FA: + phyconf->mode = PHY_MODE_AUTONEGO; + break; + default: + phyconf->mode = PHY_MODE_MANUAL; + break; + } + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_100FA: + case PHYCFGR_OPMDC_100F: + case PHYCFGR_OPMDC_100H: + phyconf->speed = PHY_SPEED_100; + break; + default: + phyconf->speed = PHY_SPEED_10; + break; + } + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_100FA: + case PHYCFGR_OPMDC_100F: + case PHYCFGR_OPMDC_10F: + phyconf->duplex = PHY_DUPLEX_FULL; + break; + default: + phyconf->duplex = PHY_DUPLEX_HALF; + break; + } +} + +void wizphy_getphystat(wiz_PhyConf* phyconf) +{ + uint8_t tmp = getPHYCFGR(); + phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; +} + +int8_t wizphy_setphypmode(uint8_t pmode) +{ + uint8_t tmp = 0; + tmp = getPHYCFGR(); + if((tmp & PHYCFGR_OPMD)== 0) return -1; + tmp &= ~PHYCFGR_OPMDC_ALLA; + if( pmode == PHY_POWER_DOWN) + tmp |= PHYCFGR_OPMDC_PDOWN; + else + tmp |= PHYCFGR_OPMDC_ALLA; + setPHYCFGR(tmp); + wizphy_reset(); + tmp = getPHYCFGR(); + if( pmode == PHY_POWER_DOWN) + { + if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; + } + else + { + if(tmp & PHYCFGR_OPMDC_ALLA) return 0; + } + return -1; +} +#endif + + +void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) +{ + setSHAR(pnetinfo->mac); + setGAR(pnetinfo->gw); + setSUBR(pnetinfo->sn); + setSIPR(pnetinfo->ip); + _DNS_[0] = pnetinfo->dns[0]; + _DNS_[1] = pnetinfo->dns[1]; + _DNS_[2] = pnetinfo->dns[2]; + _DNS_[3] = pnetinfo->dns[3]; + _DHCP_ = pnetinfo->dhcp; +} + +void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) +{ + getSHAR(pnetinfo->mac); + getGAR(pnetinfo->gw); + getSUBR(pnetinfo->sn); + getSIPR(pnetinfo->ip); + pnetinfo->dns[0]= _DNS_[0]; + pnetinfo->dns[1]= _DNS_[1]; + pnetinfo->dns[2]= _DNS_[2]; + pnetinfo->dns[3]= _DNS_[3]; + pnetinfo->dhcp = _DHCP_; +} + +int8_t wizchip_setnetmode(netmode_type netmode) +{ + uint8_t tmp = 0; +#if _WIZCHIP_ != W5500 + if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; +#else + if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; +#endif + tmp = getMR(); + tmp |= (uint8_t)netmode; + setMR(tmp); + return 0; +} + +netmode_type wizchip_getnetmode(void) +{ + return (netmode_type) getMR(); +} + +void wizchip_settimeout(wiz_NetTimeout* nettime) +{ + setRCR(nettime->retry_cnt); + setRTR(nettime->time_100us); +} + +void wizchip_gettimeout(wiz_NetTimeout* nettime) +{ + nettime->retry_cnt = getRCR(); + nettime->time_100us = getRTR(); +} diff --git a/Libraries/Ethernet/wizchip_conf.h b/Libraries/Ethernet/wizchip_conf.h new file mode 100644 index 0000000..2e96308 --- /dev/null +++ b/Libraries/Ethernet/wizchip_conf.h @@ -0,0 +1,661 @@ +//***************************************************************************** +// +//! \file wizchip_conf.h +//! \brief WIZCHIP Config Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2015/02/05> Notice +//! The version history is not updated after this point. +//! Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary. +//! >> https://github.com/Wiznet/ioLibrary_Driver +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +/** + * @defgroup extra_functions 2. WIZnet Extra Functions + * + * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. + * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n + * + */ + +#ifndef _WIZCHIP_CONF_H_ +#define _WIZCHIP_CONF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +/** + * @brief Select WIZCHIP. + * @todo You should select one, \b W5100, \b W5100S, \b W5200, \b W5300, \b W5500 or etc. \n\n + * ex> #define \_WIZCHIP_ W5500 + */ + +#define W5100 5100 +#define W5100S 5100+5 +#define W5200 5200 +#define W5300 5300 +#define W5500 5500 + +#ifndef _WIZCHIP_ + #define _WIZCHIP_ W5500 // W5100, W5100S, W5200, W5300, W5500 +#endif + +#define _WIZCHIP_IO_MODE_NONE_ 0x0000 +#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ +#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ +//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 +//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 +// Add to +// + +#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ +#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ + +#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ +#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ +#define _WIZCHIP_IO_MODE_SPI_5500_ (_WIZCHIP_IO_MODE_SPI_ + 3) /**< SPI interface mode for fixed length data mode*/ + +#if (_WIZCHIP_ == W5100) + #define _WIZCHIP_ID_ "W5100\0" +/** + * @brief Define interface mode. + * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ + */ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ + +//A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; +//A20150401 : Indclude W5100.h file + #include "W5100/w5100.h" + +#elif (_WIZCHIP_ == W5100S) +#define _WIZCHIP_ID_ "W5100S\0" +/** +* @brief Define interface mode. +* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ +*/ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ + //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_5500_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ + +//A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; +//A20150401 : Indclude W5100.h file + #include "W5100S/w5100s.h" +#elif (_WIZCHIP_ == W5200) + #define _WIZCHIP_ID_ "W5200\0" +/** + * @brief Define interface mode. + * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \ _WIZCHIP_IO_MODE_BUS_INDIR_ + */ +#ifndef _WIZCHIP_IO_MODE_ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ +#endif +//A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; + #include "W5200/w5200.h" +#elif (_WIZCHIP_ == W5500) + #define _WIZCHIP_ID_ "W5500\0" + +/** + * @brief Define interface mode. \n + * @todo Should select interface mode as chip. + * - @ref \_WIZCHIP_IO_MODE_SPI_ \n + * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n + * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n + * - @ref \_WIZCHIP_IO_MODE_BUS_ \n + * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n + * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n + * - Others will be defined in future. \n\n + * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ + * + */ +#ifndef _WIZCHIP_IO_MODE_ + //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ +#endif +//A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; + #include "W5500/w5500.h" +#elif ( _WIZCHIP_ == W5300) + #define _WIZCHIP_ID_ "W5300\0" +/** + * @brief Define interface mode. + * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ + */ +#ifndef _WIZCHIP_IO_MODE_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ +#endif + +//A20150601 : Define the unit and bus width of IO DATA. + /** + * @brief Select the data width 8 or 16 bits. + * @todo you should select the bus width. Select one of 8 or 16. + */ + #ifndef _WIZCHIP_IO_BUS_WIDTH_ + #define _WIZCHIP_IO_BUS_WIDTH_ 16 // 8 + #endif + #if _WIZCHIP_IO_BUS_WIDTH_ == 8 + typedef uint8_t iodata_t; + #elif _WIZCHIP_IO_BUS_WIDTH_ == 16 + typedef uint16_t iodata_t; + #else + #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. It should be 8 or 16." + #endif +// + #include "W5300/w5300.h" +#else + #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" +#endif + +#ifndef _WIZCHIP_IO_MODE_ + #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" +#endif + +/** + * @brief Define I/O base address when BUS IF mode. + * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, + * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n + * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000 + */ +#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_ +// #define _WIZCHIP_IO_BASE_ 0x60000000 // for 5100S IND + #define _WIZCHIP_IO_BASE_ 0x68000000 // for W5300 +#elif _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_ + #define _WIZCHIP_IO_BASE_ 0x00000000 // for 5100S SPI +#endif + +#ifndef _WIZCHIP_IO_BASE_ +#define _WIZCHIP_IO_BASE_ 0x00000000 // 0x8000 +#endif + +//M20150401 : Typing Error +//#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS +#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_ + #ifndef _WIZCHIP_IO_BASE_ + #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." + #endif +#endif + +#if _WIZCHIP_ >= W5200 + #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP +#else + #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP +#endif + + +/******************************************************** +* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. +*********************************************************/ +/** + * @ingroup DATA_TYPE + * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 + */ +typedef struct __WIZCHIP +{ + uint16_t if_mode; ///< host interface mode + uint8_t id[8]; ///< @b WIZCHIP ID such as @b 5100, @b 5100S, @b 5200, @b 5500, and so on. + /** + * The set of critical section callback func. + */ + struct _CRIS + { + void (*_enter) (void); ///< crtical section enter + void (*_exit) (void); ///< critial section exit + }CRIS; + /** + * The set of @ref \_WIZCHIP_ select control callback func. + */ + struct _CS + { + void (*_select) (void); ///< @ref \_WIZCHIP_ selected + void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected + }CS; + /** + * The set of interface IO callback func. + */ + union _IF + { + /** + * For BUS interface IO + */ + //M20156501 : Modify the function name for integrating with W5300 + //struct + //{ + // uint8_t (*_read_byte) (uint32_t AddrSel); + // void (*_write_byte) (uint32_t AddrSel, uint8_t wb); + //}BUS; + struct + { + iodata_t (*_read_data) (uint32_t AddrSel); + void (*_write_data) (uint32_t AddrSel, iodata_t wb); + }BUS; + + /** + * For SPI interface IO + */ + struct + { + uint8_t (*_read_byte) (void); + void (*_write_byte) (uint8_t wb); + void (*_read_burst) (uint8_t* pBuf, uint16_t len); + void (*_write_burst) (uint8_t* pBuf, uint16_t len); + }SPI; + // To be added + // + }IF; +}_WIZCHIP; + +extern _WIZCHIP WIZCHIP; + +/** + * @ingroup DATA_TYPE + * WIZCHIP control type enumration used in @ref ctlwizchip(). + */ +typedef enum +{ + CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly + CW_INIT_WIZCHIP, ///< Initializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. + CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP + CW_CLR_INTERRUPT, ///< Clears interrupt + CW_SET_INTRMASK, ///< Masks interrupt + CW_GET_INTRMASK, ///< Get interrupt mask + CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. + CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. + CW_GET_ID, ///< Gets WIZCHIP name. + +//D20150601 : For no modification your application code +//#if _WIZCHIP_ == W5500 + CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5500 + CW_SET_PHYCONF, ///< When PHY configured by internal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 + CW_GET_PHYCONF, ///< Get PHY operation mode in internal register. Valid Only W5500 + CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5500 + CW_SET_PHYPOWMODE, ///< Set PHY power mode as normal and down when PHYSTATUS.OPMD == 1. Valid Only W5500 +//#endif +//D20150601 : For no modification your application code +//#if _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500 + CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal, Valid Only W5100, W5200 + CW_GET_PHYLINK ///< Get PHY Link status, Valid Only W5100, W5200 +//#endif +}ctlwizchip_type; + +/** + * @ingroup DATA_TYPE + * Network control type enumration used in @ref ctlnetwork(). + */ +typedef enum +{ + CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo + CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo + CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode + CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode + CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. + CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. +}ctlnetwork_type; + +/** + * @ingroup DATA_TYPE + * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK + * and CW_GET_INTRMASK is used in @ref ctlnetwork(). + * It can be used with OR operation. + */ +typedef enum +{ +#if _WIZCHIP_ == W5500 + IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. +#elif _WIZCHIP_ == W5300 + IK_FMTU = (1 << 4), ///< Received a ICMP message (Fragment MTU) +#endif + + IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected + +#if _WIZCHIP_ != W5200 + IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreachable, No use in W5200 +#endif + + IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred + + IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt + IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt + IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt + IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt +#if _WIZCHIP_ > W5100S + IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 + IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 + IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 + IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 +#endif + +#if _WIZCHIP_ > W5100S + IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrupt +#else + IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrupt +#endif +}intr_kind; + +#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin +#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register +#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. +#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation +#define PHY_SPEED_10 0 ///< Link Speed 10 +#define PHY_SPEED_100 1 ///< Link Speed 100 +#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex +#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex +#define PHY_LINK_OFF 0 ///< Link Off +#define PHY_LINK_ON 1 ///< Link On +#define PHY_POWER_NORM 0 ///< PHY power normal mode +#define PHY_POWER_DOWN 1 ///< PHY power down mode + + +#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500 +/** + * @ingroup DATA_TYPE + * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, + * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n + * Valid only in W5500. + */ +typedef struct wiz_PhyConf_t +{ + uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW + uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO + uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 + uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL + //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN + //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF + }wiz_PhyConf; +#endif + +/** + * @ingroup DATA_TYPE + * It used in setting dhcp_mode of @ref wiz_NetInfo. + */ +typedef enum +{ + NETINFO_STATIC = 1, ///< Static IP configuration by manually. + NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever +}dhcp_mode; + +/** + * @ingroup DATA_TYPE + * Network Information for WIZCHIP + */ +typedef struct wiz_NetInfo_t +{ + uint8_t mac[6]; ///< Source Mac Address + uint8_t ip[4]; ///< Source IP Address + uint8_t sn[4]; ///< Subnet Mask + uint8_t gw[4]; ///< Gateway IP Address + uint8_t dns[4]; ///< DNS server IP Address + dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP +}wiz_NetInfo; + +/** + * @ingroup DATA_TYPE + * Network mode + */ +typedef enum +{ +#if _WIZCHIP_ == W5500 + NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 +#endif + NM_WAKEONLAN = (1<<5), ///< Wake On Lan + NM_PINGBLOCK = (1<<4), ///< Block ping-request + NM_PPPOE = (1<<3), ///< PPPoE mode +}netmode_type; + +/** + * @ingroup DATA_TYPE + * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. + */ +typedef struct wiz_NetTimeout_t +{ + uint8_t retry_cnt; ///< retry count + uint16_t time_100us; ///< time unit 100us +}wiz_NetTimeout; + +/** + *@brief Registers call back function for critical section of I/O functions such as + *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. + *@param cris_en : callback function for critical section enter. + *@param cris_ex : callback function for critical section exit. + *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. + *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. + */ +void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); + + +/** + *@brief Registers call back function for WIZCHIP select & deselect. + *@param cs_sel : callback function for WIZCHIP select + *@param cs_desel : callback fucntion for WIZCHIP deselect + *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); + +/** + *@brief Registers call back function for bus interface. + *@param bus_rb : callback function to read byte data using system bus + *@param bus_wb : callback function to write byte data using system bus + *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function + *or register your functions. + *@note If you do not describe or register, null function is called. + */ +//M20150601 : For integrating with W5300 +//void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); +void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb)); + +/** + *@brief Registers call back function for SPI interface. + *@param spi_rb : callback function to read byte using SPI + *@param spi_wb : callback function to write byte using SPI + *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function + *or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb)); + +/** + *@brief Registers call back function for SPI interface. + *@param spi_rb : callback function to burst read using SPI + *@param spi_wb : callback function to burst write using SPI + *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function + *or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len)); + +/** + * @ingroup extra_functions + * @brief Controls to the WIZCHIP. + * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), + * controls interrupt & mask and so on. + * @param cwtype : Decides to the control type + * @param arg : arg type is dependent on cwtype. + * @return 0 : Success \n + * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP + */ +int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); + +/** + * @ingroup extra_functions + * @brief Controls to network. + * @details Controls to network environment, mode, timeout and so on. + * @param cntype : Input. Decides to the control type + * @param arg : Inout. arg type is dependent on cntype. + * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n + * 0 : Success + */ +int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); + + +/* + * The following functions are implemented for internal use. + * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). + */ + +/** + * @ingroup extra_functions + * @brief Reset WIZCHIP by softly. + */ +void wizchip_sw_reset(void); + +/** + * @ingroup extra_functions + * @brief Initializes WIZCHIP with socket buffer size + * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. + * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. + * @return 0 : succcess \n + * -1 : fail. Invalid buffer size + */ +int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); + +/** + * @ingroup extra_functions + * @brief Clear Interrupt of WIZCHIP. + * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +void wizchip_clrinterrupt(intr_kind intr); + +/** + * @ingroup extra_functions + * @brief Get Interrupt of WIZCHIP. + * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +intr_kind wizchip_getinterrupt(void); + +/** + * @ingroup extra_functions + * @brief Mask or Unmask Interrupt of WIZCHIP. + * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +void wizchip_setinterruptmask(intr_kind intr); + +/** + * @ingroup extra_functions + * @brief Get Interrupt mask of WIZCHIP. + * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. + */ +intr_kind wizchip_getinterruptmask(void); + +//todo +#if _WIZCHIP_ > W5100 + int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 + int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 +#endif + +#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500 + void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 +/** + * @ingroup extra_functions + * @brief Set the phy information for WIZCHIP without power mode + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_setphyconf(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief Get phy configuration information. + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_getphyconf(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief Get phy status. + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_getphystat(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 + * @param pmode Settig value of power down mode. + */ + int8_t wizphy_setphypmode(uint8_t pmode); +#endif + +/** +* @ingroup extra_functions + * @brief Set the network information for WIZCHIP + * @param pnetinfo : @ref wizNetInfo + */ +void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); + +/** + * @ingroup extra_functions + * @brief Get the network information for WIZCHIP + * @param pnetinfo : @ref wizNetInfo + */ +void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); + +/** + * @ingroup extra_functions + * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. + * @param pnetinfo Value of network mode. Refer to @ref netmode_type. + */ +int8_t wizchip_setnetmode(netmode_type netmode); + +/** + * @ingroup extra_functions + * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. + * @return Value of network mode. Refer to @ref netmode_type. + */ +netmode_type wizchip_getnetmode(void); + +/** + * @ingroup extra_functions + * @brief Set retry time value(@ref _RTR_) and retry count(@ref _RCR_). + * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission. + * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. + */ +void wizchip_settimeout(wiz_NetTimeout* nettime); + +/** + * @ingroup extra_functions + * @brief Get retry time value(@ref _RTR_) and retry count(@ref _RCR_). + * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission. + * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. + */ +void wizchip_gettimeout(wiz_NetTimeout* nettime); +#ifdef __cplusplus + } +#endif + +#endif // _WIZCHIP_CONF_H_ diff --git a/Libraries/GrIP/ComIf.c b/Libraries/GrIP/ComIf.c index 3523949..b15545e 100644 --- a/Libraries/GrIP/ComIf.c +++ b/Libraries/GrIP/ComIf.c @@ -140,7 +140,7 @@ void ComIf_Update(void) else { // Read max 64 bytes from usart buffer - for(uint16_t read = 0; read < MAX_READ_SIZE; read++) + for(uint8_t read = 0; read < MAX_READ_SIZE; read++) { char c; if(Getc(&c) == 0) diff --git a/Libraries/GrIP/GrIP.c b/Libraries/GrIP/GrIP.c index 6ec37df..46a8d74 100644 --- a/Libraries/GrIP/GrIP.c +++ b/Libraries/GrIP/GrIP.c @@ -17,7 +17,7 @@ */ #include "GrIP.h" #include "CRC.h" -#include "util2.h" +#include "ServerTCP.h" #include "ComIf.h" #include "Print.h" #include @@ -64,8 +64,6 @@ void GrIP_Init(void) // Init generic interface ComIf_Init(IF_ETH, 0); - // Init CRC module - CRC_Init(); } diff --git a/Libraries/Printf/Print.c b/Libraries/Printf/Print.c index 64848dc..6f2218d 100644 --- a/Libraries/Printf/Print.c +++ b/Libraries/Printf/Print.c @@ -19,7 +19,7 @@ static uint16_t buf_idx = 0; void Printf_Init(void) { - Usart_Init(STDOUT, BAUD_RATE); + Usart_Init(STDOUT, SERIAL_BAUDRATE); } @@ -79,7 +79,7 @@ void Printf_Flush(void) return; } -#ifdef ETH_IF +#if (USE_ETH_IF) Pdu_t data; data.Data = (uint8_t*)buf; @@ -103,7 +103,7 @@ void Printf_Float(float n, uint8_t decimal_places) { if(n < 0) { - Putc('-'); + Printf("-"); n = -n; } @@ -147,8 +147,8 @@ void Printf_Float(float n, uint8_t decimal_places) { if(i == decimal_places) { - Putc('.'); + Printf("."); } // Insert decimal point in right place. - Putc(buf[i-1]); + Printf("%c", buf[i - 1]); } } diff --git a/Makefile b/Makefile index 1477a36..14fc5dd 100644 --- a/Makefile +++ b/Makefile @@ -26,9 +26,9 @@ OBJDUMP = ${GCC_BASE}/arm-none-eabi-objdump #--------------------------------------------------------------------------------- TARGET := GRBL_Advanced BUILD := build -SOURCES := ./ ARM/cmsis/ grbl/ HAL/ HAL/EXTI HAL/FLASH HAL/GPIO HAL/I2C HAL/SPI HAL/STM32 \ +SOURCES := ./ ARM/ ARM/cmsis/ grbl/ HAL/ HAL/EXTI HAL/FLASH HAL/GPIO HAL/I2C HAL/SPI HAL/STM32 \ HAL/TIM HAL/USART ARM/SPL/src Src/ Libraries/GrIP Libraries/CRC Libraries/Ethernet \ - Libraries/Ethernet/utility Libraries/Encoder Libraries/EEPROM Libraries/Printf + Libraries/Ethernet/W5500 Libraries/Encoder Libraries/EEPROM Libraries/Printf INCLUDES := $(SOURCES) ARM/SPL/inc @@ -57,7 +57,7 @@ CFLAGS := -O2 -g1 -std=c11 -Wall -Wextra $(INCLUDE) -fno-common -fsingle-p -ffunction-sections -fomit-frame-pointer -mlittle-endian -DUSE_STDPERIPH_DRIVER -D__FPU_USED -DARM_MATH_CM4 -Wimplicit-fallthrough=0 CXXFLAGS := $(CFLAGS) -LDFLAGS := -lm -flto -Wl,--gc-sections -Wl,-M=$(OUTPUT).map --specs=nosys.specs -nostartfiles --specs=nano.specs -u _scanf_float +LDFLAGS := -lm -flto -Wl,--gc-sections -Wl,-M=$(OUTPUT).map --specs=nosys.specs -nostartfiles --specs=nano.specs #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project @@ -133,6 +133,7 @@ clean: #--------------------------------------------------------------------------------- flash: $(OUTPUT).bin st-flash write $(OUTPUT).bin 0x8000000 + st-flash reset #--------------------------------------------------------------------------------- else diff --git a/README.md b/README.md index b6d7e2a..64b1110 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Grbl-Advanced includes full acceleration management with look ahead. That means ### Extras: #### Backlash Compensation: -Backlash compensation enabled by default. You can switch it off in Config.h. +Backlash compensation enabled by default. Edit defaults.h to your needs. * $140=(X Backlash [mm]) @@ -46,11 +46,11 @@ G33 / G76 (Requires rotary encoder) Uses Dynamic TLO when $14 = (2 or 3) #### I2C EEPROM -Added support for external EEPROM (e.g. ST M24C08). Uncomment 'USE_EXT_EEPROM' in Config.h. +Added support for external 1Kb EEPROM (e.g. ST M24C08). Enable 'USE_EXT_EEPROM' in Config.h. ![EEPROM](https://github.com/Schildkroet/GRBL-Advanced/blob/software/doc/eeprom.png?raw=true) #### ETHERNET Support -GRBL-Advanced can be controlled with USB or ETHERNET. For ETHERNET an additional W5500 Module is required. Then uncomment ETH_IF in Platform.h. The default IP Address is 192.168.1.20. +GRBL-Advanced can be controlled with USB or ETHERNET. For ETHERNET an additional W5500 Module is required. Then enable USE_ETH_IF in Config.h. The default IP Address is 192.168.1.20 : 30501. Use [Candle 2](https://github.com/Schildkroet/Candle2) as control interface. ![W5500](https://github.com/Schildkroet/GRBL-Advanced/blob/software/doc/w5500.png?raw=true) @@ -129,5 +129,6 @@ List of Supported G-Codes in Grbl-Advanced: - Coolant Control: M7*, M8, M9 - Spindle Control: M3, M4, M5 - Tool Control: M6, M61 + - Input/output control: M62, M63, M64, M65 - Valid Non-Command Words: A, B, D, E, F, H, I, J, K, L, N, P, Q, R, S, T, X, Y, Z ``` diff --git a/Src/Platform.h b/Src/Platform.h index dd352b7..0722267 100644 --- a/Src/Platform.h +++ b/Src/Platform.h @@ -35,10 +35,6 @@ #define FIFO_DIR_TX 1 -// Communication interface -// Comment out to use serial interface -//#define ETH_IF - #define ETH_SOCK 0 #define ETH_PORT 30501 diff --git a/grbl/Config.h b/grbl/Config.h index 4d9f536..4b9d5da 100644 --- a/grbl/Config.h +++ b/grbl/Config.h @@ -4,7 +4,7 @@ Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2017-2020 Patrick F. + Copyright (c) 2017-2024 Patrick F. Grbl-Advanced is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,31 +28,42 @@ #define CONFIG_H -#define GRBL_VERSION "1.1j" -#define GRBL_VERSION_BUILD __DATE__ +#define GRBL_VERSION "1.1k" +#define GRBL_VERSION_BUILD __DATE__ + + +// Compatibility with original grbl +//#define GRBL_COMPATIBLE // Define CPU pin map and default settings. // NOTE: OEMs can avoid the need to maintain/update the defaults.h and cpu_map.h files and use only // one configuration file by placing their specific defaults and pin map at the bottom of this file. // If doing so, simply comment out these two defines and see instructions below. +//#define DEFAULTS_GENERIC #define DEFAULTS_GENERIC + // Serial baud rate -#define BAUD_RATE 115200 -//#define BAUD_RATE 230400 +#ifndef SERIAL_BAUDRATE + #ifdef GRBL_COMPATIBLE + #define SERIAL_BAUDRATE 115200 + #else + #define SERIAL_BAUDRATE 115200 + #endif +#endif // Uncomment to use external I2C EEPROM -//#define USE_EXT_EEPROM +#ifndef USE_EXT_EEPROM + #define USE_EXT_EEPROM 0 // false +#endif -// Uncomment to use 4th/5th axis -//#define USE_MULTI_AXIS -// Uncomment for lathe mode -//#define LATHE_MODE -// Pulses/revolutions of spindle encoder -#define PULSES_PER_REV 360 +// Communication interface: 0 - USB; 1 - Ethernet +#ifndef USE_ETH_IF + #define USE_ETH_IF 0 // false +#endif // Define realtime command special characters. These characters are 'picked-off' directly from the @@ -61,18 +72,18 @@ // used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in // g-code programs, maybe selected for interface programs. // NOTE: If changed, manually update help message in report.c. -#define CMD_RESET 0x18 // ctrl-x. -#define CMD_RESET_HARD 0x19 // ctrl-y. -#define CMD_STATUS_REPORT '?' -#define CMD_CYCLE_START '~' -#define CMD_FEED_HOLD '!' -#define CMD_STEPPER_DISABLE 0x17 +#define CMD_RESET 0x18 // ctrl-x. +#define CMD_RESET_HARD 0x19 // ctrl-y. +#define CMD_STATUS_REPORT '?' +#define CMD_CYCLE_START '~' +#define CMD_FEED_HOLD '!' +#define CMD_STEPPER_DISABLE 0x17 // NOTE: All override realtime commands must be in the extended ASCII character set, starting // at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands, // such as status reports, feed hold, reset, and cycle start, are moved to the extended set -// space, serial.c's RX ISR will need to be modified to accomodate the change. +// space, RX ISR will need to be modified to accomodate the change. // #define CMD_RESET 0x80 // #define CMD_STATUS_REPORT 0x81 // #define CMD_CYCLE_START 0x82 @@ -102,7 +113,7 @@ // If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces // the user to perform the homing cycle (or override the locks) before doing anything else. This is // mainly a safety feature to remind the user to home, since position is unknown to Grbl. -#define HOMING_INIT_LOCK // Comment to disable +#define HOMING_INIT_LOCK 1 // true // Define the homing cycle patterns with bitmasks. The homing cycle first performs a search mode @@ -120,9 +131,9 @@ // on separate pin, but homed in one cycle. Also, it should be noted that the function of hard limits // will not be affected by pin sharing. // NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y. -#define HOMING_CYCLE_0 (1< +#include #define COOLANT_NO_SYNC false @@ -43,10 +44,10 @@ void Coolant_Stop(void); uint8_t Coolant_GetState(void); // Sets the coolant pins according to state specified. -void Coolant_SetState(uint8_t mode); +void Coolant_SetState(const uint8_t mode); // G-code parser entry-point for setting coolant states. Checks for and executes additional conditions. -void Coolant_Sync(uint8_t mode); +void Coolant_Sync(const uint8_t mode); #endif // COOLANTCONTROL_H diff --git a/grbl/GCode.c b/grbl/GCode.c index 8e4d892..212b017 100644 --- a/grbl/GCode.c +++ b/grbl/GCode.c @@ -34,15 +34,16 @@ #include "util.h" #include "ToolChange.h" #include "GCode.h" +#include "Print.h" // Modal Group M9: Override control #ifdef DEACTIVATE_PARKING_UPON_INIT -#define OVERRIDE_DISABLED 0 // (Default: Must be zero) -#define OVERRIDE_PARKING_MOTION 1 // M56 +#define OVERRIDE_DISABLED 0 // (Default: Must be zero) +#define OVERRIDE_PARKING_MOTION 1 // M56 #else -#define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) -#define OVERRIDE_DISABLED 1 // Parking disabled. +#define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) +#define OVERRIDE_DISABLED 1 // Parking disabled. #endif @@ -67,6 +68,11 @@ void GC_Init(void) { memset(&gc_state, 0, sizeof(Parser_State_t)); + for (uint8_t i = 0; i < N_AXIS; i++) + { + gc_state.tool_length_offset_dynamic[i] = 0.0; + } + // Load default G54 coordinate system. if(!(Settings_ReadCoordData(gc_state.modal.coord_select, gc_state.coord_system))) { @@ -88,7 +94,7 @@ void GC_SyncPosition(void) // characters have been removed. In this function, all units and positions are converted and // exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine // coordinates, respectively. -uint8_t GC_ExecuteLine(char *line) +uint8_t GC_ExecuteLine(const char *line) { /* ------------------------------------------------------------------------------------- STEP 1: Initialize parser block struct and copy current g-code state modes. The parser @@ -130,7 +136,8 @@ uint8_t GC_ExecuteLine(char *line) perform initial error-checks for command word modal group violations, for any repeated words, and for negative values set for the value words F, N, P, T, and S. */ - uint16_t word_bit = 0; // Bit-value for assigning tracking variables + // Bit-value for assigning tracking variables + uint16_t word_bit = 0; uint8_t char_counter = 0; char letter = 0; float value = 0.0; @@ -138,6 +145,7 @@ uint8_t GC_ExecuteLine(char *line) uint16_t mantissa = 0; float old_xyz[N_AXIS] = {0.0}; uint8_t change_tool = 0, update_tooltable = 0, apply_tool = 0; + uint8_t io_cmd = 0; memcpy(old_xyz, gc_state.position, N_AXIS*sizeof(float)); @@ -152,20 +160,23 @@ uint8_t GC_ExecuteLine(char *line) char_counter = 0; } - while(line[char_counter] != 0) // Loop until no more g-code words in line. + // Loop until no more g-code words in line. + while(line[char_counter] != 0) { // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out. letter = line[char_counter]; if((letter < 'A') || (letter > 'Z')) { + // [Expected word letter] return STATUS_EXPECTED_COMMAND_LETTER; - } // [Expected word letter] + } char_counter++; if(!Read_Float(line, &char_counter, &value)) { + // [Expected word value] return STATUS_BAD_NUMBER_FORMAT; - } // [Expected word value] + } // Convert values to smaller uint8 significand and mantissa values for parsing this word. // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more @@ -174,8 +185,9 @@ uint8_t GC_ExecuteLine(char *line) // a good enough comprimise and catch most all non-integer errors. To make it compliant, // we would simply need to change the mantissa to int16, but this add compiled flash space. // Maybe update this later. - int_value = trunc(value); - mantissa = round(100*(value - int_value)); // Compute mantissa for Gxx.x commands. + int_value = truncf(value); + // Compute mantissa for Gxx.x commands. + mantissa = roundf(100*(value - int_value)); // NOTE: Rounding must be used to catch small floating point errors. // Check if the g-code word is supported or errors due to modal group violations or has @@ -191,7 +203,7 @@ uint8_t GC_ExecuteLine(char *line) { case 7: // Lathe Diameter Mode - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G12; gc_block.modal.lathe_mode = LATHE_DIAMETER_MODE; @@ -204,7 +216,7 @@ uint8_t GC_ExecuteLine(char *line) case 8: // Lathe Radius Mode (default) - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G12; gc_block.modal.lathe_mode = LATHE_RADIUS_MODE; @@ -244,13 +256,14 @@ uint8_t GC_ExecuteLine(char *line) return STATUS_GCODE_UNSUPPORTED_COMMAND; } gc_block.non_modal_command += mantissa; - mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Set to zero to indicate valid non-integer G command. + mantissa = 0; } break; case 33: // Spindle Synchronized Motion - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G1; gc_block.modal.motion = int_value; @@ -264,7 +277,7 @@ uint8_t GC_ExecuteLine(char *line) case 76: // Threading Cycle - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G1; gc_block.modal.motion = int_value; @@ -278,7 +291,7 @@ uint8_t GC_ExecuteLine(char *line) case 96: // Constant Surface Speed - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext , BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G14; gc_block.modal.spindle_mode = SPINDLE_SURFACE_MODE; @@ -291,7 +304,7 @@ uint8_t GC_ExecuteLine(char *line) case 97: // RPM Mode (default) - if(settings.flags2 & BITFLAG_LATHE_MODE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) { word_bit = MODAL_GROUP_G14; gc_block.modal.spindle_mode = SPINDLE_RPM_MODE; @@ -325,10 +338,12 @@ uint8_t GC_ExecuteLine(char *line) { if(!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) { - return STATUS_GCODE_UNSUPPORTED_COMMAND; // [Unsupported G38.x command] + // [Unsupported G38.x command] + return STATUS_GCODE_UNSUPPORTED_COMMAND; } gc_block.modal.motion += (mantissa/10)+100; - mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Set to zero to indicate valid non-integer G command. + mantissa = 0; } break; @@ -371,7 +386,8 @@ uint8_t GC_ExecuteLine(char *line) // [G90.1 not supported] return STATUS_GCODE_UNSUPPORTED_COMMAND; } - mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Set to zero to indicate valid non-integer G command. + mantissa = 0; // Otherwise, arc IJK incremental mode is default. G91.1 does nothing. } break; @@ -420,15 +436,15 @@ uint8_t GC_ExecuteLine(char *line) else if(mantissa < 0.001) // G43 { update_tooltable = 1; - gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; + gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE; } else { // [Unsupported G43.x command] return STATUS_GCODE_UNSUPPORTED_COMMAND; } - - mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Set to zero to indicate valid non-integer G command. + mantissa = 0; break; case 54: @@ -439,7 +455,8 @@ uint8_t GC_ExecuteLine(char *line) case 59: // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.) word_bit = MODAL_GROUP_G12; - gc_block.modal.coord_select = int_value - 54; // Shift to array indexing. + // Shift to array indexing. + gc_block.modal.coord_select = int_value - 54; break; case 61: @@ -453,7 +470,8 @@ uint8_t GC_ExecuteLine(char *line) break; default: - return STATUS_GCODE_UNSUPPORTED_COMMAND; // [Unsupported G command] + // [Unsupported G command] + return STATUS_GCODE_UNSUPPORTED_COMMAND; } if(mantissa > 0) @@ -497,7 +515,8 @@ uint8_t GC_ExecuteLine(char *line) break; // Optional stop not supported. Ignore. default: - gc_block.modal.program_flow = int_value; // Program end and reset + // Program end and reset + gc_block.modal.program_flow = int_value; } break; @@ -525,27 +544,28 @@ uint8_t GC_ExecuteLine(char *line) change_tool = 1; break; - case 61: // Tool change + case 61: // Set current tool apply_tool = 1; break; -#ifdef ENABLE_M7 case 7: case 8: case 9: -#else - case 8: - case 9: -#endif word_bit = MODAL_GROUP_M8; switch(int_value) { -#ifdef ENABLE_M7 case 7: - gc_block.modal.coolant |= COOLANT_MIST_ENABLE; + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) + { + gc_block.modal.coolant |= COOLANT_MIST_ENABLE; + } + else + { + return STATUS_GCODE_UNSUPPORTED_COMMAND; + } break; -#endif + case 8: gc_block.modal.coolant |= COOLANT_FLOOD_ENABLE; break; @@ -563,8 +583,25 @@ uint8_t GC_ExecuteLine(char *line) gc_block.modal.override = OVERRIDE_PARKING_MOTION; break; #endif + + // M62 - M65 Digital Output Control + case 62: + // Turn on IO in sync + case 63: + // Turn off IO in sync + case 64: + // Turn on IO immediately + case 65: + // Turn off IO immediately + case 66: + // Wait on user input + word_bit = MODAL_GROUP_M5; + io_cmd = int_value; + break; + default: - return STATUS_GCODE_UNSUPPORTED_COMMAND; // [Unsupported M command] + // [Unsupported M command] + return STATUS_GCODE_UNSUPPORTED_COMMAND; } // Check for more than one command per modal group violations in the current block @@ -581,20 +618,24 @@ uint8_t GC_ExecuteLine(char *line) /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining legal g-code words and stores their value. Error-checking is performed later since some words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */ - switch(letter) + switch (letter) { -#ifdef USE_MULTI_AXIS case 'A': - word_bit = WORD_A; - gc_block.values.xyz[A_AXIS] = value; - axis_words |= (1<= MAX_TOOL_NR) + if (gc_block.values.h >= TOOLTABLE_MAX_TOOL_NR) { return STATUS_GCODE_MAX_VALUE_EXCEEDED; } @@ -856,6 +900,65 @@ uint8_t GC_ExecuteLine(char *line) BIT_FALSE(value_words, BIT(WORD_H)); } + // [Input Output Control ]: + if (BIT_IS_TRUE(command_words, BIT(MODAL_GROUP_M5))) + { + if (io_cmd == 66) + { + if (BIT_IS_FALSE(value_words, BIT(WORD_P)) && BIT_IS_FALSE(value_words, BIT(WORD_E))) + { + // We need either P or E + return STATUS_GCODE_VALUE_WORD_MISSING; + } + else if (BIT_IS_TRUE(value_words, BIT(WORD_P)) && BIT_IS_TRUE(value_words, BIT(WORD_E))) + { + // Only one must be true + return STATUS_GCODE_WORD_REPEATED; + } + + if (BIT_IS_TRUE(value_words, BIT(WORD_P))) + { + if (gc_block.values.p < 0.0) + { + return STATUS_GCODE_INVALID_TARGET; + } + BIT_FALSE(value_words, BIT(WORD_P)); + } + if (BIT_IS_TRUE(value_words, BIT(WORD_E))) + { + if (gc_block.values.e < 0.0) + { + return STATUS_GCODE_INVALID_TARGET; + } + BIT_FALSE(value_words, BIT(WORD_E)); + } + if (BIT_IS_TRUE(value_words, BIT(WORD_L))) + { + if(gc_block.values.l > 4) + { + return STATUS_GCODE_MAX_VALUE_EXCEEDED; + } + BIT_FALSE(value_words, BIT(WORD_L)); + } + if (BIT_IS_TRUE(value_words, BIT(WORD_Q))) + { + if(gc_block.values.q < 0.0) + { + return STATUS_GCODE_INVALID_TARGET; + } + BIT_FALSE(value_words, BIT(WORD_Q)); + } + } + else + { + if (BIT_IS_FALSE(value_words, BIT(WORD_P))) + { + return STATUS_GCODE_VALUE_WORD_MISSING; + } + BIT_FALSE(value_words, BIT(WORD_P)); + } + } + // [7. Spindle control ]: if(BIT_IS_TRUE(command_words, BIT(MODAL_GROUP_G14)) && (gc_block.modal.motion == SPINDLE_SURFACE_MODE)) { @@ -969,7 +1072,8 @@ uint8_t GC_ExecuteLine(char *line) uint8_t idx; if(gc_block.modal.units == UNITS_MODE_INCHES) { - for(idx = 0; idx < N_AXIS; idx++) // Axes indices are consistent, so loop may be used. + // Axes indices are consistent, so loop may be used. + for(idx = 0; idx < N_AXIS; idx++) { if(BIT_IS_TRUE(axis_words, BIT(idx))) { @@ -983,7 +1087,7 @@ uint8_t GC_ExecuteLine(char *line) // NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40 // only for the purpose to not error when G40 is sent with a g-code program header to setup the default modes. - // [14. Cutter length compensation ]: G43 NOT SUPPORTED, but G43.1 and G49 are. + // [14. Cutter length compensation ]: // [G43.1 Errors]: Motion command in same line. // NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid // axis that is configured (in config.h). There should be an error if the configured axis @@ -997,6 +1101,17 @@ uint8_t GC_ExecuteLine(char *line) return STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR; } } + if (gc_block.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE) + { + if (BIT_IS_TRUE(value_words, BIT(WORD_H))) + { + if (gc_block.values.h > TOOLTABLE_MAX_TOOL_NR - 1) + { + return STATUS_GCODE_MAX_VALUE_EXCEEDED; + } + } + BIT_FALSE(value_words, BIT(WORD_H)); + } } // [15. Coordinate system selection ]: *N/A. Error, if cutter radius comp is active. @@ -1007,7 +1122,8 @@ uint8_t GC_ExecuteLine(char *line) float block_coord_system[N_AXIS]; memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system)); - if(BIT_IS_TRUE(command_words,BIT(MODAL_GROUP_G12))) // Check if called in block + // Check if called in block + if(BIT_IS_TRUE(command_words,BIT(MODAL_GROUP_G12))) { if(gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { @@ -1050,7 +1166,8 @@ uint8_t GC_ExecuteLine(char *line) return STATUS_GCODE_VALUE_WORD_MISSING; } - coord_select = trunc(gc_block.values.p); // Convert p value to int. + // Convert p value to int. + coord_select = truncf(gc_block.values.p); if(coord_select > N_COORDINATE_SYSTEM) { // [Greater than N sys] @@ -1107,7 +1224,7 @@ uint8_t GC_ExecuteLine(char *line) gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx]; //if(idx == TOOL_LENGTH_OFFSET_AXIS) { - gc_block.values.ijk[idx] -= gc_state.tool_length_offset[idx]; + gc_block.values.ijk[idx] -= gc_state.tool_length_offset_dynamic[idx] + gc_state.tool_length_offset[idx]; } } else @@ -1137,7 +1254,7 @@ uint8_t GC_ExecuteLine(char *line) gc_block.values.xyz[idx] = gc_state.position[idx] - block_coord_system[idx] - gc_block.values.xyz[idx]; //if(idx == TOOL_LENGTH_OFFSET_AXIS) { - gc_block.values.xyz[idx] -= gc_state.tool_length_offset[idx]; + gc_block.values.xyz[idx] -= gc_state.tool_length_offset_dynamic[idx] + gc_state.tool_length_offset[idx]; } } else @@ -1156,11 +1273,12 @@ uint8_t GC_ExecuteLine(char *line) { if(axis_words) { - for(idx = 0; idx < N_AXIS; idx++) // Axes indices are consistent, so loop may be used to save flash space. + for(idx = 0; idx < N_AXIS; idx++) { if(BIT_IS_FALSE(axis_words, BIT(idx))) { - gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position. + // No axis word in block. Keep same axis position. + gc_block.values.xyz[idx] = gc_state.position[idx]; } else { @@ -1174,7 +1292,7 @@ uint8_t GC_ExecuteLine(char *line) gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx]; //if(idx == TOOL_LENGTH_OFFSET_AXIS) { - gc_block.values.xyz[idx] += gc_state.tool_length_offset[idx]; + gc_block.values.xyz[idx] += gc_state.tool_length_offset_dynamic[idx] + gc_state.tool_length_offset[idx]; } } else @@ -1224,7 +1342,8 @@ uint8_t GC_ExecuteLine(char *line) } else { - axis_command = AXIS_COMMAND_NONE; // Set to none if no intermediate motion. + // Set to none if no intermediate motion. + axis_command = AXIS_COMMAND_NONE; } break; @@ -1243,7 +1362,8 @@ uint8_t GC_ExecuteLine(char *line) // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary. if(!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) { - return STATUS_GCODE_G53_INVALID_MOTION_MODE; // [G53 G0/1 not active] + // [G53 G0/1 not active] + return STATUS_GCODE_G53_INVALID_MOTION_MODE; } break; } @@ -1368,7 +1488,8 @@ uint8_t GC_ExecuteLine(char *line) break; case MOTION_MODE_CW_ARC: - gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional. + // No break intentional. + gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; case MOTION_MODE_CCW_ARC: // [G2/3 Errors All-Modes]: Feed rate undefined. @@ -1395,7 +1516,8 @@ uint8_t GC_ExecuteLine(char *line) x = gc_block.values.xyz[axis_0]-gc_state.position[axis_0]; // Delta x between current position and target y = gc_block.values.xyz[axis_1]-gc_state.position[axis_1]; // Delta y between current position and target - if(value_words & BIT(WORD_R)) // Arc Radius Mode + // Arc Radius Mode + if(value_words & BIT(WORD_R)) { BIT_FALSE(value_words, BIT(WORD_R)); if(isequal_position_vector(gc_state.position, gc_block.values.xyz)) @@ -1440,19 +1562,19 @@ uint8_t GC_ExecuteLine(char *line) Expanding the equations: - d -> sqrt(x^2 + y^2) - h -> sqrt(4 * r^2 - x^2 - y^2)/2 - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + d -> sqrtf(x^2 + y^2) + h -> sqrtf(4 * r^2 - x^2 - y^2)/2 + i -> (x - (y * sqrtf(4 * r^2 - x^2 - y^2)) / sqrtf(x^2 + y^2)) / 2 + j -> (y + (x * sqrtf(4 * r^2 - x^2 - y^2)) / sqrtf(x^2 + y^2)) / 2 Which can be written: - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + i -> (x - (y * sqrtf(4 * r^2 - x^2 - y^2))/sqrtf(x^2 + y^2))/2 + j -> (y + (x * sqrtf(4 * r^2 - x^2 - y^2))/sqrtf(x^2 + y^2))/2 Which we for size and speed reasons optimize to: - h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) + h_x2_div_d = sqrtf(4 * r^2 - x^2 - y^2)/sqrtf(x^2 + y^2) i = (x - (y * h_x2_div_d))/2 j = (y + (x * h_x2_div_d))/2 */ @@ -1468,7 +1590,8 @@ uint8_t GC_ExecuteLine(char *line) } // Finish computing h_x2_div_d. - h_x2_div_d = -sqrt(h_x2_div_d)/hypot_f(x,y); // == -(h * 2 / d) + //h_x2_div_d = -sqrtf(h_x2_div_d) / hypot_f(x,y); // == -(h * 2 / d) + h_x2_div_d = -sqrtf(h_x2_div_d) / hypotf(x, y); // == -(h * 2 / d) // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) if(gc_block.modal.motion == MOTION_MODE_CCW_ARC) { @@ -1494,7 +1617,7 @@ uint8_t GC_ExecuteLine(char *line) // even though it is advised against ever generating such circles in a single line of g-code. By // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of // travel and thus we get the unadvisably long arcs as prescribed. - if(gc_block.values.r < 0) + if(gc_block.values.r < 0.0) { h_x2_div_d = -h_x2_div_d; gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc @@ -1517,7 +1640,7 @@ uint8_t GC_ExecuteLine(char *line) // Convert IJK values to proper units. if(gc_block.modal.units == UNITS_MODE_INCHES) { - for(idx = 0; idx < N_LINEAR_AXIS; idx++) // Axes indices are consistent, so loop may be used to save flash space. + for(idx = 0; idx < N_LINEAR_AXIS; idx++) { if(ijk_words & BIT(idx)) { @@ -1530,13 +1653,15 @@ uint8_t GC_ExecuteLine(char *line) x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target - float target_r = hypot_f(x,y); + //float target_r = hypot_f(x,y); + float target_r = hypotf(x, y); // Compute arc radius for mc_arc. Defined from current location to center. - gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); + //gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); + gc_block.values.r = hypotf(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); // Compute difference between current location and target radii for final error-checks. - float delta_r = fabs(target_r-gc_block.values.r); + float delta_r = fabsf(target_r-gc_block.values.r); if(delta_r > 0.005) { if(delta_r > 0.5) @@ -1586,6 +1711,7 @@ uint8_t GC_ExecuteLine(char *line) case MOTION_MODE_DRILL_BREAK: if(BIT_TRUE(value_words, (BIT(WORD_L)))) { + // Optional } BIT_FALSE(value_words, BIT(WORD_L)); break; @@ -1630,7 +1756,7 @@ uint8_t GC_ExecuteLine(char *line) Planner_LineData_t *pl_data = &plan_data; memset(pl_data, 0, sizeof(Planner_LineData_t)); // Zero pl_data struct - if((settings.flags2 & BITFLAG_LATHE_MODE) && gc_block.modal.lathe_mode == LATHE_DIAMETER_MODE) + if ((BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) && gc_block.modal.lathe_mode == LATHE_DIAMETER_MODE) { gc_block.values.xyz[X_AXIS] /= 2.0; } @@ -1691,7 +1817,8 @@ uint8_t GC_ExecuteLine(char *line) { if (BIT_IS_TRUE(gc_parser_flags, GC_PARSER_LASER_DISABLE)) { - gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode. + // Change from G1/2/3 motion mode. + gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; } } else @@ -1709,7 +1836,8 @@ uint8_t GC_ExecuteLine(char *line) // [0. Non-specific/common error-checks and miscellaneous setup]: // NOTE: If no line number is present, the value is zero. gc_state.line_number = gc_block.values.n; - pl_data->line_number = gc_state.line_number; // Record data for planner use. + // Record data for planner use. + pl_data->line_number = gc_state.line_number; // [1. Comments feedback ]: NOT SUPPORTED @@ -1742,8 +1870,8 @@ uint8_t GC_ExecuteLine(char *line) } } } - - gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. + // Update spindle speed state. + gc_state.spindle_speed = gc_block.values.s; gc_state.modal.spindle_mode = SPINDLE_RPM_MODE; gc_state.spindle_limit = 0; } @@ -1790,6 +1918,51 @@ uint8_t GC_ExecuteLine(char *line) } } + // [Input Output Control ]: + if(io_cmd > 0) + { + uint8_t io_on = 0; + + switch (io_cmd) + { + case 62: + io_on = 1; + case 63: + // Syncronized + Protocol_BufferSynchronize(); + + if(io_on) + { + // Switch IO P on + } + else + { + // Switch IO P off + } + break; + + case 64: + io_on = 1; + case 65: + if(io_on) + { + // Switch IO P on + } + else + { + // Switch IO P off + } + break; + + case 66: + + break; + + default: + break; + } + } + // [7. Spindle control ]: if(gc_state.modal.spindle != gc_block.modal.spindle) { @@ -1800,7 +1973,8 @@ uint8_t GC_ExecuteLine(char *line) gc_state.modal.spindle = gc_block.modal.spindle; } - pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. + // Set condition flag for planner use. + pl_data->condition |= gc_state.modal.spindle; // [8. Coolant control ]: if (gc_state.modal.coolant != gc_block.modal.coolant) @@ -1810,7 +1984,8 @@ uint8_t GC_ExecuteLine(char *line) Coolant_Sync(gc_block.modal.coolant); gc_state.modal.coolant = gc_block.modal.coolant; } - pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use. + // Set condition flag for planner use. + pl_data->condition |= gc_state.modal.coolant; // [9. Override control ]: NOT SUPPORTED. Always enabled. Except for a Grbl-only parking control. #ifdef ENABLE_PARKING_OVERRIDE_CONTROL @@ -1846,11 +2021,16 @@ uint8_t GC_ExecuteLine(char *line) if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) // G49 { gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0; + + for (uint8_t i = 0; i < N_AXIS; i++) + { + gc_state.tool_length_offset[i] = 0.0; + } } // G43.1 - if((update_tooltable == 0) && gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]) + if ((update_tooltable == 0) && gc_state.tool_length_offset_dynamic[TOOL_LENGTH_OFFSET_AXIS] != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]) { - gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]; + gc_state.tool_length_offset_dynamic[TOOL_LENGTH_OFFSET_AXIS] = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]; System_FlagWcoChange(); } // G43 @@ -1881,7 +2061,7 @@ uint8_t GC_ExecuteLine(char *line) switch(gc_block.non_modal_command) { case NON_MODAL_SET_COORDINATE_DATA: - Settings_WriteCoordData(coord_select,gc_block.values.ijk); + Settings_WriteCoordData(coord_select, gc_block.values.ijk); // Update system coordinate system if currently active. if(gc_state.modal.coord_select == coord_select) { @@ -1894,7 +2074,8 @@ uint8_t GC_ExecuteLine(char *line) case NON_MODAL_GO_HOME_1: // Move to intermediate position before going home. Obeys current coordinate system and offsets // and absolute and incremental modes. - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; if(axis_command) { MC_Line(gc_block.values.xyz, pl_data); @@ -1918,7 +2099,8 @@ uint8_t GC_ExecuteLine(char *line) break; case NON_MODAL_RESET_COORDINATE_OFFSET: - clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector. + // Disable G92 offsets by zeroing offset vector. + clear_vector(gc_state.coord_offset); System_FlagWcoChange(); break; } @@ -1939,7 +2121,8 @@ uint8_t GC_ExecuteLine(char *line) } else if(gc_state.modal.motion == MOTION_MODE_SEEK) { - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(gc_block.values.xyz, pl_data); } else if((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) @@ -1947,7 +2130,8 @@ uint8_t GC_ExecuteLine(char *line) MC_Arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r, axis_0, axis_1, axis_linear, BIT_IS_TRUE(gc_parser_flags, GC_PARSER_ARC_IS_CLOCKWISE)); } - else if (gc_state.modal.motion == MOTION_MODE_DRILL || gc_state.modal.motion == MOTION_MODE_DRILL_DWELL || gc_state.modal.motion == MOTION_MODE_DRILL_PECK || gc_state.modal.motion == MOTION_MODE_DRILL_BREAK) + else if (gc_state.modal.motion == MOTION_MODE_DRILL || gc_state.modal.motion == MOTION_MODE_DRILL_DWELL || + gc_state.modal.motion == MOTION_MODE_DRILL_PECK || gc_state.modal.motion == MOTION_MODE_DRILL_BREAK) { float xyz[N_AXIS] = {0.0}; float clear_z = gc_block.values.r + gc_state.coord_system[Z_AXIS] + gc_state.coord_offset[Z_AXIS]; @@ -1964,7 +2148,7 @@ uint8_t GC_ExecuteLine(char *line) } else { - clear_z += gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS]; + clear_z += gc_state.tool_length_offset_dynamic[TOOL_LENGTH_OFFSET_AXIS] + gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS]; } if(clear_z < gc_block.values.xyz[Z_AXIS]) @@ -1982,7 +2166,8 @@ uint8_t GC_ExecuteLine(char *line) memcpy(xyz, old_xyz, N_AXIS*sizeof(float)); xyz[Z_AXIS] = clear_z; - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); } else @@ -2002,19 +2187,22 @@ uint8_t GC_ExecuteLine(char *line) // 1. Rapid move to XY (XY) xyz[X_AXIS] = gc_block.values.xyz[X_AXIS] + (delta_x*repeat); xyz[Y_AXIS] = gc_block.values.xyz[Y_AXIS] + (delta_y*repeat); - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); // 2. Rapid move to R (Z) xyz[Z_AXIS] = clear_z; - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); if (gc_state.modal.motion == MOTION_MODE_DRILL || gc_state.modal.motion == MOTION_MODE_DRILL_DWELL) { //-- G81 -- G82 --// // 3. Move the Z-axis at the current feed rate to the Z position. - pl_data->condition &= ~PL_COND_FLAG_RAPID_MOTION; // Clear rapid move + // Clear rapid move + pl_data->condition &= ~PL_COND_FLAG_RAPID_MOTION; xyz[Z_AXIS] = gc_block.values.xyz[Z_AXIS]; MC_Line(xyz, pl_data); } @@ -2032,7 +2220,8 @@ uint8_t GC_ExecuteLine(char *line) } // Move the Z-axis at the current feed rate to the Z position. - pl_data->condition &= ~PL_COND_FLAG_RAPID_MOTION; // Clear rapid move + // Clear rapid move + pl_data->condition &= ~PL_COND_FLAG_RAPID_MOTION; xyz[Z_AXIS] = curr_z; MC_Line(xyz, pl_data); @@ -2040,14 +2229,16 @@ uint8_t GC_ExecuteLine(char *line) { // Rapid move to R xyz[Z_AXIS] = clear_z; - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); } else { // Back off a bit xyz[Z_AXIS] += 2; - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); } @@ -2056,7 +2247,8 @@ uint8_t GC_ExecuteLine(char *line) // Prepare next hole // Rapid move to bottom of hole (backed off a bit) xyz[Z_AXIS] = curr_z + 0.4; - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); } } @@ -2081,8 +2273,8 @@ uint8_t GC_ExecuteLine(char *line) // Retract to r xyz[Z_AXIS] = clear_z; } - - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; MC_Line(xyz, pl_data); } // Update position @@ -2108,7 +2300,7 @@ uint8_t GC_ExecuteLine(char *line) if(!isEqual_f(gc_block.values.xyz[X_AXIS], old_xyz[X_AXIS])) { // Also movement in X-axis - float f = sqrt(pow(gc_block.values.xyz[X_AXIS], 2.0) + pow(gc_block.values.ijk[Z_AXIS], 2.0)); + float f = sqrtf(powf(gc_block.values.xyz[X_AXIS], 2.0) + powf(gc_block.values.ijk[Z_AXIS], 2.0)); pl_data->feed_rate *= f; } @@ -2142,7 +2334,7 @@ uint8_t GC_ExecuteLine(char *line) uint16_t idx = 0; // Calculate z offset for angled slide compensation - float z_offset = doc * tan(angle*M_PI/180.0); + float z_offset = doc * tanf(angle*M_PI/180.0); // Wait till everything is finished @@ -2159,7 +2351,7 @@ uint8_t GC_ExecuteLine(char *line) if(!isEqual_f(gc_block.values.xyz[X_AXIS], old_xyz[X_AXIS])) { // Also movement in X-axis - float f = sqrt(pow(gc_block.values.xyz[X_AXIS], 2.0) + pow(pitch, 2.0)); + float f = sqrtf(powf(gc_block.values.xyz[X_AXIS], 2.0) + powf(pitch, 2.0)); pl_data->feed_rate *= f; } @@ -2279,11 +2471,13 @@ uint8_t GC_ExecuteLine(char *line) // in any intermediate location. if(gc_update_pos == GC_UPDATE_POS_TARGET) { - memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[] + // gc_state.position[] = gc_block.values.xyz[] + memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) { - GC_SyncPosition(); // gc_state.position[] = sys_position + // gc_state.position[] = sys_position + GC_SyncPosition(); } // == GC_UPDATE_POS_NONE } } @@ -2294,14 +2488,17 @@ uint8_t GC_ExecuteLine(char *line) gc_state.modal.program_flow = gc_block.modal.program_flow; if(gc_state.modal.program_flow) { - Protocol_BufferSynchronize(); // Sync and finish all remaining buffered motions before moving on. + // Sync and finish all remaining buffered motions before moving on. + Protocol_BufferSynchronize(); if(gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) { if(sys.state != STATE_CHECK_MODE) { - System_SetExecStateFlag(EXEC_FEED_HOLD); // Use feed hold for program pause. - Protocol_ExecuteRealtime(); // Execute suspend. + // Use feed hold for program pause. + System_SetExecStateFlag(EXEC_FEED_HOLD); + // Execute suspend. + Protocol_ExecuteRealtime(); } } else // == PROGRAM_FLOW_COMPLETED @@ -2339,8 +2536,8 @@ uint8_t GC_ExecuteLine(char *line) { return STATUS_SETTING_READ_FAIL; } - - System_FlagWcoChange(); // Set to refresh immediately just in case something altered. + // Set to refresh immediately just in case something altered. + System_FlagWcoChange(); Spindle_SetState(SPINDLE_DISABLE, 0.0); Coolant_SetState(COOLANT_DISABLE); } @@ -2349,8 +2546,8 @@ uint8_t GC_ExecuteLine(char *line) Report_FeedbackMessage(MESSAGE_PROGRAM_END); } - - gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow. + // Reset program flow. + gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; } // TODO: % to denote start of program. @@ -2362,12 +2559,10 @@ uint8_t GC_ExecuteLine(char *line) /* Not supported: - - Canned cycles - Tool radius compensation - Evaluation of expressions - Variables - Override control (TBD) - - Tool changes - Switches (*) Indicates optional parameter, enabled through config.h and re-compile diff --git a/grbl/GCode.h b/grbl/GCode.h index 258227b..eabf52f 100644 --- a/grbl/GCode.h +++ b/grbl/GCode.h @@ -50,6 +50,7 @@ #define MODAL_GROUP_G15 13 // [G7, G8] Lathe Diameter Mode #define MODAL_GROUP_M4 11 // [M0,M1,M2,M30] Stopping +#define MODAL_GROUP_M5 15 // [M62-M65] #define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning #define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control #define MODAL_GROUP_M9 14 // [M56] Override control @@ -142,17 +143,18 @@ // Modal Group G8: Tool length offset #define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero) #define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1 +#define TOOL_LENGTH_OFFSET_ENABLE 2 // G43 // Modal Group G12: Active work coordinate system // N/A: Stores coordinate system value (54-59) to change to. // Modal Group G12: Lathe Mode -#define LATHE_RADIUS_MODE 0 -#define LATHE_DIAMETER_MODE 1 +#define LATHE_RADIUS_MODE 0 // G8 (Default: Must be zero) +#define LATHE_DIAMETER_MODE 1 // G7 // Modal Group G14: Spindle Control Mode -#define SPINDLE_RPM_MODE 0 -#define SPINDLE_SURFACE_MODE 1 +#define SPINDLE_RPM_MODE 0 // G97 RPM (Default: Must be zero) +#define SPINDLE_SURFACE_MODE 1 // G96 CSS // Define parameter word mapping. @@ -234,16 +236,16 @@ typedef struct uint16_t d; uint8_t h; float e; - float f; // Feed - float ijk[N_AXIS]; // I,J,K Axis arc offsets - uint8_t l; // G10 or canned cycles parameters - int32_t n; // Line number - float p; // G10 or dwell parameters - float q; // G82 peck drilling - float r; // Arc radius - float s; // Spindle speed - uint8_t t; // Tool selection - float xyz[N_AXIS]; // X,Y,Z Translational axes + float f; // Feed + float ijk[N_AXIS]; // I,J,K Axis arc offsets + uint8_t l; // G10 or canned cycles parameters + int32_t n; // Line number + float p; // G10 or dwell parameters + float q; // G82 peck drilling + float r; // Arc radius + float s; // Spindle speed + uint8_t t; // Tool selection + float xyz[N_AXIS]; // X,Y,Z Translational axes } GC_Values_t; @@ -260,11 +262,12 @@ typedef struct float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine - // position in mm. Loaded from EEPROM when called. + // Position in mm. Loaded from EEPROM when called. float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to - // machine zero in mm. Non-persistent. Cleared upon reset and boot. - float tool_length_offset[N_AXIS]; // Tracks tool length offset value when enabled. + // Machine zero in mm. Non-persistent. Cleared upon reset and boot. + float tool_length_offset_dynamic[N_AXIS]; // Tracks tool length offset value when enabled. + float tool_length_offset[N_AXIS]; } Parser_State_t; @@ -284,8 +287,7 @@ void GC_Init(void); // Set g-code parser position. Input in steps. void GC_SyncPosition(void); -// Execute one block of rs275/ngc/g-code -uint8_t GC_ExecuteLine(char *line); - +// Execute one block of rs274/ngc/g-code +uint8_t GC_ExecuteLine(const char *line); #endif // GCODE_H diff --git a/grbl/Jog.c b/grbl/Jog.c index 10c5090..3d00bc9 100644 --- a/grbl/Jog.c +++ b/grbl/Jog.c @@ -28,7 +28,7 @@ // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. -uint8_t Jog_Execute(Planner_LineData_t *pl_data, Parser_Block_t *gc_block) +uint8_t Jog_Execute(Planner_LineData_t *pl_data, const Parser_Block_t *gc_block) { // Initialize planner data struct for jogging motions. // NOTE: Spindle and coolant are allowed to fully function with overrides during a jog. diff --git a/grbl/Jog.h b/grbl/Jog.h index a58046c..0459595 100644 --- a/grbl/Jog.h +++ b/grbl/Jog.h @@ -31,7 +31,7 @@ // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. -uint8_t Jog_Execute(Planner_LineData_t *pl_data, Parser_Block_t *gc_block); +uint8_t Jog_Execute(Planner_LineData_t *pl_data, const Parser_Block_t *gc_block); #endif // JOG_H diff --git a/grbl/Limits.c b/grbl/Limits.c index 1b3899d..fe3862e 100644 --- a/grbl/Limits.c +++ b/grbl/Limits.c @@ -29,7 +29,6 @@ #include "Protocol.h" #include "Limits.h" #include "GPIO.h" - #include "System32.h" @@ -49,6 +48,7 @@ void Limits_Init(void) // TODO: Hard limits via interrupt if(BIT_IS_TRUE(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)) { + // Enable hard limits settings.system_flags |= BITFLAG_ENABLE_LIMITS; } else @@ -58,9 +58,9 @@ void Limits_Init(void) } -// Disables hard limits. void Limits_Disable(void) { + // Disables hard limits. settings.system_flags &= ~BITFLAG_ENABLE_LIMITS; } @@ -72,11 +72,12 @@ uint8_t Limits_GetState(void) { uint8_t limit_state = 0; - limit_state = (GPIO_ReadInputDataBit(GPIO_LIM_X_PORT, GPIO_LIM_X_PIN)<feed_rate = homing_rate; // Set current homing rate. Planner_BufferLine(target, pl_data); // Bypass mc_line(). Directly plan homing motion. - sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags. - Stepper_PrepareBuffer(); // Prep and fill segment buffer from newly planned block. - Stepper_WakeUp(); // Initiate motion + // Set to execute homing motion and clear existing flags. + sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; + // Prep and fill segment buffer from newly planned block. + Stepper_PrepareBuffer(); + // Initiate motion + Stepper_WakeUp(); do { @@ -297,7 +306,8 @@ void Limits_GoHome(uint8_t cycle_mask) sys.homing_axis_lock = axislock; } - Stepper_PrepareBuffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us. + // Check and prep segment buffer. NOTE: Should take no longer than 200us. + Stepper_PrepareBuffer(); // Exit routines: No time to run protocol_execute_realtime() in this loop. if(sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) @@ -326,7 +336,8 @@ void Limits_GoHome(uint8_t cycle_mask) } if(sys_rt_exec_alarm) { - MC_Reset(); // Stop motors, if they are running. + // Stop motors, if they are running. + MC_Reset(); Protocol_ExecuteRealtime(); return; @@ -342,8 +353,10 @@ void Limits_GoHome(uint8_t cycle_mask) } while(0x3F & axislock); - Stepper_Reset(); // Immediately force kill steppers and reset step segment buffer. - Delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate. + // Immediately force kill steppers and reset step segment buffer. + Stepper_Reset(); + // Delay to allow transient dynamics to dissipate. + Delay_ms(settings.homing_debounce_delay); // Reverse direction and reset homing rate for locate cycle(s). approach = !approach; @@ -369,26 +382,28 @@ void Limits_GoHome(uint8_t cycle_mask) // set up pull-off maneuver from axes limit switches that have been homed. This provides // some initial clearance off the switches and should also help prevent them from falsely // triggering when hard limits are enabled or when more than one axes shares a limit pin. - int32_t set_axis_position; + int32_t set_axis_position = 0; // Set machine positions for homed limit switches. Don't update non-homed axes. - for(idx = 0; idx < N_AXIS; idx++) + for (idx = 0; idx < N_AXIS; idx++) { // NOTE: settings.max_travel[] is stored as a negative value. - if(cycle_mask & BIT(idx)) + if (cycle_mask & BIT(idx)) { -#ifdef HOMING_FORCE_SET_ORIGIN - set_axis_position = 0; -#else - if(BIT_IS_TRUE(settings.homing_dir_mask, BIT(idx))) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_FORCE_SET_ORIGIN)) { - set_axis_position = lround((settings.max_travel[idx]+settings.homing_pulloff)*settings.steps_per_mm[idx]); + set_axis_position = 0; } else { - set_axis_position = lround(-settings.homing_pulloff*settings.steps_per_mm[idx]); + if (BIT_IS_TRUE(settings.homing_dir_mask, BIT(idx))) + { + set_axis_position = lroundf((settings.max_travel[idx] + settings.homing_pulloff) * settings.steps_per_mm[idx]); + } + else + { + set_axis_position = lroundf(-settings.homing_pulloff * settings.steps_per_mm[idx]); + } } -#endif - #ifdef COREXY if(idx == X_AXIS) { @@ -409,22 +424,23 @@ void Limits_GoHome(uint8_t cycle_mask) #else sys_position[idx] = set_axis_position; #endif - } } // Necessary for backlash compensation MC_Init(); - sys.step_control = STEP_CONTROL_NORMAL_OP; // Return step control to normal operation. - sys.is_homed = 1; // Machine is homed and knows its position + // Return step control to normal operation. + sys.step_control = STEP_CONTROL_NORMAL_OP; + // Machine is homed and knows its position + sys.is_homed = 1; } // Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed, // the workspace volume is in all negative space, and the system is in normal operation. // NOTE: Used by jogging to limit travel within soft-limit volume. -void Limits_SoftCheck(float *target) +void Limits_SoftCheck(const float *target) { if(System_CheckTravelLimits(target)) { @@ -448,10 +464,11 @@ void Limits_SoftCheck(float *target) while(sys.state != STATE_IDLE); } - MC_Reset(); // Issue system reset and ensure spindle and coolant are shutdown. - System_SetExecAlarm(EXEC_ALARM_SOFT_LIMIT); // Indicate soft limit critical event - Protocol_ExecuteRealtime(); // Execute to enter critical event loop and system abort - - return; + // Issue system reset and ensure spindle and coolant are shutdown. + MC_Reset(); + // Indicate soft limit critical event + System_SetExecAlarm(EXEC_ALARM_SOFT_LIMIT); + // Execute to enter critical event loop and system abort + Protocol_ExecuteRealtime(); } } diff --git a/grbl/Limits.h b/grbl/Limits.h index 52058fd..ae52718 100644 --- a/grbl/Limits.h +++ b/grbl/Limits.h @@ -40,7 +40,7 @@ void Limit_PinChangeISR(void); void Limits_GoHome(uint8_t cycle_mask); // Check for soft limit violations -void Limits_SoftCheck(float *target); +void Limits_SoftCheck(const float *target); #endif // LIMITS_H diff --git a/grbl/MotionControl.c b/grbl/MotionControl.c index 34f49dc..16cf893 100644 --- a/grbl/MotionControl.c +++ b/grbl/MotionControl.c @@ -36,6 +36,7 @@ #include "defaults.h" #include "PID.h" #include "Encoder.h" +#include "Print.h" #define DIR_POSITIV 0 @@ -104,16 +105,16 @@ void MC_SyncBacklashPosition(void) // segments, must pass through this routine before being passed to the planner. The seperation of // mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being // in the planner and to let backlash compensation or canned cycle integration simple and direct. -void MC_Line(float *target, Planner_LineData_t *pl_data) +void MC_Line(const float *target, const Planner_LineData_t *pl_data) { - Planner_LineData_t pl_backlash = {0}; - uint8_t backlash_update = 0; + //uint8_t backlash_update = 0; + float target_new[N_AXIS] = {}; + Planner_LineData_t pl_data_new; + memcpy(target_new, target, sizeof(float)*N_AXIS); + memcpy(&pl_data_new, pl_data, sizeof(Planner_LineData_t)); - pl_backlash.spindle_speed = pl_data->spindle_speed; - pl_backlash.line_number = pl_data->line_number; - pl_backlash.feed_rate = pl_data->feed_rate; - + pl_data_new.backlash_motion = 0; // If enabled, check for soft limit violations. Placed here all line motions are picked up // from everywhere in Grbl. @@ -170,90 +171,119 @@ void MC_Line(float *target, Planner_LineData_t *pl_data) } } while(1); -#ifdef ENABLE_BACKLASH_COMPENSATION - pl_backlash.backlash_motion = 1; - pl_backlash.condition = pl_data->condition | PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. - - // Backlash compensation (not for A & B) - for(uint8_t i = 0; i < N_LINEAR_AXIS; i++) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_BACKLASH_COMP)) { - // Move positive? - if(target[i] > target_prev[i]) + float delta_prev[N_AXIS] = {}; + float vec_norm[N_AXIS] = {}; + + // Backlash compensation (not for A & B) + for (uint8_t i = 0; i < N_LINEAR_AXIS; i++) { - // Last move negative? - if(dir_negative[i] == DIR_NEGATIV) + delta_prev[i] = target[i] - target_prev[i]; + vec_norm[i] = 0.0; + pl_data_new.backlash[i] = 0.0; + + // Move positive? + if (target[i] > target_prev[i]) { - dir_negative[i] = DIR_POSITIV; - target_prev[i] += settings.backlash[i]; + // Last move negative? + if (dir_negative[i] == DIR_NEGATIV) + { + dir_negative[i] = DIR_POSITIV; + target_new[i] += settings.backlash[i]; + vec_norm[i] = settings.backlash[i]; + pl_data_new.backlash[i] = -settings.backlash[i]; + current_backlash[i] += settings.backlash[i] * settings.steps_per_mm[i]; - backlash_update = 1; + pl_data_new.backlash_motion |= BIT(i); + } } - } - // Move negative? - else if(target[i] < target_prev[i]) - { - // Last move positive? - if(dir_negative[i] == DIR_POSITIV) + // Move negative? + else if (target[i] < target_prev[i]) { - dir_negative[i] = DIR_NEGATIV; - target_prev[i] -= settings.backlash[i]; + // Last move positive? + if (dir_negative[i] == DIR_POSITIV) + { + dir_negative[i] = DIR_NEGATIV; + target_new[i] -= settings.backlash[i]; + vec_norm[i] = -settings.backlash[i]; + pl_data_new.backlash[i] = settings.backlash[i]; + current_backlash[i] -= (settings.backlash[i] * settings.steps_per_mm[i]); - backlash_update = 1; + pl_data_new.backlash_motion |= BIT(i); + } } } - } - if(backlash_enable && backlash_update) - { - // Perform backlash move if necessary - Planner_BufferLine(target_prev, &pl_backlash); - } + if (backlash_enable && pl_data_new.backlash_motion) + { + float vec_len = sqrtf(powf(delta_prev[X_AXIS], 2.0) + powf(delta_prev[Y_AXIS], 2.0) + powf(delta_prev[Z_AXIS], 2.0)); - memcpy(target_prev, target, N_AXIS*sizeof(float)); + pl_data_new.feed_rate *= 1.1; - // Backlash move needs a slot in planner buffer, so we have to check again, if planner is free - do - { - Protocol_ExecuteRealtime(); // Check for any run-time commands + // Normalize target vector and reduce to a length of 0.1 and add it to previous target + for (uint8_t i = 0; i < N_LINEAR_AXIS; i++) + { + vec_norm[i] += ((delta_prev[i] / vec_len) / 10.0) + target_prev[i]; + } - if(sys.abort) - { - // Bail, if system abort. - return; + // Perform backlash move if necessary + if (vec_len > 0.1) + { + Planner_BufferLine(vec_norm, &pl_data_new); + pl_data_new.backlash_motion = 0; + } } - if(Planner_CheckBufferFull()) - { - // Auto-cycle start when buffer is full. - Protocol_AutoCycleStart(); - } - else + // Save target for next function call + memcpy(target_prev, target, N_AXIS*sizeof(float)); + + // Backlash move needs a slot in planner buffer, so we have to check again, if planner is free + do { - break; - } - } while(1); -#else - (void)backlash_update; - (void)pl_backlash; -#endif + Protocol_ExecuteRealtime(); // Check for any run-time commands + + if (sys.abort) + { + // Bail, if system abort. + return; + } + + if (Planner_CheckBufferFull()) + { + // Auto-cycle start when buffer is full. + Protocol_AutoCycleStart(); + } + else + { + break; + } + } while(1); + } + + if(pl_data_new.backlash_motion != 0) + { + Planner_BufferLine(target_new, &pl_data_new); + return; + } // Plan and queue motion into planner buffer - if(Planner_BufferLine(target, pl_data) == PLAN_EMPTY_BLOCK) + if (Planner_BufferLine(target, &pl_data_new) == PLAN_EMPTY_BLOCK) { if(BIT_IS_TRUE(settings.flags, BITFLAG_LASER_MODE)) { // Correctly set spindle state, if there is a coincident position passed. Forces a buffer // sync while in M3 laser mode only. - if(pl_data->condition & PL_COND_FLAG_SPINDLE_CW) + if (pl_data_new.condition & PL_COND_FLAG_SPINDLE_CW) { - Spindle_Sync(PL_COND_FLAG_SPINDLE_CW, pl_data->spindle_speed); + Spindle_Sync(PL_COND_FLAG_SPINDLE_CW, pl_data_new.spindle_speed); } } } } -void MC_LineSync(float *target, Planner_LineData_t *pl_data, float pitch) +void MC_LineSync(const float *target, const Planner_LineData_t *pl_data, float pitch) { uint8_t old_f_override = sys.f_override; @@ -369,7 +399,7 @@ void MC_UpdateSyncMove(void) EncValue += cnt_diff; // Calculate revolutions since start - float rev_actual = (float)EncValue / PULSES_PER_REV; + float rev_actual = (float)EncValue / settings.enc_ppr; // Distance since start float dist_expected = rev_actual * sync_pitch; @@ -396,8 +426,15 @@ void MC_UpdateSyncMove(void) // The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance // of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal // distance from segment to the circle when the end points both lie on the circle. -void MC_Arc(float *target, Planner_LineData_t *pl_data, float *position, float *offset, float radius, - uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc) +void MC_Arc(const float *target, + Planner_LineData_t *pl_data, + float *position, + const float *offset, + float radius, + uint8_t axis_0, + uint8_t axis_1, + uint8_t axis_linear, + uint8_t is_clockwise_arc) { float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; @@ -427,8 +464,8 @@ void MC_Arc(float *target, Planner_LineData_t *pl_data, float *position, float * // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation. // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases. + radius += settings.arc_tolerance; uint16_t segments = floor(fabs(0.5*angular_travel*radius) / sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance))); - if(segments) { // Multiply inverse feed_rate to compensate for the fact that this movement is approximated @@ -476,14 +513,13 @@ void MC_Arc(float *target, Planner_LineData_t *pl_data, float *position, float * float sin_Ti; float cos_Ti; float r_axisi; - uint16_t i; uint8_t count = 0; - for(i = 1; i < segments; i++) // Increment (segments-1). + for (uint16_t i = 1; i < segments; i++) // Increment (segments-1). { if(count < N_ARC_CORRECTION) { - // Apply vector rotation matrix. ~40 usec + // Apply vector rotation matrix. ~180 nsec r_axisi = r_axis0*sin_T + r_axis1*cos_T; r_axis0 = r_axis0*cos_T - r_axis1*sin_T; r_axis1 = r_axisi; @@ -491,7 +527,7 @@ void MC_Arc(float *target, Planner_LineData_t *pl_data, float *position, float * } else { - // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec + // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~37 usec // Compute exact location by applying transformation matrix from initial radius vector(=-offset). cos_Ti = cos(i*theta_per_segment); sin_Ti = sin(i*theta_per_segment); @@ -601,7 +637,7 @@ void MC_HomigCycle(uint8_t cycle_mask) // Perform tool length probe cycle. Requires probe switch. // NOTE: Upon probe failure, the program will be stopped and placed into ALARM state. -uint8_t MC_ProbeCycle(float *target, Planner_LineData_t *pl_data, uint8_t parser_flags) +uint8_t MC_ProbeCycle(const float *target, const Planner_LineData_t *pl_data, uint8_t parser_flags) { // TODO: Need to update this cycle so it obeys a non-auto cycle start. if(sys.state == STATE_CHECK_MODE) @@ -719,7 +755,7 @@ void MC_OverrideCtrlUpdate(uint8_t override_state) // Plans and executes the single special motion case for parking. Independent of main planner buffer. // NOTE: Uses the always free planner ring buffer head to store motion parameters for execution. #ifdef PARKING_ENABLE -void MC_ParkingMotion(float *parking_target, Planner_LineData_t *pl_data) +void MC_ParkingMotion(const float *parking_target, const Planner_LineData_t *pl_data) { if(sys.abort) { diff --git a/grbl/MotionControl.h b/grbl/MotionControl.h index edc03db..841b47a 100644 --- a/grbl/MotionControl.h +++ b/grbl/MotionControl.h @@ -44,9 +44,9 @@ void MC_SyncBacklashPosition(void); // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in // (1 minute)/feed_rate time. -void MC_Line(float *target, Planner_LineData_t *pl_data); +void MC_Line(const float *target, const Planner_LineData_t *pl_data); -void MC_LineSync(float *target, Planner_LineData_t *pl_data, float pitch); +void MC_LineSync(const float *target, const Planner_LineData_t *pl_data, float pitch); void MC_LineSyncStart(void); @@ -56,7 +56,7 @@ void MC_UpdateSyncMove(void); // offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is // the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used // for vector transformation direction. -void MC_Arc(float *target, Planner_LineData_t *pl_data, float *position, float *offset, float radius, +void MC_Arc(const float *target, Planner_LineData_t *pl_data, float *position, const float *offset, const float radius, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc); // Dwell for a specific number of seconds @@ -66,13 +66,13 @@ void MC_Dwell(float seconds); void MC_HomigCycle(uint8_t cycle_mask); // Perform tool length probe cycle. Requires probe switch. -uint8_t MC_ProbeCycle(float *target, Planner_LineData_t *pl_data, uint8_t parser_flags); +uint8_t MC_ProbeCycle(const float *target, const Planner_LineData_t *pl_data, uint8_t parser_flags); // Handles updating the override control state. void MC_OverrideCtrlUpdate(uint8_t override_state); // Plans and executes the single special motion case for parking. Independent of main planner buffer. -void MC_ParkingMotion(float *parking_target, Planner_LineData_t *pl_data); +void MC_ParkingMotion(const float *parking_target, const Planner_LineData_t *pl_data); // Performs system reset. If in motion state, kills all motion and sets system alarm. void MC_Reset(void); diff --git a/grbl/Nvm.c b/grbl/Nvm.c index 30746cc..dce50d8 100644 --- a/grbl/Nvm.c +++ b/grbl/Nvm.c @@ -4,7 +4,7 @@ Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2019-2020 Patrick F. + Copyright (c) 2019-2024 Patrick F. Grbl-Advanced is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,59 +21,82 @@ */ #include "Nvm.h" #include "Config.h" -#include "eeprom.h" #include "M24C0X.h" +#include "System32.h" +#include "eeprom.h" void Nvm_Init(void) { -#ifdef USE_EXT_EEPROM +#if (USE_EXT_EEPROM) M24C0X_Init(); #else EE_Init(); #endif } + uint8_t Nvm_ReadByte(uint16_t Address) { -#ifdef USE_EXT_EEPROM +#if (USE_EXT_EEPROM) return M24C0X_ReadByte(Address); #else return EE_ReadByte(Address); #endif } + void Nvm_WriteByte(uint16_t Address, uint8_t Data) { -#ifdef USE_EXT_EEPROM - M24C0X_WriteByte(Address, Data); +#if (USE_EXT_EEPROM) + uint8_t ret = 1; + uint8_t timeout = 8; + + while (ret > 0 && timeout > 0) + { + ret = M24C0X_WriteByte(Address, Data); + timeout--; + Delay_ms(1); + } #else EE_WriteByte(Address, Data); #endif } + uint8_t Nvm_Read(uint8_t *DataOut, uint16_t Address, uint16_t size) { -#ifdef USE_EXT_EEPROM +#if (USE_EXT_EEPROM) return M24C0X_ReadByteArray(Address, DataOut, size); #else return EE_ReadByteArray(DataOut, Address, size); #endif } -uint8_t Nvm_Write(uint16_t Address, uint8_t *DataIn, uint16_t size) + +uint8_t Nvm_Write(uint16_t Address, const uint8_t *DataIn, uint16_t size) { -#ifdef USE_EXT_EEPROM - return M24C0X_WriteByteArray(Address, DataIn, size); +#if (USE_EXT_EEPROM) + uint8_t ret = 1; + uint8_t timeout = 8; + + while(ret > 0 && timeout > 0) + { + ret = M24C0X_WriteByteArray(Address, (uint8_t*)DataIn, size); + timeout--; + Delay_ms(1); + } + return ret; #else EE_WriteByteArray(Address, DataIn, size); return 0; #endif } + void Nvm_Update(void) { -#ifdef USE_EXT_EEPROM +#if (USE_EXT_EEPROM) // Do nothing #else EE_Program(); diff --git a/grbl/Nvm.h b/grbl/Nvm.h index 15c04d2..7c50326 100644 --- a/grbl/Nvm.h +++ b/grbl/Nvm.h @@ -36,7 +36,7 @@ uint8_t Nvm_ReadByte(uint16_t Address); void Nvm_WriteByte(uint16_t Address, uint8_t Data); uint8_t Nvm_Read(uint8_t *DataOut, uint16_t Address, uint16_t size); -uint8_t Nvm_Write(uint16_t Address, uint8_t *DataIn, uint16_t size); +uint8_t Nvm_Write(uint16_t Address, const uint8_t *DataIn, uint16_t size); void Nvm_Update(void); diff --git a/grbl/Planner.c b/grbl/Planner.c index a6c4c99..d17eca5 100644 --- a/grbl/Planner.c +++ b/grbl/Planner.c @@ -28,6 +28,7 @@ #include "Settings.h" #include "Stepper.h" #include "Planner.h" +#include "Print.h" // Define planner variables @@ -90,7 +91,7 @@ void Planner_ResetBuffer(void) head. It avoids changing the planner state and preserves the buffer to ensure subsequent gcode motions are still planned correctly, while the stepper module only points to the block buffer head to execute the special system motion. */ -uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) +uint8_t Planner_BufferLine(const float *target, const Planner_LineData_t *pl_data) { // Prepare and initialize new block. Copy relevant pl_data for block execution. Planner_Block_t *block = &block_buffer[block_buffer_head]; @@ -103,6 +104,8 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) // Compute and store initial move distance data. int32_t target_steps[N_AXIS], position_steps[N_AXIS]; float unit_vec[N_AXIS], delta_mm; + int32_t target_steps_orig[N_AXIS]; + float unit_vec_orig[N_AXIS], delta_mm_orig; uint8_t idx; // Copy position data based on type of motion being planned. @@ -124,8 +127,8 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) } #ifdef COREXY - target_steps[A_MOTOR] = lround(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]); - target_steps[B_MOTOR] = lround(target[B_MOTOR]*settings.steps_per_mm[B_MOTOR]); + target_steps[A_MOTOR] = lroundf(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]); + target_steps[B_MOTOR] = lroundf(target[B_MOTOR]*settings.steps_per_mm[B_MOTOR]); block->steps[A_MOTOR] = labs((target_steps[X_AXIS]-position_steps[X_AXIS]) + (target_steps[Y_AXIS]-position_steps[Y_AXIS])); block->steps[B_MOTOR] = labs((target_steps[X_AXIS]-position_steps[X_AXIS]) - (target_steps[Y_AXIS]-position_steps[Y_AXIS])); #endif @@ -138,7 +141,7 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) #ifdef COREXY if(!(idx == A_MOTOR) && !(idx == B_MOTOR)) { - target_steps[idx] = lround(target[idx]*settings.steps_per_mm[idx]); + target_steps[idx] = lroundf(target[idx]*settings.steps_per_mm[idx]); block->steps[idx] = labs(target_steps[idx]-position_steps[idx]); } @@ -157,12 +160,15 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) delta_mm = (target_steps[idx] - position_steps[idx])/settings.steps_per_mm[idx]; } #else - target_steps[idx] = lround(target[idx]*settings.steps_per_mm[idx]); + target_steps[idx] = lroundf(target[idx]*settings.steps_per_mm[idx]); + target_steps_orig[idx] = lroundf((target[idx] + pl_data->backlash[idx]) * settings.steps_per_mm[idx]); block->steps[idx] = labs(target_steps[idx]-position_steps[idx]); block->step_event_count = max(block->step_event_count, block->steps[idx]); delta_mm = (target_steps[idx] - position_steps[idx])/settings.steps_per_mm[idx]; + delta_mm_orig = (target_steps_orig[idx] - position_steps[idx]) / settings.steps_per_mm[idx]; #endif unit_vec[idx] = delta_mm; // Store unit vector numerator + unit_vec_orig[idx] = delta_mm_orig; // Set direction bits. Bit enabled always means direction is negative. if(delta_mm < 0.0) @@ -256,7 +262,7 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) { convert_delta_vector_to_unit_vector(junction_unit_vec); float junction_acceleration = limit_value_by_axis_maximum(settings.acceleration, junction_unit_vec); - float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive. + float sin_theta_d2 = sqrtf(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive. block->max_junction_speed_sqr = max(MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED, (junction_acceleration * settings.junction_deviation * sin_theta_d2)/(1.0-sin_theta_d2)); } @@ -277,6 +283,12 @@ uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data) memcpy(planner.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[] memcpy(planner.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[] } + else + { + // Update previous path unit_vector and planner position. + memcpy(planner.previous_unit_vec, unit_vec_orig, sizeof(unit_vec_orig)); // pl.previous_unit_vec[] = unit_vec[] + memcpy(planner.position, target_steps_orig, sizeof(target_steps_orig)); // pl.position[] = target_steps[] + } // New block is all set. Update buffer head and next buffer head indices. block_buffer_head = next_buffer_head; @@ -354,7 +366,7 @@ float Planner_GetExecBlockExitSpeedSqr(void) // Computes and returns block nominal speed based on running condition and override values. // NOTE: All system motion commands, such as homing/parking, are not subject to overrides. -float Planner_ComputeProfileNominalSpeed(Planner_Block_t *block) +float Planner_ComputeProfileNominalSpeed(const Planner_Block_t *block) { float nominal_speed = block->programmed_rate; diff --git a/grbl/Planner.h b/grbl/Planner.h index ba7ec0b..b3f129e 100644 --- a/grbl/Planner.h +++ b/grbl/Planner.h @@ -88,6 +88,7 @@ typedef struct int32_t line_number; // Desired line number to report when executing. uint8_t backlash_motion; + float backlash[N_AXIS]; } Planner_LineData_t; @@ -99,7 +100,7 @@ void Planner_ResetBuffer(void); // Reset buffer only. // Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position // in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. -uint8_t Planner_BufferLine(float *target, Planner_LineData_t *pl_data); +uint8_t Planner_BufferLine(const float *target, const Planner_LineData_t *pl_data); // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. @@ -118,7 +119,7 @@ uint8_t Planner_NextBlockIndex(uint8_t block_index); float Planner_GetExecBlockExitSpeedSqr(void); // Called by main program during planner calculations and step segment buffer during initialization. -float Planner_ComputeProfileNominalSpeed(Planner_Block_t *block); +float Planner_ComputeProfileNominalSpeed(const Planner_Block_t *block); // Re-calculates buffered motions profile parameters upon a motion-based override change. void Planner_UpdateVelocityProfileParams(void); diff --git a/grbl/Protocol.c b/grbl/Protocol.c index 8c982a7..9cbf652 100644 --- a/grbl/Protocol.c +++ b/grbl/Protocol.c @@ -34,9 +34,10 @@ #include "GrIP.h" #include "Platform.h" #include "ServerTCP.h" - #include "Print.h" +#include + // Line buffer size from the serial input stream to be executed. // NOTE: Not a problem except for extreme cases, but the line buffer size can be too small @@ -55,7 +56,7 @@ #define LINE_FLAG_COMMENT_SEMICOLON BIT(2) -static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. +static char line[LINE_BUFFER_SIZE] = {}; // Line to be executed. Zero-terminated. static void Protocol_ExecRtSuspend(void); extern void ProcessReceive(char c); @@ -65,16 +66,17 @@ extern void ProcessReceive(char c); void Protocol_MainLoop(void) { // Perform some machine checks to make sure everything is good to go. -#ifdef CHECK_LIMITS_AT_INIT - if(BIT_IS_TRUE(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)) + if (BIT_IS_TRUE(settings.flags, BITFLAG_CHECK_LIMITS_AT_INIT)) { - if(Limits_GetState()) + if (BIT_IS_TRUE(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)) { - sys.state = STATE_ALARM; // Ensure alarm state is active. - Report_FeedbackMessage(MESSAGE_CHECK_LIMITS); + if (Limits_GetState()) + { + sys.state = STATE_ALARM; // Ensure alarm state is active. + Report_FeedbackMessage(MESSAGE_CHECK_LIMITS); + } } } -#endif // Check for and report alarm state after a reset, error, or an initial power up. // NOTE: Sleep mode disables the stepper drivers and position can't be guaranteed. @@ -159,7 +161,7 @@ void Protocol_MainLoop(void) // Reset tracking data for next line. line_flags = 0; char_counter = 0; - + memset(line, 0, LINE_BUFFER_SIZE); } else { @@ -293,7 +295,8 @@ void Protocol_ExecuteRealtime(void) Protocol_ExecRtSystem(); -#ifdef ETH_IF +#if (USE_ETH_IF) + ServerTCP_Update(); GrIP_Update(); if(GrIP_Receive(&packet)) { @@ -302,7 +305,6 @@ void Protocol_ExecuteRealtime(void) ProcessReceive(packet.Data[i]); } } - ServerTCP_Update(); #else (void)packet; #endif @@ -711,40 +713,43 @@ void Protocol_ExecRtSystem(void) if((sys.state == STATE_IDLE) || (sys.state & (STATE_CYCLE | STATE_HOLD | STATE_JOG))) { uint8_t coolant_state = gc_state.modal.coolant; -#ifdef ENABLE_M7 - if(rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) { - if(coolant_state & COOLANT_MIST_ENABLE) + if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) { - BIT_FALSE(coolant_state,COOLANT_MIST_ENABLE); + if (coolant_state & COOLANT_MIST_ENABLE) + { + BIT_FALSE(coolant_state, COOLANT_MIST_ENABLE); + } + else + { + coolant_state |= COOLANT_MIST_ENABLE; + } } - else + + if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) { - coolant_state |= COOLANT_MIST_ENABLE; + if (coolant_state & COOLANT_FLOOD_ENABLE) + { + BIT_FALSE(coolant_state, COOLANT_FLOOD_ENABLE); + } + else + { + coolant_state |= COOLANT_FLOOD_ENABLE; + } } } - - if(rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) + else { - if(coolant_state & COOLANT_FLOOD_ENABLE) + if (coolant_state & COOLANT_FLOOD_ENABLE) { - BIT_FALSE(coolant_state,COOLANT_FLOOD_ENABLE); + BIT_FALSE(coolant_state, COOLANT_FLOOD_ENABLE); } else { coolant_state |= COOLANT_FLOOD_ENABLE; } } -#else - if(coolant_state & COOLANT_FLOOD_ENABLE) - { - BIT_FALSE(coolant_state,COOLANT_FLOOD_ENABLE); - } - else - { - coolant_state |= COOLANT_FLOOD_ENABLE; - } -#endif Coolant_SetState(coolant_state); // Report counter set in coolant_set_state(). gc_state.modal.coolant = coolant_state; } @@ -816,7 +821,7 @@ static void Protocol_ExecRtSuspend(void) return; } -#ifdef ETH_IF +#if (USE_ETH_IF) GrIP_Update(); if(GrIP_Receive(&packet)) { diff --git a/grbl/Report.c b/grbl/Report.c index d7b053b..f9b7684 100644 --- a/grbl/Report.c +++ b/grbl/Report.c @@ -3,7 +3,7 @@ Part of Grbl-Advanced Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC - Copyright (c) 2017-2020 Patrick F. + Copyright (c) 2017-2024 Patrick F. Grbl-Advanced is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,23 +47,22 @@ // Internal report utilities to reduce flash with repetitive tasks turned into functions. static void Report_SettingPrefix(uint8_t n) { - Putc('$'); + Printf("$"); Printf("%d", n); - Putc('='); + Printf("="); } static void Report_LineFeed(void) { - Putc('\r'); - Putc('\n'); + Printf("\r\n"); Printf_Flush(); } static void report_util_feedback_line_feed(void) { - Putc(']'); + Printf("]"); Report_LineFeed(); } @@ -85,8 +84,13 @@ static void Report_AxisValue(float *axis_value) uint8_t idx; uint8_t axis_num = N_LINEAR_AXIS; -#ifdef USE_MULTI_AXIS - axis_num = N_AXIS; + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_MULTI_AXIS)) + { + axis_num = N_AXIS; + } + +#ifdef GRBL_COMPATIBLE + axis_num = N_LINEAR_AXIS; #endif for(idx = 0; idx < axis_num; idx++) @@ -95,7 +99,7 @@ static void Report_AxisValue(float *axis_value) if(idx < (axis_num-1)) { - Putc(','); + Printf(","); } } } @@ -147,7 +151,8 @@ void Report_AlarmMessage(uint8_t alarm_code) Printf("%d", alarm_code); Report_LineFeed(); - Delay_ms(200); // Force delay to ensure message clears serial write buffer. + // Force delay to ensure message clears serial write buffer. + Delay_ms(100); } @@ -218,8 +223,11 @@ void Report_FeedbackMessage(uint8_t message_code) // Welcome message void Report_InitMessage(void) { - //Printf("\r\nGRBL-Advanced %s ['$' for help]\r\n", GRBL_VERSION); - Printf("\r\nGrbl %s [Advanced Edition | '$' for help]\r\n", GRBL_VERSION); +#ifdef GRBL_COMPATIBLE + Printf("\r\nGrbl 1.1h ['$' for help]\r\n"); +#else + Printf("\r\nGRBL %s [Advanced Edition | '$' for help]\r\n", GRBL_VERSION); +#endif Printf_Flush(); } @@ -227,8 +235,10 @@ void Report_InitMessage(void) // Grbl help message void Report_GrblHelp(void) { - Printf("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n"); + Printf("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H $T ~ ! ? ctrl-x ctrl-y ctrl-w]\r\n"); +#ifndef GRBL_COMPATIBLE Printf("[GRBL-Advanced by Schildkroet]\r\n"); +#endif Printf_Flush(); } @@ -250,6 +260,7 @@ void Report_GrblSettings(void) report_util_float_setting(12, settings.arc_tolerance, N_DECIMAL_SETTINGVALUE); report_util_uint8_setting(13, BIT_IS_TRUE(settings.flags, BITFLAG_REPORT_INCHES)); report_util_uint8_setting(14, settings.tool_change); + report_util_uint8_setting(15, settings.enc_ppr); report_util_uint8_setting(20, BIT_IS_TRUE(settings.flags, BITFLAG_SOFT_LIMIT_ENABLE)); report_util_uint8_setting(21, BIT_IS_TRUE(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)); report_util_uint8_setting(22, BIT_IS_TRUE(settings.flags, BITFLAG_HOMING_ENABLE)); @@ -261,18 +272,37 @@ void Report_GrblSettings(void) report_util_float_setting(30, settings.rpm_max, N_DECIMAL_RPMVALUE); report_util_float_setting(31, settings.rpm_min, N_DECIMAL_RPMVALUE); - report_util_uint8_setting(32, BIT_IS_TRUE(settings.flags,BITFLAG_LASER_MODE)); - report_util_uint8_setting(33, BIT_IS_TRUE(settings.flags2,BITFLAG_LATHE_MODE)); + report_util_uint8_setting(32, BIT_IS_TRUE(settings.flags, BITFLAG_LASER_MODE)); + + report_util_uint8_setting(33, BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)); + report_util_uint8_setting(34, BIT_IS_TRUE(settings.flags_ext, BITFLAG_BUFFER_SYNC_NVM_WRITE)); + report_util_uint8_setting(35, BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)); + report_util_uint8_setting(36, BIT_IS_TRUE(settings.flags_ext, BITFLAG_FORCE_HARD_LIMIT_CHECK)); + report_util_uint8_setting(37, BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_BACKLASH_COMP)); + report_util_uint8_setting(38, BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_MULTI_AXIS)); + report_util_uint8_setting(39, BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_INIT_LOCK)); + report_util_uint8_setting(40, BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_FORCE_SET_ORIGIN)); + report_util_uint8_setting(41, BIT_IS_TRUE(settings.flags_ext, BITFLAG_FORCE_INITIALIZATION_ALARM)); + report_util_uint8_setting(42, BIT_IS_TRUE(settings.flags_ext, BITFLAG_CHECK_LIMITS_AT_INIT)); - Delay_ms(5); + Delay_ms(1); // Print axis settings - uint8_t idx, set_idx; + uint8_t axis_num = N_LINEAR_AXIS; uint8_t val = AXIS_SETTINGS_START_VAL; - for(set_idx = 0; set_idx < AXIS_N_SETTINGS; set_idx++) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_MULTI_AXIS)) + { + axis_num = N_AXIS; + } + +#ifdef GRBL_COMPATIBLE + axis_num = N_LINEAR_AXIS; +#endif + + for (uint8_t set_idx = 0; set_idx < AXIS_N_SETTINGS; set_idx++) { - for(idx = 0; idx < N_AXIS; idx++) + for (uint8_t idx = 0; idx < axis_num; idx++) { switch(set_idx) { @@ -312,39 +342,47 @@ void Report_GrblSettings(void) // These values are retained until Grbl is power-cycled, whereby they will be re-zeroed. void Report_ProbeParams(void) { - float print_position[N_AXIS]; + float print_position[N_AXIS] = {}; // Report in terms of machine position. Printf("[PRB:"); System_ConvertArraySteps2Mpos(print_position, sys_probe_position); - Report_AxisValue(print_position); - Putc(':'); - Printf("%d", sys.probe_succeeded); + + // Report only linear axis + for (uint8_t idx = 0; idx < N_LINEAR_AXIS; idx++) + { + PrintFloat_CoordValue(print_position[idx]); + + if (idx < (N_LINEAR_AXIS - 1)) + { + Printf(","); + } + } + + Printf(":%d", sys.probe_succeeded); report_util_feedback_line_feed(); } void Report_TLSParams(void) { - float print_position[N_AXIS]; - uint8_t idx = 0; + float print_position[N_AXIS] = {}; // Report in terms of machine position. Printf("[TLS:"); System_ConvertArraySteps2Mpos(print_position, settings.tls_position); - for(idx = 0; idx < 3; idx++) + for (uint8_t idx = 0; idx < N_LINEAR_AXIS; idx++) { PrintFloat_CoordValue(print_position[idx]); - if(idx < (3-1)) + if (idx < (N_LINEAR_AXIS - 1)) { - Putc(','); + Printf(","); } } - Putc(':'); - Printf("%d", settings.tls_valid); + Printf(":%d", settings.tls_valid); report_util_feedback_line_feed(); } @@ -356,11 +394,11 @@ void Report_ToolParams(uint8_t tool_nr) TT_GetToolParams(tool_nr, ¶ms); PrintFloat_CoordValue(params.x_offset); - Putc(':'); + Printf(":"); PrintFloat_CoordValue(params.y_offset); - Putc(':'); + Printf(":"); PrintFloat_CoordValue(params.z_offset); - Putc(':'); + Printf(":"); PrintFloat_CoordValue(params.reserved); report_util_feedback_line_feed(); } @@ -394,31 +432,36 @@ void Report_NgcParams(void) break; default: + // G54-G59 Printf("%d", coord_select+54); - break; // G54-G59 + break; } - Putc(':'); + Printf(":"); Report_AxisValue(coord_data); report_util_feedback_line_feed(); } - Printf("[G92:"); // Print G92,G92.1 which are not persistent in memory + // Print G92,G92.1 which are not persistent in memory + Printf("[G92:"); Report_AxisValue(gc_state.coord_offset); report_util_feedback_line_feed(); - Printf("[TLO:"); // Print tool length offset value - for(uint8_t idx = 0; idx < N_AXIS; idx++) + // Print tool length offset value + Printf("[TLO:"); + for(uint8_t idx = 0; idx < N_LINEAR_AXIS; idx++) { - PrintFloat_CoordValue(gc_state.tool_length_offset[idx]); - if(idx < (N_AXIS-1)) + PrintFloat_CoordValue(gc_state.tool_length_offset_dynamic[idx] + gc_state.tool_length_offset[idx]); + if (idx < (N_LINEAR_AXIS - 1)) { Printf(","); } } report_util_feedback_line_feed(); - Report_ProbeParams(); // Print probe parameters. Not persistent in memory. - Report_TLSParams(); // Print tls position. Persistent in memory. + // Print probe parameters. Not persistent in memory. + Report_ProbeParams(); + // Print tls position. Persistent in memory. + Report_TLSParams(); Printf_Flush(); } @@ -464,7 +507,7 @@ void Report_GCodeModes(void) switch(gc_state.modal.program_flow) { case PROGRAM_FLOW_PAUSED: - Putc('0'); + Printf("0"); break; // case PROGRAM_FLOW_OPTIONAL_STOP : Putc('1'); break; // M1 is ignored and not supported. @@ -483,49 +526,40 @@ void Report_GCodeModes(void) switch(gc_state.modal.spindle) { case SPINDLE_ENABLE_CW: - Putc('3'); + Printf("3"); break; case SPINDLE_ENABLE_CCW: - Putc('4'); + Printf("4"); break; case SPINDLE_DISABLE: - Putc('5'); + Printf("5"); break; } -#ifdef ENABLE_M7 - if(gc_state.modal.coolant) // Note: Multiple coolant states may be active at the same time. + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) { - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) + // Note: Multiple coolant states may be active at the same time. + if (gc_state.modal.coolant) { - report_util_gcode_modes_M(); - Putc('7'); + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) + { + report_util_gcode_modes_M(); + Printf("7"); + } + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) + { + report_util_gcode_modes_M(); + Printf("8"); + } } - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) + else { report_util_gcode_modes_M(); - Putc('8'); + Printf("9"); } } - else - { - report_util_gcode_modes_M(); - Putc('9'); - } -#else - report_util_gcode_modes_M(); - - if(gc_state.modal.coolant) - { - Putc('8'); - } - else - { - Putc('9'); - } -#endif #ifdef ENABLE_PARKING_OVERRIDE_CONTROL if(sys.override_ctrl == OVERRIDE_PARKING_MOTION) @@ -542,110 +576,118 @@ void Report_GCodeModes(void) PrintFloat_RateValue(gc_state.feed_rate); Printf(" S"); - Printf_Float(gc_state.spindle_speed, N_DECIMAL_RPMVALUE); + //PrintFloat(gc_state.spindle_speed, N_DECIMAL_RPMVALUE); + Printf("%d", Spindle_GetRPM()); report_util_feedback_line_feed(); } // Prints specified startup line -void Report_StartupLine(uint8_t n, char *line) +void Report_StartupLine(uint8_t n, const char *line) { Printf("$N"); Printf("%d", n); - Putc('='); - Printf("%s", line); + Printf("=%s", line); Report_LineFeed(); } -void Report_ExecuteStartupMessage(char *line, uint8_t status_code) +void Report_ExecuteStartupMessage(const char *line, uint8_t status_code) { - Putc('>'); + Printf(">"); Printf("%s", line); - Putc(':'); + Printf(":"); Report_StatusMessage(status_code); } // Prints build info line -void Report_BuildInfo(char *line) +void Report_BuildInfo(const char *line) { - Printf("[VER: %s, %s:", GRBL_VERSION, GRBL_VERSION_BUILD); +#ifdef GRBL_COMPATIBLE + Printf("[VER: 1.1, %s: ", GRBL_VERSION_BUILD); +#else + Printf("[VER: %s, %s, GCC %s: ", GRBL_VERSION, GRBL_VERSION_BUILD, __VERSION__); +#endif Printf("%s", line); report_util_feedback_line_feed(); - Printf("[OPT:"); // Generate compile-time build option list - Putc('V'); - -//#ifdef USE_LINE_NUMBERS - Putc('N'); -//#endif -#ifdef ENABLE_M7 - Putc('M'); -#endif + Printf("[OPT:"); + Printf("V"); + Printf("N"); + + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_BUFFER_SYNC_NVM_WRITE)) + { + Printf("E"); + } + + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) + { + Printf("M"); + } + #ifdef COREXY - Putc('C'); + Printf("C"); #endif #ifdef PARKING_ENABLE - Putc('P'); -#endif -#ifdef HOMING_FORCE_SET_ORIGIN - Putc('Z'); + Printf("P"); #endif + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_FORCE_SET_ORIGIN)) + { + Printf("Z"); + } #ifdef HOMING_SINGLE_AXIS_COMMANDS - Putc('H'); + Printf("H"); #endif #ifdef LIMITS_TWO_SWITCHES_ON_AXES - Putc('T'); + Printf("T"); #endif #ifdef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES - Putc('A'); + Printf("A"); #endif #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED - Putc('0'); + Printf("0"); #endif #ifdef ENABLE_SOFTWARE_DEBOUNCE - Putc('S'); + Printf("S"); #endif #ifdef ENABLE_PARKING_OVERRIDE_CONTROL - Putc('R'); + Printf("R"); #endif #ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled. - Putc('*'); + Printf("*"); #endif #ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled. - Putc('$'); + Printf("$"); #endif #ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled. - Putc('#'); + Printf("#"); #endif #ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled. - Putc('I'); -#endif -#ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled. - Putc('E'); + Printf("I"); #endif #ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled. - Putc('W'); -#endif -#ifndef HOMING_INIT_LOCK - Putc('L'); + Printf("W"); #endif + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_INIT_LOCK)) + { + Printf("L"); + } #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - Putc('+'); -#endif -#ifdef USE_MULTI_AXIS - Putc('A'); -#endif -#ifdef LATHE_MODE - Putc('D'); + Printf("+"); #endif + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_MULTI_AXIS)) + { + Printf("X"); + } + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) + { + Printf("D"); + } // NOTE: Compiled values, like override increments/max/min values, may be added at some point later. - Putc(','); - Printf("%d", BLOCK_BUFFER_SIZE-1); - Putc(','); - Printf("%d", LINE_BUFFER_SIZE); + Printf(",%d", BLOCK_BUFFER_SIZE-1); + Printf(",%d", LINE_BUFFER_SIZE); report_util_feedback_line_feed(); } @@ -676,7 +718,8 @@ void Report_RealtimeStatus(void) System_ConvertArraySteps2Mpos(print_position, current_position); // Report current machine state and sub-states - Putc('<'); + // For better syncing purposes + Printf("<"); switch(sys.state) { @@ -695,12 +738,14 @@ void Report_RealtimeStatus(void) if(sys.suspend & SUSPEND_HOLD_COMPLETE) { - Putc('0'); - } // Ready to resume + // Ready to resume + Printf("0"); + } else { - Putc('1'); - } // Actively holding + // Actively holding + Printf("1"); + } break; } // Continues to print jog state during jog cancel. @@ -720,7 +765,8 @@ void Report_RealtimeStatus(void) Printf("Door:"); if (sys.suspend & SUSPEND_INITIATE_RESTORE) { - Putc('3'); // Restoring + // Restoring + Printf("3"); } else { @@ -728,16 +774,19 @@ void Report_RealtimeStatus(void) { if(sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { - Putc('1'); // Door ajar + // Door ajar + Printf("1"); } else { - Putc('0'); - } // Door closed and ready to resume + // Door closed and ready to resume + Printf("0"); + } } else { - Putc('2'); // Retracting + // Retracting + Printf("2"); } } break; @@ -754,19 +803,23 @@ void Report_RealtimeStatus(void) Printf("Tool"); break; + case STATE_BUSY: + Printf("Busy"); + break; + default: break; } float wco[N_AXIS]; - if(BIT_IS_FALSE(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE) || (sys.report_wco_counter == 0) ) + if(BIT_IS_FALSE(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE) || (sys.report_wco_counter == 0) ) { for (idx = 0; idx < N_AXIS; idx++) { // Apply work coordinate offsets and tool length offset to current position. wco[idx] = gc_state.coord_system[idx]+gc_state.coord_offset[idx]; - wco[idx] += gc_state.tool_length_offset[idx]; + wco[idx] += gc_state.tool_length_offset_dynamic[idx] + gc_state.tool_length_offset[idx]; if(BIT_IS_FALSE(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE)) { @@ -788,172 +841,175 @@ void Report_RealtimeStatus(void) Report_AxisValue(print_position); // Returns planner and serial read buffer states. -#ifdef REPORT_FIELD_BUFFER_STATE - if(BIT_IS_TRUE(settings.status_report_mask, BITFLAG_RT_STATUS_BUFFER_STATE)) + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_BUFFER_STATE)) { - Printf("|Bf:"); - Printf("%d", Planner_GetBlockBufferAvailable()); - Putc(','); - Printf("%d", FifoUsart_Available(STDOUT_NUM)); + if (BIT_IS_TRUE(settings.status_report_mask, BITFLAG_RT_STATUS_BUFFER_STATE)) + { + Printf("|Bf:%d,%d", Planner_GetBlockBufferAvailable(), FifoUsart_Available(STDOUT_NUM)); + } } -#endif -#ifdef REPORT_FIELD_LINE_NUMBERS - // Report current line number - Planner_Block_t * cur_block = Planner_GetCurrentBlock(); - if(cur_block != NULL) + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_LINE_NUMBERS)) { - uint32_t ln = cur_block->line_number; - - if(ln > 0) + // Report current line number + Planner_Block_t *cur_block = Planner_GetCurrentBlock(); + if (cur_block != NULL) { - Printf("|Ln:"); - Printf("%d", ln); + uint32_t ln = cur_block->line_number; + + if (ln > 0) + { + Printf("|Ln:%d", ln); + } } } -#endif // Report realtime feed speed -#ifdef REPORT_FIELD_CURRENT_FEED_SPEED - Printf("|FS:"); - PrintFloat_RateValue(Stepper_GetRealtimeRate()); - Putc(','); - Printf_Float(sys.spindle_speed, N_DECIMAL_RPMVALUE); -#endif - -#ifdef REPORT_FIELD_PIN_STATE - uint8_t lim_pin_state = Limits_GetState(); - uint8_t ctrl_pin_state = System_GetControlState(); - uint8_t prb_pin_state = Probe_GetState(); + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_CUR_FEED_SPEED)) + { + Printf("|FS:"); + PrintFloat_RateValue(Stepper_GetRealtimeRate()); + Printf(","); + Printf_Float(sys.spindle_speed, N_DECIMAL_RPMVALUE); + } - if(lim_pin_state | ctrl_pin_state | prb_pin_state) + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_PIN_STATE)) { - Printf("|Pn:"); - if(prb_pin_state) - { - Putc('P'); - } + uint8_t lim_pin_state = Limits_GetState(); + uint8_t ctrl_pin_state = System_GetControlState(); + uint8_t prb_pin_state = Probe_GetState(); - if(lim_pin_state) + if (lim_pin_state | ctrl_pin_state | prb_pin_state) { - if (BIT_IS_TRUE(lim_pin_state, BIT(X_AXIS))) - { - Putc('X'); - } - if (BIT_IS_TRUE(lim_pin_state, BIT(Y_AXIS))) - { - Putc('Y'); - } - if (BIT_IS_TRUE(lim_pin_state, BIT(Z_AXIS))) + Printf("|Pn:"); + if (prb_pin_state) { - Putc('Z'); + Printf("P"); } - } - if(ctrl_pin_state) - { - if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) - { - Putc('D'); - } - if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) + if (lim_pin_state) { - Putc('R'); - } - if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) - { - Putc('H'); + if (BIT_IS_TRUE(lim_pin_state, BIT(X_AXIS))) + { + Printf("X"); + } + if (BIT_IS_TRUE(lim_pin_state, BIT(Y_AXIS))) + { + Printf("Y"); + } + if (BIT_IS_TRUE(lim_pin_state, BIT(Z_AXIS))) + { + Printf("Z"); + } } - if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) + + if (ctrl_pin_state) { - Putc('S'); + if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) + { + Printf("D"); + } + if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) + { + Printf("R"); + } + if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) + { + Printf("H"); + } + if (BIT_IS_TRUE(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) + { + Printf("S"); + } } } } -#endif -#ifdef REPORT_FIELD_WORK_COORD_OFFSET - if(sys.report_wco_counter > 0) + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_WORK_COORD_OFFSET)) { - sys.report_wco_counter--; - } - else - { - if(sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) + if (sys.report_wco_counter > 0) { - sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh + sys.report_wco_counter--; } else { - sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT-1); - } + if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) + { + // Reset counter for slow refresh + sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT - 1); + } + else + { + sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT - 1); + } - if(sys.report_ovr_counter == 0) - { - sys.report_ovr_counter = 1; - } // Set override on next report. + if (sys.report_ovr_counter == 0) + { + // Set override on next report. + sys.report_ovr_counter = 1; + } - Printf("|WCO:"); - Report_AxisValue(wco); + Printf("|WCO:"); + Report_AxisValue(wco); + } } -#endif -#ifdef REPORT_FIELD_OVERRIDES - if(sys.report_ovr_counter > 0) + if (BIT_IS_TRUE(settings.flags_report, BITFLAG_REPORT_FIELD_OVERRIDES)) { - sys.report_ovr_counter--; - } - else - { - if(sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) + if (sys.report_ovr_counter > 0) { - sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh + sys.report_ovr_counter--; } else { - sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT-1); - } - - Printf("|Ov:"); - Printf("%d", sys.f_override); - Putc(','); - Printf("%d", sys.r_override); - Putc(','); - Printf("%d", sys.spindle_speed_ovr); + if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) + { + // Reset counter for slow refresh + sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT - 1); + } + else + { + sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); + } - uint8_t sp_state = Spindle_GetState(); - uint8_t cl_state = Coolant_GetState(); + Printf("|Ov:%d,%d,%d", sys.f_override, sys.r_override, sys.spindle_speed_ovr); - if(sp_state || cl_state) - { - Printf("|A:"); + uint8_t sp_state = Spindle_GetState(); + uint8_t cl_state = Coolant_GetState(); - if(sp_state) // != SPINDLE_STATE_DISABLE + if (sp_state || cl_state) { - if(sp_state == SPINDLE_STATE_CW) - { - Putc('S'); - } // CW - else + Printf("|A:"); + + if (sp_state) // != SPINDLE_STATE_DISABLE { - Putc('C'); - } // CCW - } + if (sp_state == SPINDLE_STATE_CW) + { + // CW + Printf("S"); + } + else + { + // CCW + Printf("C"); + } + } - if(cl_state & COOLANT_STATE_FLOOD) - { - Putc('F'); - } -#ifdef ENABLE_M7 - if(cl_state & COOLANT_STATE_MIST) - { - Putc('M'); + if (cl_state & COOLANT_STATE_FLOOD) + { + Printf("F"); + } + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_ENABLE_M7)) + { + if (cl_state & COOLANT_STATE_MIST) + { + Printf("M"); + } + } } -#endif } } -#endif - Putc('>'); + Printf(">"); Report_LineFeed(); } diff --git a/grbl/Report.h b/grbl/Report.h index 3ba75d4..7de0b39 100644 --- a/grbl/Report.h +++ b/grbl/Report.h @@ -66,6 +66,9 @@ #define STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR 37 #define STATUS_GCODE_MAX_VALUE_EXCEEDED 38 +#define STATUS_PROBE_ERROR 39 +#define STATUS_TOOLS_READ_FAIL 40 + // Define Grbl alarm codes. Valid values (1-255). 0 is reserved. #define ALARM_HARD_LIMIT_ERROR EXEC_ALARM_HARD_LIMIT #define ALARM_SOFT_LIMIT_ERROR EXEC_ALARM_SOFT_LIMIT @@ -132,12 +135,12 @@ void Report_NgcParams(void); void Report_GCodeModes(void); // Prints startup line when requested and executed. -void Report_StartupLine(uint8_t n, char *line); +void Report_StartupLine(uint8_t n, const char *line); -void Report_ExecuteStartupMessage(char *line, uint8_t status_code); +void Report_ExecuteStartupMessage(const char *line, uint8_t status_code); // Prints build info and user info -void Report_BuildInfo(char *line); +void Report_BuildInfo(const char *line); #endif // REPORT_H diff --git a/grbl/Settings.c b/grbl/Settings.c index e5b8d0e..ca9e070 100644 --- a/grbl/Settings.c +++ b/grbl/Settings.c @@ -4,7 +4,7 @@ Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2017-2020 Patrick F. + Copyright (c) 2017-2024 Patrick F. Grbl-Advanced is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,77 +19,54 @@ You should have received a copy of the GNU General Public License along with Grbl-Advanced. If not, see . */ +#include "Settings.h" +#include "CRC.h" #include "Config.h" #include "GCode.h" #include "Limits.h" -#include "Protocol.h" +#include "Nvm.h" #include "Probe.h" +#include "Protocol.h" #include "Report.h" -#include "Settings.h" #include "SpindleControl.h" -#include "System.h" #include "Stepper.h" +#include "System.h" #include "defaults.h" -#include "Nvm.h" -#include #include -Settings_t settings; - - -// Method to store startup lines into EEPROM -void Settings_StoreStartupLine(uint8_t n, char *line) -{ -#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE - Protocol_BufferSynchronize(); // A startup line may contain a motion and be executing. -#endif - - uint32_t addr = n*(STARTUP_LINE_LEN+1)+EEPROM_ADDR_STARTUP_BLOCK; - Nvm_Write(addr, (uint8_t*)line, STARTUP_LINE_LEN); - Nvm_Update(); -} +static void WriteGlobalSettings(void); +static uint8_t ReadGlobalSettings(void); -// Method to store build info into EEPROM -// NOTE: This function can only be called in IDLE state. -void Settings_StoreBuildInfo(char *line) -{ - // Build info can only be stored when state is IDLE. - Nvm_Write(EEPROM_ADDR_BUILD_INFO, (uint8_t*)line, STARTUP_LINE_LEN); - Nvm_Update(); -} +Settings_t settings; -// Method to store coord data parameters into EEPROM -void Settings_WriteCoordData(uint8_t coord_select, float *coord_data) +// Initialize the config subsystem +void Settings_Init(void) { -#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE - Protocol_BufferSynchronize(); -#endif - - uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; - Nvm_Write(addr, (uint8_t*)coord_data, sizeof(float)*N_AXIS); - - Nvm_Update(); -} - + Nvm_Init(); -// Method to store Grbl global settings struct and version number into EEPROM -// NOTE: This function can only be called in IDLE state. -void WriteGlobalSettings(void) -{ - Nvm_WriteByte(0, SETTINGS_VERSION); - Nvm_Write(EEPROM_ADDR_GLOBAL, (uint8_t*)&settings, sizeof(Settings_t)); + if (!ReadGlobalSettings()) + { + Report_StatusMessage(STATUS_SETTING_READ_FAIL); + // Force restore all EEPROM data. + Settings_Restore(SETTINGS_RESTORE_ALL); + Report_GrblSettings(); + } - Nvm_Update(); + // Read tool table + TT_Init(); } // Method to restore EEPROM-saved Grbl global settings back to defaults. void Settings_Restore(uint8_t restore_flag) { - if(restore_flag & SETTINGS_RESTORE_DEFAULTS) + sys.state = STATE_BUSY; + Report_RealtimeStatus(); + + if (restore_flag & SETTINGS_RESTORE_DEFAULTS) { settings.system_flags = DEFAULT_SYSTEM_INVERT_MASK; settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME; @@ -101,6 +78,7 @@ void Settings_Restore(uint8_t restore_flag) settings.rpm_max = DEFAULT_SPINDLE_RPM_MAX; settings.rpm_min = DEFAULT_SPINDLE_RPM_MIN; + settings.enc_ppr = DEFAULT_ENCODER_PULSES_PER_REV; settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK; settings.homing_feed_rate = DEFAULT_HOMING_FEED_RATE; @@ -110,44 +88,107 @@ void Settings_Restore(uint8_t restore_flag) // Flags settings.flags = 0; - if(DEFAULT_REPORT_INCHES) + if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; } - if(DEFAULT_LASER_MODE) + if (DEFAULT_LASER_MODE) { settings.flags |= BITFLAG_LASER_MODE; } - if(DEFAULT_INVERT_ST_ENABLE) + if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } - if(DEFAULT_HARD_LIMIT_ENABLE) + if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } - if(DEFAULT_HOMING_ENABLE) + if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; } - if(DEFAULT_SOFT_LIMIT_ENABLE) + if (DEFAULT_SOFT_LIMIT_ENABLE) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; } - if(DEFAULT_INVERT_LIMIT_PINS) + if (DEFAULT_INVERT_LIMIT_PINS) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; } - if(DEFAULT_INVERT_PROBE_PIN) + if (DEFAULT_INVERT_PROBE_PIN) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; } - // Flags2 - settings.flags2 = 0; - if(DEFAULT_LATHE_MODE) + // flags_ext + settings.flags_ext = 0; + if (DEFAULT_LATHE_MODE) + { + settings.flags_ext |= BITFLAG_LATHE_MODE; + } + if (BUFFER_SYNC_DURING_EEPROM_WRITE) + { + settings.flags_ext |= BITFLAG_BUFFER_SYNC_NVM_WRITE; + } + if (DEFAULT_ENABLE_M7) + { + settings.flags_ext |= BITFLAG_ENABLE_M7; + } + if (HARD_LIMIT_FORCE_STATE_CHECK) + { + settings.flags_ext |= BITFLAG_FORCE_HARD_LIMIT_CHECK; + } + if (ENABLE_BACKLASH_COMPENSATION) + { + settings.flags_ext |= BITFLAG_ENABLE_BACKLASH_COMP; + } + if (USE_MULTI_AXIS) + { + settings.flags_ext |= BITFLAG_ENABLE_MULTI_AXIS; + } + if (HOMING_INIT_LOCK) + { + settings.flags_ext |= BITFLAG_HOMING_INIT_LOCK; + } + if (HOMING_FORCE_SET_ORIGIN) + { + settings.flags_ext |= BITFLAG_HOMING_FORCE_SET_ORIGIN; + } + if (FORCE_INITIALIZATION_ALARM) + { + settings.flags_ext |= BITFLAG_FORCE_INITIALIZATION_ALARM; + } + if (CHECK_LIMITS_AT_INIT) + { + settings.flags_ext |= BITFLAG_CHECK_LIMITS_AT_INIT; + } + + // Flags report + settings.flags_report = 0; + if (DEFAULT_REPORT_FIELD_BUFFER_STATE) + { + settings.flags_report |= BITFLAG_REPORT_FIELD_BUFFER_STATE; + } + if (DEFAULT_REPORT_FIELD_PIN_STATE) + { + settings.flags_report |= BITFLAG_REPORT_FIELD_PIN_STATE; + } + if (DEFAULT_REPORT_FIELD_CURRENT_FEED_SPEED) + { + settings.flags_report |= BITFLAG_REPORT_FIELD_CUR_FEED_SPEED; + } + if (DEFAULT_REPORT_FIELD_WORK_COORD_OFFSET) + { + settings.flags_report |= BITFLAG_REPORT_FIELD_WORK_COORD_OFFSET; + } + if (DEFAULT_REPORT_FIELD_OVERRIDES) + { + settings.flags_report |= BITFLAG_REPORT_FIELD_OVERRIDES; + } + if (DEFAULT_REPORT_FIELD_LINE_NUMBERS) { - settings.flags2 |= BITFLAG_LATHE_MODE; + settings.flags_report |= BITFLAG_REPORT_FIELD_LINE_NUMBERS; } settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM; @@ -187,43 +228,101 @@ void Settings_Restore(uint8_t restore_flag) WriteGlobalSettings(); } - if(restore_flag & SETTINGS_RESTORE_PARAMETERS) + if (restore_flag & SETTINGS_RESTORE_PARAMETERS) { uint8_t idx; float coord_data[N_AXIS]; memset(&coord_data, 0, sizeof(coord_data)); - for(idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) + for (idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) { Settings_WriteCoordData(idx, coord_data); } + Nvm_Update(); } - if(restore_flag & SETTINGS_RESTORE_STARTUP_LINES) + if (restore_flag & SETTINGS_RESTORE_COORDS) { -#if N_STARTUP_LINE > 0 - Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK, 0); - Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK+1, 0); // Checksum -#endif -#if N_STARTUP_LINE > 1 - Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK+(STARTUP_LINE_LEN+1), 0); - Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK+(STARTUP_LINE_LEN+2), 0); // Checksum -#endif + float coord_data[N_AXIS]; + + memset(&coord_data, 0, sizeof(coord_data)); + + for (uint8_t idx = 0; idx < N_COORDINATE_SYSTEM; idx++) + { + Settings_WriteCoordData(idx, coord_data); + } Nvm_Update(); } - if(restore_flag & SETTINGS_RESTORE_BUILD_INFO) + if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) { - Nvm_WriteByte(EEPROM_ADDR_BUILD_INFO , 0); - Nvm_WriteByte(EEPROM_ADDR_BUILD_INFO+1 , 0); // Checksum + for (uint8_t i = 0; i < N_STARTUP_LINE; i++) + { + Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK + ((STARTUP_LINE_LEN + 1) * i), 0); + Nvm_WriteByte(EEPROM_ADDR_STARTUP_BLOCK + ((STARTUP_LINE_LEN + 1) * i + 1), 0); // Checksum + } + Nvm_Update(); } - if(restore_flag & SETTINGS_RESTORE_TOOLS) + if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) + { + Nvm_WriteByte(EEPROM_ADDR_BUILD_INFO, 0); + Nvm_WriteByte(EEPROM_ADDR_BUILD_INFO + 1, 0); // Checksum + Nvm_Update(); + } + + if (restore_flag & SETTINGS_RESTORE_TOOLS) { TT_Reset(); + Nvm_Update(); } + + sys.state = STATE_IDLE; +} + + +// Method to store startup lines into EEPROM +void Settings_StoreStartupLine(uint8_t n, const char *line) +{ + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_BUFFER_SYNC_NVM_WRITE)) + { + // A startup line may contain a motion and be executing. + Protocol_BufferSynchronize(); + } + + uint32_t addr = n*(STARTUP_LINE_LEN+1)+EEPROM_ADDR_STARTUP_BLOCK; + Nvm_Write(addr, (uint8_t*)line, STARTUP_LINE_LEN); + Nvm_Update(); +} + + +// Method to store build info into EEPROM +// NOTE: This function can only be called in IDLE state. +void Settings_StoreBuildInfo(const char *line) +{ + // Build info can only be stored when state is IDLE. + Nvm_Write(EEPROM_ADDR_BUILD_INFO, (uint8_t*)line, STARTUP_LINE_LEN); + Nvm_Update(); +} + + +// Method to store coord data parameters into EEPROM +void Settings_WriteCoordData(uint8_t coord_select, const float *coord_data) +{ + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_BUFFER_SYNC_NVM_WRITE)) + { + Protocol_BufferSynchronize(); + } + + uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; + Nvm_Write(addr, (uint8_t*)coord_data, sizeof(float)*N_AXIS); + + uint8_t crc = CRC_CalculateCRC8((const uint8_t *)coord_data, sizeof(float) * N_AXIS); + Nvm_WriteByte(addr + (sizeof(float) * N_AXIS), crc); + + Nvm_Update(); } @@ -234,7 +333,7 @@ uint8_t Settings_ReadStartupLine(uint8_t n, char *line) if(!(Nvm_Read((uint8_t*)line, addr, STARTUP_LINE_LEN))) { // Reset line with default value - line[0] = 0; // Empty line + line[0] = 0; Settings_StoreStartupLine(n, line); return false; @@ -244,16 +343,22 @@ uint8_t Settings_ReadStartupLine(uint8_t n, char *line) } -void Settings_StoreToolTable(ToolTable_t *table) +void Settings_StoreToolTable(const ToolTable_t *table) { Nvm_Write(EEPROM_ADDR_TOOLTABLE, (uint8_t*)table, sizeof(ToolTable_t)); + + uint8_t crc = CRC_CalculateCRC8((const uint8_t *)table, sizeof(ToolTable_t)); + Nvm_WriteByte(EEPROM_ADDR_TOOLTABLE_CRC, crc); } -void Settings_StoreToolParams(uint8_t tool_nr, ToolParams_t *params) +/*void Settings_StoreToolParams(uint8_t tool_nr, const ToolParams_t *params) { Nvm_Write(EEPROM_ADDR_TOOLTABLE+(tool_nr*sizeof(ToolParams_t)), (uint8_t*)params, sizeof(ToolParams_t)); -} + + uint8_t crc = CRC_CalculateCRC8((const uint8_t *)table, sizeof(ToolTable_t)); + Nvm_WriteByte(EEPROM_ADDR_TOOLTABLE_CRC, crc); +}*/ uint8_t Settings_ReadToolTable(ToolTable_t *table) @@ -262,6 +367,11 @@ uint8_t Settings_ReadToolTable(ToolTable_t *table) { return false; } + uint8_t crc = CRC_CalculateCRC8((const uint8_t *)table, sizeof(ToolTable_t)); + if (crc != Nvm_ReadByte(EEPROM_ADDR_TOOLTABLE_CRC)) + { + return false; + } return true; } @@ -273,7 +383,7 @@ uint8_t Settings_ReadBuildInfo(char *line) if(!(Nvm_Read((uint8_t*)line, EEPROM_ADDR_BUILD_INFO, STARTUP_LINE_LEN))) { // Reset line with default value - line[0] = 0; // Empty line + line[0] = 0; Settings_StoreBuildInfo(line); return false; @@ -290,31 +400,13 @@ uint8_t Settings_ReadCoordData(uint8_t coord_select, float *coord_data) if(!(Nvm_Read((uint8_t*)coord_data, addr, sizeof(float)*N_AXIS))) { // Reset with default zero vector - memset(&coord_data, 0.0, sizeof(coord_data)); + memset(coord_data, 0, sizeof(float) * N_AXIS); Settings_WriteCoordData(coord_select, coord_data); return false; } - - return true; -} - - -// Reads Grbl global settings struct from EEPROM. -uint8_t ReadGlobalSettings() -{ - // Check version-byte of eeprom - uint8_t version = Nvm_ReadByte(0); - - if(version == SETTINGS_VERSION) - { - // Read settings-record and check checksum - if(!(Nvm_Read((uint8_t*)&settings, EEPROM_ADDR_GLOBAL, sizeof(Settings_t)))) - { - return false; - } - } - else + uint8_t crc = CRC_CalculateCRC8((const uint8_t *)coord_data, sizeof(float)*N_AXIS); + if (crc != Nvm_ReadByte(addr + (sizeof(float) * N_AXIS))) { return false; } @@ -366,16 +458,19 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) break; case 2: + // Convert to mm/min^2 for grbl internal use. settings.acceleration[parameter] = value*60*60; - break; // Convert to mm/min^2 for grbl internal use. + break; case 3: + // Store as negative for grbl internal use. settings.max_travel[parameter] = -value; - break; // Store as negative for grbl internal use. + break; case 4: settings.backlash[parameter] = value; break; } - break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call. + // Exit while-loop after setting has been configured and proceed to the EEPROM write call. + break; } else { @@ -392,12 +487,12 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) else { // Store non-axis Grbl settings - uint8_t int_value = trunc(value); + uint8_t int_value = truncf(value); switch(parameter) { case 0: - //settings.system_flags = int_value; + settings.system_flags = int_value & CONTROL_MASK; break; case 1: @@ -406,12 +501,14 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) case 2: settings.step_invert_mask = int_value; - Stepper_GenerateStepDirInvertMasks(); // Regenerate step and direction port invert masks. + // Regenerate step and direction port invert masks. + Stepper_GenerateStepDirInvertMasks(); break; case 3: settings.dir_invert_mask = int_value; - Stepper_GenerateStepDirInvertMasks(); // Regenerate step and direction port invert masks. + // Regenerate step and direction port invert masks. + Stepper_GenerateStepDirInvertMasks(); break; case 4: // Reset to ensure change. Immediate re-init may cause problems. @@ -448,6 +545,10 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) Probe_ConfigureInvertMask(false); break; + case 7: + settings.flags_report = int_value; + break; + case 10: settings.status_report_mask = int_value; break; @@ -469,19 +570,25 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) { settings.flags &= ~BITFLAG_REPORT_INCHES; } - System_FlagWcoChange(); // Make sure WCO is immediately updated. + // Make sure WCO is immediately updated. + System_FlagWcoChange(); break; case 14: + // Check for range? settings.tool_change = int_value; - break; // Check for range? + break; + + case 15: + settings.enc_ppr = (uint16_t)value; + break; case 20: if (int_value) { if (BIT_IS_FALSE(settings.flags, BITFLAG_HOMING_ENABLE)) { - return(STATUS_SOFT_LIMIT_ERROR); + return (STATUS_SOFT_LIMIT_ERROR); } settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; } @@ -500,7 +607,8 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } - Limits_Init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. + // Re-init to immediately change. NOTE: Nice to have but could be problematic later. + Limits_Init(); break; case 22: @@ -511,33 +619,43 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) else { settings.flags &= ~BITFLAG_HOMING_ENABLE; - settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits. + // Force disable soft-limits. + settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } break; case 23: settings.homing_dir_mask = int_value; break; + case 24: settings.homing_feed_rate = value; break; + case 25: settings.homing_seek_rate = value; break; + case 26: settings.homing_debounce_delay = int_value; break; + case 27: settings.homing_pulloff = value; break; + case 30: settings.rpm_max = value; + // Re-initialize spindle rpm calibration Spindle_Init(); - break; // Re-initialize spindle rpm calibration + break; + case 31: settings.rpm_min = value; + // Re-initialize spindle rpm calibration Spindle_Init(); - break; // Re-initialize spindle rpm calibration + break; + case 32: if (int_value) { @@ -552,16 +670,115 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value) case 33: if (int_value) { - settings.flags2 |= BITFLAG_LATHE_MODE; + settings.flags_ext |= BITFLAG_LATHE_MODE; + } + else + { + settings.flags_ext &= ~BITFLAG_LATHE_MODE; + } + break; + + case 34: + if (int_value) + { + settings.flags_ext |= BITFLAG_BUFFER_SYNC_NVM_WRITE; + } + else + { + settings.flags_ext &= ~BITFLAG_BUFFER_SYNC_NVM_WRITE; + } + break; + + case 35: + if (int_value) + { + settings.flags_ext |= BITFLAG_ENABLE_M7; + } + else + { + settings.flags_ext &= ~BITFLAG_ENABLE_M7; + } + break; + + case 36: + if (int_value) + { + settings.flags_ext |= BITFLAG_FORCE_HARD_LIMIT_CHECK; + } + else + { + settings.flags_ext &= ~BITFLAG_FORCE_HARD_LIMIT_CHECK; + } + break; + + case 37: + if (int_value) + { + settings.flags_ext |= BITFLAG_ENABLE_BACKLASH_COMP; + } + else + { + settings.flags_ext &= ~BITFLAG_ENABLE_BACKLASH_COMP; + } + break; + + case 38: + if (int_value) + { + settings.flags_ext |= BITFLAG_ENABLE_MULTI_AXIS; + } + else + { + settings.flags_ext &= ~BITFLAG_ENABLE_MULTI_AXIS; + } + break; + + case 39: + if (int_value) + { + settings.flags_ext |= BITFLAG_HOMING_INIT_LOCK; + } + else + { + settings.flags_ext &= ~BITFLAG_HOMING_INIT_LOCK; + } + break; + + case 40: + if (int_value) + { + settings.flags_ext |= BITFLAG_HOMING_FORCE_SET_ORIGIN; + } + else + { + settings.flags_ext &= ~BITFLAG_HOMING_FORCE_SET_ORIGIN; + } + break; + + case 41: + if (int_value) + { + settings.flags_ext |= BITFLAG_FORCE_INITIALIZATION_ALARM; + } + else + { + settings.flags_ext &= ~BITFLAG_FORCE_INITIALIZATION_ALARM; + } + break; + + case 42: + if (int_value) + { + settings.flags_ext |= BITFLAG_CHECK_LIMITS_AT_INIT; } else { - settings.flags2 &= ~BITFLAG_LATHE_MODE; + settings.flags_ext &= ~BITFLAG_CHECK_LIMITS_AT_INIT; } break; default: - return(STATUS_INVALID_STATEMENT); + return (STATUS_INVALID_STATEMENT); } } @@ -580,23 +797,6 @@ void Settings_StoreTlsPosition(void) } -// Initialize the config subsystem -void Settings_Init(void) -{ - Nvm_Init(); - - if(!ReadGlobalSettings()) - { - Report_StatusMessage(STATUS_SETTING_READ_FAIL); - Settings_Restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data. - Report_GrblSettings(); - } - - // Read tool table - TT_Init(); -} - - // Returns step pin mask according to Grbl internal axis indexing. uint8_t Settings_GetStepPinMask(uint8_t axis_idx) { @@ -606,18 +806,22 @@ uint8_t Settings_GetStepPinMask(uint8_t axis_idx) } if(axis_idx == Y_AXIS) { - return (1<= 100 for axis settings. Up to 255. #define AXIS_SETTINGS_INCREMENT 10 // Must be greater than the number of axis settings #ifndef SETTINGS_RESTORE_ALL -#define SETTINGS_RESTORE_ALL 0xFF // All bitflags + #define SETTINGS_RESTORE_ALL 0xFF // All bitflags #endif @@ -113,7 +134,6 @@ typedef struct uint8_t tls_valid; // Remaining Grbl settings - // TODO: document system_flags uint8_t system_flags; uint8_t step_invert_mask; uint8_t dir_invert_mask; @@ -124,9 +144,11 @@ typedef struct float rpm_max; float rpm_min; + uint16_t enc_ppr; // Encoder pulses per revolution uint8_t flags; // Contains default boolean settings - uint8_t flags2; + uint16_t flags_ext; + uint8_t flags_report; uint8_t homing_dir_mask; float homing_feed_rate; @@ -153,12 +175,12 @@ uint8_t Settings_StoreGlobalSetting(uint8_t parameter, float value); void Settings_StoreTlsPosition(void); // Stores the protocol line variable as a startup line in EEPROM -void Settings_StoreStartupLine(uint8_t n, char *line); +void Settings_StoreStartupLine(uint8_t n, const char *line); // Stores tool table in EEPROM -void Settings_StoreToolTable(ToolTable_t *table); +void Settings_StoreToolTable(const ToolTable_t *table); -void Settings_StoreToolParams(uint8_t tool_nr, ToolParams_t *params); +void Settings_StoreToolParams(uint8_t tool_nr, const ToolParams_t *params); // Read tool table uint8_t Settings_ReadToolTable(ToolTable_t *table); @@ -167,13 +189,13 @@ uint8_t Settings_ReadToolTable(ToolTable_t *table); uint8_t Settings_ReadStartupLine(uint8_t n, char *line); // Stores build info user-defined string -void Settings_StoreBuildInfo(char *line); +void Settings_StoreBuildInfo(const char *line); // Reads build info user-defined string uint8_t Settings_ReadBuildInfo(char *line); // Writes selected coordinate data to EEPROM -void Settings_WriteCoordData(uint8_t coord_select, float *coord_data); +void Settings_WriteCoordData(uint8_t coord_select, const float *coord_data); // Reads selected coordinate data from EEPROM uint8_t Settings_ReadCoordData(uint8_t coord_select, float *coord_data); diff --git a/grbl/SpindleControl.c b/grbl/SpindleControl.c index f8f94c4..d0d4516 100644 --- a/grbl/SpindleControl.c +++ b/grbl/SpindleControl.c @@ -45,9 +45,10 @@ void Spindle_Init(void) TIM1_Init(); //TIM3_Init(); -#if defined(LATHE_MODE) - Encoder_Init(); -#endif + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_LATHE_MODE)) + { + Encoder_Init(settings.enc_ppr); + } pwm_gradient = SPINDLE_PWM_RANGE/(settings.rpm_max-settings.rpm_min); spindle_dir_cw = 1; @@ -165,7 +166,7 @@ uint8_t Spindle_ComputePwmValue(float rpm) // 328p PWM register is 8-bit. // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. sys.spindle_speed = rpm; - pwm_value = floor((rpm-settings.rpm_min)*pwm_gradient) + SPINDLE_PWM_MIN_VALUE; + pwm_value = floorf((rpm-settings.rpm_min)*pwm_gradient) + SPINDLE_PWM_MIN_VALUE; } return pwm_value; @@ -208,7 +209,7 @@ void Spindle_SetState(uint8_t state, float rpm) #endif // NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off. - if(settings.flags & BITFLAG_LASER_MODE) + if (BIT_IS_TRUE(settings.flags, BITFLAG_LASER_MODE)) { if(state == SPINDLE_ENABLE_CCW) { @@ -244,7 +245,7 @@ void Spindle_SetSurfaceSpeed(float x_pos) { x_pos = 0.5; } - float u = (fabs(x_pos) * 2) * M_PI; + float u = (fabsf(x_pos) * 2) * M_PI; float rpm = gc_state.spindle_speed / (u / 1000); // Limit Max RPM diff --git a/grbl/Stepper.c b/grbl/Stepper.c index 38c5398..55e9744 100644 --- a/grbl/Stepper.c +++ b/grbl/Stepper.c @@ -21,6 +21,7 @@ */ #include #include +#include #include "Config.h" #include "Planner.h" #include "Probe.h" @@ -57,12 +58,13 @@ // NOTE: AMASS cutoff frequency multiplied by ISR overdrive factor must not exceed maximum step frequency. // NOTE: Current settings are set to overdrive the ISR to no more than 16kHz, balancing CPU overhead // and timer accuracy. Do not alter these settings unless you know what you are doing. -#define MAX_AMASS_LEVEL 4 +#define MAX_AMASS_LEVEL 5 // AMASS_LEVEL0: Normal operation. No AMASS. No upper cutoff frequency. Starts at LEVEL1 cutoff frequency. -#define AMASS_LEVEL1 (uint32_t)(F_TIMER_STEPPER / 8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz) +#define AMASS_LEVEL1 (uint32_t)(F_TIMER_STEPPER / 8000) // Over-drives ISR (x2). Defined as F_TIMER_STEPPER/(Cutoff frequency in Hz) #define AMASS_LEVEL2 (uint32_t)(F_TIMER_STEPPER / 4000) // Over-drives ISR (x4) #define AMASS_LEVEL3 (uint32_t)(F_TIMER_STEPPER / 2000) // Over-drives ISR (x8) #define AMASS_LEVEL4 (uint32_t)(F_TIMER_STEPPER / 1000) // Over-drives ISR (x16) +#define AMASS_LEVEL5 (uint32_t)(F_TIMER_STEPPER / 500) // Over-drives ISR (x32) #if MAX_AMASS_LEVEL <= 0 error "AMASS must have 1 or more levels to operate correctly." @@ -186,6 +188,9 @@ static float tim_ovr = 0; static uint8_t update_g96 = G96_UPDATE_CNT; +float current_backlash[N_AXIS] = {}; + + /* BLOCK VELOCITY PROFILE DEFINITION __________________________ /| |\ _________________ ^ @@ -233,6 +238,19 @@ void Stepper_Init(void) // Init TIM9 TIM9_Init(); + + if(BIT_IS_TRUE(settings.flags, BITFLAG_HOMING_ENABLE)) + { + Stepper_Disable(1); + } + + tim_ovr = 0; + update_g96 = G96_UPDATE_CNT; + + for(int i = 0; i < N_AXIS; i++) + { + current_backlash[i] = 0.0; + } } @@ -371,22 +389,22 @@ void Stepper_MainISR(void) GPIO_SetBits(GPIO_STEP_X_PORT, GPIO_STEP_X_PIN); } } -#if !defined(LATHE_MODE) - if(st.step_outbits & (1<cycles_per_tick * tim_ovr; new_cycles_per_tick = st.exec_segment->cycles_per_tick + new_cycles_per_tick; - if(new_cycles_per_tick > 0xFFFF) + if (new_cycles_per_tick > 0xFFFF) { new_cycles_per_tick = 0xFFFF; } @@ -488,16 +506,17 @@ void Stepper_MainISR(void) { GPIO_ResetBits(GPIO_DIR_X_PORT, GPIO_DIR_X_PIN); } -#if !defined(LATHE_MODE) - if(st.dir_outbits & (1<step_event_count; - if(st.exec_segment->backlash_motion == 0) + if (st.exec_block->direction_bits & (1 << X_DIRECTION_BIT)) { - if(st.exec_block->direction_bits & (1< 0.5) + { + if (current_backlash[X_AXIS] > 0.0) { + current_backlash[X_AXIS] -= 1.0; sys_position[X_AXIS]--; } else { + current_backlash[X_AXIS] += 1.0; sys_position[X_AXIS]++; } } @@ -595,19 +624,30 @@ void Stepper_MainISR(void) st.counter_y += st.steps[Y_AXIS]; - if(st.counter_y > st.exec_block->step_event_count) + if (st.counter_y > st.exec_block->step_event_count) { - st.step_outbits |= (1<step_event_count; - if(st.exec_segment->backlash_motion == 0) + if (st.exec_block->direction_bits & (1 << Y_DIRECTION_BIT)) { - if(st.exec_block->direction_bits & (1< 0.5) + { + if (current_backlash[Y_AXIS] > 0.0) { + current_backlash[Y_AXIS] -= 1.0; sys_position[Y_AXIS]--; } else { + current_backlash[Y_AXIS] += 1.0; sys_position[Y_AXIS]++; } } @@ -615,19 +655,30 @@ void Stepper_MainISR(void) st.counter_z += st.steps[Z_AXIS]; - if(st.counter_z > st.exec_block->step_event_count) + if (st.counter_z > st.exec_block->step_event_count) { - st.step_outbits |= (1<step_event_count; - if(st.exec_segment->backlash_motion == 0) + if (st.exec_block->direction_bits & (1 << Z_DIRECTION_BIT)) + { + sys_position[Z_AXIS]--; + } + else + { + sys_position[Z_AXIS]++; + } + + if (fabsf(current_backlash[Z_AXIS]) > 0.5) { - if(st.exec_block->direction_bits & (1< 0.0) { + current_backlash[Z_AXIS] -= 1.0; sys_position[Z_AXIS]--; } else { + current_backlash[Z_AXIS] += 1.0; sys_position[Z_AXIS]++; } } @@ -715,16 +766,17 @@ void Stepper_PortResetISR(void) } // Y -#if !defined(LATHE_MODE) - if(step_port_invert_mask & (1<entry_speed_sqr); + prep.current_speed = sqrtf(pl_block->entry_speed_sqr); } // Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the // spindle off. st_prep_block->is_pwm_rate_adjusted = false; - if(settings.flags & BITFLAG_LASER_MODE) + if (BIT_IS_TRUE(settings.flags, BITFLAG_LASER_MODE)) { if(pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { @@ -1018,7 +1071,7 @@ void Stepper_PrepareBuffer(void) if(decel_dist < 0.0) { // Deceleration through entire planner block. End of feed hold is not in this block. - prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); + prep.exit_speed = sqrtf(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); } else { @@ -1042,7 +1095,7 @@ void Stepper_PrepareBuffer(void) else { exit_speed_sqr = Planner_GetExecBlockExitSpeedSqr(); - prep.exit_speed = sqrt(exit_speed_sqr); + prep.exit_speed = sqrtf(exit_speed_sqr); } nominal_speed = Planner_ComputeProfileNominalSpeed(pl_block); @@ -1060,7 +1113,7 @@ void Stepper_PrepareBuffer(void) // prep.maximum_speed = prep.current_speed; // Compute override block exit speed since it doesn't match the planner exit speed. - prep.exit_speed = sqrt(pl_block->entry_speed_sqr - 2*pl_block->acceleration*pl_block->millimeters); + prep.exit_speed = sqrtf(pl_block->entry_speed_sqr - 2*pl_block->acceleration*pl_block->millimeters); prep.recalculate_flag |= PREP_FLAG_DECEL_OVERRIDE; // Flag to load next block as deceleration override. // TODO: Determine correct handling of parameters in deceleration-only. @@ -1100,7 +1153,7 @@ void Stepper_PrepareBuffer(void) { prep.accelerate_until = intersect_distance; prep.decelerate_after = intersect_distance; - prep.maximum_speed = sqrt(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr); + prep.maximum_speed = sqrtf(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr); } } else // Deceleration-only type @@ -1312,8 +1365,8 @@ void Stepper_PrepareBuffer(void) supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm). */ float step_dist_remaining = prep.step_per_mm*mm_remaining; // Convert mm_remaining to steps - float n_steps_remaining = ceil(step_dist_remaining); // Round-up current steps remaining - float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining + float n_steps_remaining = ceilf(step_dist_remaining); // Round-up current steps remaining + float last_n_steps_remaining = ceilf(prep.steps_remaining); // Round-up last steps remaining prep_segment->n_step = last_n_steps_remaining-n_steps_remaining; // Compute number of steps to execute. // Bail if we are at the end of a feed hold and don't have a step to execute. @@ -1347,7 +1400,7 @@ void Stepper_PrepareBuffer(void) float inv_rate = dt/(last_n_steps_remaining - step_dist_remaining); // Compute adjusted step rate inverse // Compute CPU cycles per step for the prepped segment. - uint32_t cycles = ceil((TICKS_PER_MICROSECOND*1000000*60)*inv_rate); // (cycles/step) + uint32_t cycles = ceilf((TICKS_PER_MICROSECOND*1000000*60)*inv_rate); // (cycles/step) // Compute step timing and multi-axis smoothing level. // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required. @@ -1369,10 +1422,14 @@ void Stepper_PrepareBuffer(void) { prep_segment->amass_level = 3; } - else + else if (cycles < AMASS_LEVEL5) { prep_segment->amass_level = 4; } + else + { + prep_segment->amass_level = 5; + } cycles >>= prep_segment->amass_level; prep_segment->n_step <<= prep_segment->amass_level; diff --git a/grbl/Stepper.h b/grbl/Stepper.h index 17752ff..60a2aab 100644 --- a/grbl/Stepper.h +++ b/grbl/Stepper.h @@ -23,6 +23,9 @@ #define STEPPER_H +extern float current_backlash[]; + + // Initialize and setup the stepper motor subsystem void Stepper_Init(void); diff --git a/grbl/System.c b/grbl/System.c index 9ef5e3f..db88dd4 100644 --- a/grbl/System.c +++ b/grbl/System.c @@ -3,7 +3,7 @@ Part of Grbl-Advanced Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC - Copyright (c) 2017-2020 Patrick F. + Copyright (c) 2017-2024 Patrick F. Grbl-Advanced is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with Grbl-Advanced. If not, see . */ -#include #include #include #include @@ -35,6 +34,24 @@ #include "System32.h" +// Declare system global variable structure +System_t sys; +// Real-time machine (aka home) position vector in steps. +int32_t sys_position[N_AXIS]; +// Last probe position in machine coordinates and steps. +int32_t sys_probe_position[N_AXIS]; +// Probing state value. Used to coordinate the probing cycle with stepper ISR. +volatile uint8_t sys_probe_state; +// Global realtime executor bitflag variable for state management. See EXEC bitmasks. +volatile uint16_t sys_rt_exec_state; +// Global realtime executor bitflag variable for setting various alarms. +volatile uint8_t sys_rt_exec_alarm; +// Global realtime executor bitflag variable for motion-based overrides. +volatile uint8_t sys_rt_exec_motion_override; +// Global realtime executor bitflag variable for spindle/coolant overrides. +volatile uint8_t sys_rt_exec_accessory_override; + + void System_Init(void) { GPIO_InitGPIO(GPIO_SYSTEM); @@ -43,11 +60,13 @@ void System_Init(void) void System_Clear(void) { - memset(&sys, 0, sizeof(System_t)); // Clear system struct variable. + // Clear system struct variable. + memset(&sys, 0, sizeof(System_t)); - sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% - sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% - sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% + // Set overrides to 100% + sys.f_override = DEFAULT_FEED_OVERRIDE; + sys.r_override = DEFAULT_RAPID_OVERRIDE; + sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; } @@ -86,7 +105,8 @@ uint8_t System_GetControlState(void) { control_state |= CONTROL_PIN_INDEX_CYCLE_START; } - /*if(BIT_IS_TRUE(pin, (1< 0) - uint8_t n; - - for(n = 0; n < N_STARTUP_LINE; n++) + for (uint8_t n = 0; n < N_STARTUP_LINE; n++) { if(!(Settings_ReadStartupLine(n, line))) { @@ -155,9 +172,6 @@ void System_ExecuteStartup(char *line) } } } -#else - (void)line; -#endif } @@ -191,7 +205,8 @@ uint8_t System_ExecuteLine(char *line) { return STATUS_INVALID_STATEMENT; } - return GC_ExecuteLine(line); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. + // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. + return GC_ExecuteLine(line); break; case '$': @@ -208,8 +223,9 @@ uint8_t System_ExecuteLine(char *line) case '$': // Prints Grbl settings if(sys.state & (STATE_CYCLE | STATE_HOLD)) { + // Block during cycle. Takes too long to print. return(STATUS_IDLE_ERROR); - } // Block during cycle. Takes too long to print. + } else { Report_GrblSettings(); @@ -225,7 +241,7 @@ uint8_t System_ExecuteLine(char *line) // Perform reset when toggling off. Check g-code mode should only work if Grbl // is idle and ready, regardless of alarm locks. This is mainly to keep things // simple and consistent. - if(sys.state == STATE_CHECK_MODE ) + if(sys.state == STATE_CHECK_MODE) { MC_Reset(); Report_FeedbackMessage(MESSAGE_DISABLED); @@ -264,7 +280,7 @@ uint8_t System_ExecuteLine(char *line) case 'T': if(line[++char_counter] == 0) { - // Tool change finished. Continue execution + // Tool change by user finished. Continue execution System_ClearExecStateFlag(EXEC_TOOL_CHANGE); sys.state = STATE_IDLE; @@ -278,7 +294,10 @@ uint8_t System_ExecuteLine(char *line) if(settings.tls_valid) { // Probe new tool - TC_ProbeTLS(); + if(TC_ProbeTLS() != 0) + { + return STATUS_PROBE_ERROR; + } } else { @@ -287,7 +306,7 @@ uint8_t System_ExecuteLine(char *line) } else if(settings.tool_change == 3) { - // Change tool with tool table + // Change tool with tool table (Apply offsets) TC_ApplyToolOffset(); } else @@ -319,7 +338,7 @@ uint8_t System_ExecuteLine(char *line) if(c == '=') { // Save params of new tool - char tmp_float[10]; + char tmp_float[10] = {}; int t = 0; float value_f[4] = {}; @@ -332,7 +351,10 @@ uint8_t System_ExecuteLine(char *line) if(strlen(tmp_float) > 0) { // Convert string to float - sscanf(tmp_float, "%f", &value_f[i]); + //sscanf(tmp_float, "%f", &value_f[i]); + //tmp_float[0] = '\0'; + uint8_t cnt = 0; + Read_Float(tmp_float, &cnt, &value_f[i]); tmp_float[0] = '\0'; } else @@ -360,13 +382,13 @@ uint8_t System_ExecuteLine(char *line) case 'P': if(sys.is_homed) { + // Store position of TLS Settings_StoreTlsPosition(); } else { return STATUS_MACHINE_NOT_HOMED; } - break; default: @@ -400,7 +422,8 @@ uint8_t System_ExecuteLine(char *line) return STATUS_CHECK_DOOR; } - sys.state = STATE_HOMING; // Set system state variable + // Set homing state + sys.state = STATE_HOMING; if(line[2] == 0) { @@ -441,10 +464,13 @@ uint8_t System_ExecuteLine(char *line) return STATUS_INVALID_STATEMENT; } - if(!sys.abort) // Execute startup scripts after successful homing. + if(!sys.abort) { - sys.state = STATE_IDLE; // Set to IDLE when complete. - Stepper_Disable(0); // Set steppers to the settings idle state before returning. + // Execute startup scripts after successful homing. + // Set to IDLE when complete. + sys.state = STATE_IDLE; + // Set steppers to the settings idle state before returning. + Stepper_Disable(0); if(line[2] == 0) { @@ -462,7 +488,7 @@ uint8_t System_ExecuteLine(char *line) break; case 'I': // Print or store build info. [IDLE/ALARM] - if(line[++char_counter] == 0 ) + if(line[++char_counter] == 0) { Settings_ReadBuildInfo(line); Report_BuildInfo(line); @@ -474,8 +500,8 @@ uint8_t System_ExecuteLine(char *line) { return STATUS_INVALID_STATEMENT; } - - helper_var = char_counter; // Set helper variable as counter to start of user info line. + // Set helper variable as counter to start of user info line. + helper_var = char_counter; do { @@ -493,38 +519,65 @@ uint8_t System_ExecuteLine(char *line) { return(STATUS_INVALID_STATEMENT); } + switch(line[5]) { #ifdef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS case '$': + // Restore defaults Settings_Restore(SETTINGS_RESTORE_DEFAULTS); break; #endif #ifdef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS case '#': + // Reset coord system Settings_Restore(SETTINGS_RESTORE_PARAMETERS); break; #endif #ifdef ENABLE_RESTORE_EEPROM_WIPE_ALL case '*': + // Restore all Settings_Restore(SETTINGS_RESTORE_ALL); break; #endif +#ifdef ENABLE_RESTORE_EEPROM_CLEAR_TOOLS case 'T': + // Reset tool table TT_Reset(); break; +#endif +#ifdef ENABLE_RESTORE_EEPROM_CLEAR_COORD + case 'C': + // Reset coord system G54-G59 + Settings_Restore(SETTINGS_RESTORE_COORDS); + break; +#endif +#ifdef ENABLE_RESTORE_EEPROM_CLEAR_STARTUP + case 'N': + { + // Reset line with default value + // Empty line + char startup[STARTUP_LINE_LEN] = {}; + for (int i = 0; i < N_STARTUP_LINE; i++) + { + Settings_StoreStartupLine(i, startup); + } + break; + } +#endif default: return STATUS_INVALID_STATEMENT; } Report_FeedbackMessage(MESSAGE_RESTORE_DEFAULTS); - MC_Reset(); // Force reset to ensure settings are initialized correctly. + // Force reset to ensure settings are initialized correctly. + MC_Reset(); break; case 'N': // Startup lines. [IDLE/ALARM] -#if (N_STARTUP_LINE > 0) - if(line[++char_counter] == 0 ) // Print startup lines + // Print startup lines + if(line[++char_counter] == 0) { for(helper_var = 0; helper_var < N_STARTUP_LINE; helper_var++) { @@ -546,10 +599,10 @@ uint8_t System_ExecuteLine(char *line) // Store only when idle. return STATUS_IDLE_ERROR; } - helper_var = true; // Set helper_var to flag storing method. + // Set helper_var to flag storing method. + helper_var = true; // No break. Continues into default: to read remaining command characters. } -#endif default: // Storing setting methods [IDLE/ALARM] if(!Read_Float(line, &char_counter, ¶meter)) @@ -572,16 +625,21 @@ uint8_t System_ExecuteLine(char *line) while(line[char_counter++] != 0); // Execute gcode block to ensure block is valid. - helper_var = GC_ExecuteLine(line); // Set helper_var to returned status code. + // Set helper_var to returned status code. + helper_var = GC_ExecuteLine(line); if(helper_var) { - return(helper_var); + return (helper_var); } else { - helper_var = trunc(parameter); // Set helper_var to int value of parameter - Settings_StoreStartupLine(helper_var, line); + // Set helper_var to int value of parameter + helper_var = truncf(parameter); + if (helper_var < N_STARTUP_LINE) + { + Settings_StoreStartupLine(helper_var, line); + } } } else // Store global setting. @@ -599,12 +657,11 @@ uint8_t System_ExecuteLine(char *line) } } } - - return STATUS_OK; // If '$' command makes it to here, then everything's ok. + // If '$' command makes it to here, then everything's ok. + return STATUS_OK; } - void System_FlagWcoChange(void) { #ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE @@ -621,26 +678,28 @@ float System_ConvertAxisSteps2Mpos(const int32_t *steps, const uint8_t idx) { float pos = 0.0; -#ifdef COREXY - if(idx == X_AXIS) - { - pos = (float)system_convert_corexy_to_x_axis_steps(steps) / settings.steps_per_mm[idx]; - } - else if (idx == Y_AXIS) - { - pos = (float)system_convert_corexy_to_y_axis_steps(steps) / settings.steps_per_mm[idx]; - } - else + if (steps) { - pos = steps[idx]/settings.steps_per_mm[idx]; - } +#ifdef COREXY + if (idx == X_AXIS) + { + pos = (float)system_convert_corexy_to_x_axis_steps(steps) / settings.steps_per_mm[idx]; + } + else if (idx == Y_AXIS) + { + pos = (float)system_convert_corexy_to_y_axis_steps(steps) / settings.steps_per_mm[idx]; + } + else + { + pos = steps[idx] / settings.steps_per_mm[idx]; + } #else - if(settings.steps_per_mm[idx] != 0) - { - pos = steps[idx] / settings.steps_per_mm[idx]; - } - + if (settings.steps_per_mm[idx] > 0.0) + { + pos = steps[idx] / settings.steps_per_mm[idx]; + } #endif + } return pos; } @@ -648,11 +707,12 @@ float System_ConvertAxisSteps2Mpos(const int32_t *steps, const uint8_t idx) void System_ConvertArraySteps2Mpos(float *position, const int32_t *steps) { - uint8_t idx; - - for(idx = 0; idx < N_AXIS; idx++) + if (position) { - position[idx] = System_ConvertAxisSteps2Mpos(steps, idx); + for (uint8_t idx = 0; idx < N_AXIS; idx++) + { + position[idx] = System_ConvertAxisSteps2Mpos(steps, idx); + } } return; @@ -661,12 +721,12 @@ void System_ConvertArraySteps2Mpos(float *position, const int32_t *steps) // CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps. #ifdef COREXY -int32_t system_convert_corexy_to_x_axis_steps(int32_t *steps) +int32_t system_convert_corexy_to_x_axis_steps(const int32_t *steps) { return ((steps[A_MOTOR] + steps[B_MOTOR])/2); } -int32_t system_convert_corexy_to_y_axis_steps(int32_t *steps) +int32_t system_convert_corexy_to_y_axis_steps(const int32_t *steps) { return ((steps[A_MOTOR] - steps[B_MOTOR])/2); } @@ -674,36 +734,37 @@ int32_t system_convert_corexy_to_y_axis_steps(int32_t *steps) // Checks and reports if target array exceeds machine travel limits. -uint8_t System_CheckTravelLimits(float *target) +uint8_t System_CheckTravelLimits(const float *target) { - uint8_t idx; - - for(idx = 0; idx < N_AXIS; idx++) + for (uint8_t idx = 0; idx < N_AXIS; idx++) { -#ifdef HOMING_FORCE_SET_ORIGIN - // When homing forced set origin is enabled, soft limits checks need to account for directionality. - // NOTE: max_travel is stored as negative - if(BIT_IS_TRUE(settings.homing_dir_mask, BIT(idx))) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_FORCE_SET_ORIGIN)) { - if(target[idx] < 0 || target[idx] > -settings.max_travel[idx]) + // When homing forced set origin is enabled, soft limits checks need to account for directionality. + // NOTE: max_travel is stored as negative + if (BIT_IS_TRUE(settings.homing_dir_mask, BIT(idx))) { - return true; + if (target[idx] < 0 || target[idx] > -settings.max_travel[idx]) + { + return true; + } + } + else + { + if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) + { + return true; + } } } else { - if(target[idx] > 0 || target[idx] < settings.max_travel[idx]) + // NOTE: max_travel is stored as negative + if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return true; } } -#else - // NOTE: max_travel is stored as negative - if(target[idx] > 0 || target[idx] < settings.max_travel[idx]) - { - return true; - } -#endif } return false; diff --git a/grbl/System.h b/grbl/System.h index bcba08a..276e0fd 100644 --- a/grbl/System.h +++ b/grbl/System.h @@ -96,6 +96,7 @@ #define STATE_FEED_DWELL BIT(8) // Dwell #define STATE_TOOL_CHANGE BIT(9) // Tool change in progress +#define STATE_BUSY BIT(10) // Writing NVM etc. // Define system suspend flags. Used in various ways to manage suspend states and procedures. #define SUSPEND_DISABLE 0 // Must be zero. @@ -134,7 +135,7 @@ // Define global system variables typedef struct { - uint16_t state; // Tracks the current system state of Grbl. + uint16_t state; // Tracks the current system state of Grbl. uint8_t abort; // System abort flag. Forces exit back to main loop for reset. uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door. uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean) @@ -197,11 +198,11 @@ float System_ConvertAxisSteps2Mpos(const int32_t *steps, const uint8_t idx); void System_ConvertArraySteps2Mpos(float *position, const int32_t *steps); // CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps. -int32_t system_convert_corexy_to_x_axis_steps(int32_t *steps); -int32_t system_convert_corexy_to_y_axis_steps(int32_t *steps); +int32_t system_convert_corexy_to_x_axis_steps(const int32_t *steps); +int32_t system_convert_corexy_to_y_axis_steps(const int32_t *steps); // Checks and reports if target array exceeds machine travel limits. -uint8_t System_CheckTravelLimits(float *target); +uint8_t System_CheckTravelLimits(const float *target); // Special handlers for setting and clearing Grbl's real-time execution flags. void System_SetExecStateFlag(uint16_t mask); diff --git a/grbl/ToolChange.c b/grbl/ToolChange.c index eb61649..d889b52 100644 --- a/grbl/ToolChange.c +++ b/grbl/ToolChange.c @@ -31,7 +31,9 @@ #include "defaults.h" -#define TOOL_SENSOR_OFFSET 70.0 // mm +#define TOOL_SENSOR_OFFSET (70.0) // mm +#define TOOL_PROBE_FAST (250.0) // mm/min +#define TOOL_PROBE_SLOW (40.0) // mm/min static uint8_t isFirstTC = 1; @@ -59,8 +61,8 @@ void TC_Init(void) void TC_ChangeCurrentTool(void) { - Planner_LineData_t pl_data = {0}; - float position[N_AXIS] = {0.0}; + Planner_LineData_t pl_data = {}; + float position[N_AXIS] = {}; if(sys.state == STATE_CHECK_MODE) @@ -111,16 +113,21 @@ void TC_ChangeCurrentTool(void) } -void TC_ProbeTLS(void) +uint8_t TC_ProbeTLS(void) { - Planner_LineData_t pl_data = {0}; - float position[N_AXIS] = {0.0}; + Planner_LineData_t pl_data = {}; + float position[N_AXIS] = {}; uint8_t flags = 0; - if(sys.state == STATE_CHECK_MODE || settings.tls_valid == 0) + if(sys.state == STATE_CHECK_MODE) { - return; + return 0; + } + if(settings.tls_valid == 0) + { + // Error + return 1; } // Move to XY position of TLS @@ -145,34 +152,34 @@ void TC_ProbeTLS(void) Protocol_BufferSynchronize(); // Set up fast probing - pl_data.feed_rate = 220.0; + pl_data.feed_rate = TOOL_PROBE_FAST; pl_data.condition = 0; // Reset rapid motion condition flag. // Probe TLS fast - position[TOOL_LENGTH_OFFSET_AXIS] -= 200.0; + position[TOOL_LENGTH_OFFSET_AXIS] -= 300.0; uint8_t ret = MC_ProbeCycle(position, &pl_data, flags); if(ret != GC_PROBE_FOUND) { // Error - return; + return 2; } // Get current position System_ConvertArraySteps2Mpos(position, sys_position); - position[TOOL_LENGTH_OFFSET_AXIS] += 1.8; + position[TOOL_LENGTH_OFFSET_AXIS] += 2.0; // Move up a little bit for slow probing - pl_data.feed_rate = 200.0; + pl_data.feed_rate = TOOL_PROBE_FAST; MC_Line(position, &pl_data); // Probe TLS slow - pl_data.feed_rate = 12.0; + pl_data.feed_rate = TOOL_PROBE_SLOW; position[TOOL_LENGTH_OFFSET_AXIS] -= 200; ret = MC_ProbeCycle(position, &pl_data, flags); if(ret != GC_PROBE_FOUND) { // Error - return; + return 2; } if(isFirstTC) @@ -186,8 +193,8 @@ void TC_ProbeTLS(void) // Calculate tool offset toolOffset = sys_probe_position[TOOL_LENGTH_OFFSET_AXIS] - toolReferenz; - // Apply offset as dynamic tool length offset - gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; + // Apply offset + //gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE; gc_state.tool_length_offset[TOOL_LENGTH_OFFSET_AXIS] = toolOffset / settings.steps_per_mm[TOOL_LENGTH_OFFSET_AXIS]; } @@ -206,6 +213,8 @@ void TC_ProbeTLS(void) Protocol_BufferSynchronize(); GC_SyncPosition(); + + return 0; } @@ -216,7 +225,7 @@ void TC_ApplyToolOffset(void) TT_GetToolParams(gc_state.tool, ¶ms); // Apply offset as dynamic tool length offset - gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; + //gc_state.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; gc_state.tool_length_offset[X_AXIS] = params.x_offset; gc_state.tool_length_offset[Y_AXIS] = params.y_offset; diff --git a/grbl/ToolChange.h b/grbl/ToolChange.h index b3db747..e203463 100644 --- a/grbl/ToolChange.h +++ b/grbl/ToolChange.h @@ -27,7 +27,7 @@ void TC_Init(void); void TC_ChangeCurrentTool(void); -void TC_ProbeTLS(void); +uint8_t TC_ProbeTLS(void); void TC_ApplyToolOffset(void); diff --git a/grbl/ToolTable.c b/grbl/ToolTable.c index 6ce1202..a086e71 100644 --- a/grbl/ToolTable.c +++ b/grbl/ToolTable.c @@ -23,12 +23,12 @@ #include -static ToolTable_t tool_table = {0}; +static ToolTable_t tool_table = {}; void TT_Init(void) { - for(uint8_t i = 0; i < MAX_TOOL_NR; i++) + for (uint8_t i = 0; i < TOOLTABLE_MAX_TOOL_NR; i++) { tool_table.tools[i].x_offset = 0.0; tool_table.tools[i].y_offset = 0.0; @@ -36,13 +36,16 @@ void TT_Init(void) tool_table.tools[i].reserved = 0.0; } - Settings_ReadToolTable(&tool_table); + if (!Settings_ReadToolTable(&tool_table)) + { + Report_StatusMessage(STATUS_TOOLS_READ_FAIL); + } } void TT_Reset(void) { - for(uint8_t i = 0; i < MAX_TOOL_NR; i++) + for (uint8_t i = 0; i < TOOLTABLE_MAX_TOOL_NR; i++) { tool_table.tools[i].x_offset = 0.0; tool_table.tools[i].y_offset = 0.0; @@ -56,7 +59,7 @@ void TT_Reset(void) void TT_GetToolParams(uint8_t tool_nr, ToolParams_t *params) { - if(tool_nr < MAX_TOOL_NR) + if (tool_nr < TOOLTABLE_MAX_TOOL_NR) { memcpy(params, &tool_table.tools[tool_nr], sizeof(ToolParams_t)); } @@ -69,10 +72,11 @@ void TT_GetToolParams(uint8_t tool_nr, ToolParams_t *params) void TT_SaveToolParams(uint8_t tool_nr, ToolParams_t *params) { - if(tool_nr < MAX_TOOL_NR) + if (tool_nr < TOOLTABLE_MAX_TOOL_NR) { memcpy(&tool_table.tools[tool_nr], params, sizeof(ToolParams_t)); - Settings_StoreToolParams(tool_nr, params); + //Settings_StoreToolParams(tool_nr, params); + Settings_StoreToolTable(&tool_table); } else { diff --git a/grbl/ToolTable.h b/grbl/ToolTable.h index 2d68f44..fe76a1d 100644 --- a/grbl/ToolTable.h +++ b/grbl/ToolTable.h @@ -21,9 +21,7 @@ #define TOOLTABLE_H_INCLUDED #include - - -#define MAX_TOOL_NR 20 +#include "Config.h" #pragma pack(push, 1) // exact fit - no padding @@ -38,7 +36,7 @@ typedef struct typedef struct { - ToolParams_t tools[MAX_TOOL_NR]; + ToolParams_t tools[TOOLTABLE_MAX_TOOL_NR]; } ToolTable_t; #pragma pack(pop) diff --git a/grbl/defaults.h b/grbl/defaults.h index 77588c0..8035d12 100644 --- a/grbl/defaults.h +++ b/grbl/defaults.h @@ -80,6 +80,8 @@ #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) #define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_TOOL_CHANGE_MODE 0 // 0 = Ignore M6; 1 = Manual tool change; 2 = Manual tool change + TLS + #define DEFAULT_ENCODER_PULSES_PER_REV 360 // PPR for lathe encoder + #define USE_MULTI_AXIS 0 // false #endif diff --git a/grbl/util.c b/grbl/util.c index f48f198..7758d1f 100644 --- a/grbl/util.c +++ b/grbl/util.c @@ -40,9 +40,9 @@ // Scientific notation is officially not supported by g-code, and the 'E' character may // be a g-code word on some CNC systems. So, 'E' notation will not be recognized. // NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod(). -uint8_t Read_Float(char *line, uint8_t *char_counter, float *float_ptr) +uint8_t Read_Float(const char *line, uint8_t *char_counter, float *float_ptr) { - char *ptr = line + *char_counter; + char *ptr = (char *)line + *char_counter; unsigned char c; // Grab first character and increment pointer. No spaces assumed in line. @@ -150,10 +150,12 @@ uint8_t Read_Float(char *line, uint8_t *char_counter, float *float_ptr) // Search a float in a string and return it as string -uint8_t ExtractFloat(char *line, int start_idx, char *float_char) +uint8_t ExtractFloat(const char *line, int start_idx, char *float_char) { unsigned int i = 0; + float_char[0] = '\0'; + for(i = start_idx; i < strlen(line); i++) { // Search for start of float (digit or '-') @@ -216,7 +218,7 @@ void PrintFloat_RateValue(float n) // Non-blocking delay function used for general operation and suspend features. void Delay_sec(float seconds, uint8_t mode) { - uint16_t i = ceil(1000/DWELL_TIME_STEP*seconds); + uint16_t i = ceilf(1000/DWELL_TIME_STEP*seconds); while(i-- > 0) { @@ -246,14 +248,14 @@ void Delay_sec(float seconds, uint8_t mode) } // Simple hypotenuse computation function. -float hypot_f(float x, float y) +/*float hypot_f(float x, float y) { - return sqrt(x*x + y*y); -} + return sqrtf(x*x + y*y); +}*/ bool isEqual_f(float a, float b) { - if(fabs(a-b) < 0.00001) + if(fabsf(a-b) < 0.00001) { return true; } @@ -274,7 +276,7 @@ float convert_delta_vector_to_unit_vector(float *vector) } } - magnitude = sqrt(magnitude); + magnitude = sqrtf(magnitude); float inv_magnitude = 1.0/magnitude; for(idx = 0; idx < N_AXIS; idx++) @@ -294,7 +296,7 @@ float limit_value_by_axis_maximum(float *max_value, float *unit_vec) { if(unit_vec[idx] != 0) // Avoid divide by zero. { - limit_value = min(limit_value,fabs(max_value[idx]/unit_vec[idx])); + limit_value = min(limit_value,fabsf(max_value[idx]/unit_vec[idx])); } } diff --git a/grbl/util.h b/grbl/util.h index 0cf3afb..bf41098 100644 --- a/grbl/util.h +++ b/grbl/util.h @@ -42,7 +42,6 @@ #define BIT_IS_FALSE(x,mask) ((x & mask) == 0) -#define F_CPU 96000000UL #define F_TIMER_STEPPER 24000000UL #define N_AXIS 5 @@ -120,12 +119,10 @@ // Read a floating point value from a string. Line points to the input buffer, char_counter // is the indexer pointing to the current character of the line, while float_ptr is // a pointer to the result variable. Returns true when it succeeds -uint8_t Read_Float(char *line, uint8_t *char_counter, float *float_ptr); - -uint8_t ExtractFloat(char *line, int start_idx, char *float_char); +uint8_t Read_Float(const char *line, uint8_t *char_counter, float *float_ptr); +uint8_t ExtractFloat(const char *line, int start_idx, char *float_char); void PrintFloat_CoordValue(float n); - void PrintFloat_RateValue(float n); // Non-blocking delay function used for general operation and suspend features. diff --git a/main.c b/main.c old mode 100644 new mode 100755 index 21737e8..52d7e28 --- a/main.c +++ b/main.c @@ -17,16 +17,14 @@ You should have received a copy of the GNU General Public License along with Grbl-Advanced. If not, see . */ -#include -#include #include -#include "System32.h" -#include "grbl_advance.h" -#include "Ethernet.h" +#include "CRC.h" #include "GrIP.h" #include "ServerTCP.h" -#include "util2.h" +#include "System32.h" +#include "grbl_advance.h" +#include "w5500.h" #include "Print.h" #include "FIFO_USART.h" @@ -34,52 +32,35 @@ #include "Platform.h" -// Declare system global variable structure -System_t sys; -int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. -int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. -volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. -volatile uint16_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. -volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. -volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. -volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. - -#ifdef ETH_IF - uint8_t MAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; - - // IP Address of tcp server - IPAddress_t IP = {{192, 168, 1, 20}}; - IPAddress_t GatewayIP = {{192, 168, 1, 1}}; - IPAddress_t SubnetMask = {{255, 255, 255, 0}}; - IPAddress_t MyDns = {{8, 8, 8, 8}}; -#endif - - int main(void) { // Init formatted output Printf_Init(); + + // Init CRC module + CRC_Init(); + + // Initialize GrIP protocol + GrIP_Init(); + System_Init(); - Stepper_Init(); Settings_Init(); + Stepper_Init(); System_ResetPosition(); -#ifdef ETH_IF - // Initialize W5500 - Ethernet_Init(MAC, &IP, &MyDns, &GatewayIP, &SubnetMask); + Limits_Init(); +#if (USE_ETH_IF) // Initialize TCP server ServerTCP_Init(ETH_SOCK, ETH_PORT); #endif - // Initialize GrIP protocol - GrIP_Init(); - - // Init SysTick 1ms - SysTick_Init(); - - if(BIT_IS_TRUE(settings.flags, BITFLAG_HOMING_ENABLE)) + if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_HOMING_INIT_LOCK) && BIT_IS_TRUE(settings.flags, BITFLAG_HOMING_ENABLE)) + { + sys.state = STATE_ALARM; + } + else if (BIT_IS_TRUE(settings.flags_ext, BITFLAG_FORCE_INITIALIZATION_ALARM)) { sys.state = STATE_ALARM; } @@ -88,6 +69,9 @@ int main(void) sys.state = STATE_IDLE; } + // Init SysTick 1ms + SysTick_Init(); + // Grbl-Advanced initialization loop upon power-up or a system abort. For the latter, all processes // will return to this loop to be cleanly re-initialized. while(1) @@ -108,6 +92,9 @@ int main(void) sys_rt_exec_motion_override = 0; sys_rt_exec_accessory_override = 0; + // Clear serial buffer to prevent undefined behavior + FifoUsart_Init(); + // Reset Grbl-Advanced primary systems. GC_Init(); Planner_Init(); @@ -127,12 +114,10 @@ int main(void) // Print welcome message. Indicates an initialization has occured at power-up or with a reset. Report_InitMessage(); + //--------------------------------------------------------------------------------// //-- Start Grbl-Advanced main loop. Processes program inputs and executes them. --// Protocol_MainLoop(); //--------------------------------------------------------------------------------// - - // Clear serial buffer after soft reset to prevent undefined behavior - FifoUsart_Init(); } return 0;