Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 06c07c8

Browse files
Christian EhlersChristian Ehlers
authored andcommitted
Added missing esp32/tools/pypic.py
Added missing esp32/tools/pypic.py
1 parent f81fb9a commit 06c07c8

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

esp32/tools/pypic.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#!/usr/bin/env python
2+
3+
from __future__ import print_function
4+
5+
import sys
6+
import argparse
7+
import errno
8+
import serial
9+
import struct
10+
import time
11+
12+
__version__ = '0.9.1'
13+
14+
CMD_PEEK = (0x0)
15+
CMD_POKE = (0x01)
16+
CMD_MAGIC = (0x02)
17+
CMD_HW_VER = (0x10)
18+
CMD_FW_VER = (0x11)
19+
CMD_PROD_ID = (0x12)
20+
CMD_SETUP_SLEEP = (0x20)
21+
CMD_GO_SLEEP = (0x21)
22+
CMD_CALIBRATE = (0x22)
23+
CMD_BAUD_CHANGE = (0x30)
24+
CMD_DFU = (0x31)
25+
26+
ANSELA_ADDR = (0x18C)
27+
ANSELB_ADDR = (0x18D)
28+
ANSELC_ADDR = (0x18E)
29+
30+
ADCON0_ADDR = (0x9D)
31+
ADCON1_ADDR = (0x9E)
32+
33+
IOCAP_ADDR = (0x391)
34+
IOCAN_ADDR = (0x392)
35+
36+
_ADCON0_CHS_POSN = (0x02)
37+
_ADCON0_ADON_MASK = (0x01)
38+
_ADCON1_ADCS_POSN = (0x04)
39+
_ADCON0_GO_nDONE_MASK = (0x02)
40+
41+
ADRESL_ADDR = (0x09B)
42+
ADRESH_ADDR = (0x09C)
43+
44+
TRISC_ADDR = (0x08E)
45+
46+
PORTA_ADDR = (0x00C)
47+
PORTC_ADDR = (0x00E)
48+
49+
WPUA_ADDR = (0x20C)
50+
51+
PCON_ADDR = (0x096)
52+
STATUS_ADDR = (0x083)
53+
54+
55+
# helper functions
56+
def eprint(*args, **kwargs):
57+
print(*args, file=sys.stderr, **kwargs)
58+
59+
def log(*args):
60+
print(' '.join(str(a) for a in args))
61+
62+
def error(msg):
63+
eprint('error:', msg)
64+
65+
def exit_with_error(code, msg):
66+
error(msg)
67+
sys.exit(code)
68+
69+
def warn(msg):
70+
eprint('warning:', msg)
71+
72+
73+
class Pypic:
74+
75+
def __init__(self, port):
76+
# we need bytesize to be 5 bits in order for the PIC to process the commands
77+
self.serial = serial.Serial(port, baudrate=115200, bytesize=serial.FIVEBITS, timeout=0.25)
78+
self.detected = False
79+
80+
try:
81+
if self.read_fw_version() < 6:
82+
raise ValueError('PIC firmware out of date')
83+
else:
84+
self.detected = True
85+
except Exception:
86+
pass
87+
88+
def _write(self, data, read=True):
89+
self.serial.write(data)
90+
if read:
91+
r_data = self.serial.read(2)
92+
if not r_data:
93+
raise Exception('Timeout while waiting for Rx data')
94+
return struct.unpack('B', r_data[0])[0]
95+
96+
def _send_cmd(self, cmd):
97+
return self._write(bytearray([cmd]))
98+
99+
def read_hw_version(self):
100+
return self._send_cmd(CMD_HW_VER)
101+
102+
def read_fw_version(self):
103+
return self._send_cmd(CMD_FW_VER)
104+
105+
def read_product_id(self):
106+
return self._send_cmd(CMD_PROD_ID)
107+
108+
def peek_memory(self, addr):
109+
return self._write(bytearray([CMD_PEEK, addr & 0xFF, (addr >> 8) & 0xFF]))
110+
111+
def poke_memory(self, addr, value):
112+
self._write(bytearray([CMD_POKE, addr & 0xFF, (addr >> 8) & 0xFF, value & 0xFF]), False)
113+
114+
def magic_write_read(self, addr, _and=0xFF, _or=0, _xor=0):
115+
return self._write(bytearray([CMD_MAGIC, addr & 0xFF, (addr >> 8) & 0xFF, _and & 0xFF, _or & 0xFF, _xor & 0xFF]))
116+
117+
def magic_write(self, addr, _and=0xFF, _or=0, _xor=0):
118+
self._write(bytearray([CMD_MAGIC, addr & 0xFF, (addr >> 8) & 0xFF, _and & 0xFF, _or & 0xFF, _xor & 0xFF]), False)
119+
120+
def toggle_bits_in_memory(self, addr, bits):
121+
self.magic_write(addr, _xor=bits)
122+
123+
def mask_bits_in_memory(self, addr, mask):
124+
self.magic_write(addr, _and=mask)
125+
126+
def set_bits_in_memory(self, addr, bits):
127+
self.magic_write(addr, _or=bits)
128+
129+
def reset_pycom_module(self):
130+
# make RC5 an output
131+
self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 5))
132+
# drive RC5 low
133+
self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 5))
134+
time.sleep(0.25)
135+
# drive RC5 high
136+
self.set_bits_in_memory(PORTC_ADDR, 1 << 5)
137+
time.sleep(0.1)
138+
139+
def enter_pycom_programming_mode(self):
140+
# make RC0 an output
141+
self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 0))
142+
# set RC0 low
143+
self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 0))
144+
self.reset_pycom_module()
145+
146+
def exit_pycom_programming_mode(self):
147+
# make RC0 an output
148+
self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 0))
149+
# set RC0 high
150+
self.set_bits_in_memory(PORTC_ADDR, 1 << 0)
151+
self.reset_pycom_module()
152+
153+
def isdetected(self):
154+
return self.detected
155+
156+
def close(self):
157+
self.serial.close()
158+
159+
160+
def main(args):
161+
parser = argparse.ArgumentParser(description='Sends internal commands to pu the Pycom module in programming mode')
162+
parser.add_argument('-p', '--port', metavar='PORT', help='the serial port used to communicate with the PIC')
163+
parser.add_argument('--enter', action='store_true', help='enter programming mode')
164+
parser.add_argument('--exit', action='store_true', help='exit programming mode')
165+
args = parser.parse_args()
166+
167+
if not args.port:
168+
exit_with_error(1, 'no serial port specified')
169+
170+
if (args.enter and args.exit) or (not args.enter and not args.exit):
171+
exit_with_error(1, 'invalid action requested')
172+
173+
pic = Pypic(args.port)
174+
175+
if pic.isdetected():
176+
if args.enter:
177+
pic.enter_pycom_programming_mode()
178+
elif args.exit:
179+
pic.exit_pycom_programming_mode()
180+
181+
pic.close()
182+
183+
184+
if __name__ == "__main__":
185+
sys.exit(main(sys.argv[1:]))

0 commit comments

Comments
 (0)