def checkPortStatus(self, update_button_state):
        try:
            with serial.Serial(self.port[0],
                               115200,
                               timeout=0.2,
                               writeTimeout=0.2) as ser:
                fpga = TinyFPGAB(ser)

                if fpga.is_bootloader_active():
                    com_port_status_sv.set(
                        "Connected to TinyFPGA B2. Ready to program.")
                    return True
                else:
                    com_port_status_sv.set(
                        "Unable to communicate with TinyFPGA. Reconnect and reset TinyFPGA before programming."
                    )
                    return False

        except serial.SerialTimeoutException:
            com_port_status_sv.set(
                "Hmm...try pressing the reset button on TinyFPGA again.")
            return False

        except:
            com_port_status_sv.set(
                "Bootloader not active. Press reset button on TinyFPGA before programming."
            )
            return False
示例#2
0
def test_wait_while_busy():
    # prepare
    serial = FakeSerial('0101010100'.decode('hex'))
    fpga = TinyFPGAB(serial)
    # run
    assert fpga.wait_while_busy() is None
    # check
    assert not serial.read_data
    serial.assert_written(['010100020005'.decode('hex')] * 5)
示例#3
0
def test_wait_while_busy():
    # prepare
    serial = FakeSerial(bytearray.fromhex('0101010100'))
    fpga = TinyFPGAB(serial)
    # run
    assert fpga.wait_while_busy() is None
    # check
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex('010100020005')] * 5)
示例#4
0
def test_wait_while_busy():
    # prepare
    serial = FakeSerial(bytearray.fromhex('0101010100'))
    fpga = TinyFPGAB(serial)
    # run
    assert fpga.wait_while_busy() is None
    # check
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex('010100020005')] * 5)
示例#5
0
def test_read(length, serial_outs):
    # prepare
    serial = FakeSerial(DATA[:length])
    fpga = TinyFPGAB(serial)
    # run
    output = fpga.read(0x123456, length)
    # check
    assert output == DATA[:length]
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex(d) for d in serial_outs])
示例#6
0
def test_read(length, serial_outs):
    # prepare
    serial = FakeSerial(DATA[:length])
    fpga = TinyFPGAB(serial)
    # run
    output = fpga.read(0x123456, length)
    # check
    assert output == DATA[:length]
    assert not serial.read_data
    serial.assert_written([d.decode('hex') for d in serial_outs])
示例#7
0
def test_program_bitstream(success):
    # prepare
    calls = []
    fpga = TinyFPGAB(None, lambda *a: calls.append(('progress', a)))
    # patching methods
    fpga.wake = lambda *a: calls.append(('wake', a))
    fpga.read_sts = lambda *a: calls.append(('read_sts', a))
    fpga.read = lambda *a: calls.append(('read', a))
    if success:
        fpga.program = lambda *a: calls.append(('program', a)) or True
    else:
        fpga.program = lambda *a: calls.append(('program', a)) or False
    fpga.boot = lambda *a: calls.append(('boot', a))
    # run
    output = fpga.program_bitstream(0x123456, DATA)
    # check
    assert output == success
    expected_calls = [
        ('progress', ('Waking up SPI flash', )),
        ('progress', ('35 bytes to program', )),
        ('program', (0x123456, DATA)),
    ]
    if success:
        expected_calls.append(('boot', ()))
    assert calls == expected_calls
示例#8
0
def test_write(offset, length, serial_outs):
    # prepare
    serial = FakeSerial()
    fpga = TinyFPGAB(serial)
    fpga.write_enable = lambda: None  # patch write_enable
    fpga.wait_while_busy = lambda: None  # patch wait_while_busy
    data = DATA[:length]
    # run
    assert fpga.write(offset, data) is None
    # check
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex(d) for d in serial_outs])
示例#9
0
def test_write(offset, length, serial_outs):
    # prepare
    serial = FakeSerial()
    fpga = TinyFPGAB(serial)
    fpga.write_enable = lambda: None  # patch write_enable
    fpga.wait_while_busy = lambda: None  # patch wait_while_busy
    data = DATA[:length]
    # run
    assert fpga.write(offset, data) is None
    # check
    assert not serial.read_data
    serial.assert_written([d.decode('hex') for d in serial_outs])
