-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmb_23LC1024.py
147 lines (114 loc) · 5.43 KB
/
mb_23LC1024.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
mb_23LC1024.py
Micropython module/driver for Microchip 23LC1024 SPI SRAM with RP2040
Author: mark@marksbench.com
Version: 0.1, 2021-05-07
**NOTE: There is no guarantee that this software will work in the way you expect (or at all).
**Use at your own risk.
Prerequisites:
- RP2040 silicon (tested with Raspberry Pi Pico)
- MicroPython v1.15 on 2021-04-18; Raspberry Pi Pico with RP2040
- 23LC1024 connected to hardware SPI port0 or port1 pins
- Dedicated /CS pin (can be any GP pin that's not already being used for SPI). Do not tie /CS to
GND - the 23LC1024 requires state changes on /CS to function properly.
Usage:
- from machine import Pin, SPI
- import utime
- import mb_23LC1024
- Set up SPI using a hardware SPI port 0 or 1. Polarity and phase are both 0.
- specify /CS pin (can be any GP pin that's not already being used for SPI):
cs = GP#
- Create constructor:
thisMemoryChipDeviceName = mb_23LC1024.mb_23LC1024(spi, cs)
- To write a single byte to an address:
thisMemoryChipDeviceName.write_byte(address, value)
- To read a single byte from an address:
thisMemoryChipDeviceName.read_byte(address)
- See mb_23LC1024_example.py
For more information, consult the Raspberry Pi Pico MicroPython SDK documentation at:
https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-python-sdk.pdf
and the Microchip 23LC1024 datasheet at:
http://ww1.microchip.com/downloads/en/DeviceDoc/20005142C.pdf
"""
from machine import Pin, SPI
import utime
# Instruction set for 23LC1024
_READ = const(0x03)
_WRITE = const(0x02)
_EDIO = const(0x3b) # Dual I/O access (SDI bus mode)
_EQIO = const(0x38) # Quad I/O access (SQI bus mode)
_RSTIO = const(0xff) # Reset dual and quad I/O (revert to SPI bus mode)
_RDMR = const(0x05) # Read mode register
_WRMR = const(0x01) # Write mode register
# The WRMR register instruction has 8 bits, the 2 MSb of which set the MODE register.
# 0 0 = byte mode, 1 0 = Page mode, 0 1 = Sequential mode (default), 1 1 = reserved
# Bits 0 through 5 are reserved and should always be set to 0
# Only going to use byte mode in this library, though.
# The RDMR register instruction reads the MODE register. Not really needed at this point.
# Mode selection
_MODE_BYTE = const(0x00) # binary 00000000
_MODE_PAGE = const(0x40) # binary 01000000
_MODE_SEQ = const(0xc0) # binary 11000000 (default mode)
# The 23LC1024 is a 128kib*8 (1Mbit) device. Maximum address available is 131071 (dec)
_MAX_ADDRESS = const(131071)
class mb_23LC1024:
"""Driver for 23LC1024 SPI SRAM module"""
def __init__(self, spi, cs):
# Init with SPI settings
self.spi = spi
# Init /CS pin
self.cs = Pin(cs, Pin.OUT)
# The datasheet says a high-low transition is required on /CS to enter active state after startup
self.cs.value(1)
self.cs.value(0)
self.cs.value(1)
# Set mode (setting to byte mode)
self.cs.value(0)
self.spi.write(bytearray([_WRMR, 0b00000000]))
self.cs.value(1)
utime.sleep_us(50)
def write_byte(self, address, data):
# Check to make sure the address is within 0 and 131071
if((address > 131071) or (address < 0)):
raise ValueError("Address is outside of device address range (0 to 131071)")
return()
# Now check to make sure the data is within 0 and 255
if((data > 255) or (data < 0)):
raise ValueError("You can only pass an 8-bit data value (0-255) to this function")
return()
# Break the address into three bytes to send (we're using 8-bit SPI)
# SRAM addresses on the 23LC1024 are 24 bits, with the first 7 MSbs as "don't care" bits. This is a 1Mbit
# device, so it's 128kiB. So the last 17 bits (1 1111 1111 1111 1111 = 131071 in decimal
address_byte = [0,0,0]
address_byte[2] = address & 0x0000ff
address_byte[1] = (address & 0x00ff00) >> 8
address_byte[0] = (address & 0xff0000) >> 16
# Set the /CS pin low
self.cs.value(0)
# Write the byte of data to the selected address, using a bytearray
self.spi.write(bytearray([_WRITE, address_byte[0], address_byte[1], address_byte[2], data]))
# Set /CS pin high
self.cs.value(1)
return()
def read_byte(self, address):
# Check to make sure the address is within 0 and 131071
if((address > 131071) or (address < 0)):
raise ValueError("Address is outside of device address range (0 to 131071 (0x1ffff))")
return()
# Break the address into three bytes to send (using 8-bit SPI)
address_byte = [0,0,0]
address_byte[2] = address & 0x0000ff
address_byte[1] = (address & 0x00ff00) >> 8
address_byte[0] = (address & 0xff0000) >> 16
# Set /CS pin low
self.cs.value(0)
# Write the read command and address to read from
self.spi.write(bytearray([_READ, address_byte[0], address_byte[1], address_byte[2]]))
# Returned byte is what we're looking for
self.value_read = self.spi.read(1)
# Set /CS pin high
self.cs.value(1)
# Convert from byte to int
self.value_read = int.from_bytes(self.value_read, "big")
# Return value to calling program
return(self.value_read)