Akzeptieren und dekodieren Sie analoges Fernsehen mit SDR und Python

Hallo Habr.

Heute setzen wir das Thema SDR-Empfang und Signalverarbeitung fort. Ich habe mich nach einer Frage von einem der Leser ganz zufällig für den Empfang von analogem Fernsehen interessiert. Dies stellte sich jedoch aufgrund des banalen Mangels an Signalabtastungen als nicht so einfach heraus - vielerorts wurde das analoge Fernsehen bereits ausgeschaltet. Der Reader hat sogar eine Aufnahme mit RTL-SDR gesendet, die Breite der Aufnahme bei RTL beträgt jedoch ungefähr 2 MHz, während die TV-Signalbandbreite ungefähr 8 MHz beträgt und bei der Aufnahme nichts klar war. Infolgedessen wurde das Thema für eine lange Zeit aufgegeben, und schließlich nahm ich gerade bei der nächsten Reise zu meinen Verwandten SDRPlay mit und stellte die Frequenzen der Fernsehkanäle ein. Ich sah das gewünschte Signal auf dem Bildschirm.

Ein kleines Python-Programm, und alles funktioniert:



Für alle, die sich für Details interessieren, weiter unter dem Schnitt.

Theorie


In den alten Nachkriegsjahren, als digitale Geheimsignale nur in Geheimlabors bekannt waren, die Leute aber schon fernsehen wollten, gab es drei konkurrierende analoge Standards. Das erste war das seit den 40er Jahren entwickelte amerikanische NTSC (National Television System System Committee), das für die amerikanische Netzfrequenz von 60 Hz „geschärft“ wurde und eine vertikale Auflösung von nur 486 Zeilen aufwies. Wenig später wurde in Deutschland der PAL- Standard (Phase Alternating Line) entwickelt, der etwas besser war als der amerikanische (Auflösung der „ganzen“ 576 Leitungen und Konzentration auf die europäische Netzfrequenz von 50 Hz), und etwas später erschien der französische SECAM- Standard (Séquentiel couleur à mémoire). Es wurden einige der Mängel des PAL im Zusammenhang mit der Farbwiedergabe beseitigt, und es gibt eine Version, in der die Annahme von zwei Standards auch eine politische Entscheidung war, sodass Einwohner einiger Länder keine Programme aus anderen Ländern sehen konnten (etwa 50 Jahre vor der Vereinten Europäischen Union und Schengen). . So oder so, aber die ganze Welt war so geteilt:



Weil Habr ist immer noch eine russischsprachige Site, dann werden wir in Zukunft SECAM in Betracht ziehen, obwohl es auch interessant wäre, wenn jemand ein Beispielsignal PAL sendet.

Das SECAM-Spektrum ist nach alten Schriftrollen wie folgt:



Auf der linken Seite befindet sich bei der Frequenz F0 das amplitudenmodulierte Luminanzsignal (L). Dies ist eigentlich ein Schwarz-Weiß-Bild, das immer noch auf einem alten Schwarz-Weiß-Fernseher mit Warmweiß-Lampe angezeigt werden kann. Das Problem von Legacy und dem Vorhandensein von alten Geräten bei den Benutzern bestand bereits damals, so dass der Farbkanal separat hinzugefügt wurde, ohne die Kompatibilität mit alten Fernsehgeräten zu verlieren. Zwei Farbkanäle wurden abwechselnd in Frequenzmodulation mit Frequenzen von 4,25 und 4,406 MHz übertragen. Und schließlich wurde der Ton, der eine noch höhere Frequenz aufwies, separat übertragen, auch bei der Frequenzmodulation.

Übrigens, mit dem Empfang des Fernsehens in St. Petersburg gibt es einen lustigen Moment. Wie die russischen Medien berichteten, wurde das analoge Fernsehen im Oktober abgeschaltet:



Dies gilt jedoch nur für staatliche Kanäle , niemand zwingt kommerzielle Kanäle, ihre Sendungen auszuschalten. Zumindest zum Zeitpunkt des Schreibens (Dezember 2019) sind noch ca. 5-6 Kanäle im „Analog“ mitten in St. Petersburg verfügbar. Aber wie lange es dauern wird, ist unbekannt. Wer also "for history" -Signal-Samples aufnehmen möchte, sollte es trotzdem eilig haben.

Schließlich ist es Zeit, den SDR einzuschalten und zu sehen, was wir im wirklichen Leben haben:



