#!/usr/bin/python """ Benutzung: python lookuptable.py bla.csv bla.h bla.c liest bla.csv aus, interpoliert das ganze und schreibt eine tabelle in bla.c und bla.h Achtung, bla.c und bla.h werden brutal ueberschrieben! Das csv muss tabs, kommas oder semikolons als trenner haben und folgende felder enthalten: #LowValue wird als y fuer alle x-werte, die kleiner als der kleinste x-Wert im csv sind, benutzt #HighValue wird als y fuer alle x-werte, die groesser als der groesste x-Wert im csv sind, benutzt #DataType Datentyp der y-Werte (uint16_t oder uint8_t) #IndexType Datentyp der x-Werte (uint16_t oder uint8_t) #ArrayName Name des Arrays Siehe example.csv!! Benutzung auf eigene Gefahr. """ import fileinput import re import os import sys # bei bedarf ergaezen. AdditionalIncludes = [ '', '' ] def create_printable_table(table, dataType, arrayName): """ returns a string with the table in *.c format """ result = '/** autogenerated lookup table */\n' result += 'const ' + dataType + " g_LOOKUP_" + arrayName + '[] PROGMEM =\n' result += '{\n' for x in sorted(table.keys()): y = table[x] result += ' /* ' + repr(x).rjust(12) + ' */ ' + repr(y).rjust(12) + ',\n' result += '};' return result def create_lookup_function(dataType, indexType, arrayName, biggestKey, highValue): header = '' body = '' header += '/**\n' header += ' * autogenerated lookup function for ' + arrayName + "\n" header += ' * @param i x value\n' header += ' * @return f(i), or ' + str(highValue) + ' if i is out of range\n' header += ' */\n' header += dataType + ' lookup_' + arrayName + '(' + indexType + ' i);' body += dataType + ' lookup_' + arrayName + '(' + indexType + ' i)\n' body += '{\n' body += ' if (i <= ' + str(biggestKey) + ')\n' body += ' return ' if dataType == 'uint16_t': body += 'pgm_read_word(&g_LOOKUP_' + arrayName + '[i]);\n' elif dataType == 'uint8_t': body += 'pgm_read_byte(&g_LOOKUP_' + arrayName + '[i]);\n' else: body += 'ERROR: no suitable datatype\n' body += ' else\n' body += ' return ' + str(highValue) + '; /* #HighValue */\n' body += '}\n' return header, body def interpolate_lookup_table(table, lowValue): #sortieren, durchgehen und interpolieren. oldX = 0 for nextX in sorted(table.keys()): if not oldX in table.keys(): if oldX == 0: startY = lowValue nextY = lowValue else: startY = table[oldX] nextY = table[nextX] for thisX in range(oldX, nextX): # die punkte zwischen den stuetzstellen durchgehen thisY = startY + (nextY - startY) * (thisX - oldX) / (nextX - oldX) # lin. interpol. table[thisX] = thisY oldX = nextX return table def parse_csv(filename): dataType = 'uint16_t' indexType = 'uint8_t' arrayName = 'TestArray' lowestKey = 'ERROR' biggestKey = 'ERROR' highValue = 'ERROR' lowValue = 'ERROR' data = {} csvFile = open(filename, 'r') for line in csvFile: zeile = line.strip().strip('"') if re.match('\#', zeile): myLine = re.split('[\t ;,]+', zeile) if re.match('\#LowValue', myLine[0]): lowValue = int(myLine[1].strip('"')) elif re.match('\#HighValue', myLine[0]): highValue = int(myLine[1].strip('"')) elif re.match('\#DataType', myLine[0]): dataType = str(myLine[1].strip('"')) elif re.match('\#IndexType', myLine[0]): indexType = str(myLine[1].strip('"')) elif re.match('\#ArrayName', myLine[0]): arrayName = str(myLine[1].strip('"')) elif re.match('[0-9]+[,;\t]+[0-9]+', zeile): myLine = re.split('[\t ;,]+', zeile) data[int(myLine[0])] = int(myLine[1]) lowestKey = min(data.keys()); biggestKey = max(data.keys()); return dataType, indexType, arrayName, biggestKey, lowestKey, highValue, lowValue, data def write_header_file(filename, content, additionalIncludes): headerfile = open(filename, 'w') includeGuard = re.sub('\.', '_', filename) + '_' headerfile.write('#ifndef ' + includeGuard + '\n') headerfile.write('#define ' + includeGuard + '\n\n') for h in additionalIncludes: headerfile.write('#include ' + h + '\n') headerfile.write('\n') headerfile.write(content) headerfile.write('\n\n#endif /* ' + includeGuard + ' */\n\n') headerfile.close() return def write_body_file(bodyFileName, headerFileName, table, funct): bodyfile = open(bodyFileName, 'w') bodyfile.write('#include "' + headerFileName + '"\n\n') bodyfile.write(table) bodyfile.write('\n\n') bodyfile.write(funct) bodyfile.write('\n\n') bodyfile.close() return def print_usage(): print "MOEP: Benutzung python", sys.argv[0], "bla.csv bla.h bla.c" print "bla.csv muss existieren, bla.h und bla.c werden ueberschrieben" if len(sys.argv) < 4: print_usage() sys.exit() csvFile = sys.argv[1] headerFileName = sys.argv[2] bodyFileName = sys.argv[3] dataType, indexType, arrayName, biggestKey, lowestKey, highValue, lowValue, data = parse_csv(csvFile) fullTable = interpolate_lookup_table(data, lowValue) header, body = create_lookup_function(dataType, indexType, arrayName, biggestKey, highValue) write_header_file(headerFileName, header, AdditionalIncludes) write_body_file(bodyFileName, headerFileName, create_printable_table(fullTable, dataType, arrayName), body) sys.exit()