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()
Пример #2
0
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
Пример #5
0
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()
Пример #6
0
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()
Пример #10
0
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()
Пример #11
0
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")
Пример #12
0
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()
Пример #14
0
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(