示例#10
0
def test_slurp(bitstream_dir, ext):
    # prepare
    fpga = TinyFPGAB(None)
    filename = os.path.join(bitstream_dir, 'bitstream.{}'.format(ext))
    expected = (0x30000, DATA)
    # run
    if ext == 'unknown':
        with pytest.raises(ValueError):
            fpga.slurp(filename)
    else:
        output = fpga.slurp(filename)
        # check
        assert output == expected
示例#11
0
def test_slurp(bitstream_dir, ext):
    # prepare
    fpga = TinyFPGAB(None)
    filename = os.path.join(bitstream_dir, 'bitstream.{}'.format(ext))
    expected = (0x30000, DATA)
    # run
    if ext == 'unknown':
        with pytest.raises(ValueError):
            fpga.slurp(filename)
    else:
        output = fpga.slurp(filename)
        # check
        assert output == expected
示例#12
0
def test_program_bitstream(success):
    # prepare
    calls = []
    fpga = TinyFPGAB(None, lambda *a: calls.append(('progress', a)))
    # patching methods
    fpga.wake = lambda *a: calls.append(('wake', a))
    fpga.read_sts = lambda *a: calls.append(('read_sts', a))
    fpga.read = lambda *a: calls.append(('read', a))
    if success:
        fpga.program = lambda *a: calls.append(('program', a)) or True
    else:
        fpga.program = lambda *a: calls.append(('program', a)) or False
    fpga.boot = lambda *a: calls.append(('boot', a))
    # run
    output = fpga.program_bitstream(0x123456, DATA)
    # check
    assert output == success
    expected_calls = [
        ('progress', ('Waking up SPI flash', )),
        ('progress', ('35 bytes to program', )),
        ('program', (0x123456, DATA)),
    ]
    if success:
        expected_calls.append(('boot', ()))
    assert calls == expected_calls
示例#13
0
def test_write(offset, length, serial_outs):
    # prepare
    serial = FakeSerial()
    fpga = TinyFPGAB(serial)
    fpga.write_enable = lambda: None  # patch write_enable
    fpga.wait_while_busy = lambda: None  # patch wait_while_busy
    data = DATA[:length]
    # run
    assert fpga.write(offset, data) is None
    # check
    assert not serial.read_data
    prueba = [bytes.fromhex(d) for d in serial_outs]
    print("Creado: {}".format(prueba))
    serial.assert_written(prueba)
示例#14
0
    def program(self, filename, progress):
        global max_progress

        with serial.Serial(self.port[0], 115200, timeout=2, writeTimeout=2) as ser:
            fpga = TinyFPGAB(ser, progress)

            (addr, bitstream) = fpga.slurp(filename)

            max_progress = len(bitstream) * 3 

            try:
                fpga.program_bitstream(addr, bitstream)
            except:
                program_failure = True
                traceback.print_exc()
示例#15
0
    def exitBootloader(self):
        with serial.Serial(self.port[0], 10000000, timeout=0.2, writeTimeout=0.2) as ser:
            try:
                TinyFPGAB(ser).boot()

            except serial.SerialTimeoutException:
                com_port_status_sv.set("Hmm...try pressing the reset button on TinyFPGA again.")
示例#16
0
def test_is_bootloader_active(success_after):
    # prepare
    calls = []
    fpga = TinyFPGAB(None)
    read_id = ['ABC'] * success_after + [b'\x1f\x84\x01']
    # patching methods
    fpga.wake = lambda *a: calls.append(('wake', a))
    fpga.read = lambda *a: calls.append(('read', a))
    fpga.read_id = lambda *a: calls.append(('read_id', a)) or read_id.pop(0)
    # run
    output = fpga.is_bootloader_active()
    # check
    assert output == (success_after < 6)
    expected_calls = [
        ('wake', ()),
        ('read', (0, 16)),
        ('wake', ()),
        ('read_id', ()),
    ] * min(success_after + 1, 6)
    assert calls == expected_calls
