Files
50ohm-contents-dl/contents/html/applet_pm.html
T

159 lines
5.0 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="container" style="max-width:860px;">
<div class="mb-2">
<div class="small text-secondary fw-semibold mb-1">Modulierendes Signal (Nachricht)</div>
<canvas id="fmpm-c0" height="140" class="w-100 d-block rounded"></canvas>
</div>
<div class="mb-2">
<div class="small text-secondary fw-semibold mb-1">Trägersignal (unmoduliert)</div>
<canvas id="fmpm-c1" height="70" class="w-100 d-block rounded"></canvas>
</div>
<div class="mb-2">
<div class="small text-secondary fw-semibold mb-1">FM – Frequenz des Trägers folgt dem Signal-Wert</div>
<canvas id="fmpm-c2" height="70" class="w-100 d-block rounded"></canvas>
</div>
<div class="mb-3">
<div class="small text-secondary fw-semibold mb-1">PM – Phase des Trägers folgt dem Signal-Wert direkt</div>
<canvas id="fmpm-c3" height="70" class="w-100 d-block rounded"></canvas>
</div>
<hr>
<div class="d-flex flex-column gap-3">
<div class="row align-items-center g-2">
<div class="col-auto" style="min-width:170px;">
<label class="col-form-label col-form-label-sm">Signalform</label>
</div>
<div class="col">
<select class="form-select form-select-sm" id="fmpm-shape">
<option value="sine">Sinus</option>
<option value="square">Rechteck</option>
<option value="saw">Sägezahn</option>
<option value="ramp">Linearer Anstieg</option>
</select>
</div>
</div>
</div>
</div>
<script>
(function () {
const IDS = ['fmpm-c0','fmpm-c1','fmpm-c2','fmpm-c3'];
const COLORS = ['#1D9E75','#888780','#378ADD','#D85A30'];
const N = 1200;
const FC = 8;
const DEPTH = 1.5;
function signal(shape, n) {
const t = n / N, fs = 1.2;
switch (shape) {
case 'sine': return Math.sin(2 * Math.PI * fs * t);
case 'square': return Math.sign(Math.sin(2 * Math.PI * fs * t));
case 'saw': return 2 * (fs * t % 1) - 1;
case 'ramp': return Math.max(-1, Math.min(1, 2 * t - 1));
default: return 0;
}
}
function draw() {
const depth = DEPTH;
const shape = document.getElementById('fmpm-shape').value;
const gridCount = 24;
const cvs = IDS.map(id => document.getElementById(id));
const dpr = window.devicePixelRatio || 1;
const w = cvs[0].offsetWidth || 800;
cvs.forEach(c => {
c.width = w * dpr;
c.height = c.offsetHeight * dpr;
});
let fmPhase = 0;
const pts = new Array(N);
for (let n = 0; n < N; n++) {
const t = n / N;
const sig = signal(shape, n);
const car = Math.sin(2 * Math.PI * FC * t);
fmPhase += 2 * Math.PI * (FC + depth * sig) / N;
const fm = Math.sin(fmPhase);
const pm = Math.sin(2 * Math.PI * FC * t + depth * sig);
pts[n] = { sig, car, fm, pm };
}
const zeros = [];
for (let n = 1; n < N; n++) {
if (pts[n-1].car <= 0 && pts[n].car > 0) zeros.push(n / N);
}
const series = [
pts.map(p => p.sig),
pts.map(p => p.car),
pts.map(p => p.fm),
pts.map(p => p.pm),
];
const gH = 'rgba(0,0,0,1)';
const gV = 'rgba(70,70,70,.5)';
const zV = 'rgba(120,120,120,0)';
series.forEach((data, i) => {
const c = cvs[i];
const ctx = c.getContext('2d');
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.scale(dpr, dpr);
const h = c.offsetHeight;
const mid = h / 2;
const amp = mid * 0.78;
ctx.strokeStyle = gH;
ctx.lineWidth = 0.9;
ctx.setLineDash([]);
ctx.beginPath(); ctx.moveTo(0, mid); ctx.lineTo(w, mid); ctx.stroke();
ctx.strokeStyle = gV;
ctx.lineWidth = 0.9;
ctx.setLineDash([4, 4]);
for (let g = 1; g < gridCount; g++) {
const x = (g / gridCount) * w;
ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, h); ctx.stroke();
}
if (i === 2 || i === 3) {
ctx.strokeStyle = zV;
ctx.lineWidth = 0.5;
ctx.setLineDash([2, 5]);
zeros.forEach(t => {
const x = t * w;
ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, h); ctx.stroke();
});
}
if (i === 1) {
ctx.setLineDash([]);
ctx.fillStyle = 'rgba(95,95,95,.60)';
zeros.forEach(t => {
ctx.beginPath();
ctx.arc(t * w, mid, 2.5, 0, 2 * Math.PI);
ctx.fill();
});
}
ctx.setLineDash([]);
ctx.strokeStyle = COLORS[i];
ctx.lineWidth = i === 0 ? 2 : 1.5;
ctx.lineJoin = 'round';
ctx.beginPath();
data.forEach((v, n) => {
const x = n / N * w;
const y = mid - v * amp;
n === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();
});
}
document.getElementById('fmpm-shape').addEventListener('change', draw);
new ResizeObserver(draw).observe(document.getElementById('fmpm-c0'));
draw();
})();
</script>