126 """Key wrapper class"""
132 setter: Callable[[str], str]
133 getter: Callable[[str], str]
141 options: tuple =
None,
142 setter: Callable[[str], str] = str,
143 getter: Callable[[str], str] = str,
144 default: object =
None,
145 advanced: bool =
False,
149 self.
optionsoptions = tuple(str(x)
for x
in options)
if options
else None
155 def __str__(self) -> str:
156 out = f
"{self.key} : {self.desc}"
160 out += f
"\n Default: {self.value}"
162 out +=
"\n Options: "
167 """Sets the value for this option
170 value (Any): The value to use to set
173 bool: The value was successfully set
185 """Get the value for this option
188 str: The value of this option
192 FRONT_TEENSY_PORT =
Option(
"FRONT_TEENSY_PORT",
"Port representing the front ecu (COMx)", getter=
lambda x: x.upper())
193 BACK_TEENSY_PORT =
Option(
"BACK_TEENSY_PORT",
"Port representing the back ecu (COMx)", getter=
lambda x: x.upper())
196 "Enable graphical plotting of data",
198 lambda x:
"yes" if x
in (
"-g",
"yes")
else "",
199 lambda x:
"-g" if x ==
"yes" else "",
202 CORE_MODEL =
Option(
"CORE_MODEL",
"Model number of the teensy to compile for", (36, 40, 41), default=41)
207 lambda x:
"yes" if x
in (
"-l${workspaceFolder}\\logs",
"yes")
else "",
208 lambda x:
"-l${workspaceFolder}\\logs" if x ==
"yes" else "",
211 CORE_SPEED =
Option(
"CORE_SPEED",
"Speed at which the CPU will run (MHz)", default=
"AUTOSET VALUE", advanced=
True)
212 CORE_NAME =
Option(
"CORE_NAME",
"Model of the cpu", default=
"AUTOSET VALUE", advanced=
True)
213 CORE =
Option(
"CORE",
"Core folder to compile with", default=
"AUTOSET VALUE", advanced=
True)
214 BAUDRATE =
Option(
"BAUDRATE",
"Baudrate to use with serial", (9600, 19200, 38400, 57600, 115200), default=115200, advanced=
True)
215 USB_SETTING =
Option(
"USB_SETTING",
"USB behavior of the core", default=
"USB_SERIAL", advanced=
True)
216 TOOLCHAIN_OFFSET =
Option(
"TOOLCHAIN_OFFSET",
"Offset to the toolchain", default=
"../TeensyToolchain", advanced=
True)
217 ADDITIONAL_CMAKE_VARS =
Option(
218 "ADDITIONAL_CMAKE_VARS",
"More defines passed to CMake", default=
"-DCUSTOM_BUILD_PATH_PREFIX:STRING=build/Pre_Build/", advanced=
True
233 ADDITIONAL_CMAKE_VARS,
236 settings: dict[str, str]
238 def __init__(self, settings_dict: dict[str, str]) ->
None:
239 self.load(settings_dict)
240 self.CORE_SPEED.getter = self.__get_core_speed
241 self.CORE_NAME.getter = self.__get_core_name
242 self.CORE.getter = self.__get_core
244 def __get_core_speed(self, _) -> str:
245 model = int(self.CORE_MODEL.value)
248 if model == 40
or model == 41:
252 def __get_core_name(self, _) -> str:
253 model = int(self.CORE_MODEL.value)
256 if model == 40
or model == 41:
260 def __get_core(self, _) -> str:
261 model = int(self.CORE_MODEL.value)
264 if model == 40
or model == 41:
268 def load(self, settings_dict: dict[str, str]) ->
None:
269 """Loads settings dict
272 settings_dict (dict[str, str]): settings dict
275 KeyError: Key is not found in the settings JSON
280 raise KeyError(f
"Key not found in settings JSON: {option.value}")
285 """Print the current settings"""
287 print(option.key, option.value)
289 def unload(self, file: TextIOBase) ->
None:
290 """Write settings to file
293 file (TextIOBase): The file to write to
303 thread: threading.Thread
305 msg =
" Available ports:"
307 def __init__(self) -> None:
324 ports = listify(serial_ports())
328 print(f
"\033[s\r\033[1A\033[K\r{self.msg} {ports}\033[u", end=
"")
331def writeBackup() -> None:
332 """Output the backup settings"""
333 with open(SETTINGS_PATH,
"w", encoding=
"UTF-8")
as sett:
334 sett.write(BACKUP_SET)
337def get_settings() -> Settings:
338 """Return the current settings or fallback to the backup
341 Settings: The active settings
345 except (json.JSONDecodeError, FileNotFoundError):
347 return get_settings()
356 if sys.version_info.major < 3
or sys.version_info.minor < 10:
357 sys.exit(
"This project requires at least python 3.10")
359 vs_code_startup = len(sys.argv) == 2
and sys.argv[1] ==
"thisisbeingrunonstartup"
361 first_time =
not os.path.exists(SETTINGS_PATH)
363 settings = get_settings()
365 toolchain_missing =
not os.path.exists(settings.TOOLCHAIN_OFFSET.get_value())
367 if toolchain_missing:
368 path = settings.TOOLCHAIN_OFFSET.get_value()
369 print(f
"Toolchain is missing. Cloning to relative directory {path}")
370 subprocess.call(f
"git clone --recurse-submodules -j8 {TOOLCHAIN_REPO}", cwd=os.path.abspath(
"../"))
373 subprocess.call(
"git submodule update --init")
374 elif vs_code_startup:
375 print(f
"Configured for Teensy{settings.CORE_MODEL.get_value()} @ {int(int(settings.CORE_SPEED.get_value())/1000000)} Mhz")
376 print(f
"Current ports:\n Front:\t{settings.FRONT_TEENSY_PORT.get_value()}\n Back:\t{settings.BACK_TEENSY_PORT.get_value()}")
377 print(f
"Data Plotting: {settings.GRAPH_ARG.value}")
378 print(f
"Data Logging: {settings.LOGGING_OPTION.value}")
379 print(f
"\nRead Documentation Online at: {DOCUMENTATION_URL}")
384 for option
in settings.options:
385 if option.advanced
and not adv_mode:
388 if input(
"Enter 'Yes' to edit advanced options: ") !=
"Yes":
392 if option
is settings.FRONT_TEENSY_PORT
or option
is settings.BACK_TEENSY_PORT:
397 if not option.set_value(input(
"Input option, blank for default: ")):
398 while not option.set_value(input(
"Invalid option: ")):
401 with open(SETTINGS_PATH,
"w", encoding=
"UTF-8")
as sett:
402 settings.unload(sett)
404 if not vs_code_startup:
405 subprocess.call(
"git pull --recurse-submodules")
406 subprocess.call(
"git pull --recurse-submodules", cwd=settings.TOOLCHAIN_OFFSET.get_value())
409if __name__ ==
"__main__":