- Sections and slides rewritten in Swedish; German law and institutions replaced by Swedish/CEPT/ITU equivalents (PTS, SSA, PTSFS 2025:1, SSMFS 2008:18), unverified statements marked "% TODO VERIFY" - New toc: INSTEG, HAREC, UPPGRADERING; section idents are Swedish (see ident-map.tsv) - Exam-question tags, BNetzA question pool, solutions and the German SWL course removed - Static pages, snippets, applets, READMEs and image alt-texts translated - TikZ labels translated; SVG drawings regenerated (drawing 689 still fails to build upstream: it references a missing photo) - Changed from the original: not endorsed by DARC e.V., SSA or PTS Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
199 lines
5.3 KiB
HTML
199 lines
5.3 KiB
HTML
<script src="https://www.50ohm.de/assets/chartjs/4.4.1/chart.min.js"></script>
|
|
|
|
<style>
|
|
.sq-applet {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
min-width: 0;
|
|
box-sizing: border-box;
|
|
display: grid;
|
|
gap: .8rem;
|
|
font-size: 15px;
|
|
container-type: inline-size;
|
|
}
|
|
|
|
.sq-applet .sq-controls {
|
|
display: grid;
|
|
grid-template-columns: minmax(9.5em, 1.2fr) minmax(8em, 2fr) minmax(7.5em, auto);
|
|
gap: .55rem .8rem;
|
|
align-items: center;
|
|
min-width: 0;
|
|
}
|
|
|
|
.sq-applet label,
|
|
.sq-applet output {
|
|
margin: 0;
|
|
line-height: 1.2;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.sq-applet label {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.sq-applet input[type="range"] {
|
|
display: block;
|
|
width: 100%;
|
|
min-width: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.sq-applet output {
|
|
display: block;
|
|
min-width: 7.5em;
|
|
text-align: left;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.sq-applet .sq-chart-wrap {
|
|
position: relative;
|
|
width: 100%;
|
|
height: clamp(220px, 43cqw, 360px);
|
|
min-width: 0;
|
|
min-height: 0;
|
|
}
|
|
|
|
.sq-applet canvas {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: block;
|
|
width: 100% !important;
|
|
height: 100% !important;
|
|
}
|
|
|
|
@container (max-width: 520px) {
|
|
.sq-applet .sq-controls {
|
|
grid-template-columns: minmax(7.5em, auto) minmax(6em, 1fr) 6.8em;
|
|
gap: .45rem .55rem;
|
|
}
|
|
|
|
.sq-applet output {
|
|
min-width: 6.8em;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div class="sq-applet" aria-label="Prova sampling och kvantisering">
|
|
<div class="sq-controls">
|
|
<label>Tidssampling:</label>
|
|
<input data-sq-time type="range" value="4" min="1" max="10" step="1" aria-label="Samplingfrekvens">
|
|
<output data-sq-time-output>16 sampel/s</output>
|
|
|
|
<label>Värdekvantisering:</label>
|
|
<input data-sq-value type="range" value="16" min="1" max="16" step="1" aria-label="Kvantiseringsbitar">
|
|
<output data-sq-value-output>16 bit</output>
|
|
</div>
|
|
|
|
<div class="sq-chart-wrap">
|
|
<canvas data-sq-chart aria-label="Tidskontinuerlig samt tids- och värdediskret signal"></canvas>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
const applet = document.currentScript.closest('.sq-applet');
|
|
const timeInput = applet.querySelector('[data-sq-time]');
|
|
const valueInput = applet.querySelector('[data-sq-value]');
|
|
const timeOutput = applet.querySelector('[data-sq-time-output]');
|
|
const valueOutput = applet.querySelector('[data-sq-value-output]');
|
|
const canvas = applet.querySelector('[data-sq-chart]');
|
|
const amplitude = 100;
|
|
const duration = 1;
|
|
|
|
const chart = new Chart(canvas, {
|
|
type: 'scatter',
|
|
data: {
|
|
datasets: [
|
|
{
|
|
label: 'Värde- och tidsdiskret signal',
|
|
data: [],
|
|
borderColor: '#00AEDF',
|
|
borderWidth: 2,
|
|
pointRadius: 0,
|
|
showLine: true,
|
|
stepped: true
|
|
},
|
|
{
|
|
label: 'Tidskontinuerlig signal',
|
|
data: [],
|
|
borderColor: '#999999',
|
|
borderWidth: 2,
|
|
pointRadius: 0,
|
|
showLine: true,
|
|
tension: .1
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
animation: false,
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
interaction: { mode: null },
|
|
plugins: {
|
|
legend: {
|
|
position: 'top',
|
|
labels: {
|
|
boxWidth: 28,
|
|
boxHeight: 10,
|
|
padding: 12,
|
|
font: { size: 12 }
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
y: {
|
|
min: -120,
|
|
max: 120,
|
|
ticks: {
|
|
maxTicksLimit: 5,
|
|
callback: function (value) { return value + '%'; }
|
|
}
|
|
},
|
|
x: {
|
|
min: 0,
|
|
max: duration,
|
|
title: { display: true, text: 'Tid' },
|
|
ticks: {
|
|
stepSize: 1,
|
|
callback: function (value) { return value + ' s'; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
function update() {
|
|
const samples = Math.pow(2, Number(timeInput.value));
|
|
const bits = Number(valueInput.value);
|
|
const levels = Math.pow(2, bits);
|
|
const sampleDistance = duration / samples;
|
|
const quantizationStep = 2 * amplitude / levels;
|
|
const continuous = [];
|
|
const quantized = [];
|
|
|
|
for (let x = 0; x <= duration + 1e-9; x += 1 / 128) {
|
|
continuous.push({ x: x, y: amplitude * Math.sin(2 * Math.PI * x) });
|
|
}
|
|
|
|
for (let x = 0; x <= duration + 1e-9; x += sampleDistance) {
|
|
const value = amplitude * Math.sin(2 * Math.PI * x);
|
|
const quantizedValue = Math.max(
|
|
-amplitude,
|
|
Math.min(amplitude, Math.sign(value) * quantizationStep * Math.floor(Math.abs(value) / quantizationStep + 1))
|
|
);
|
|
quantized.push({ x: x, y: quantizedValue });
|
|
}
|
|
|
|
chart.data.datasets[0].data = quantized;
|
|
chart.data.datasets[1].data = continuous;
|
|
chart.update('none');
|
|
timeOutput.textContent = samples + ' sampel/s';
|
|
valueOutput.textContent = bits + ' bit';
|
|
}
|
|
|
|
timeInput.addEventListener('input', update);
|
|
valueInput.addEventListener('input', update);
|
|
update();
|
|
}());
|
|
</script>
|
|
</div>
|