SystemK v1.00 #9
2 changed files with 231 additions and 0 deletions
11
Settings/Settings.csv
Normal file
11
Settings/Settings.csv
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
Setting ID,Type,Key,Default Value,Description
|
||||||
|
SYSTEMK_SETTING_IS_RIGHT_HANDED,uint8_t,"Is_Right_Handed",1,"1 if this device is configured for a right-handed player, 0 otherwise."
|
||||||
|
SYSTEMK_SETTING_AUDIO_VOLUME,uint8_t,"Audio_Volume",CONFIG_KTAG_MAX_AUDIO_VOLUME,"Value from CONFIG_KTAG_MIN_AUDIO_VOLUME to CONFIG_KTAG_MAX_AUDIO_VOLUME representing the current volume."
|
||||||
|
SYSTEMK_SETTING_TEAMID,uint8_t,"Team_ID",BASIC_TEAMS_MINIMUM,"Selected team."
|
||||||
|
SYSTEMK_SETTING_PLAYERID,uint8_t,"Player_ID",0,"Unique-per-team identification of a player."
|
||||||
|
SYSTEMK_SETTING_WEAPONID,uint8_t,"Weapon_ID",DUBUQUE_PROTOCOL_ID,"Selected weapon."
|
||||||
|
SYSTEMK_SETTING_MAX_HEALTH,uint8_t,"Max_Health",100,"Maximum health for the game."
|
||||||
|
SYSTEMK_SETTING_N_SPECIAL_WEAPONS_ON_REENTRY,uint8_t,"N_Special_Weapons_On_Reentry",1,"Number of special weapons (currently only bombs) obtained when reentering after being tagged out."
|
||||||
|
SYSTEMK_SETTING_T_START_GAME_in_ms,uint32_t,"T_Start_Game_in_ms",30000,"Time (in milliseconds) after starting a game before the countdown begins."
|
||||||
|
SYSTEMK_SETTING_T_GAME_LENGTH_in_ms,uint32_t,"T_Game_Length_in_ms",600000,"Duration of a game (in milliseconds). If this is zero or UINT32_MAX, the game is untimed."
|
||||||
|
SYSTEMK_SETTING_SECONDARY_COLOR,uint32_t,"Secondary_Color",0xFE000000,"Color in addition to the team color used to identify a player's device. The format is Brightness-Red-Green-Blue, where a brightness of 0xFF indicates a false flag."
|
||||||
|
220
Settings/generate_settings_code.py
Normal file
220
Settings/generate_settings_code.py
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
#!/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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue