217 lines
5.9 KiB
Python
217 lines
5.9 KiB
Python
|
import csv
|
||
|
import argparse
|
||
|
import string
|
||
|
|
||
|
|
||
|
def parse_pins(filename):
|
||
|
"""Parse CSV file given in filename.
|
||
|
The CSV file should have the following columns:
|
||
|
mcu_name, board_name, port (integer), pin (integer)
|
||
|
The CSV file should also have a header row"""
|
||
|
pins = {}
|
||
|
with open(filename, newline="") as csv_file:
|
||
|
reader = csv.reader(csv_file)
|
||
|
reader.__next__()
|
||
|
for row in reader:
|
||
|
entry = (row[0].strip(), row[1].strip(), int(row[2].strip()), int(row[3].strip()))
|
||
|
pins[row[0].lower()] = entry
|
||
|
return pins
|
||
|
|
||
|
|
||
|
def parse_pin_functions(filename):
|
||
|
"""Parse a CSV file with peripheral pin mappings.
|
||
|
The CSV file should have the following columns
|
||
|
func_name, LOC0,LOC1,...,LOC31
|
||
|
There should not be any header row"""
|
||
|
functions = {}
|
||
|
with open(filename, newline="") as csv_file:
|
||
|
reader = csv.reader(csv_file)
|
||
|
for row in reader:
|
||
|
entry = row[1:]
|
||
|
functions[row[0].strip()] = entry
|
||
|
return functions
|
||
|
|
||
|
|
||
|
def make_pin_name(pin):
|
||
|
"""Create pin name"""
|
||
|
return "pin_" + pin[0]
|
||
|
|
||
|
|
||
|
def make_mcu_dict_entry(pin):
|
||
|
"""Create a pin mcu dictionary entry"""
|
||
|
entry = "{ MP_ROM_QSTR(MP_QSTR_" + pin[0] + "), MP_ROM_PTR(&" + make_pin_name(pin) + ") },"
|
||
|
return entry
|
||
|
|
||
|
|
||
|
def make_mcu_dict_entry2(pin):
|
||
|
"""Create a pin mcu dictionary entry"""
|
||
|
entry = (
|
||
|
"{ MP_ROM_QSTR(MP_QSTR_" + pin[1] + "), \t\t\tMP_ROM_PTR(&" + make_pin_name(pin) + ") },"
|
||
|
)
|
||
|
return entry
|
||
|
|
||
|
|
||
|
def make_mcu_dict(pins):
|
||
|
"""Create the mcu dictionary"""
|
||
|
decl = "\n\nSTATIC const mp_rom_map_elem_t board_module_globals_table[] = {\n"
|
||
|
decl += "\tCIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS\n"
|
||
|
for pin in pins.values():
|
||
|
decl += "\t" + make_mcu_dict_entry(pin) + "\n"
|
||
|
|
||
|
decl += "\n"
|
||
|
for pin in pins.values():
|
||
|
if pin[1] != "":
|
||
|
decl += "\t" + make_mcu_dict_entry2(pin) + "\n"
|
||
|
|
||
|
decl += "\t{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },\n"
|
||
|
decl += "\t{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },\n"
|
||
|
decl += "};\n"
|
||
|
decl += "MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);\n"
|
||
|
return decl
|
||
|
|
||
|
|
||
|
def make_board_dict_entry(pin):
|
||
|
"""Create a pin board dictionary entry"""
|
||
|
entry = "{ MP_OBJ_NEW_QSTR(MP_QSTR_" + pin[1] + "), (mp_obj_t)&" + make_pin_name(pin) + " },"
|
||
|
return entry
|
||
|
|
||
|
|
||
|
def make_pin_function_list_decl(pin, fcns):
|
||
|
"""Create a pin function list declaration"""
|
||
|
decl = "\nconst uint8_t pin_" + pin + "_functions[] = { \n"
|
||
|
if len(fcns) > 0:
|
||
|
decl += str(fcns[0])
|
||
|
for i in fcns[1:]:
|
||
|
decl += ", " + str(i)
|
||
|
decl += "\n};\n"
|
||
|
return decl
|
||
|
|
||
|
|
||
|
def make_pin_declaration(pin):
|
||
|
"""Create a pin declaration"""
|
||
|
decl = (
|
||
|
"\nconst mcu_pin_obj_t "
|
||
|
+ make_pin_name(pin)
|
||
|
+ " = PIN("
|
||
|
+ str(pin[2])
|
||
|
+ ","
|
||
|
+ str(pin[3])
|
||
|
+ ","
|
||
|
+ make_pin_name(pin).lower()
|
||
|
+ "_functions"
|
||
|
");"
|
||
|
)
|
||
|
return decl
|
||
|
|
||
|
|
||
|
def define_pin_exists(pin):
|
||
|
ret = "\n#define GPIO_" + pin[0] + "_EXISTS\t1"
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def make_pin_function_lists(functions, pins):
|
||
|
"""Create lists of pin functions from the parsed CSV data"""
|
||
|
fcn_list = {}
|
||
|
decl = ""
|
||
|
i = 0
|
||
|
for fcn, fcn_pins in sorted(functions.items()):
|
||
|
for j in range(0, len(fcn_pins)):
|
||
|
pin = fcn_pins[j].lower()
|
||
|
if pin == "":
|
||
|
continue
|
||
|
if pin not in fcn_list:
|
||
|
fcn_list[pin] = [255] * len(functions)
|
||
|
fcn_list[pin][i] = 1
|
||
|
i += 1
|
||
|
for pin in pins.keys():
|
||
|
if not pin in fcn_list:
|
||
|
fcn_list[pin] = []
|
||
|
|
||
|
decl += make_pin_function_list_decl(pin, fcn_list[pin])
|
||
|
|
||
|
return decl
|
||
|
|
||
|
|
||
|
def make_source_file(src_file, pins, fcn):
|
||
|
"""Make pins.c"""
|
||
|
with open(src_file, "w") as f:
|
||
|
f.write('#include "shared-bindings/board/__init__.h"\n')
|
||
|
f.write('#include "pin_functions.h"\n')
|
||
|
|
||
|
f.write(make_pin_function_lists(fcn, pins))
|
||
|
|
||
|
for pin in pins.values():
|
||
|
f.write(make_pin_declaration(pin))
|
||
|
f.write(make_mcu_dict(pins))
|
||
|
f.close()
|
||
|
return
|
||
|
|
||
|
|
||
|
def make_header_file(hdr_file, pins, fcns):
|
||
|
"""Make pins.h"""
|
||
|
hdr_file_name = hdr_file.split("/")[-1]
|
||
|
guard_name = "__" + hdr_file_name.replace(".", "_").upper() + "__"
|
||
|
with open(hdr_file, "w") as f:
|
||
|
f.write("#ifndef " + guard_name + "\n")
|
||
|
f.write("#define " + guard_name + "\n\n")
|
||
|
|
||
|
fcn_names = sorted(fcns.keys())
|
||
|
for i in range(len(fcn_names)):
|
||
|
f.write("#define " + "FN_" + fcn_names[i] + "\t\t\t(" + str(i) + ")\n")
|
||
|
|
||
|
for pin in pins.values():
|
||
|
f.write(define_pin_exists(pin))
|
||
|
|
||
|
f.write("\n\n")
|
||
|
f.write("\n\n#endif /*" + guard_name + "*/\n")
|
||
|
f.close()
|
||
|
|
||
|
return
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
parser = argparse.ArgumentParser(
|
||
|
prog="make_pins",
|
||
|
usage="%(prog)s [options]",
|
||
|
description="Parse a CSV file with pin data and store as corresponding C source and header files.",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"-s",
|
||
|
"--source_file",
|
||
|
dest="source_file",
|
||
|
action="store",
|
||
|
help="Name of the output source file",
|
||
|
default="pins.c",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"-e",
|
||
|
"--header_file",
|
||
|
dest="header_file",
|
||
|
action="store",
|
||
|
help="Name of the output header file",
|
||
|
default="pin_functions.h",
|
||
|
)
|
||
|
|
||
|
parser.add_argument(
|
||
|
"csv_file",
|
||
|
action="store",
|
||
|
help="Name of the input csv file",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"fcn_csv",
|
||
|
action="store",
|
||
|
help="Name of the csv file with pin functions",
|
||
|
)
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
src_file = args.source_file
|
||
|
hdr_file = args.header_file
|
||
|
|
||
|
csv_file = args.csv_file
|
||
|
fcn_csv = args.fcn_csv
|
||
|
|
||
|
pins = parse_pins(csv_file)
|
||
|
fcns = parse_pin_functions(fcn_csv)
|
||
|
make_source_file(src_file, pins, fcns)
|
||
|
make_header_file(hdr_file, pins, fcns)
|