Browse Source

More Pythonic API for A and B, implement W

The LPC class now has properties for getting and setting echo, baudrate,
and stopbits.  Low-level access is now private to avoid letting users
break the public properties.

Also, a new write_ram method implements the W command.  If no number of
bytes is specified, the length of the data is used.
Clara Hobbs 6 years ago
parent
commit
3d93cf8b8c
1 changed files with 89 additions and 37 deletions
  1. 89
    37
      alpaca_isp/__init__.py

+ 89
- 37
alpaca_isp/__init__.py View File

22
     """Interface for LPC in-system programming"""
22
     """Interface for LPC in-system programming"""
23
 
23
 
24
     def __init__(self, serport, baudrate=115200, clock=12000, timeout=0.1):
24
     def __init__(self, serport, baudrate=115200, clock=12000, timeout=0.1):
25
-        self.serport = serport
26
-        self.baudrate = baudrate
27
-        self.clock = clock
28
-        self.timeout = timeout
25
+        self._serport = serport
26
+        self._baudrate = baudrate
27
+        self._clock = clock
28
+        self._timeout = timeout
29
         self._echo = True
29
         self._echo = True
30
 
30
 
31
     def open(self):
31
     def open(self):
32
         """Open the serial port to communicate with the microcontroller"""
32
         """Open the serial port to communicate with the microcontroller"""
33
-        self._uart = serial.Serial(self.serport, baudrate=self.baudrate,
34
-                timeout=self.timeout)
33
+        self._uart = serial.Serial(self._serport, baudrate=self._baudrate,
34
+                timeout=self._timeout)
35
 
35
 
36
-    def readline(self):
37
-        """Read a line terminated with '\r\n'"""
36
+    def _readline(self):
37
+        """Read a line terminated with b'\r\n'"""
38
         s = b""
38
         s = b""
39
         while True:
39
         while True:
40
             c = self._uart.read(1)
40
             c = self._uart.read(1)
45
             if s.endswith(b"\r\n"):
45
             if s.endswith(b"\r\n"):
46
                 return s
46
                 return s
47
 
47
 
48
-    def writeline(self, line):
49
-        """Write a line to the microcontroller and read the echoed response"""
48
+    def _writeline(self, line, plain=False):
49
+        """Write a line to the microcontroller and read the echoed response
50
+
51
+        If plain is True, the command is taken to be raw binary data.
52
+        """
50
         self._uart.write(line)
53
         self._uart.write(line)
51
         self._uart.flush()
54
         self._uart.flush()
52
 
55
 
53
-        if not self._echo:
56
+        # If echo is disabled, don't try to read back what we sent
57
+        if not self.echo:
54
             return
58
             return
59
+
55
         # Read the response, raising the exception if there is one
60
         # Read the response, raising the exception if there is one
56
-        response = self.readline()
61
+        if plain:
62
+            response = self._uart.read(len(line))
63
+        else:
64
+            response = self._readline()
57
         # If we got the wrong response, raise an exception
65
         # If we got the wrong response, raise an exception
58
         if response != line:
66
         if response != line:
59
             raise ISPError("Wrong text echoed: {}".format(response))
67
             raise ISPError("Wrong text echoed: {}".format(response))
60
 
68
 
61
-    def send_command_raw(self, cmd):
69
+    def _send_command_raw(self, cmd):
62
         """Send a command to the microcontroller, returning bytes"""
70
         """Send a command to the microcontroller, returning bytes"""
63
-        self.writeline(cmd)
64
-        return self.readline()
71
+        self._writeline(cmd)
72
+        return self._readline()
65
 
73
 
66
-    def send_command(self, cmd):
74
+    def _send_command(self, cmd):
67
         """Send a command to the microcontroller, returning the result"""
75
         """Send a command to the microcontroller, returning the result"""
68
-        rr = self.send_command_raw(cmd)
76
+        rr = self._send_command_raw(cmd)
69
         lr = [int(n) for n in rr.split()]
77
         lr = [int(n) for n in rr.split()]
70
         lr[0] = ReturnCode(lr[0])
78
         lr[0] = ReturnCode(lr[0])
71
         return lr
79
         return lr
72
 
80
 
73
-    def start_isp(self, delay=0.01):
81
+    def enter_isp(self, delay=0.01):
74
         """Enter ISP mode by controlling the DTR (/RST) and RTS (/ISP) lines
82
         """Enter ISP mode by controlling the DTR (/RST) and RTS (/ISP) lines
75
 
83
 
76
-        This operation is performed synchronously.
84
+        This operation is performed synchronously, with delays.
77
         """
85
         """
78
         self._uart.rts = True
86
         self._uart.rts = True
79
         time.sleep(delay)
87
         time.sleep(delay)
83
         time.sleep(delay)
91
         time.sleep(delay)
84
         self._uart.rts = False
92
         self._uart.rts = False
85
 
93
 
86
-    def start_comms(self, verbose=False):
87
-        """Start communication with the microcontroller"""
94
+    def synchronize(self, verbose=False):
95
+        """Begin communication with the microcontroller"""
88
         # Synchronize with the MCU
96
         # Synchronize with the MCU
89
         while True:
97
         while True:
