66'''
77
88import json
9+ import re
910import ttboard .util .time as time
1011from ttboard .pins import Pins
1112from ttboard .boot .rom import ChipROM
12-
1313import ttboard .logging as logging
1414log = logging .getLogger (__name__ )
1515
1616'''
1717Fetched with
18- https://index.tinytapeout.com/tt03p5.json?fields=repo,address,commit,clock_hz
19- https://index.tinytapeout.com/tt04.json?fields=repo,address,commit,clock_hz
18+ https://index.tinytapeout.com/tt03p5.json?fields=repo,address,commit,clock_hz,title
19+ https://index.tinytapeout.com/tt04.json?fields=repo,address,commit,clock_hz,title
2020
2121'''
2222class Design :
23+ BadCharsRe = re .compile (r'[^\w\d\s]+' )
24+ SpaceCharsRe = re .compile (r'\s+' )
2325 def __init__ (self , projectMux , projindex :int , info :dict ):
2426 self .mux = projectMux
2527 self .project_index = projindex
2628 self .count = int (projindex )
29+ self .macro = info ['macro' ]
2730 self .name = info ['macro' ]
2831 self .repo = info ['repo' ]
2932 self .commit = info ['commit' ]
3033 self .clock_hz = info ['clock_hz' ]
34+ # special cleanup for wokwi gen'ed names
35+ if self .name .startswith ('tt_um_wokwi' ) and 'title' in info and len (info ['title' ]):
36+ new_name = self .SpaceCharsRe .sub ('_' , self .BadCharsRe .sub ('' , info ['title' ])).lower ()
37+ if len (new_name ):
38+ self .name = f'tt_um_wokwi_{ new_name } '
39+
3140 self ._all = info
3241
3342 def enable (self ):
@@ -51,8 +60,12 @@ def __init__(self, projectMux, src_JSON_file:str='shuttle_index.json'):
5160 index = json .load (fh )
5261 for project in index ["projects" ]:
5362 des = Design (projectMux , project ["address" ], project )
54- self ._shuttle_index [des .name ] = des
55- setattr (self , des .name , des )
63+ attrib_name = des .name
64+ if attrib_name in self ._shuttle_index :
65+ log .warn (f'Already have a "{ attrib_name } " here...' )
66+ attrib_name = des .macro
67+ self ._shuttle_index [attrib_name ] = des
68+ setattr (self , attrib_name , des )
5669 self ._project_count += 1
5770 except OSError :
5871 log .error (f'Could not open shuttle index { src_JSON_file } ' )
@@ -71,8 +84,28 @@ def all(self):
7184 return self ._shuttle_index .values ()
7285
7386 def get (self , project_name :str ) -> Design :
74- return self ._shuttle_index [project_name ]
87+ if project_name in self ._shuttle_index :
88+ return self ._shuttle_index [project_name ]
89+
90+ # maybe it's an integer?
91+ try :
92+ des_idx = int (project_name )
93+ for des in self .all :
94+ if des .count == des_idx :
95+ return des
96+ except ValueError :
97+ pass
98+
99+ raise ValueError (f'Unknown project "{ project_name } "' )
100+
101+ def __len__ (self ):
102+ return len (self ._shuttle_index )
103+
104+ def __getitem__ (self , idx :int ) -> Design :
105+ return self .get (idx )
75106
107+ def __repr__ (self ):
108+ return f'<DesignIndex { len (self )} projects>'
76109
77110class ProjectMux :
78111 def __init__ (self , pins :Pins , shuttle_index_file :str = None ):
@@ -107,7 +140,6 @@ def disable(self):
107140 self .enabled = None
108141
109142 def enable (self , design :Design ):
110-
111143 log .info (f'Enable design { design .name } ' )
112144 self .reset_and_clock_mux (design .count )
113145 self .enabled = design
@@ -188,7 +220,16 @@ def get(self, project_name:str) -> Design:
188220 return getattr (self .projects , project_name )
189221
190222 def __getattr__ (self , name ):
191- if hasattr (self .projects , name ):
223+ if hasattr (self , 'projects' ) and hasattr ( self .projects , name ):
192224 return getattr (self .projects , name )
193- raise AttributeError
225+ raise AttributeError (f"What is '{ name } '?" )
226+
227+ def __getitem__ (self , key ) -> Design :
228+ if hasattr (self , 'projects' ):
229+ return self .projects [key ]
230+ raise None
231+
232+ def __repr__ (self ):
233+ des_idx = self .projects
234+ return f'<ProjectMux with { len (des_idx )} projects>'
194235
0 commit comments