#!/usr/bin/env python3 """ SystemK settings code generator. This program source code file is part of SystemK, a library in the KTag project. 🛡️ https://ktag.clubk.club Copyright © 2025 Joseph P. Kearney and the KTag developers. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. A copy of the GNU Affero General Public License should be available in the LICENSE file in the root of this repository. If not, see http://www.gnu.org/licenses/. """ import csv from typing import List, Dict def parse_csv(filename: str) -> List[Dict[str, str]]: """Parse the settings CSV file.""" settings = [] with open(filename, "r") as f: reader = csv.DictReader(f) for row in reader: settings.append(row) return settings def generate_get_function(settings: List[Dict[str, str]], datatype: str) -> str: """Generate the SETTINGS_get function for a specific datatype.""" func_name = f"SETTINGS_get_{datatype}" code = f"""SystemKResult_T {func_name}(SystemKSettingID_T id, {datatype} *value) {{ SystemKResult_T result = SYSTEMK_RESULT_UNSPECIFIED_FAILURE; switch (id) {{ """ for setting in settings: if setting["Type"] != datatype: continue setting_id = setting["Setting ID"] key = setting["Key"] cache_var = f"Cached_{key}" code += f""" case {setting_id}: *value = {cache_var}; result = SYSTEMK_RESULT_SUCCESS; break; """ code += """ default: result = SYSTEMK_RESULT_WRONG_DATATYPE; break; } return result; } """ return code def generate_set_function(settings: List[Dict[str, str]], datatype: str) -> str: """Generate the SETTINGS_set function for a specific datatype.""" func_name = f"SETTINGS_set_{datatype}" kv_func = f"KV_Set_Value_{datatype.replace('_t', '')}" code = f"""SystemKResult_T {func_name}(SystemKSettingID_T id, {datatype} value) {{ SystemKResult_T result = SYSTEMK_RESULT_SUCCESS; switch (id) {{ """ for setting in settings: if setting["Type"] != datatype: continue setting_id = setting["Setting ID"] key = setting["Key"] cache_var = f"Cached_{key}" code += f""" case {setting_id}: {cache_var} = value; result = {kv_func}(CONFIG_FILE, "{key}", &value); break; """ code += """ default: result = SYSTEMK_RESULT_WRONG_DATATYPE; break; } return result; } """ return code def generate_initialize_function(settings: List[Dict[str, str]]) -> str: """Generate the Initialize_Settings function.""" code = """SystemKResult_T Initialize_Settings(void) { SystemKResult_T result = SYSTEMK_RESULT_SUCCESS; SystemKResult_T temp_result; """ # Group settings by datatype. datatypes = set(s["Type"] for s in settings) for datatype in sorted(datatypes): code += f" {datatype} value_{datatype};\n" code += """ KLOG_INFO(TAG, "Initializing settings..."); """ # Generate initialization code for each setting. for setting in settings: setting_id = setting["Setting ID"] datatype = setting["Type"] key = setting["Key"] default_value = setting["Default Value"] code += f""" // Initialize {key} temp_result = KV_Get_Value_{datatype.replace('_t', '')}(CONFIG_FILE, "{key}", &value_{datatype}); if (temp_result != SYSTEMK_RESULT_SUCCESS) {{ // Try to get from default config temp_result = KV_Get_Value_{datatype.replace('_t', '')}(DEFAULT_CONFIG_FILE, "{key}", &value_{datatype}); if (temp_result != SYSTEMK_RESULT_SUCCESS) {{ // Use hardcoded default value_{datatype} = {default_value}; KLOG_WARN(TAG, "{key} not found in config files; using default value of {default_value}."); }} // Save to config file temp_result = KV_Set_Value_{datatype.replace('_t', '')}(CONFIG_FILE, "{key}", &value_{datatype}); if (temp_result != SYSTEMK_RESULT_SUCCESS) {{ result = temp_result; KLOG_ERROR(TAG, "Failed to set {key} in config file."); }} }} """ # Initialize the cache variable cache_var = f"Cached_{key}" code += f" {cache_var} = value_{datatype};\n" code += "\n" code += """ xEventGroupSetBits(Get_System_Events(), SYS_SETTINGS_READY); KLOG_INFO(TAG, "Settings initialized."); return result; } """ return code def generate_cache_declarations(settings: List[Dict[str, str]]) -> str: """Generate static cache variable declarations initialized to defaults.""" code = "" # Generate cache variable declarations for all settings for setting in settings: datatype = setting["Type"] key = setting["Key"] description = setting["Description"] default_value = setting["Default Value"] cache_var = f"Cached_{key}" code += f"// {description}\n" code += f"static {datatype} {cache_var} = {default_value};\n" return code def main(): """Main function to generate all settings code.""" settings = parse_csv("Settings.csv") # Get unique datatypes datatypes = sorted(set(s["Type"] for s in settings)) print("// Cache variable declarations") print(generate_cache_declarations(settings)) print() # Generate get and set functions for each datatype for datatype in datatypes: print(generate_get_function(settings, datatype)) print() print(generate_set_function(settings, datatype)) print() # Generate initialize function print(generate_initialize_function(settings)) if __name__ == "__main__": main()