176 lines
5.6 KiB
Python
176 lines
5.6 KiB
Python
#!/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 = [ '<avr/pgmspace.h>', '<inttypes.h>' ]
|
|
|
|
|
|
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()
|