示例#17
0
def test_simple_cmds(method, serial_out, serial_in, expected):
    # prepare
    serial = FakeSerial(serial_in.decode('hex'))
    fpga = TinyFPGAB(serial)
    if expected is not None:
        expected = expected.decode('hex')
    # run
    output = getattr(fpga, method)()
    # check
    assert output == expected
    assert not serial.read_data
    serial.assert_written([serial_out.decode('hex')])
示例#18
0
def test_simple_cmds(method, serial_out, serial_in, expected):
    # prepare
    serial = FakeSerial(bytearray.fromhex(serial_in))
    fpga = TinyFPGAB(serial)
    if expected is not None:
        expected = bytearray.fromhex(expected)
    # run
    output = getattr(fpga, method)()
    # check
    assert output == expected
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex(serial_out)])
示例#19
0
def test_program(success):
    # prepare
    calls = []
    fpga = TinyFPGAB(None, lambda *a: calls.append(('progress', a)))
    # patching methods
    fpga.erase = lambda *a: calls.append(('erase', a))
    fpga.write = lambda *a: calls.append(('write', a))
    if success:
        fpga.read = lambda *a: calls.append(('read', a)) or DATA
    else:
        fpga.read = lambda *a: calls.append(('read', a)) or 'This is a fail'
    # run
    output = fpga.program(0x123456, DATA)
    # check
    assert output == success
    expected_calls = [
        ('progress', ('Erasing designated flash pages', )),
        ('erase', (0x123456, 35)),
        ('progress', ('Writing bitstream', )),
        ('write', (0x123456, DATA)),
        ('progress', ('Verifying bitstream', )),
        ('read', (0x123456, 35)),
    ]

    if success:
        expected_calls.extend([
            ('progress', ('Success!', )),
        ])
    else:
        expected_calls.extend([
            ('progress', ('Need to rewrite some pages...', )),
            ('progress', ('len: 000023 00000e', )),
            ('progress', ('rewriting page 123456', )),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, 'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('progress', ('Verification Failed!', )),
        ])

    assert calls == expected_calls