90
             # Send a ?
98
             # Send a ?
94
                 print("?")
102
                 print("?")
95
             # Receive a response
103
             # Receive a response
96
             try:
104
             try:
97
-                s = self.readline()
105
+                s = self._readline()
98
             except RecvTimeout:
106
             except RecvTimeout:
99
                 continue
107
                 continue
100
             # If we got the right response, break
108
             # If we got the right response, break
101
             if s == b"Synchronized\r\n":
109
             if s == b"Synchronized\r\n":
102
                 break
110
                 break
103
         # Tell the MCU we've synchronized
111
         # Tell the MCU we've synchronized
104
-        s = self.send_command_raw(b"Synchronized\r\n")
112
+        s = self._send_command_raw(b"Synchronized\r\n")
105
         # Next, it should say OK, at which point we're done synchronizing
113
         # Next, it should say OK, at which point we're done synchronizing
106
         if s != b"OK\r\n":
114
         if s != b"OK\r\n":
107
             raise ISPError("Wrong response during synchronization")
115
             raise ISPError("Wrong response during synchronization")
108
 
116
 
109
         # Send clock frequency in kHz
117
         # Send clock frequency in kHz
110
-        s = self.send_command_raw("{:d}\r\n".format(self.clock).encode("utf-8"))
118
+        s = self._send_command_raw("{:d}\r\n".format(self._clock).encode(
119
+            "utf-8"))
111
         # Next, it should say OK
120
         # Next, it should say OK
112
         if s != b"OK\r\n":
121
         if s != b"OK\r\n":
113
             raise ISPError("Wrong response during synchronization")
122
             raise ISPError("Wrong response during synchronization")
118
 
127
 
119
     def unlock(self, code="23130"):
128
     def unlock(self, code="23130"):
120
         """Unlock the flash write, erase, and go commands"""
129
         """Unlock the flash write, erase, and go commands"""
121
-        return self.send_command("U {}\r\n".format(code).encode("utf-8"))
130
+        return self._send_command("U {}\r\n".format(code).encode("utf-8"))
131
+
132
+    @property
133
+    def baudrate(self):
134
+        """The baud rate used for communication"""
135
+        return self._uart.baudrate
136
+
137
+    @baudrate.setter
138
+    def baudrate(self, br):
139
+        r = self._send_command("B {} {}\r\n".format(br,
140
+            self._uart.stopbits).encode("utf-8"))
141
+        # Update the baud rate for our UART
142
+        if r[0] != ReturnCode.CMD_SUCCESS:
143
+            raise ISPError(r)
144
+        self._uart.baudrate = br
145
+
146
+    @property
147
+    def stopbits(self):
148
+        """The number of stop bits used for communication"""
149
+        return self._uart.stopbits
150
+
151
+    @stopbits.setter
152
+    def stopbits(self, sb):
153
+        r = self._send_command("B {} {}\r\n".format(self._uart.baudrate,
154
+            sb).encode("utf-8"))
155
+        # Update the number of stop bits for our UART
156
+        if r[0] != ReturnCode.CMD_SUCCESS:
157
+            raise ISPError(r)
158
+        self._uart.stopbits = sb
159
+
160
+    @property
161
+    def echo(self):
162
+        """Whether the microcontroller echoes characters back to the host"""
163
+        return self._echo
164
+
165
+    @echo.setter
166
+    def echo(self, setting):
167
+        setting = bool(setting)
168
+        r = self._send_command("A {}\r\n".format(int(setting)).encode("utf-8"))
169
+        if r[0] != ReturnCode.CMD_SUCCESS:
170
+            raise ISPError(r)
171
+        self._echo = setting
122
 
172
 
123
-    def setbaudrate(self, baudrate, stopbits):
124
-        """Update the baud rate and number of stop bits"""
125
-        r = self.send_command("B {} {}\r\n".format(baudrate, stopbits).encode(
173
+    def write_ram(self, start, data, count=None):
174
+        """Write count bytes from data to RAM at the given start address
175
+        
176
+        Start and count must be multiples of four.  If count is not specified,
177
+        len(data) is used.
178
+        """
179
+        # Get the length of the data we're writing
180
+        if count is None:
181
+            count = len(data)
182
+        # Ask to write data
183
+        r = self._send_command("W {} {}\r\n".format(start, count).encode(
126
             "utf-8"))
184
             "utf-8"))
127
-        # Update the baud rate and number of stop bits for our UART connection
185
+        # If the MCU is okay with what we intend to do, send the data
128
         if r[0] == ReturnCode.CMD_SUCCESS:
186
         if r[0] == ReturnCode.CMD_SUCCESS:
129
-            self._uart.baudrate = baudrate
130
-            self._uart.stopbits = stopbits
131
-        return r
132
-
133
-    def echo(self, setting):
134
-        """Set whether echo is enabled or disabled"""
135
-        r = self.send_command("A {}\r\n".format(int(setting)).encode("utf-8"))
136
-        self._echo = setting
187
+            # NOTE: this is right for LPC8xx chips, not others
188
+            ok = self._writeline(data[:count], plain=True)
137
         return r
189
         return r
138
 
190
 
139
 
191
 

Loading…
Cancel
Save