1212log = logging .getLogger (__name__ )
1313
1414class UserProjectConfig :
15+ '''
16+ Configuration specific to a project, held in a section with the
17+ project's shuttle name, e.g.
18+
19+ [tt_um_psychogenic_neptuneproportional]
20+ # set clock to 4kHz
21+ clock_frequency = 4000
22+ # clock config 4k, disp single bits
23+ input_byte = 0b11001000
24+ mode = ASIC_ON_BOARD
25+
26+ You can use this to set:
27+ - mode (str)
28+ - start_in_reset (bool)
29+ - input_byte (int)
30+ - bidir_direction (int)
31+ - bidir_byte (int)
32+ - clock_frequency (int)
33+
34+ all keys are optional.
35+
36+ A repr function lets you see the basics, do a print(tt.user_config.tt_um_someproject) to
37+ see more info.
38+
39+ '''
1540 def __init__ (self , section :str , conf :ConfigParser ):
1641 self .section = section
1742 self ._config = conf
@@ -20,6 +45,8 @@ def __init__(self, section:str, conf:ConfigParser):
2045 def config (self ):
2146 return self ._config
2247
48+
49+
2350 def has (self , name :str ):
2451 return self .config .has_option (self .section , name )
2552
@@ -31,10 +58,58 @@ def get(self, name:str):
3158
3259 def __getattr__ (self , name ):
3360 return self .get (name )
61+
62+ def _properties_dict (self , include_unset :bool = False ):
63+ ret = dict ()
64+ known_attribs = ['mode' , 'start_in_reset' , 'input_byte' ,
65+ 'bidir_direction' ,
66+ 'bidir_byte' ,
67+ 'clock_frequency' ,
68+ ]
69+ for atr in known_attribs :
70+ v = self .get (atr )
71+ if v is not None or include_unset :
72+ ret [atr ] = v
73+
74+ return ret
3475
76+ def __repr__ (self ):
77+ props = self ._properties_dict (True )
78+ return f'<UserProjectConfig { self .section } , { props ["clock_frequency" ]} Hz, mode: { props ["mode" ]} >'
3579
80+ def __str__ (self ):
81+ return f'UserProjectConfig { self .section } \n { self ._properties_dict ()} '
3682
3783class UserConfig (ConfigFile ):
84+ '''
85+ Encapsulates the configuration for defaults and all the projects, in sections.
86+ The DEFAULT section holds system wide defaults and the default project to load
87+ on startup.
88+
89+ DEFAULT section may have
90+
91+ # project: project to load by default
92+ project = tt_um_test
93+
94+ # start in reset (bool)
95+ start_in_reset = no
96+
97+ # mode can be any of
98+ # - SAFE: all RP2040 pins inputs
99+ # - ASIC_ON_BOARD: TT inputs,nrst and clock driven, outputs monitored
100+ # - ASIC_MANUAL_INPUTS: basically same as safe, but intent is clear
101+ mode = ASIC_ON_BOARD
102+
103+ # log_level can be one of
104+ # - DEBUG
105+ # - INFO
106+ # - WARN
107+ # - ERROR
108+ log_level = INFO
109+ Each project section is named [SHUTTLE_PROJECT_NAME]
110+ and will be an instance of, and described by, UserProjectConfig
111+ '''
112+
38113 def __init__ (self , ini_filepath :str = 'config.ini' ):
39114 super ().__init__ (ini_filepath )
40115
@@ -70,5 +145,19 @@ def project(self, name:str):
70145
71146 return UserProjectConfig (name , self .ini_file )
72147
148+ def __getattr__ (self , name ):
149+ if name in self .sections :
150+ return self .project (name )
151+
152+ def __dir__ (self ):
153+ return self .sections
154+ def __repr__ (self ):
155+ return f'<UserConfig { self .filepath } , default project: { self .default_project } >'
156+
157+ def __str__ (self ):
158+ def_mode = self .default_mode
159+ if def_mode is not None :
160+ def_mode = RPMode .to_string (def_mode )
161+ return f'UserConfig { self .filepath } , Defaults:\n project: { self .default_project } \n mode: { def_mode } '
73162
74163
0 commit comments