circuitpython/ports/silabs/tools/make_pins.py

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)