示例#20
0
def test_program(success):
    # prepare
    calls = []
    fpga = TinyFPGAB(None, lambda *a: calls.append(('progress', a)))
    # patching methods
    fpga.erase = lambda *a: calls.append(('erase', a))
    fpga.write = lambda *a: calls.append(('write', a))
    if success:
        fpga.read = lambda *a: calls.append(('read', a)) or DATA
    else:
        fpga.read = lambda *a: calls.append(('read', a)) or 'This is a fail'
    # run
    output = fpga.program(0x123456, DATA)
    # check
    assert output == success
    expected_calls = [
        ('progress', ('Erasing designated flash pages', )),
        ('erase', (0x123456, 35)),
        ('progress', ('Writing bitstream', )),
        ('write', (0x123456, DATA)),
        ('progress', ('Verifying bitstream', )),
        ('read', (0x123456, 35)),
    ]

    if success:
        expected_calls.extend([
            ('progress', ('Success!',)),
        ])
    else:
        expected_calls.extend([
            ('progress', ('Need to rewrite some pages...',)),
            ('progress', ('len: 000023 00000e',)),
            ('progress', ('rewriting page 123456',)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('erase', (1193046, 35)),
            ('write', (1193046, b'Thequickbrownfoxjumpsoverthelazydog')),
            ('read', (1193046, 35)),
            ('progress', ('Verification Failed!',)),
        ])

    assert calls == expected_calls
示例#21
0
def test_erase(offset, length, block_len, serial_outs):
    # prepare
    calls = []
    serial = FakeSerial()
    fpga = TinyFPGAB(serial)
    fpga.write_enable = lambda: None  # patch write_enable
    fpga.wait_while_busy = lambda: None  # patch wait_while_busy
    fpga.read = lambda *a: calls.append(('read', a)) \
        or DATA_4096[a[0] % 4096:][:a[1]]
    fpga.write = lambda *a: calls.append(('write', a))
    # run
    assert fpga.erase(offset, length) is None
    # check
    assert not serial.read_data
    serial.assert_written([d.decode('hex') for d in serial_outs])
    expected_calls = []
    restore_first_block = None
    if offset % block_len > 0:  # restore start of first block
        restore_offset = offset & ~(block_len - 1)
        restore_len = offset % block_len
        expected_calls.append(('read', (restore_offset, restore_len)))
        expected_calls.append(
            ('write', (restore_offset, DATA_4096[:restore_len])))
        restore_first_block = restore_offset
    if (offset + length) % block_len > 0:  # restore end of last block
        restore_offset = offset + length
        restore_len = block_len - (restore_offset % block_len)
        read_call = ('read', (restore_offset, restore_len))
        if restore_first_block == ((offset + length) & ~(block_len - 1)):
            # restore before and after erase in same block
            expected_calls.insert(1, read_call)  # 2nd read before 1st write
        else:
            expected_calls.append(read_call)  # 2nd read after 1st write
        expected_calls.append(
            ('write', (restore_offset,
                       DATA_4096[restore_offset % block_len:])))
    assert calls == expected_calls
示例#22
0
def test_is_bootloader_active(success_after):
    # prepare
    calls = []
    fpga = TinyFPGAB(None)
    read_id = ['ABC'] * success_after + ['\x1f\x84\x01']
    # patching methods
    fpga.wake = lambda *a: calls.append(('wake', a))
    fpga.read = lambda *a: calls.append(('read', a))
    fpga.read_id = lambda *a: calls.append(('read_id', a)) or read_id.pop(0)
    # run
    output = fpga.is_bootloader_active()
    # check
    assert output == (success_after < 6)
    expected_calls = [
        ('wake', ()),
        ('read', (0, 16)),
        ('wake', ()),
        ('read_id', ()),
    ] * min(success_after + 1, 6)
    assert calls == expected_calls
示例#23
0
def test_program(success):
    # prepare
    calls = []
    fpga = TinyFPGAB(None, lambda *a: calls.append(('progress', a)))
    # patching methods
    fpga.erase = lambda *a: calls.append(('erase', a))
    fpga.write = lambda *a: calls.append(('write', a))
    if success:
        fpga.read = lambda *a: calls.append(('read', a)) or DATA
    else:
        fpga.read = lambda *a: calls.append(('read', a)) or 'This is a fail'
    # run
    output = fpga.program(0x123456, DATA)
    # check
    assert output == success
    assert calls == [
        ('progress', ('Erasing designated flash pages', )),
        ('erase', (0x123456, 35)),
        ('progress', ('Writing bitstream', )),
        ('write', (0x123456, DATA)),
        ('progress', ('Verifying bitstream', )),
        ('read', (0x123456, 35)),
        ('progress', ('Success!' if success else 'Verification Failed!', )),
    ]
示例#24
0
def test_erase(offset, length, block_len, serial_outs):
    # prepare
    calls = []
    serial = FakeSerial()
    fpga = TinyFPGAB(serial)
    fpga.write_enable = lambda: None  # patch write_enable
    fpga.wait_while_busy = lambda: None  # patch wait_while_busy
    fpga.read = lambda *a: calls.append(('read', a)) \
        or DATA_4096[a[0] % 4096:][:a[1]]
    fpga.write = lambda *a: calls.append(('write', a))
    # run
    assert fpga.erase(offset, length) is None
    # check
    assert not serial.read_data
    serial.assert_written([bytearray.fromhex(d) for d in serial_outs])
    expected_calls = []
    restore_first_block = None
    if offset % block_len > 0:  # restore start of first block
        restore_offset = offset & ~(block_len - 1)
        restore_len = offset % block_len
        expected_calls.append((
            'read', (restore_offset, restore_len)))
        expected_calls.append((
            'write', (restore_offset, DATA_4096[:restore_len])))
        restore_first_block = restore_offset
    if (offset + length) % block_len > 0:  # restore end of last block
        restore_offset = offset + length
        restore_len = block_len - (restore_offset % block_len)
        read_call = ('read', (restore_offset, restore_len))
        if restore_first_block == ((offset + length) & ~(block_len - 1)):
            # restore before and after erase in same block
            expected_calls.insert(1, read_call)  # 2nd read before 1st write
        else:
            expected_calls.append(read_call)  # 2nd read after 1st write
        expected_calls.append((
            'write', (restore_offset, DATA_4096[restore_offset % block_len:])))
    assert calls == expected_calls
示例#25
0
def _main():
    import argparse
    from serial.tools.list_ports import comports
    from tinyfpgab import TinyFPGAB

    parser = argparse.ArgumentParser()

    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list connected and active TinyFPGA B-series "
                        "boards")
    parser.add_argument("-p",
                        "--program",
                        type=str,
                        help="program TinyFPGA board with the given bitstream")
    parser.add_argument("-b",
                        "--boot",
                        action="store_true",
                        help="command the TinyFPGA B-series board to exit the "
                        "bootloader and load the user configuration")
    parser.add_argument("-c", "--com", type=str, help="serial port name")
    parser.add_argument("-d",
                        "--device",
                        type=str,
                        default="1209:2100",
                        help="device id (vendor:product); default is "
                        "TinyFPGA-B (1209:2100)")
    parser.add_argument("-a",
                        "--addr",
                        type=int,
                        help="force the address to write the bitstream to")

    args = parser.parse_args()

    print ""
    print "    TinyFPGA B-series Programmer CLI"
    print "    --------------------------------"

    device = args.device.lower().replace(':', '')
    if len(device) != 8 or not all(c in '0123456789abcdef' for c in device):
        print "    Invalid device id, use format vendor:product"
        sys.exit(1)
    device = '{}:{}'.format(device[:4], device[4:])
    print "    Using device id {}".format(device)
    active_boards = [p[0] for p in comports() if device in p[2].lower()]

    # find port to use
    active_port = None
    if args.com is not None:
        active_port = args.com
    elif not active_boards:
        print "    No port was specified and no active bootloaders found."
        print "    Activate bootloader by pressing the reset button."
        sys.exit(1)
    elif len(active_boards) == 1:
        print "    Only one board with active bootloader, using it."
        active_port = active_boards[0]
    else:
        print "    Please choose a board with the -c option."

    # list boards
    if args.list or active_port is None:
        print "    Boards with active bootloaders:"
        for p in active_boards:
            print "        " + p
        if len(active_boards) == 0:
            print "        No active bootloaders found.  Check USB connections"
            print "        and press reset button to activate bootloader."

    # program the flash memory
    elif args.program is not None:
        print "    Programming " + active_port + " with " + args.program

        def progress(info):
            if isinstance(info, str):
                print "    " + info

        for attempt in range(3):
            with serial.Serial(active_port,
                               115200,
                               timeout=0.2,
                               writeTimeout=0.2) as ser:
                fpga = TinyFPGAB(ser, progress)
                (addr, bitstream) = fpga.slurp(args.program)
                if args.addr is not None:
                    addr = args.addr
                if addr < 0:
                    print "    Negative write addr: {}".format(addr)
                    sys.exit(1)
                if addr + len(bitstream) >= 0x400000:
                    print "    Write addr over 4Mio: {}".format(addr)
                    sys.exit(1)
                if not fpga.is_bootloader_active():
                    print "    Bootloader not active"
                    continue
                print "    Programming at addr {:06x}".format(addr)
                if fpga.program_bitstream(addr, bitstream):
                    sys.exit(0)
                else:
                    continue

    # boot the FPGA
    if args.boot:
        print "    Booting " + active_port
        with serial.Serial(active_port, 115200, timeout=0.2,
                           writeTimeout=0.2) as ser:
            fpga = TinyFPGAB(ser)
            fpga.boot()
    elif args.program is not None:
        # exit with error if programming is not successful
        sys.exit(1)
