From 298d5dddce1549927b355d28d7f863511246a824 Mon Sep 17 00:00:00 2001 From: Louiswiz <75520034+min-hs@users.noreply.github.com> Date: Wed, 17 Nov 2021 17:11:53 +0900 Subject: [PATCH 1/3] add W5100s --- adafruit_wiznet5k/adafruit_wiznet5k.py | 164 +++++++++++++----- adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py | 21 ++- adafruit_wiznet5k/adafruit_wiznet5k_ntp.py | 62 +++++++ adafruit_wiznet5k/adafruit_wiznet5k_socket.py | 20 +++ .../adafruit_wiznet5k_wsgiserver.py | 14 +- 5 files changed, 226 insertions(+), 55 deletions(-) create mode 100644 adafruit_wiznet5k/adafruit_wiznet5k_ntp.py diff --git a/adafruit_wiznet5k/adafruit_wiznet5k.py b/adafruit_wiznet5k/adafruit_wiznet5k.py index fb4bd51..08a1f01 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k.py @@ -45,9 +45,11 @@ REG_GAR = const(0x0001) # Gateway IP Address REG_SUBR = const(0x0005) # Subnet Mask Address REG_VERSIONR_W5500 = const(0x0039) # W5500 Silicon Version +REG_VERSIONR_W5100S = const(0x0080) # W5100S Silicon Version REG_SHAR = const(0x0009) # Source Hardware Address REG_SIPR = const(0x000F) # Source IP Address REG_PHYCFGR = const(0x002E) # W5500 PHY Configuration +REG_PHYCFGR_W5100S = const(0x003C) # W5100S PHY Configuration # Wiznet5k Socket Registers REG_SNMR = const(0x0000) # Socket n Mode @@ -99,6 +101,7 @@ CH_SIZE = const(0x100) SOCK_SIZE = const(0x800) # MAX W5k socket size +SOCK_MASK = const(0x7FF) # Register commands MR_RST = const(0x80) # Mode Register RST # Socket mode register @@ -116,6 +119,7 @@ # Maximum number of sockets to support, differs between chip versions. W5200_W5500_MAX_SOCK_NUM = const(0x08) +W5100_MAX_SOCK_NUM = const(0x04) SOCKET_INVALID = const(255) # UDP socket struct. @@ -179,8 +183,18 @@ def __init__( self.src_port = 0 self._dns = 0 - # Set DHCP + # First, wait link status is on + # to avoid the code during DHCP, socket listen, connect ... - assert self.link_status, "Ethernet cable disconnected!" + start_time = time.monotonic() + while True: + if self.link_status or ((time.monotonic() - start_time) > 5): + break + time.sleep(1) + if self._debug: + print("My Link is:", self.link_status) self._dhcp_client = None + + # Set DHCP if is_dhcp: ret = self.set_dhcp(hostname, dhcp_timeout) if ret != 0: @@ -198,16 +212,6 @@ def set_dhcp(self, hostname=None, response_timeout=30): if self._debug: print("* Initializing DHCP") - # First, wait link status is on - # to avoid the code during DHCP - assert self.link_status, "Ethernet cable disconnected!" - start_time = time.monotonic() - while True: - if self.link_status or ((time.monotonic() - start_time) > 5): - break - time.sleep(1) - if self._debug: - print("My Link is:", self.link_status) - # Return IP assigned by DHCP self._dhcp_client = dhcp.DHCP( self, self.mac_address, hostname, response_timeout, debug=self._debug @@ -251,6 +255,8 @@ def max_sockets(self): """Returns max number of sockets supported by chip.""" if self._chip_type == "w5500": return W5200_W5500_MAX_SOCK_NUM + elif self._chip_type == "w5100s": + return W5100_MAX_SOCK_NUM return -1 @property @@ -319,6 +325,9 @@ def link_status(self): if self._chip_type == "w5500": data = self.read(REG_PHYCFGR, 0x00) return data[0] & 0x01 + elif self._chip_type == "w5100s": + data = self.read(REG_PHYCFGR_W5100S, 0x00) + return data[0] & 0x01 return 0 def remote_port(self, socket_num): @@ -367,25 +376,44 @@ def _w5100_init(self): self.write(0x1E, ctrl_byte, 2) self.write(0x1F, ctrl_byte, 2) else: - return 0 + # Detect if chip is Wiznet W5100S + if self.detect_w5100s() == 1: + pass + else: + return 0 return 1 def detect_w5500(self): """Detects W5500 chip.""" + self._chip_type = "w5500" assert self.sw_reset() == 0, "Chip not reset properly!" self._write_mr(0x08) - assert self._read_mr()[0] == 0x08, "Expected 0x08." + # assert self._read_mr()[0] == 0x08, "Expected 0x08." + if self._read_mr()[0] != 0x08 : return -1 self._write_mr(0x10) - assert self._read_mr()[0] == 0x10, "Expected 0x10." + # assert self._read_mr()[0] == 0x10, "Expected 0x10." + if self._read_mr()[0] != 0x10 : return -1 self._write_mr(0x00) - assert self._read_mr()[0] == 0x00, "Expected 0x00." + # assert self._read_mr()[0] == 0x00, "Expected 0x00." + if self._read_mr()[0] != 0x00 : return -1 if self.read(REG_VERSIONR_W5500, 0x00)[0] != 0x04: return -1 - self._chip_type = "w5500" - self._ch_base_msb = 0x10 + # self._chip_type = "w5500" + # self._ch_base_msb = 0x10 + return 1 + + def detect_w5100s(self): + """Detects W5100S chip.""" + self._chip_type = "w5100s" + # sw reset + assert self.sw_reset() == 0, "Chip not reset properly!" + if self.read(REG_VERSIONR_W5100S, 0x00)[0] != 0x51: + return -1 + + self._ch_base_msb = 0x0400 return 1 def sw_reset(self): @@ -396,7 +424,9 @@ def sw_reset(self): mode_reg = self._read_mr() self._write_mr(0x80) mode_reg = self._read_mr() - if mode_reg[0] != 0x00: + + # W5100S case => 0x03 + if (mode_reg[0] != 0x00) and (mode_reg[0] != 0x03): return -1 return 0 @@ -418,9 +448,16 @@ def read(self, addr, callback, length=1, buffer=None): """ with self._device as bus_device: - bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member - bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member - bus_device.write(bytes([callback])) # pylint: disable=no-member + if self._chip_type == "w5500": + bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member + bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member + bus_device.write(bytes([callback])) # pylint: disable=no-member + else : + #if self._chip_type == "w5100s": + bus_device.write(bytes([0x0F])) # pylint: disable=no-member + bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member + bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member + if buffer is None: self._rxbuf = bytearray(length) bus_device.readinto(self._rxbuf) # pylint: disable=no-member @@ -437,9 +474,15 @@ def write(self, addr, callback, data): """ with self._device as bus_device: - bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member - bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member - bus_device.write(bytes([callback])) # pylint: disable=no-member + if self._chip_type == "w5500": + bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member + bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member + bus_device.write(bytes([callback])) # pylint: disable=no-member + else : + #if self._chip_type == "w5100s": + bus_device.write(bytes([0xF0])) # pylint: disable=no-member + bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member + bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member if hasattr(data, "from_bytes"): bus_device.write(bytes([data])) # pylint: disable=no-member @@ -687,14 +730,28 @@ def socket_read(self, socket_num, length): # Read the starting save address of the received data ptr = self._read_snrx_rd(socket_num) - # Read data from the starting address of snrx_rd - ctrl_byte = 0x18 + (socket_num << 5) - - resp = self.read(ptr, ctrl_byte, ret) + if self._chip_type == "w5500": + # Read data from the starting address of snrx_rd + ctrl_byte = 0x18 + (socket_num << 5) + + resp = self.read(ptr, ctrl_byte, ret) + else : + #if self._chip_type == "w5100s": + offset = ptr & SOCK_MASK + src_addr = offset + (socket_num * SOCK_SIZE + 0x6000) + if (offset + ret > SOCK_SIZE) : + size = SOCK_SIZE - offset + resp1 = self.read(src_addr, 0x00, size) + size = ret - size + src_addr = (socket_num * SOCK_SIZE + 0x6000) + resp2 = self.read(src_addr, 0x00, size) + resp = resp1 + resp2 + else : + resp = self.read(src_addr, 0x00, ret) # After reading the received data, update Sn_RX_RD to the increased # value as many as the reading size. - ptr += ret + ptr = (ptr + ret) & 0xFFFF self._write_snrx_rd(socket_num, ptr) # Notify the W5k of the updated Sn_Rx_RD @@ -740,16 +797,34 @@ def socket_write(self, socket_num, buffer, timeout=0): # Read the starting address for saving the transmitting data. ptr = self._read_sntx_wr(socket_num) - offset = ptr & 0x07FF - dst_addr = offset + (socket_num * 2048 + 0x8000) + offset = ptr & SOCK_MASK + if self._chip_type == "w5500": + dst_addr = offset + (socket_num * SOCK_SIZE + 0x8000) + + txbuf = buffer[:ret] + cntl_byte = 0x14 + (socket_num << 5) + self.write(dst_addr, cntl_byte, txbuf) + + else : + #if self._chip_type == "w5100s": + dst_addr = offset + (socket_num * SOCK_SIZE + 0x4000) + + if (offset + ret > SOCK_SIZE) : + size = SOCK_SIZE - offset + txbuf = buffer[0:size] + self.write(dst_addr, 0x00, txbuf) + txbuf = buffer[size:ret] + size = ret - size + dst_addr = (socket_num * SOCK_SIZE + 0x4000) + self.write(dst_addr, 0x00, txbuf) + else : + txbuf = buffer[:ret] + self.write(dst_addr, 0x00, buffer[:ret]) # update sn_tx_wr to the value + data size - ptr = (ptr + len(buffer)) & 0xFFFF + ptr = (ptr + ret) & 0xFFFF self._write_sntx_wr(socket_num, ptr) - cntl_byte = 0x14 + (socket_num << 5) - self.write(dst_addr, cntl_byte, buffer) - self._write_sncr(socket_num, CMD_SOCK_SEND) self._read_sncr(socket_num) @@ -863,11 +938,20 @@ def _read_snmr(self, sock): def _write_socket(self, sock, address, data): """Write to a W5k socket register.""" - base = self._ch_base_msb << 8 - cntl_byte = (sock << 5) + 0x0C - return self.write(base + sock * CH_SIZE + address, cntl_byte, data) + if self._chip_type == "w5500": + cntl_byte = (sock << 5) + 0x0C + return self.write(address, cntl_byte, data) + else : + #if self._chip_type == "w5100s": + cntl_byte = 0 + return self.write(self._ch_base_msb + sock * CH_SIZE + address, cntl_byte, data) def _read_socket(self, sock, address): """Read a W5k socket register.""" - cntl_byte = (sock << 5) + 0x08 - return self.read(address, cntl_byte) + if self._chip_type == "w5500": + cntl_byte = (sock << 5) + 0x08 + return self.read(address, cntl_byte) + else : + #if self._chip_type == "w5100s": + cntl_byte = 0 + return self.read(self._ch_base_msb + sock * CH_SIZE + address, cntl_byte) diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py index e5c79ef..b5768fb 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py @@ -192,8 +192,8 @@ def send_dhcp_message(self, state, time_elapsed, renew=False): # HW Type - ETH _BUFF[245] = 0x01 # Client MAC Address - for mac, val in enumerate(self._mac_address): - _BUFF[246 + mac] = val + for mac in range(0, len(self._mac_address)): + _BUFF[246 + mac] = self._mac_address[mac] # Option - Host Name _BUFF[252] = 12 @@ -471,13 +471,9 @@ def _dhcp_state_machine(self): print("* DHCP: Time to renew lease") if ( - self._dhcp_state - in ( - STATE_DHCP_DISCOVER, - STATE_DHCP_REQUEST, - ) - and time.monotonic() > (self._start_time + self._response_timeout) - ): + self._dhcp_state == STATE_DHCP_DISCOVER + or self._dhcp_state == STATE_DHCP_REQUEST + ) and time.monotonic() > (self._start_time + self._response_timeout): self._dhcp_state = STATE_DHCP_WAIT if self._sock is not None: self._sock.close() @@ -485,10 +481,13 @@ def _dhcp_state_machine(self): def request_dhcp_lease(self): """Request to renew or acquire a DHCP lease.""" - if self._dhcp_state in (STATE_DHCP_LEASED, STATE_DHCP_WAIT): + if self._dhcp_state == STATE_DHCP_LEASED or self._dhcp_state == STATE_DHCP_WAIT: self._dhcp_state = STATE_DHCP_START - while self._dhcp_state not in (STATE_DHCP_LEASED, STATE_DHCP_WAIT): + while ( + self._dhcp_state != STATE_DHCP_LEASED + and self._dhcp_state != STATE_DHCP_WAIT + ): self._dhcp_state_machine() return self._dhcp_state == STATE_DHCP_LEASED diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py b/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py new file mode 100644 index 0000000..8b4253c --- /dev/null +++ b/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +`wiznet5k_ntp` +================================================================================ + +Network Time Protocol (NTP) helper for CircuitPython + + * Author(s): irinakim + +Implementation Notes +-------------------- +**Hardware:** +**Software and Dependencies:** + + +""" +import time + +import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket +from adafruit_wiznet5k.adafruit_wiznet5k_socket import htons + + +##__version__ = "0.0.0-auto.0" +##__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NTP.git" + + +class NTP: + def __init__(self, iface, ntp_address,utc,debug=False): + self._debug = debug + self._iface = iface + socket.set_interface(self._iface) + self._sock = socket.socket(type=socket.SOCK_DGRAM) + self._sock.settimeout(1) + self._utc = utc + + self._ntp_server = ntp_address + self._host = 0 + self._request_id = 0 # request identifier + + self._pkt_buf_ = bytearray() + + def _build_ntp_header(self,ip): + self._pkt_buf_.append(0x23) + + for i in range(55): + self._pkt_buf_.append(0x00) + + def get_time(self): + self._build_ntp_header(self._ntp_server) + self._sock.bind((None,50001)) + self._sock.sendto(self._pkt_buf_,(self._ntp_server, 123)) + while True: + data = self._sock.recv() + if data: + sec = data[40:44] + int_cal = int.from_bytes(sec,"big") + cal =int_cal - 2208988800 + self._utc *3600 + cal = time.localtime(cal) + return cal diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py b/adafruit_wiznet5k/adafruit_wiznet5k_socket.py index aa9bd16..b55c881 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_socket.py @@ -325,6 +325,26 @@ def recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches gc.collect() return ret + def embed_recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches + """Reads some bytes from the connected remote address and then return recv(). + :param int bufsize: Maximum number of bytes to receive. + :param int flags: ignored, present for compatibility. + """ + # print("Socket read", bufsize) + ret = None + avail = self.available() + if avail: + if self._sock_type == SOCK_STREAM: + self._buffer += _the_interface.socket_read(self.socknum, avail)[1] + elif self._sock_type == SOCK_DGRAM: + self._buffer += _the_interface.read_udp(self.socknum, avail)[1] + gc.collect() + ret = self._buffer + # print("RET ptr:", id(ret), id(self._buffer)) + self._buffer = b"" + gc.collect() + return ret + def recvfrom(self, bufsize=0, flags=0): """Reads some bytes from the connected remote address. :param int bufsize: Maximum number of bytes to receive. diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_wsgiserver.py b/adafruit_wiznet5k/adafruit_wiznet5k_wsgiserver.py index 738c2b6..ac4beea 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_wsgiserver.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_wsgiserver.py @@ -44,8 +44,8 @@ def set_interface(iface): socket.set_interface(iface) -# Maximum number of sockets for the web server (number of connections we can hold) -MAX_SOCK_NUM = const(6) +# # Maximum number of sockets for the web server (number of connections we can hold) +# MAX_SOCK_NUM = const(6) # pylint: disable=invalid-name class WSGIServer: @@ -62,6 +62,12 @@ def __init__(self, port=80, debug=False, application=None): self._response_status = None self._response_headers = [] + if _the_interface.chip == "w5100s" : + self.MAX_SOCK_NUM = const(2) + print("MAX_SOCK_NUM is 2") + else: + self.MAX_SOCK_NUM = const(6) + print("MAX_SOCK_NUM is 6") def start(self): """ @@ -69,7 +75,7 @@ def start(self): Call update_poll in the main loop for the application callable to be invoked on receiving an incoming request. """ - for _ in range(MAX_SOCK_NUM): + for _ in range(self.MAX_SOCK_NUM): new_sock = socket.socket() new_sock.settimeout(self._timeout) new_sock.bind((None, self.port)) @@ -95,7 +101,7 @@ def update_poll(self): for sock in self._client_sock: if sock.status == wiznet5k.adafruit_wiznet5k.SNSR_SOCK_CLOSED: self._client_sock.remove(sock) - for _ in range(len(self._client_sock), MAX_SOCK_NUM): + for _ in range(len(self._client_sock), self.MAX_SOCK_NUM): try: new_sock = socket.socket() new_sock.settimeout(self._timeout) From 2131fe2ab849c6d4581919ce9ac39bb3bbd1da7a Mon Sep 17 00:00:00 2001 From: Louiswiz <75520034+min-hs@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:37:08 +0900 Subject: [PATCH 2/3] Update adafruit_wiznet5k_ntp.py --- adafruit_wiznet5k/adafruit_wiznet5k_ntp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py b/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py index 8b4253c..e884da3 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_ntp.py @@ -8,7 +8,7 @@ Network Time Protocol (NTP) helper for CircuitPython - * Author(s): irinakim + * Author(s): Brent Rubell, irinakim Implementation Notes -------------------- From bc47d05ae62cbf2796b6ed1569f49ef9edf1c585 Mon Sep 17 00:00:00 2001 From: Louiswiz <75520034+min-hs@users.noreply.github.com> Date: Thu, 18 Nov 2021 11:22:23 +0900 Subject: [PATCH 3/3] Update adafruit_wiznet5k_socket.py --- adafruit_wiznet5k/adafruit_wiznet5k_socket.py | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py b/adafruit_wiznet5k/adafruit_wiznet5k_socket.py index b55c881..aa9bd16 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_socket.py @@ -325,26 +325,6 @@ def recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches gc.collect() return ret - def embed_recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches - """Reads some bytes from the connected remote address and then return recv(). - :param int bufsize: Maximum number of bytes to receive. - :param int flags: ignored, present for compatibility. - """ - # print("Socket read", bufsize) - ret = None - avail = self.available() - if avail: - if self._sock_type == SOCK_STREAM: - self._buffer += _the_interface.socket_read(self.socknum, avail)[1] - elif self._sock_type == SOCK_DGRAM: - self._buffer += _the_interface.read_udp(self.socknum, avail)[1] - gc.collect() - ret = self._buffer - # print("RET ptr:", id(ret), id(self._buffer)) - self._buffer = b"" - gc.collect() - return ret - def recvfrom(self, bufsize=0, flags=0): """Reads some bytes from the connected remote address. :param int bufsize: Maximum number of bytes to receive.