Skip to content

Commit 9e2d536

Browse files
authored
Merge pull request #49 from AdamCummick/main
Add W5100S chip and NTP
2 parents d93071f + fb9de78 commit 9e2d536

File tree

3 files changed

+200
-39
lines changed

3 files changed

+200
-39
lines changed

adafruit_wiznet5k/adafruit_wiznet5k.py

Lines changed: 128 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
REG_GAR = const(0x0001) # Gateway IP Address
4646
REG_SUBR = const(0x0005) # Subnet Mask Address
4747
REG_VERSIONR_W5500 = const(0x0039) # W5500 Silicon Version
48+
REG_VERSIONR_W5100S = const(0x0080) # W5100S Silicon Version
4849
REG_SHAR = const(0x0009) # Source Hardware Address
4950
REG_SIPR = const(0x000F) # Source IP Address
5051
REG_PHYCFGR = const(0x002E) # W5500 PHY Configuration
52+
REG_PHYCFGR_W5100S = const(0x003C) # W5100S PHY Configuration
5153

5254
# Wiznet5k Socket Registers
5355
REG_SNMR = const(0x0000) # Socket n Mode
@@ -99,6 +101,7 @@
99101

100102
CH_SIZE = const(0x100)
101103
SOCK_SIZE = const(0x800) # MAX W5k socket size
104+
SOCK_MASK = const(0x7FF)
102105
# Register commands
103106
MR_RST = const(0x80) # Mode Register RST
104107
# Socket mode register
@@ -116,6 +119,7 @@
116119

117120
# Maximum number of sockets to support, differs between chip versions.
118121
W5200_W5500_MAX_SOCK_NUM = const(0x08)
122+
W5100_MAX_SOCK_NUM = const(0x04)
119123
SOCKET_INVALID = const(255)
120124

