diff --git a/include/project.h b/include/project.h index e616926..b039467 100644 --- a/include/project.h +++ b/include/project.h @@ -49,11 +49,15 @@ // ************************************************************************************************* // Defines section +// moved to config.h // Comment this to not use the LCD charge pump //#define USE_LCD_CHARGE_PUMP // Comment this define to build the application without watchdog support -#define USE_WATCHDOG +//#define USE_WATCHDOG + +// end of move + // Use/not use filter when measuring physical values #define FILTER_OFF (0u) diff --git a/tools/config.py b/tools/config.py index 0cfe9a5..db585dd 100755 --- a/tools/config.py +++ b/tools/config.py @@ -4,6 +4,7 @@ import npyscreen import re, sys, random #npyscreen.disableColor() +from sorteddict import SortedDict # {0x79, 0x56, 0x34, 0x12} def rand_hw(): @@ -14,92 +15,114 @@ def rand_hw(): res.sort(reverse=True) return "{" + ",".join([hex(x) for x in res]) + "}" +DATA = SortedDict() -DATA = { -"CONFIG_FREQUENCY": { +DATA["CONFIG_FREQUENCY"] = { "name": "Frequency", "depends": [], "default": 902, "type": "choices", - "values": [902, 869, 433]}, + "values": [902, 869, 433]} -"CONFIG_METRIC_ONLY": { +DATA["CONFIG_METRIC_ONLY"] = { "name": "Metric only code (saves space)", "depends": [], "default": False -}, +} -"THIS_DEVICE_ADDRESS": { +DATA["THIS_DEVICE_ADDRESS"] = { "name": "Hardware address", "type": "text", "default": rand_hw(), "ifndef": True -}, +} + + +DATA["USE_LCD_CHARGE_PUMP"] = { + "name": "Use LCD Charge Pump", + "default": False, + "help": "Use the internal charge pump to make the display contrast same tho whole battery lifetime. But this increases currency", +} -"DEBUG": { +DATA["USE_WATCHDOG"] = { + "name": "Use Watchdog", + "default": True, + "help": "Protects the clock against deadlocks by rebooting it.", +} + + +DATA["DEBUG"] = { "name": "Debug", - "default": False}, + "default": False} # modules -"CONFIG_DAY_OF_WEEK": { - "name": "Date: Day of Week", +DATA["CONFIG_DAY_OF_WEEK"] = { + "name": "Date: Show Day of Week", "depends": [], - "default": True}, + "default": True} -"CONFIG_TEST": { +DATA["CONFIG_TEST"] = { "name": "Test Mode", "depends": [], - "default": True}, + "default": True} + +DATA["TEXT_MODULES"] = { + "name": "Modules", + "type": "info" +} + +#### MODULES #### -"CONFIG_EGGTIMER": { +DATA["CONFIG_EGGTIMER"] = { "name": "Eggtimer", "depends": [], - "default": False}, + "default": False} + +DATA["CONFIG_PHASE_CLOCK"] = { + "name": "Phase Clock", + "depends": [], + "default": False} # not yet working -"CONFIG_ACCEL": { +DATA["CONFIG_ACCEL"] = { "name": "Accleration", "depends": [], - "default": True}, -"CONFIG_ALARM": { + "default": True} +DATA["CONFIG_ALARM"] = { "name": "Alarm", "depends": [], - "default": True}, -"CONFIG_ALTITUDE": { + "default": True} +DATA["CONFIG_ALTITUDE"] = { "name": "Altitude", "depends": [], - "default": True}, -"CONFIG_BATTERY": { + "default": True} +DATA["CONFIG_BATTERY"] = { "name": "Battery", "depends": [], - "default": True}, -"CONFIG_CLOCK": { + "default": True} +DATA["CONFIG_CLOCK"] = { "name": "Clock", "depends": [], - "default": True}, -"CONFIG_DATE": { + "default": True} +DATA["CONFIG_DATE"] = { "name": "Date", "depends": [], - "default": True}, -"CONFIG_PHASE_CLOCK": { - "name": "Phase Clock", - "depends": [], - "default": False}, -"CONFIG_RFBSL": { + "default": True} +DATA["CONFIG_RFBSL"] = { "name": "Wireless Update", "depends": [], - "default": True}, -"CONFIG_STOP_WATCH": { + "default": True} +DATA["CONFIG_STOP_WATCH"] = { "name": "Stop Watch", "depends": [], - "default": True}, -"CONFIG_TEMP": { + "default": True} +DATA["CONFIG_TEMP"] = { "name": "Temperature", "depends": [], - "default": True}, -} + "default": True} + HEADER = """ @@ -161,6 +184,8 @@ class OpenChronosApp(npyscreen.NPSApp): values = field["value"]) f._key = key self.fields[key] = f + elif field["type"] == "info": + f = F.add(npyscreen.TitleText, max_height=1, name=field["name"]) # This lets the user play with the Form. @@ -177,6 +202,8 @@ class OpenChronosApp(npyscreen.NPSApp): fp.write("// !!!! DO NOT EDIT !!!, use: make config\n") fp.write(HEADER) for key,dat in DATA.iteritems(): + if not "value" in dat: + continue if DATA[key].get("ifndef", False): fp.write("#ifndef %s\n" %key) if isinstance(dat["value"], bool): @@ -195,7 +222,7 @@ class OpenChronosApp(npyscreen.NPSApp): def set_default(): for key,dat in DATA.iteritems(): #print dat - if not "value" in dat: + if not "value" in dat and "default" in dat: dat["value"] = dat["default"] try: diff --git a/tools/sorteddict.py b/tools/sorteddict.py new file mode 100644 index 0000000..4352291 --- /dev/null +++ b/tools/sorteddict.py @@ -0,0 +1,116 @@ +class SortedDict(dict): + """ + A dictionary that keeps its keys in the order in which they're inserted. + """ + def __new__(cls, *args, **kwargs): + instance = super(SortedDict, cls).__new__(cls, *args, **kwargs) + instance.keyOrder = [] + return instance + + def __init__(self, data=None): + if data is None: + data = {} + elif isinstance(data, GeneratorType): + # Unfortunately we need to be able to read a generator twice. Once + # to get the data into self with our super().__init__ call and a + # second time to setup keyOrder correctly + data = list(data) + super(SortedDict, self).__init__(data) + if isinstance(data, dict): + self.keyOrder = data.keys() + else: + self.keyOrder = [] + for key, value in data: + if key not in self.keyOrder: + self.keyOrder.append(key) + + def __deepcopy__(self, memo): + return self.__class__([(key, deepcopy(value, memo)) + for key, value in self.iteritems()]) + + def __setitem__(self, key, value): + if key not in self: + self.keyOrder.append(key) + super(SortedDict, self).__setitem__(key, value) + + def __delitem__(self, key): + super(SortedDict, self).__delitem__(key) + self.keyOrder.remove(key) + + def __iter__(self): + return iter(self.keyOrder) + + def pop(self, k, *args): + result = super(SortedDict, self).pop(k, *args) + try: + self.keyOrder.remove(k) + except ValueError: + # Key wasn't in the dictionary in the first place. No problem. + pass + return result + + def popitem(self): + result = super(SortedDict, self).popitem() + self.keyOrder.remove(result[0]) + return result + + def items(self): + return zip(self.keyOrder, self.values()) + + def iteritems(self): + for key in self.keyOrder: + yield key, self[key] + + def keys(self): + return self.keyOrder[:] + + def iterkeys(self): + return iter(self.keyOrder) + + def values(self): + return map(self.__getitem__, self.keyOrder) + + def itervalues(self): + for key in self.keyOrder: + yield self[key] + + def update(self, dict_): + for k, v in dict_.iteritems(): + self[k] = v + + def setdefault(self, key, default): + if key not in self: + self.keyOrder.append(key) + return super(SortedDict, self).setdefault(key, default) + + def value_for_index(self, index): + """Returns the value of the item at the given zero-based index.""" + return self[self.keyOrder[index]] + + def insert(self, index, key, value): + """Inserts the key, value pair before the item with the given index.""" + if key in self.keyOrder: + n = self.keyOrder.index(key) + del self.keyOrder[n] + if n < index: + index -= 1 + self.keyOrder.insert(index, key) + super(SortedDict, self).__setitem__(key, value) + + def copy(self): + """Returns a copy of this object.""" + # This way of initializing the copy means it works for subclasses, too. + obj = self.__class__(self) + obj.keyOrder = self.keyOrder[:] + return obj + + def __repr__(self): + """ + Replaces the normal dict.__repr__ with a version that returns the keys + in their sorted order. + """ + return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()]) + + def clear(self): + super(SortedDict, self).clear() + self.keyOrder = [] \ No newline at end of file