def main(): caterina_overwrite = False flash_addr = 0 flash_data = bytearray(chr(0xFF) * 32768) flash_page = 1 flash_page_count = 0 flash_page_used = [False] * 256 ################################################################################ bootloader = BootLoader() bootloader.start() # Erase print("\nErasing sketch startup page") bootloader.write(b"A\x00\x00") # select page 0 bootloader.read(1) bootloader.write( b"B\x00\x00F") # writing 0 length block will erase page only bootloader.read(1) bootloader.write(b"A\x00\x00") # select page 0 bootloader.read(1) bootloader.write(b"g\x00\x80F") # read 128 byte page if bytearray(bootloader.read(128)) == bytearray("\xff" * 128): print("\nErase successful") else: print("\nErase failed") bootloader.exit() delayed_exit()
def usage(): print(f"\nUSAGE:\n\n{os.path.basename(sys.argv[0])} imagefile\n") print( "Create a C++ include file containing the image data of a .bmp or .png file that" ) print( "is suitable for Arduboy drawing functions. When an image contains transparency" ) print("the image data will also contain mask data.\n") print( "A image file may contain multiple tiles or sprites in which case the width and" ) print("height must be specified in the filename as following:\n") print("filename_[width]x[height].png\n") print( "where [width] and [height] should be replaced by their pixel values.") print( "Tiles and sprites in a tilesheet may be seperated by some spacing. The" ) print( "number of pixels surrounding the tile or sprite must be the same. The" ) print("spacing must be specified in the filename as following:\n") print("filename_[width]x[height]_[spacing].png\n") print( "where [width], [height] and [spacing] should be replaced by their pixel values." ) delayed_exit()
def load_hex_file_data(hex_filename): if not os.path.isabs(hex_filename): hex_filename = path + hex_filename if not os.path.isfile(hex_filename): return bytearray() f = open(hex_filename, "r") records = f.readlines() f.close() buffer = bytearray(b'\xFF' * 32768) flash_end = 0 for rcd in records: if rcd == ":00000001FF": break if rcd[0] == ":": rcd_len = int(rcd[1:3], 16) rcd_typ = int(rcd[7:9], 16) rcd_addr = int(rcd[3:7], 16) rcd_sum = int(rcd[9 + rcd_len * 2:11 + rcd_len * 2], 16) if (rcd_typ == 0) and (rcd_len > 0): flash_addr = rcd_addr checksum = rcd_sum for i in range(1, 9 + rcd_len * 2, 2): byte = int(rcd[i:i + 2], 16) checksum = (checksum + byte) & 0xFF if i >= 9: buffer[flash_addr] = byte flash_addr += 1 if flash_addr > flash_end: flash_end = flash_addr if checksum != 0: print(f"Error: Hex file '{hex_filename}' contains errors.") delayed_exit() flash_end = int((flash_end + 255) / 256) * 256 return buffer[0:flash_end]
def load_title_screen_data(screen_filename): if not os.path.isabs(screen_filename): screen_filename = path + screen_filename if not os.path.isfile(screen_filename): print(f"Error: Title screen '{screen_filename}' not found.") delayed_exit() img = Image.open(screen_filename).convert("1") width, height = img.size if (width != 128) or (height != 64): print( f"Error: Title screen '{screen_filename}' is not 128 x 64 pixels.") delayed_exit() pixels = list(img.getdata()) buffer = bytearray(int((height // 8) * width)) i = 0 b = 0 for y in range(0, height, 8): for x in range(0, width): for p in range(0, 8): b = b >> 1 if pixels[(y + p) * width + x] > 0: b |= 0x80 buffer[i] = b i += 1 return buffer
def main(): bootloader = BootLoader() bootloader.start() # check version if bootloader.get_version() < 13: print("Bootloader has no flash cart support\nWrite aborted!") delayed_exit() # detect flash cart jedec_id = bootloader.get_jedec_id() if jedec_id[0] in manufacturers.keys(): manufacturer = manufacturers[jedec_id[0]] else: manufacturer = "unknown" capacity = 1 << jedec_id[2] print( f"\nFlash cart JEDEC ID : {jedec_id[0]:02X}{jedec_id[1]:02X}{jedec_id[2]:02X}" ) print(f"Flash cart Manufacturer: {manufacturer}") print(f"Flash cart capacity : {capacity // 1024} Kbyte\n") filename = time.strftime("flashcart-backup-image-%Y%m%d-%H%M%S.bin", time.localtime()) print(f'Writing flash image to file: "{filename}"\n') oldtime = time.time() blocks = capacity // BLOCKSIZE with open(filename, "wb") as binfile: for block in range(0, blocks): if block & 1: bootloader.write(b"x\xC0") # RGB BLUE OFF, buttons disabled else: bootloader.write(b"x\xC1") # RGB BLUE RED, buttons disabled bootloader.read(1) sys.stdout.write(f"\rReading block {block + 1}/{blocks}") blockaddr = block * BLOCKSIZE // PAGESIZE bootloader.write(b"A") bootloader.write(bytearray([blockaddr >> 8, blockaddr & 0xFF])) bootloader.read(1) blocklen = BLOCKSIZE bootloader.write(b"g") bootloader.write( bytearray([(blocklen >> 8) & 0xFF, blocklen & 0xFF])) bootloader.write(b"C") contents = bootloader.read(blocklen) binfile.write(contents) bootloader.write(b"x\x44") # RGB LED GREEN, buttons enabled bootloader.read(1) time.sleep(0.5) bootloader.exit() print(f"\n\nDone in {round(time.time() - oldtime, 2)} seconds") delayed_exit()
def usage(): print(f"\nUSAGE:\n\n{os.path.basename(sys.argv[0])} [pagenumber] flashdata.bin") print(f"{os.path.basename(sys.argv[0])} [-d datafile.bin] [-s savefile.bin | -z savesize]") print() print("[pagenumber] Write flashdata.bin to flash starting at pagenumber. When no") print(" pagenumber is specified, page 0 is used instead.") print("-d --datafile Write datafile to end of flash for development.") print("-s --savefile Write savedata to end of flash for development.") print("-z --savesize Creates blank savedata (all 0xFF) at end of flash for development") delayed_exit()
def main(): bootloader = BootLoader() bootloader.start() print("Erasing EEPROM data...") bootloader.write(b"A\x00\x00") bootloader.read(1) bootloader.write(b"B\x04\x00E") bootloader.write(bytearray("\xFF" * 1024)) bootloader.read(1) bootloader.exit() print("Erase complete.") delayed_exit()
def main(): if len(sys.argv) != 2: print(f"\nUsage: {os.path.basename(sys.argv[0])} eepromfile.bin\n") delayed_exit() filename = sys.argv[1] if not os.path.isfile(filename): print(f"File not found. [{filename}]") delayed_exit() print(f'Reading EEPROM data from file "{filename}"') f = open(filename, "rb") eepromdata = bytearray(f.read()) f.close() if len(eepromdata) != 1024: print("File does not contain 1K (1024 bytes) of EEPROM data\nRestore aborted") delayed_exit() # restore bootloader = BootLoader() bootloader.start() print("Restoring EEPROM data...") bootloader.write(b"A\x00\x00") bootloader.read(1) bootloader.write(b"B\x04\x00E") bootloader.write(eepromdata) bootloader.read(1) bootloader.exit() print("Done") delayed_exit()
def main(): bootloader = BootLoader() bootloader.start() filename = time.strftime("eeprom-backup-%Y%m%d-%H%M%S.bin", time.localtime()) print("Reading 1K EEPROM data...") bootloader.write(b"A\x00\x00") bootloader.read(1) bootloader.write(b"g\x04\x00E") eepromdata = bytearray(bootloader.read(1024)) print(f'saving 1K EEPROM data to "{filename}"') f = open(filename, "wb") f.write(eepromdata) f.close() print("Done") bootloader.exit() delayed_exit()
def main(): bootloader = BootLoader() bootloader.start() filename = time.strftime("sketch-backup-%Y%m%d-%H%M%S.bin", time.localtime()) print("Reading sketch...") bootloader.write(b"A\x00\x00") bootloader.read(1) bootloader.write(b"g\x70\x00F") backupdata = bytearray(bootloader.read(0x7000)) print(f'saving sketch to "{filename}"') f = open(filename, "wb") f.write(backupdata) f.close() print("Done") bootloader.exit() delayed_exit()
def write_flash(pagenumber, flashdata): global verifyAfterWrite bootloader = BootLoader() bootloader.start() # check version if bootloader.get_version() < 13: print("Bootloader has no flash cart support\nWrite aborted!") delayed_exit() # detect flash cart jedec_id = bootloader.get_jedec_id() if jedec_id[0] in manufacturers.keys(): manufacturer = manufacturers[jedec_id[0]] else: manufacturer = "unknown" capacity = 1 << jedec_id[2] print(f"\nFlash cart JEDEC ID : {jedec_id[0]:02X}{jedec_id[1]:02X}{jedec_id[2]:02X}") print(f"Flash cart Manufacturer: {manufacturer}") print(f"Flash cart capacity : {capacity // 1024} Kbyte\n") 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: bootloader.write(b"x\xC0") # RGB LED OFF, buttons disabled else: bootloader.write(b"x\xC2") # RGB LED RED, buttons disabled bootloader.read(1) sys.stdout.write(f"\rWriting block {block + 1}/{blocks}") 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: 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]: print(" verify failed!\n\nWrite aborted.") break # write complete bootloader.write(b"x\x44") # RGB LED GREEN, buttons enabled bootloader.read(1) time.sleep(0.5) bootloader.exit() print(f"\n\nDone in {round(time.time() - oldtime, 2)} seconds")
def main(): global verifyAfterWrite try: opts, args = getopt(sys.argv[1:], "hd:s:z:", ["datafile=", "savefile=", "savesize="]) except: usage() # verify each block after writing if script name contains verify verifyAfterWrite = os.path.basename(sys.argv[0]).find("verify") >= 0 # handle development writing if len(opts) > 0: programdata = bytearray() savedata = bytearray() for o, a in opts: if o == '-d' or o == '--datafile': print(f'Reading program data from file "{a}"') f = open(a, "rb") programdata = bytearray(f.read()) f.close() elif o == '-s' or o == '--savefile': print(f'Reading save data from file "{a}"') f = open(a, "rb") savedata = bytearray(f.read()) f.close() elif (o == '-z') or (o == '--savesize'): savedata = bytearray(b'\xFF' * int(a)) else: usage() if len(programdata) % PAGESIZE: programdata += b'\xFF' * (PAGESIZE - (len(programdata) % PAGESIZE)) if len(savedata) % BLOCKSIZE: savedata += b'\xFF' * (BLOCKSIZE - (len(savedata) % BLOCKSIZE)) savepage = (MAX_PAGES - (len(savedata) // PAGESIZE)) programpage = savepage - (len(programdata) // PAGESIZE) write_flash(programpage, programdata + savedata) print("\nPlease use the following line in your program setup function:\n") if savepage < MAX_PAGES: print(f" Cart::begin(0x{programpage:04X}, 0x{savepage:04X});\n") else: print(f" Cart::begin(0x{programpage:04X});\n") print("\nor use defines at the beginning of your program:\n") print(f"#define PROGRAM_DATA_PAGE 0x{programpage:04X}") if savepage < MAX_PAGES: print(f"#define PROGRAM_SAVE_PAGE 0x{savepage:04X}") print("\nand use the following in your program setup function:\n") if savepage < MAX_PAGES: print(" Cart::begin(PROGRAM_DATA_PAGE, PROGRAM_SAVE_PAGE);\n") else: print(" Cart::begin(PROGRAM_DATA_PAGE);\n") # handle image writing ## else: if len(args) == 1: pagenumber = 0 filename = args[0] elif len(args) == 2: pagenumber = int(args[0], base=0) filename = args[1] else: usage() # load and pad imagedata to multiple of PAGESIZE bytes if not os.path.isfile(filename): print(f"File not found. [{filename}]") delayed_exit() print(f'Reading flash image from file "{filename}"') f = open(filename, "rb") flashdata = bytearray(f.read()) f.close() if len(flashdata) % PAGESIZE != 0: flashdata += b'\xFF' * (PAGESIZE - (len(flashdata) % PAGESIZE)) # Apply patch for SSD1309 displays if script name contains 1309 if os.path.basename(sys.argv[0]).find("1309") >= 0: print("Patching image for SSD1309 displays...\n") lcd_boot_program_addr = 0 while lcd_boot_program_addr >= 0: lcd_boot_program_addr = flashdata.find(lcdBootProgram, lcd_boot_program_addr) if lcd_boot_program_addr >= 0: flashdata[lcd_boot_program_addr + 2] = 0xE3 flashdata[lcd_boot_program_addr + 3] = 0xE3 write_flash(pagenumber, flashdata) delayed_exit()
def main(): if len(sys.argv) != 2: print( f"\nUsage: {os.path.basename(sys.argv[0])} flashcart-index.csv\n") delayed_exit() previouspage = 0xFFFF currentpage = 0 nextpage = 0 csvfile = os.path.abspath(sys.argv[1]) path = os.path.dirname(csvfile) + os.sep if not os.path.isfile(csvfile): print(f"Error: CSV-file '{csvfile}' not found.") delayed_exit() title_screens = 0 sketches = 0 filename = csvfile.lower().replace("-index", "").replace(".csv", "-image.bin") with open(filename, "wb") as binfile: with open(csvfile, "r") as file: data = csv.reader(file, quotechar='"', delimiter=";") next(data, None) print(f"Building: {filename}\n") print( "List Title Curr. Prev. Next ProgSize DataSize SaveSize" ) print( "---- ------------------------- ----- ----- ----- -------- -------- --------" ) for row in data: while len(row) < 7: row.append('') # add missing cells header = default_header() title = load_title_screen_data(row[ID_TITLESCREEN]) program = load_hex_file_data(row[ID_HEXFILE]) programsize = len(program) datafile = load_data_file(row[ID_DATAFILE]) datasize = len(datafile) slotsize = ((programsize + datasize) >> 8) + 5 programpage = currentpage + 5 datapage = programpage + (programsize >> 8) nextpage += slotsize header[7] = int(row[ID_LIST]) # list number header[8] = previouspage >> 8 header[9] = previouspage & 0xFF header[10] = nextpage >> 8 header[11] = nextpage & 0xFF header[12] = slotsize >> 8 header[13] = slotsize & 0xFF header[14] = programsize >> 7 # program size in 128 byte pages if programsize > 0: header[15] = programpage >> 8 header[16] = programpage & 0xFF if datasize > 0: program[0x14] = 0x18 program[0x15] = 0x95 program[0x16] = datapage >> 8 program[0x17] = datapage & 0xFF if datasize > 0: header[17] = datapage >> 8 header[18] = datapage & 0xFF binfile.write(header) binfile.write(title) binfile.write(program) binfile.write(datafile) if programsize == 0: print( f"{row[ID_LIST]:4} {row[ID_TITLE]:25} {currentpage:5} {previouspage:5} {nextpage:5}" ) else: print(( f"{row[ID_LIST]:4} {row[ID_TITLE][:24]:24} {currentpage:5} " f"{previouspage:5} {nextpage:5} {programsize:8} {datasize:8} {0:8}" )) previouspage = currentpage currentpage = nextpage if programsize > 0: sketches += 1 else: title_screens += 1 print( "---- ------------------------- ----- ----- ----- -------- -------- --------" ) print( " Page Page Page Bytes Bytes Bytes" ) print(( f"\nImage build complete with {title_screens} Title screens, {sketches} sketches, " f"{(nextpage + 3) / 4} Kbyte used.")) delayed_exit()
lcdBootProgram = b"\xD5\xF0\x8D\x14\xA1\xC8\x81\xCF\xD9\xF1\xAF\x20\x00" caterina_overwrite = False flash_addr = 0 flash_data = bytearray(b'\xFF' * 32768) flash_page = 1 flash_page_count = 0 flash_page_used = [False] * 256 ################################################################################ if len(sys.argv) != 2: print(f"\nUsage: {os.path.basename(sys.argv[0])} hexfile.hex\n") delayed_exit() # Load and parse file path = os.path.dirname(sys.argv[0]) + os.sep filename = sys.argv[1] if not os.path.isfile(filename): print(f"File not found. [{filename}]") delayed_exit() # if file is (.arduboy) zipfile, extract hex file try: compressed_file = zipfile.ZipFile(filename) for one_file in compressed_file.namelist(): if one_file.lower().endswith(".hex"): zipinfo = compressed_file.getinfo(one_file) zipinfo.filename = os.path.basename(sys.argv[0]).replace(