121125
# UDP socket struct.
@@ -179,8 +183,19 @@ def __init__(
179183
self.src_port = 0
180184
self._dns = 0
181185

182-
# Set DHCP
186+
# First, wait link status is on
187+
# to avoid the code during DHCP, socket listen, connect ...
188+
# assert self.link_status, "Ethernet cable disconnected!"
189+
start_time = time.monotonic()
190+
while True:
191+
if self.link_status or ((time.monotonic() - start_time) > 5):
192+
break
193+
time.sleep(1)
194+
if self._debug:
195+
print("My Link is:", self.link_status)
183196
self._dhcp_client = None
197+
198+
# Set DHCP
184199
if is_dhcp:
185200
ret = self.set_dhcp(hostname, dhcp_timeout)
186201
if ret != 0:
@@ -198,16 +213,6 @@ def set_dhcp(self, hostname=None, response_timeout=30):
198213
if self._debug:
199214
print("* Initializing DHCP")
200215

201-
# First, wait link status is on
202-
# to avoid the code during DHCP - assert self.link_status, "Ethernet cable disconnected!"
203-
start_time = time.monotonic()
204-
while True:
205-
if self.link_status or ((time.monotonic() - start_time) > 5):
206-
break
207-
time.sleep(1)
208-
if self._debug:
209-
print("My Link is:", self.link_status)
210-
211216
# Return IP assigned by DHCP
212217
self._dhcp_client = dhcp.DHCP(
213218
self, self.mac_address, hostname, response_timeout, debug=self._debug
@@ -251,6 +256,8 @@ def max_sockets(self):
251256
"""Returns max number of sockets supported by chip."""
252257
if self._chip_type == "w5500":
253258
return W5200_W5500_MAX_SOCK_NUM
259+
if self._chip_type == "w5100s":
260+
return W5100_MAX_SOCK_NUM
254261
return -1
255262

256263
@property
@@ -319,6 +326,9 @@ def link_status(self):
319326
if self._chip_type == "w5500":
320327
data = self.read(REG_PHYCFGR, 0x00)
321328
return data[0] & 0x01
329+
if self._chip_type == "w5100s":
330+
data = self.read(REG_PHYCFGR_W5100S, 0x00)
331+
return data[0] & 0x01
322332
return 0
323333

324334
def remote_port(self, socket_num):
@@ -367,25 +377,47 @@ def _w5100_init(self):
367377
self.write(0x1E, ctrl_byte, 2)
368378
self.write(0x1F, ctrl_byte, 2)
369379
else:
370-
return 0
380+
# Detect if chip is Wiznet W5100S
381+
if self.detect_w5100s() == 1:
382+
pass
383+
else:
384+
return 0
371385
return 1
372386

373387
def detect_w5500(self):
374388
"""Detects W5500 chip."""
389+
self._chip_type = "w5500"
375390
assert self.sw_reset() == 0, "Chip not reset properly!"
376391
self._write_mr(0x08)
377-
assert self._read_mr()[0] == 0x08, "Expected 0x08."
392+
# assert self._read_mr()[0] == 0x08, "Expected 0x08."
393+
if self._read_mr()[0] != 0x08:
394+
return -1
378395

379396
self._write_mr(0x10)
380-
assert self._read_mr()[0] == 0x10, "Expected 0x10."
397+
# assert self._read_mr()[0] == 0x10, "Expected 0x10."
398+
if self._read_mr()[0] != 0x10:
399+
return -1
381400

382401
self._write_mr(0x00)
383-
assert self._read_mr()[0] == 0x00, "Expected 0x00."
402+
# assert self._read_mr()[0] == 0x00, "Expected 0x00."
403+
if self._read_mr()[0] != 0x00:
404+
return -1
384405

385406
if self.read(REG_VERSIONR_W5500, 0x00)[0] != 0x04:
386407
return -1
387-
self._chip_type = "w5500"
388-
self._ch_base_msb = 0x10
408+
# self._chip_type = "w5500"
409+
# self._ch_base_msb = 0x10
410+
return 1
411+
412+
def detect_w5100s(self):
413+
"""Detects W5100S chip."""
414+
self._chip_type = "w5100s"
415+
# sw reset
416+
assert self.sw_reset() == 0, "Chip not reset properly!"
417+
if self.read(REG_VERSIONR_W5100S, 0x00)[0] != 0x51:
418+
return -1
419+
420+
self._ch_base_msb = 0x0400
389421
return 1
390422

391423
def sw_reset(self):
@@ -396,7 +428,9 @@ def sw_reset(self):
396428
mode_reg = self._read_mr()
397429
self._write_mr(0x80)
398430
mode_reg = self._read_mr()
399-
if mode_reg[0] != 0x00:
431+
432+
# W5100S case => 0x03
433+
if (mode_reg[0] != 0x00) and (mode_reg[0] != 0x03):
400434
return -1
401435
return 0
402436

@@ -418,9 +452,16 @@ def read(self, addr, callback, length=1, buffer=None):
418452
419453
"""
420454
with self._device as bus_device:
421-
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
422-
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
423-
bus_device.write(bytes([callback])) # pylint: disable=no-member
455+
if self._chip_type == "w5500":
456+
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
457+
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
458+
bus_device.write(bytes([callback])) # pylint: disable=no-member
459+
else:
460+
# if self._chip_type == "w5100s":
461+
bus_device.write(bytes([0x0F])) # pylint: disable=no-member
462+
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
463+
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
464+
424465
if buffer is None:
425466
self._rxbuf = bytearray(length)
426467
bus_device.readinto(self._rxbuf) # pylint: disable=no-member
@@ -437,9 +478,15 @@ def write(self, addr, callback, data):
437478
438479
"""
439480
with self._device as bus_device:
440-
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
441-
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
442-
bus_device.write(bytes([callback])) # pylint: disable=no-member
481+
if self._chip_type == "w5500":
482+
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
483+
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
484+
bus_device.write(bytes([callback])) # pylint: disable=no-member
485+
else:
486+
# if self._chip_type == "w5100s":
487+
bus_device.write(bytes([0xF0])) # pylint: disable=no-member
488+
bus_device.write(bytes([addr >> 8])) # pylint: disable=no-member
489+
bus_device.write(bytes([addr & 0xFF])) # pylint: disable=no-member
443490

444491
if hasattr(data, "from_bytes"):
445492
bus_device.write(bytes([data])) # pylint: disable=no-member
@@ -687,14 +734,28 @@ def socket_read(self, socket_num, length):
687734
# Read the starting save address of the received data
688735
ptr = self._read_snrx_rd(socket_num)
689736

690-
# Read data from the starting address of snrx_rd
691-
ctrl_byte = 0x18 + (socket_num << 5)
737+
if self._chip_type == "w5500":
738+
# Read data from the starting address of snrx_rd
739+
ctrl_byte = 0x18 + (socket_num << 5)
692740

693-
resp = self.read(ptr, ctrl_byte, ret)
741+
resp = self.read(ptr, ctrl_byte, ret)
742+
else:
743+
# if self._chip_type == "w5100s":
744+
offset = ptr & SOCK_MASK
745+
src_addr = offset + (socket_num * SOCK_SIZE + 0x6000)
746+
if offset + ret > SOCK_SIZE:
747+
size = SOCK_SIZE - offset
748+
resp1 = self.read(src_addr, 0x00, size)
749+
size = ret - size
750+
src_addr = socket_num * SOCK_SIZE + 0x6000
751+
resp2 = self.read(src_addr, 0x00, size)
752+
resp = resp1 + resp2
753+
else:
754+
resp = self.read(src_addr, 0x00, ret)
694755

695756
# After reading the received data, update Sn_RX_RD to the increased
696757
# value as many as the reading size.
697-
ptr += ret
758+
ptr = (ptr + ret) & 0xFFFF
698759
self._write_snrx_rd(socket_num, ptr)
699760

700761
# Notify the W5k of the updated Sn_Rx_RD
@@ -740,8 +801,29 @@ def socket_write(self, socket_num, buffer, timeout=0):
740801

741802
# Read the starting address for saving the transmitting data.
742803
ptr = self._read_sntx_wr(socket_num)
743-
offset = ptr & 0x07FF
744-
dst_addr = offset + (socket_num * 2048 + 0x8000)
804+
offset = ptr & SOCK_MASK
805+
if self._chip_type == "w5500":
806+
dst_addr = offset + (socket_num * SOCK_SIZE + 0x8000)
807+
808+
txbuf = buffer[:ret]
809+
cntl_byte = 0x14 + (socket_num << 5)
810+
self.write(dst_addr, cntl_byte, txbuf)
811+
812+
else:
813+
# if self._chip_type == "w5100s":
814+
dst_addr = offset + (socket_num * SOCK_SIZE + 0x4000)
815+
816+
if offset + ret > SOCK_SIZE:
817+
size = SOCK_SIZE - offset
818+
txbuf = buffer[0:size]
819+
self.write(dst_addr, 0x00, txbuf)
820+
txbuf = buffer[size:ret]
821+
size = ret - size
822+
dst_addr = socket_num * SOCK_SIZE + 0x4000
823+
self.write(dst_addr, 0x00, txbuf)
824+
else:
825+
txbuf = buffer[:ret]
826+
self.write(dst_addr, 0x00, buffer[:ret])
745827

746828
# update sn_tx_wr to the value + data size
747829
ptr = (ptr + ret) & 0xFFFF
@@ -864,10 +946,22 @@ def _read_snmr(self, sock):
864946

865947
def _write_socket(self, sock, address, data):
866948
"""Write to a W5k socket register."""
867-
cntl_byte = (sock << 5) + 0x0C
868-
return self.write(address, cntl_byte, data)
949+
if self._chip_type == "w5500":
950+
cntl_byte = (sock << 5) + 0x0C
951+
return self.write(address, cntl_byte, data)
952+
if self._chip_type == "w5100s":
953+
cntl_byte = 0
954+
return self.write(
955+
self._ch_base_msb + sock * CH_SIZE + address, cntl_byte, data
956+
)
957+
return None
869958

870959
def _read_socket(self, sock, address):
871960
"""Read a W5k socket register."""
872-
cntl_byte = (sock << 5) + 0x08
873-
return self.read(address, cntl_byte)
961+
if self._chip_type == "w5500":
962+
cntl_byte = (sock << 5) + 0x08
963+
return self.read(address, cntl_byte)
964+
if self._chip_type == "w5100s":
965+
cntl_byte = 0
966+
return self.read(self._ch_base_msb + sock * CH_SIZE + address, cntl_byte)
967+
return None
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
`wiznet5k_ntp`
7+
================================================================================
8+
9+
Network Time Protocol (NTP) helper for CircuitPython
10+
11+
* Author(s): Brent Rubell, irinakim
12+
13+
Implementation Notes
14+
--------------------
15+
**Hardware:**
16+
**Software and Dependencies:**
17+
18+
19+
"""
20+
import time
21+
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
22+
23+
##__version__ = "0.0.0-auto.0"
24+
##__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NTP.git"
25+
26+
27+
class NTP:
28+
"""
29+
Wiznet5k NTP Client
30+
:param iface: Wiznet 5k object
31+
:param str ntp_address: The hostname of the NTP server
32+
:param int utc: Numbers of hours to offset time from UTC
33+
:param bool debug: Enable debugging output.
34+
"""
35+
36+
def __init__(self, iface, ntp_address, utc, debug=False):
37+
self._debug = debug
38+
self._iface = iface
39+
socket.set_interface(self._iface)
40+
self._sock = socket.socket(type=socket.SOCK_DGRAM)
41+
self._sock.settimeout(1)
42+
self._utc = utc
43+
44+
self._ntp_server = ntp_address
45+
self._host = 0
46+
self._request_id = 0 # request identifier
47+
48+
self._pkt_buf_ = bytearray([0x23] + [0x00] * 55)
49+
50+
def get_time(self):
51+
"""
52+
Get the time from the NTP server
53+
:return: time in seconds since the epoch
54+
"""
55+
self._sock.bind((None, 50001))
56+
self._sock.sendto(self._pkt_buf_, (self._ntp_server, 123))
57+
while True:
58+
data = self._sock.recv()
59+
if data:
60+
sec = data[40:44]
61+
int_cal = int.from_bytes(sec, "big")
62+
cal = int_cal - 2208988800 + self._utc * 3600
63+
cal = time.localtime(cal)
64+
return cal

adafruit_wiznet5k/adafruit_wiznet5k_wsgiserver.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ def set_interface(iface):
4444
socket.set_interface(iface)
4545

4646

47-
# Maximum number of sockets for the web server (number of connections we can hold)
48-
MAX_SOCK_NUM = const(6)
49-
5047
# pylint: disable=invalid-name
5148
class WSGIServer:
5249
"""
@@ -62,14 +59,20 @@ def __init__(self, port=80, debug=False, application=None):
6259

6360
self._response_status = None
6461
self._response_headers = []
62+
if _the_interface.chip == "w5100s":
63+
self.MAX_SOCK_NUM = const(2)
64+
else:
65+
self.MAX_SOCK_NUM = const(6)
66+
if self._debug:
67+
print("Max sockets: ", self.MAX_SOCK_NUM)
6568

6669
def start(self):
6770
"""
6871
Starts the server and begins listening for incoming connections.
6972
Call update_poll in the main loop for the application callable to be
7073
invoked on receiving an incoming request.
7174
"""
72-
for _ in range(MAX_SOCK_NUM):
75+
for _ in range(self.MAX_SOCK_NUM):
7376
new_sock = socket.socket()
7477
new_sock.settimeout(self._timeout)
7578
new_sock.bind((None, self.port))
@@ -95,7 +98,7 @@ def update_poll(self):
9598
for sock in self._client_sock:
9699
if sock.status == wiznet5k.adafruit_wiznet5k.SNSR_SOCK_CLOSED:
97100
self._client_sock.remove(sock)
98-
for _ in range(len(self._client_sock), MAX_SOCK_NUM):
101+
for _ in range(len(self._client_sock), self.MAX_SOCK_NUM):
99102
try:
100103
new_sock = socket.socket()
101104
new_sock.settimeout(self._timeout)

0 commit comments

Comments
 (0)