Der Audiokanal ist nicht schwierig, Sie können einfach mit der „Maus“ in HDSDR darüber fahren, FM mit einer Bandbreite von ca. 50 kHz auswählen und hören. Wir werden mit dem Dekodieren des Helligkeitskanals beginnen, um ein fertiges „Bild“ zu erhalten.

Dekodierung


Wie oben beschrieben, werden Luminanzsignale zu AM übertragen. Um selbst keinen Decoder zu schreiben, verwenden wir GNU Radio - wir übertragen das Spektrum auf die Frequenz Null, starten den AM-Decoder und speichern das Ergebnis in einer Datei.



Jetzt können wir die gespeicherte Datei in Python öffnen:

import numpy as np import matplotlib.pyplot as plt lum_data = np.fromfile("pal_lum.raw", dtype='int32') lum_data = -lum_data - 4700 fs = 9000000//2 x_time = np.linspace(0, len(lum_data)/fs, num=len(lum_data)) plt.plot(x_time, lum_data) 

Wir sehen eine Sequenz von 4 Bildern auf dem Bildschirm.



Die Länge eines Frames von 0,02 s - dies ist nur 1/50 - ist ein Vielfaches der 50-Hz-Netzwerkfrequenz, deren Signale als "Taktgenerator" dienen (vergessen Sie nicht, dass das Signal analog ist). Für jeden Frame werden 320 Zeilen übertragen - wir haben Interlaced-Scanning, die endgültige Frame-Rate beträgt also 25 Hz.

Schauen wir uns die einzelnen Zeilen genauer an:



Wie Sie sehen, entspricht der Anfang jeder Zeile einer „Uhr“, dann entspricht der Signalhub den aktuellen Helligkeitswerten in dieser Zeile. Alles ist ganz einfach, und wahrscheinlich wurde praktisch unverändert ein solches Signal an die Kathodenstrahlröhre des Fernsehers angelegt.

Der Rest ist eine Frage der Technologie. Wir erstellen ein Bild im Speicher und kopieren zwei Frames hinein, weil wir haben interlaced. Die Signalspanne überschreitet nicht +200, wodurch wir diese Werte direkt als RGB-Farben schreiben können.

 # Output image frame_size = fs*1//50 img_x, img_y = 320, 650 img_size = (img_y, img_x, 3) img_data = np.zeros(img_size, dtype=np.uint8) img_data.fill(255) frame_num = 0 # Frame #1 pos_x, pos_y = 0, 0 for px in range(frame_num*frame_size, (frame_num+1)*frame_size): val = lum_data[px] if val < 0: val = 0 if val > 255: val = 255 img_data[pos_y][pos_x] = (0, val, 0) pos_x += 1 if lum_data[px] <= 0 and lum_data[px+1] > 0: pos_x = 0 pos_y += 2 print("Scan lines 1:", pos_y) # Frame #2 pos_x, pos_y = 0, 0 for px in range((frame_num+1)*frame_size, (frame_num+2)*frame_size): val = lum_data[px] if val < 0: val = 0 if val > 255: val = 255 img_data[pos_y+1][pos_x] = (0, val, 0) pos_x += 1 if lum_data[px] <= 0 and lum_data[px+1] > 0: pos_x = 0 pos_y += 2 img_resized = cv2.resize(img_data, dsize=(3*img_x, img_y), interpolation=cv2.INTER_CUBIC) plt.imshow(img_resized, interpolation='nearest') 

Wie Sie sehen, verwende ich den Nulldurchgang, um den Beginn einer neuen Linie zu erkennen. Es stellte sich heraus, dass das Bild vertikal komprimiert ist. In diesem Fall hängt es von der Abtastfrequenz des SDR ab. Am Ende habe ich nur die Größe geändert.

Das Endergebnis für die Animation von 10 Bildern (akzeptiert das Habr-Dateiarchiv nicht mehr):



Fazit


Es ist interessant, solche Standards zu analysieren, weil Erstens sind sie recht einfach zu implementieren, und zweitens ist ihre Untersuchung auch teilweise von historischem Interesse. Natürlich hatte ich nicht das Ziel, einen vollwertigen Software-TV-Tuner zu entwickeln, daher wird der Code in einer minimal bedienbaren Form angezeigt.

Wenn die Bewertungen des Artikels positiv sind, können Sie im zweiten Teil die Arbeit mit Farbe in Betracht ziehen und ein vollwertiges Farbbild anzeigen.

Für diejenigen, die alleine experimentieren möchten, kann die IQ-Datei hier heruntergeladen werden .

Alle erfolgreichen Experimente.

Source: https://habr.com/ru/post/de482014/


All Articles