all FX functions are now safe wrapped and I added the crate to the docs also it is added to the prelude
This commit is contained in:
parent
3f847e86a6
commit
522844499e
1272 changed files with 1371 additions and 61826 deletions
229
Tools/Arduboy-Python-Utilities/fxdata-upload.py
Normal file
229
Tools/Arduboy-Python-Utilities/fxdata-upload.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
|
||||
VERSION = '1.20'
|
||||
title ="Arduboy FX data uploader v" + VERSION + " by Mr.Blinky Feb.2022-Mar.2023"
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
try:
|
||||
toolspath = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||
sys.path.insert(0, toolspath)
|
||||
from serial.tools.list_ports import comports
|
||||
from serial import Serial
|
||||
except:
|
||||
sys.stderr.write("pySerial python module not found or wrong version.\n")
|
||||
sys.stderr.write("Make sure the correct module is installed or placed at {}\n".format(toolspath))
|
||||
sys.exit(-1)
|
||||
|
||||
compatibledevices = [
|
||||
#Arduboy Leonardo
|
||||
"VID:PID=2341:0036", "VID:PID=2341:8036",
|
||||
"VID:PID=2A03:0036", "VID:PID=2A03:8036",
|
||||
#Arduboy Micro
|
||||
"VID:PID=2341:0037", "VID:PID=2341:8037",
|
||||
"VID:PID=2A03:0037", "VID:PID=2A03:8037",
|
||||
#Genuino Micro
|
||||
"VID:PID=2341:0237", "VID:PID=2341:8237",
|
||||
#Sparkfun Pro Micro 5V
|
||||
"VID:PID=1B4F:9205", "VID:PID=1B4F:9206",
|
||||
#Adafruit ItsyBitsy 5V
|
||||
"VID:PID=239A:000E", "VID:PID=239A:800E",
|
||||
]
|
||||
|
||||
manufacturers = {
|
||||
0x01 : "Spansion",
|
||||
0x14 : "Cypress",
|
||||
0x1C : "EON",
|
||||
0x1F : "Adesto(Atmel)",
|
||||
0x20 : "Micron",
|
||||
0x37 : "AMIC",
|
||||
0x9D : "ISSI",
|
||||
0xC2 : "General Plus",
|
||||
0xC8 : "Giga Device",
|
||||
0xBF : "Microchip",
|
||||
0xEF : "Winbond"
|
||||
}
|
||||
|
||||
PAGESIZE = 256
|
||||
BLOCKSIZE = 65536
|
||||
PAGES_PER_BLOCK = BLOCKSIZE // PAGESIZE
|
||||
MAX_PAGES = 65536
|
||||
bootloader_active = False
|
||||
|
||||
def print(s):
|
||||
sys.stdout.write(s + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
def getComPort(verbose):
|
||||
global bootloader_active
|
||||
devicelist = list(comports())
|
||||
for device in devicelist:
|
||||
for vidpid in compatibledevices:
|
||||
if vidpid in device[2]:
|
||||
port=device[0]
|
||||
bootloader_active = (compatibledevices.index(vidpid) & 1) == 0
|
||||
if verbose : sys.stdout.write("Found {} at port {} ".format(device[1],port))
|
||||
return port
|
||||
if verbose : print("Arduboy not found.")
|
||||
|
||||
def bootloaderStart():
|
||||
global bootloader
|
||||
## find and connect to Arduboy in bootloader mode ##
|
||||
port = getComPort(True)
|
||||
if port is None : sys.exit(-1)
|
||||
if not bootloader_active:
|
||||
print("Selecting bootloader mode...")
|
||||
try:
|
||||
bootloader = Serial(port,1200)
|
||||
time.sleep(0.1)
|
||||
bootloader.close()
|
||||
time.sleep(0.5)
|
||||
except:
|
||||
sys.stderr.write("COM port not available.\n")
|
||||
sys.exit(-1)
|
||||
#wait for disconnect and reconnect in bootloader mode
|
||||
while getComPort(False) == port :
|
||||
time.sleep(0.1)
|
||||
if bootloader_active: break
|
||||
while getComPort(False) is None : time.sleep(0.1)
|
||||
port = getComPort(True)
|
||||
|
||||
sys.stdout.write("Opening port ...")
|
||||
sys.stdout.flush()
|
||||
for retries in range(20):
|
||||
try:
|
||||
time.sleep(0.1)
|
||||
bootloader = Serial(port,57600)
|
||||
break
|
||||
except:
|
||||
if retries == 19:
|
||||
print(" Failed!")
|
||||
sys.exit(-1)
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.4)
|
||||
print("\r")
|
||||
|
||||
def getVersion():
|
||||
bootloader.write(b"V")
|
||||
return int(bootloader.read(2))
|
||||
|
||||
def getJedecID():
|
||||
bootloader.write(b"j")
|
||||
jedec_id = bootloader.read(3)
|
||||
time.sleep(0.5)
|
||||
bootloader.write(b"j")
|
||||
jedec_id2 = bootloader.read(3)
|
||||
if jedec_id2 != jedec_id or jedec_id == b'\x00\x00\x00' or jedec_id == b'\xFF\xFF\xFF':
|
||||
sys.stderr.write("No FX flash chip detected.\n")
|
||||
sys.exit(-1)
|
||||
return bytearray(jedec_id)
|
||||
|
||||
def bootloaderExit():
|
||||
global bootloader
|
||||
bootloader.write(b"E")
|
||||
bootloader.read(1)
|
||||
|
||||
################################################################################
|
||||
|
||||
def writeFlash(pagenumber, flashdata):
|
||||
bootloaderStart()
|
||||
|
||||
#check version
|
||||
if getVersion() < 13:
|
||||
sys.stderr.write("Bootloader has no flash cart support\nWrite aborted!\n")
|
||||
sys.exit(-1)
|
||||
|
||||
## detect flash cart ##
|
||||
jedec_id = getJedecID()
|
||||
if jedec_id[0] in manufacturers.keys():
|
||||
manufacturer = manufacturers[jedec_id[0]]
|
||||
else:
|
||||
manufacturer = "unknown"
|
||||
capacity = 1 << jedec_id[2]
|
||||
print("Detected FX flash chip with ID {:02X}{:02X}{:02X} size {}KB".format(jedec_id[0],jedec_id[1],jedec_id[2],capacity // 1024))
|
||||
|
||||
oldtime=time.time()
|
||||
# when starting partially in a block, preserve the beginning of old block data
|
||||
if pagenumber % PAGES_PER_BLOCK:
|
||||
blocklen = pagenumber % PAGES_PER_BLOCK * PAGESIZE
|
||||
blockaddr = pagenumber // PAGES_PER_BLOCK * PAGES_PER_BLOCK
|
||||
#read partial block data start
|
||||
bootloader.write(bytearray([ord("A"), blockaddr >> 8, blockaddr & 0xFF]))
|
||||
bootloader.read(1)
|
||||
bootloader.write(bytearray([ord("g"), (blocklen >> 8) & 0xFF, blocklen & 0xFF,ord("C")]))
|
||||
flashdata = bootloader.read(blocklen) + flashdata
|
||||
pagenumber = blockaddr
|
||||
|
||||
# when ending partially in a block, preserve the ending of old block data
|
||||
if len(flashdata) % BLOCKSIZE:
|
||||
blocklen = BLOCKSIZE - len(flashdata) % BLOCKSIZE
|
||||
blockaddr = pagenumber + len(flashdata) // PAGESIZE
|
||||
#read partial block data end
|
||||
bootloader.write(bytearray([ord("A"), blockaddr >> 8, blockaddr & 0xFF]))
|
||||
bootloader.read(1)
|
||||
bootloader.write(bytearray([ord("g"), (blocklen >> 8) & 0xFF, blocklen & 0xFF,ord("C")]))
|
||||
flashdata += bootloader.read(blocklen)
|
||||
|
||||
## write to flash cart ##
|
||||
blocks = len(flashdata) // BLOCKSIZE
|
||||
for block in range (blocks):
|
||||
if (block & 1 == 0) or verifyAfterWrite:
|
||||
bootloader.write(b"x\xC2") #RGB LED RED, buttons disabled
|
||||
else:
|
||||
bootloader.write(b"x\xC0") #RGB LED OFF, buttons disabled
|
||||
bootloader.read(1)
|
||||
sys.stdout.write("\rWriting block {}/{} ".format(block + 1,blocks))
|
||||
sys.stdout.flush()
|
||||
blockaddr = pagenumber + block * BLOCKSIZE // PAGESIZE
|
||||
blocklen = BLOCKSIZE
|
||||
#write block
|
||||
bootloader.write(bytearray([ord("A"), blockaddr >> 8, blockaddr & 0xFF]))
|
||||
bootloader.read(1)
|
||||
bootloader.write(bytearray([ord("B"), (blocklen >> 8) & 0xFF, blocklen & 0xFF,ord("C")]))
|
||||
bootloader.write(flashdata[block * BLOCKSIZE : block * BLOCKSIZE + blocklen])
|
||||
bootloader.read(1)
|
||||
if verifyAfterWrite:
|
||||
sys.stdout.write("\rVerifying block {}/{}".format(block + 1,blocks))
|
||||
sys.stdout.flush()
|
||||
bootloader.write(b"x\xC1") #RGB BLUE RED, buttons disabled
|
||||
bootloader.read(1)
|
||||
bootloader.write(bytearray([ord("A"), blockaddr >> 8, blockaddr & 0xFF]))
|
||||
bootloader.read(1)
|
||||
bootloader.write(bytearray([ord("g"), (blocklen >> 8) & 0xFF, blocklen & 0xFF,ord("C")]))
|
||||
if bootloader.read(blocklen) != flashdata[block * BLOCKSIZE : block * BLOCKSIZE + blocklen]:
|
||||
sys.stderr.write(" verify failed!\n\nWrite aborted.")
|
||||
bootloader.write(b"x\x40")#RGB LED off, buttons enabled
|
||||
bootloader.read(1)
|
||||
sys.exit(-1)
|
||||
|
||||
#write complete
|
||||
bootloader.write(b"x\x44")#RGB LED GREEN, buttons enabled
|
||||
bootloader.read(1)
|
||||
time.sleep(0.5)
|
||||
bootloader.write(b"x\x40")#RGB LED off, buttons enabled
|
||||
bootloader.read(1)
|
||||
bootloader.close()
|
||||
print("\rFX Data uploaded successfully")
|
||||
|
||||
################################################################################
|
||||
|
||||
print(title)
|
||||
|
||||
if (len(sys.argv) != 2) or (os.path.isfile(sys.argv[1]) != True) :
|
||||
sys.stderr.write("FX data file not found.\n")
|
||||
|
||||
filename = os.path.abspath(sys.argv[1])
|
||||
|
||||
verifyAfterWrite = True
|
||||
|
||||
print('Uploading FX data from file "{}"'.format(filename))
|
||||
f = open(filename,"rb")
|
||||
programdata = bytearray(f.read())
|
||||
f.close()
|
||||
if len(programdata) % PAGESIZE:
|
||||
programdata += b'\xFF' * (PAGESIZE - (len(programdata) % PAGESIZE))
|
||||
programpage = MAX_PAGES - (len(programdata) // PAGESIZE)
|
||||
|
||||
writeFlash(programpage, programdata)
|
Loading…
Add table
Add a link
Reference in a new issue