NodeEEBench with Digilent BASYS3 FPGA boardINL, DNL ramp test with error correction lookup table implementationJörg Vollrath, University of Applied Science Kempten, Germany, Joerg.vollrath@hs-kempten.deMarch, 2024 OverviewIntroductionSummary |
var stepCode = Math.trunc(parseInt(document.getElementById("codesStep").value)/2); // number of code values
if (stepCode <= 0) { stepCode = 1; }
var startCode = parseInt(document.getElementById("codesStart").value); // number of code values
var endCode = Math.trunc(parseInt(document.getElementById("codesEnd").value) / 2) ; // number of code values
endCode = Math.trunc((endCode - startCode)/stepCode) * stepCode + startCode; // Ramp codes down = up
// Make triangle waveform
// Repeat 832 because DAC 100MHz, ADC 8.32us
cmdText = "T" + decToHex(startCode,4) + decToHex(endCode,4)
+ decToHex(stepCode,4) + decToHex(4*832,8);
// sendCmd "T"
document.getElementById("cmd").innerHTML = cmdText;
sendCmd();
// Make a lookup table with this data
// sort oscObjAvg with OSC codes
oscObjAvg.sort(function(a,b) { // sort for codeAWG
if ( a.codeOSC < b.codeOSC )
return -1;
if ( a.codeOSC > b.codeOSC )
return 1;
return 0;
});
var maxStep = 0;
if (nrCodes > 2) {
// get maximum step size
maxStep = oscObjAvg[1].codeOSC - oscObjAvg[0].codeOSC;
var minOSC = oscObjAvg[0].codeOSC;
var maxOSC = oscObjAvg[oscObjAvg.length - 1].codeOSC;
for (var j = 2; j < nrCodes; j++) { // Getr maximum step size
var stepOSCX = oscObjAvg[j].codeOSC - oscObjAvg[j-1].codeOSC;
if (stepOSCX > maxStep) maxStep = stepOSCX;
}
}
// make ideal curve lookup table
// maximum step = 0.5..1.5 LSB
var stepScale = parseFloat(document.getElementById("stepScale").value); // number of code values
maxStep = stepScale * maxStep;
if (maxStep == 0 ) { alert("maxStep = 0"); }
else { // maxStep not 0
var maxCodes = (maxOSC - minOSC) / maxStep;
// Look for suitable values going through sorted array
var lookupList = [];
lookupList[0] = oscObjAvg[0].codeAWG;
var nextVal = oscObjAvg[0].codeOSC + maxStep;
var indexL = 1;
lookupList[indexL] = oscObjAvg[1].codeAWG;
var errorL = Math.abs(oscObjAvg[1].codeOSC - nextVal);
for (var i = 2; i < nrCodes; i++) { // get lookup list
var errorN = oscObjAvg[i].codeOSC - nextVal;
if (errorN > 0.5 * maxStep) { // next value
indexL = indexL +1;
nextVal = nextVal + maxStep;
errorN = oscObjAvg[i].codeOSC - nextVal;
errorL = Math.abs(errorN);
lookupList[indexL] = oscObjAvg[i].codeAWG;
}
if (Math.abs(errorN) < errorL) { // absolute error better
lookupList[indexL] = oscObjAvg[i].codeAWG;
errorL = Math.abs(errorN);
}
}
var rangeN = indexL;
for (var i = indexL + 1; i < 8 * 1024; i++) { // fill up rest until 8k
lookupList[i] = oscObjAvg[nrCodes-1].codeAWG;
}
for (var i = 0; i < 4 * 1024; i++) { // copy lower 4k to upper 4k: 8k
lookupList[i + 4*1024] = lookupList[i];
}
var lText = "Min: " + oscObjAvg[0].codeOSC + " Max: " + oscObjAvg[nrCodes-1].codeOSC
+ " Step: " + maxStep + " New Codes: " + rangeN
+ " New Code Range: " + (rangeN * 16) + "<br>\n";
lText += "Lookup Table: <br>\n";
var xText = lText;
for (var i = 0; i < 16 * 4 * 8; i++) { // fill up rest
for (var j = 0; j < 16; j++) { // fill up rest
lText += lookupList[i * 16 + j] + ",";
xText += lookupList[i * 16 + j] + ",";
}
lText = lText + "<br>\n";
xText = xText +"\n";
}
xText = xText.substring(0, xText.length-2);
document.getElementById("bestL").innerHTML = lText;
document.getElementById("lookupX").value = xText;
// calculate new INL, DNL and redo with different maxStep if necessary
} // End maxStep not 0
JavaScript 80 lines of code copied from Arduino.
// Make triangle waveform
// Repeat 832 because DAC 100MHz, ADC 8.32us
cmdText = "T" + decToHex(startCode,4) + decToHex(endCode,4)
+ decToHex(stepCode,4) + decToHex((4*832),8); // 832, 416,208 4 samples
The loop has 3 parts.