187 lines
4.7 KiB
HTML
187 lines
4.7 KiB
HTML
<html>
|
|
<head>
|
|
<title>Dag Lem's DAC model</title>
|
|
<script type="text/javascript">
|
|
|
|
/* "jQuery". Maybe I start to use it for real later on. */
|
|
var $ = function(selector) {
|
|
if (selector.match(/^#/) != null) {
|
|
return document.getElementById(selector.replace("#", ""));
|
|
}
|
|
return null;
|
|
};
|
|
|
|
var term = false;
|
|
var dac = 0.966;
|
|
var _2R_div_R = 2.22;
|
|
var INFINITY = 1e6;
|
|
var bits = 12;
|
|
|
|
function make_type3_list(l1, l2) {
|
|
var approximate_dac_daglem = function(x) {
|
|
var vbit = [];
|
|
var Vsum = 0;
|
|
for (var set_bit = 0; set_bit < bits; set_bit++) {
|
|
var Vn = 1.0; // Normalized bit voltage.
|
|
var R = 1.0; // Normalized R
|
|
var _2R = _2R_div_R*R; // 2R
|
|
var Rn = term ? // Rn = 2R for correct termination,
|
|
_2R : INFINITY; // INFINITY for missing termination.
|
|
|
|
// Calculate DAC "tail" resistance by repeated parallel substitution.
|
|
for (var bit = 0; bit < set_bit; bit++) {
|
|
if (Rn == INFINITY) {
|
|
Rn = R + _2R;
|
|
}
|
|
else {
|
|
Rn = R + _2R*Rn/(_2R + Rn); // R + 2R || Rn
|
|
}
|
|
}
|
|
|
|
|
|
// Source transformation for bit voltage.
|
|
if (Rn == INFINITY) {
|
|
Rn = _2R;
|
|
} else {
|
|
Rn = _2R*Rn/(_2R + Rn); // 2R || Rn
|
|
Vn = Vn*Rn/_2R;
|
|
}
|
|
|
|
// Calculate DAC output voltage by repeated source transformation from
|
|
// the "tail".
|
|
for (; bit < bits; bit++) {
|
|
Rn += R;
|
|
var I = Vn/Rn;
|
|
Rn = _2R*Rn/(_2R + Rn); // 2R || Rn
|
|
Vn = Rn*I;
|
|
}
|
|
|
|
vbit[set_bit] = Vn;
|
|
Vsum += Vn;
|
|
}
|
|
|
|
Vo = 0;
|
|
for (var j = 0; j < bits; j++) {
|
|
Vo += (x & 0x1)*vbit[j];
|
|
x >>= 1;
|
|
}
|
|
|
|
return ((1 << bits) - 1)*Vo/Vsum
|
|
};
|
|
|
|
var approximate_dac_mine = function(x) {
|
|
var value = 0;
|
|
var bit = 1;
|
|
var weight = 1;
|
|
var dir = 2 * dac;
|
|
var sum = 0;
|
|
for (var i = 0; i < 12; i ++) {
|
|
if (x & bit)
|
|
value += weight;
|
|
sum += weight;
|
|
bit <<= 1;
|
|
weight *= dir;
|
|
}
|
|
return ((1 << bits) - 1) * value / sum;
|
|
};
|
|
|
|
for (var x = 0; x < 2048; x ++) {
|
|
var y1 = approximate_dac_mine(x);
|
|
var y2 = approximate_dac_daglem(x);
|
|
l1.push([x, y1])
|
|
l2.push([x, y2])
|
|
}
|
|
}
|
|
|
|
function viewtransform(coords) {
|
|
var x = coords[0];
|
|
var y = coords[1];
|
|
|
|
return [x, 2047 - y];
|
|
}
|
|
|
|
function clear_area(ctx) {
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 255)';
|
|
ctx.fillRect(0, 0, 2048, 2048);
|
|
}
|
|
|
|
function make_grid(ctx) {
|
|
ctx.strokeStyle = 'rgba(0, 0, 0, 255)';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(2048, 0);
|
|
ctx.lineTo(2048, 2048);
|
|
ctx.lineTo(0, 2048);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
|
|
for (var x = 0; x < 2048; x += 128) {
|
|
ctx.strokeStyle = x % 512 == 0 ? 'rgba(32, 32, 32, 128)' : 'rgba(128, 128, 128, 128)';
|
|
|
|
var coord1 = viewtransform([x, 0]);
|
|
var coord2 = viewtransform([x, 2048]);
|
|
ctx.beginPath();
|
|
ctx.moveTo(Math.floor(coord1[0]), coord1[1]);
|
|
ctx.lineTo(Math.floor(coord2[0]), coord2[1]);
|
|
ctx.stroke();
|
|
}
|
|
|
|
for (var y = 0; y < 2048; y += 128) {
|
|
ctx.strokeStyle = y % 512 == 0 ? 'rgba(32, 32, 32, 128)' : 'rgba(128, 128, 128, 128)';
|
|
|
|
var coord1 = viewtransform([0, y]);
|
|
var coord2 = viewtransform([2048, y]);
|
|
ctx.beginPath();
|
|
ctx.moveTo(Math.floor(coord1[0]), coord1[1]);
|
|
ctx.lineTo(Math.floor(coord2[0]), coord2[1]);
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
|
|
function draw_lines(ctx, list) {
|
|
if (list.length < 2)
|
|
return;
|
|
|
|
var coords = viewtransform(list[0]);
|
|
ctx.beginPath();
|
|
ctx.moveTo(coords[0], coords[1]);
|
|
for (var i = 1; i < list.length; i ++) {
|
|
coords = viewtransform(list[i]);
|
|
ctx.lineTo(coords[0], coords[1]);
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
|
|
function update_view() {
|
|
var canvas = $('#renderarea');
|
|
var ctx = canvas.getContext("2d");
|
|
clear_area(ctx);
|
|
make_grid(ctx);
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 2048);
|
|
ctx.lineTo(2048, 0);
|
|
ctx.stroke();
|
|
|
|
var l1 = [];
|
|
var l2 = [];
|
|
make_type3_list(l1, l2);
|
|
ctx.strokeStyle = 'rgba(0, 255, 0, 255)';
|
|
draw_lines(ctx, l1);
|
|
ctx.strokeStyle = 'rgba(0, 0, 255, 255)';
|
|
draw_lines(ctx, l2);
|
|
}
|
|
|
|
onload = function() {
|
|
update_view();
|
|
};
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<canvas id="renderarea" width="2048" height="2048">
|
|
<span style="color:red">Unsupported browser! No canvas element!</span>
|
|
</canvas>
|
|
</body>
|
|
</html>
|