示例#26
0
def _main():
    import argparse
    from serial.tools.list_ports import comports
    from tinyfpgab import TinyFPGAB

    parser = argparse.ArgumentParser()

    parser.add_argument("-l", "--list", action="store_true",
                        help="list connected and active TinyFPGA B-series "
                             "boards")
    parser.add_argument("-p", "--program", type=str,
                        help="program TinyFPGA board with the given bitstream")
    parser.add_argument("-b", "--boot", action="store_true",
                        help="command the TinyFPGA B-series board to exit the "
                             "bootloader and load the user configuration")
    parser.add_argument("-c", "--com", type=str, help="serial port name")
    parser.add_argument("-d", "--device", type=str, default="1209:2100",
                        help="device id (vendor:product); default is "
                             "TinyFPGA-B (1209:2100)")
    parser.add_argument("-a", "--addr", type=int,
                        help="force the address to write the bitstream to")

    args = parser.parse_args()

    print("")
    print("    TinyFPGA B-series Programmer CLI")
    print("    --------------------------------")

    device = args.device.lower().replace(':', '')
    if len(device) != 8 or not all(c in '0123456789abcdef' for c in device):
        print("    Invalid device id, use format vendor:product")
        sys.exit(1)
    device = '{}:{}'.format(device[:4], device[4:])
    print("    Using device id {}".format(device))
    active_boards = [p[0] for p in comports() if device in p[2].lower()]

    # find port to use
    active_port = None
    if args.com is not None:
        active_port = args.com
    elif not active_boards:
        print("    No port was specified and no active bootloaders found.")
        print("    Activate bootloader by pressing the reset button.")
        sys.exit(1)
    elif len(active_boards) == 1:
        print("    Only one board with active bootloader, using it.")
        active_port = active_boards[0]
    else:
        print("    Please choose a board with the -c option.")

    # list boards
    if args.list or active_port is None:
        print("    Boards with active bootloaders:")
        for p in active_boards:
            print("        " + p)
        if len(active_boards) == 0:
            print("       No active bootloaders found.  Check USB connections")
            print("       and press reset button to activate bootloader.")

    # program the flash memory
    elif args.program is not None:
        print("    Programming " + active_port + " with " + args.program)

        def progress(info):
            if isinstance(info, str):
                print("    " + info)

        for attempt in range(3):
            with serial.Serial(active_port, 115200, timeout=0.2,
                               writeTimeout=0.2) as ser:
                fpga = TinyFPGAB(ser, progress)
                (addr, bitstream) = fpga.slurp(args.program)
                if args.addr is not None:
                    addr = args.addr
                if addr < 0:
                    print("    Negative write addr: {}".format(addr))
                    sys.exit(1)
                if addr + len(bitstream) >= 0x400000:
                    print("    Write addr over 4Mio: {}".format(addr))
                    sys.exit(1)
                fpga.is_bootloader_active()
                if not fpga.is_bootloader_active():
                    print("    Bootloader not active")
                    continue
                print("    Programming at addr {:06x}".format(addr))
                if fpga.program_bitstream(addr, bitstream):
                    sys.exit(0)
                else:
                    continue

    # boot the FPGA
    if args.boot:
        print("    Booting " + active_port)
        with serial.Serial(active_port, 115200, timeout=0.2,
                           writeTimeout=0.2) as ser:
            fpga = TinyFPGAB(ser)
            fpga.boot()
    elif args.program is not None:
        # exit with error if programming is not successful
        sys.exit(1)