Neue Firmware für das DSP-Radio
von Roger Leifert
Ich habe damals das
Gerät sofort nachgebaut, weil ich von den Möglichkeiten dieses genialen
ICs, der Wahl von BASCOM und eines ATMEGA für die Steuerung und Deinem
Schaltungs- und Programm-Konzept begeistert war. Ich wollte dann selbst
noch die Radiotext-Anzeige implementieren, bin damals an irgendeiner
Stelle aber hängengeblieben und dann lag das Projekt erst mal 2 Jahre
in der Ecke.
Ich habe jetzt die Zeit gefunden, das ganze
noch einmal in Angriff zu nehmen und bin ziemlich weit gekommen.Ich
mußte leider auf den nächst größeren ATMega (328P) ausweichen, da der
Speicher dann doch recht schnell voll war.Der größere Flash, RAM und
EPROM haben mich dann zum Einbau einer Vielzahl kleinerer und größerer
Veränderungen/Erweiterungen animiert Jetzt ist der Flash schon wieder
zu 95% voll und es fehlt mir nur noch die Dekodierung der EON-Daten aus
den RDS-Daten...
Alles baut auf Deinem
Original-BASCOM-Programm auf und ist von der Nutzung des LCD, der
Tasten und der seriellen Schnittstelle fast 100% "abwärtskompatibel"
Download: ElektorDSP3.zip
Siehe auch:
http://www.elektor-labs.com/project/enhanced-software-for-elektor-dsp-radio-si4735.13905.html
http://www.mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&p=63532
Bedienungsanleitung
Elektor Si4735 DSP-Radio mit erweiterter Firmware auf ATMega 328P:
S2: (beim Einschalten) → schalte
PWM-Ausgabe in FM 1 Schritt weiter von „Stereo-Signal“ → „Ratio-Mitte“
(FM-Frequenz-Offset) → Signalstärke (RSSI) → SNR
S2: im Betrieb (→ Wechsel in FM, falls
noch im AM-Modus)
·
kurz (<0,5s): UKW-Suchlauf aufwärts
·
lang (0,5...2s): UKW-Suchlauf abwärts
·
sehr lang(>2s): UKW-Band-Scan und abspeichern in M0...Mx (max.
50)
nach Scan-Ende wird M1 angezeigt; Gerät ist im Speicher-Scrollmodus (Encoder
verändert Speicherstelle)
S3: (beim Einschalten) → toggle
manuellen Frequenzschritt für FM/LW/MW/KW zwischen „grob“ (50 kHz/9 kHz/9 kHz/5
kHz) und „fein“ (10 kHz/1 kHz/1 kHz/1 kHz)
S3: im Betrieb (→ Wechsel in AM, falls
noch im FM-Modus)
·
kurz → Bandwechsel aufwärts; Klartext-Anzeige des
Bandnamens und der Frequenzgrenzen
·
lang → Bandwechsel abwärts; Klartext-Anzeige des Bandnamens
und der Frequenzgrenzen
S4: im Betrieb (→ Wechsel in AM, falls
noch im FM-Modus)
·
kurz (<0,5s): AM-Suchlauf aufwärts
·
lang (0,5...2s): AM-Suchlauf abwärts
·
sehr lang(>2s): AM-Band-Scan und abspeichern in M0...Mx
(max. 10x LW, 1x0 MW, 3x10 KW für zusammengefasste Bänder)
·
LW: Speicher 1...10
·
MW: Speicher 11...20
·
KW: Tropenbänder 3-6 = 120-60m Speicher 21...30
·
KW: Bänder 7-10 = 49-25m Speicher 31...40
·
KW: Bänder 11-16 = 22-11m Speicher 41...50
S5: (beim Einschalten) → lösche
EEPROM-Stationen und setze Default-Properties
S5: (im Betrieb)
·
kurz (<0,5s): „STORE“ (=vorerst nur im RAM)
im AM-Modus → Eingabe des Sendernamens (10 Zeichen) mit Drehencoder
kurzer Tastendruck → nächstes Zeichen anwählen
·
lang (0,5...2s): „RECALL-Modus“ (Speicher-Nummer mit
Drehimpulsgeber verändern)
·
falls Recall-Modus aktiv und dann kurzer Tastendruck für
"Store" --> Recall-Modus wird ausgeschaltet und Frequenz nicht (!)
gespeichert
·
2s drücken → Property-Einstell-Modus starten (Scroll
mit Encoder)
·
→ kurz drücken → gewählte Property mit
Encoder verändern
·
→ nochmal kurz drücken → Property-Einstell-Modus
beenden
·
5s drücken → alle Daten ins EEPROM speichern
RS232-Steuerung:
"f" = Frequenzeingabe → gibt „Tune“
zurück → f in kHz eingeben
"m“ = Memory AM → gibt „Memory AM“
zurück → N eingeben (Speicherplatz) → f in kHz eingeben →
Sendername eingeben
"n" = Memory FM → gibt „Memory FM“
zurück → N eingeben (Speicherplatz) → f in kHz eingeben
"p" = Property → gibt „Property“
zurück → N eingeben (1...16) → Property-Wert eingeben
"i" → I2C command
"j" → einmalige RDS-Datenausgabe über
RS-232
Auswahl RDS-Infobereiche über Bit 0...6 des einzugebenden
Steuerbytes:
(Bits beliebig kombinierbar)
·
Bit 0 : 1 Satz gespeicherte Gruppen im FIFO-Speicher auslesen:
aktuelle Gruppennummer+Typ (A/B); Block A-D; Blockerror-Byte
·
Bit 1 : PI-Code (hex. und binär); TP/TA; Music/Speech; PTY
(Nummer; 16-Zeichen-Klartext; PTY-Name-Ergänzung); Decoder-Information
·
Bit 2 : PS=Sendername; Alternativ-Frequenzen (ggf. mit
Regionalisierung); (Country-Code; Area-Coverage; Program Reference Nummer;
Language (Klartext) z.Zt. wg. Platzmangel nicht aktiv)
·
Bit 3: lokale Uhrzeit „hhH mmM“;
Modified Julian Date; Wochentag; Datum „TT.MM.JJJJ“ (sofern vorhanden)
·
Bit 4 : Radiotext-Länge; „Radiotext“ (sofern vorhanden)
·
Bit 5 : Emergency Warning System (sofern vorhanden): EWS,
EWS0...EWS4 ($)
(z.Zt. aus Platzmangel nicht aktiv)
·
Bit 6: EON-Daten (sofern vorhanden):
·
EON-PS (Programmname)
·
EON-PI (hex. und binär)
·
EON-PTY (Program-Type)
·
EON-TP/TA (Travel-Program/Travel-Announcement)
·
EON-Frequenzpaare (Tuned/Mapped Frequency)
·
EON-PIN
·
Bit 7:
·
Pin_code PIN
·
Linkage actuator LA
·
Language Code LC
·
Ext. Country Code ECC
·
TMC-Ident
·
EWS-Channel
"r" → RSSI zurückgeben
"s" → SNR zurückgeben
Display bei FM mit RDS,
ohne Radiotext
Display bei FM ohne Radiotext
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Zeile1
|
Frequenz
|
RSSI
|
SNR
|
|
M
|
Speicher-nummer
|
Zeile 2
|
RDS-Sendername
|
|
HH
|
:
|
MM
|
ST
(=Stereo)
|
R
(=RDS-Data)
|
Display bei FM mit Radiotext
Display bei FM mit RDS, mit
Radiotext
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Zeile1
|
komplette
Zeile mit Radiotext gefüllt
Ping-Pong-Scrolling
bei Textlänge 17...24 Zeichen, sonst normales Scrolling
|
Zeile 2
|
RDS-Sendername
|
|
HH
|
:
|
MM
|
ST
(=Stereo)
|
RT
(=Radiotext)
|
Display bei AM
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Zeile
1
|
Frequenz
|
|
RSSI
|
SNR
|
Tuning-Kapazität
|
Zeile
2
|
„M“
|
Speicher-nummer
|
|
|
|
AM-Sendername
|
Allgemeines:
·
Auto-Speicherung der aktuell eingestellten Frequenz FM und AM
getrennt, Modus und Band im EEPROM sobald Frequenz als gültig von Si4735
quittiert wird
·
Quittierung der meisten Funktionen mit Klartext-Meldung auf LCD
·
Nach Einschalten laden der zuletzt eingestellten Werte für FM und
AM (letzte gültige Frequenz, Band, Modus)
·
FM: alternative Ausgabe der Stereo-Kanaltrennung (0%...100%;
"Stereo-Signal"), der Frequenz-Abweichung (+/-127 kHz;
"Tuning"/"Ratio-Mitte") oder des SNR über PWM (anstelle
der Feldstärke)
·
Anzeige, Bedienung und RS-232-Steuerung weitgehend
abwärts-kompatibel zu Original-Firmware
·
manueller Frequenzschritt: 50 kHz (FM), 9 kHz (LW/MW), 5 kHz (KW)
·
alternativ: 10 kHz (FM), 1 kHz (LW/MW/KW), wenn beim Einschalten
S3 gedrückt wird
·
Einstellung der Property-Werte 1-8 (FM) bzw. 9-16 (AM) je nach
aktuellem Modus mittels Dreh-Encoder:
·
Property-Einstell-Modus durch Druck auf S5 > 2s
·
Bestätigen mit kurzem Tastendruck von S5 (Memory)
·
Variation der Property mit Drehencoder nur innerhalb der
erlaubten Grenzen lt. Datenblatt Si4735
·
Bestätigen und Abspeichern der Property mit kurzem Tastendruck
von S5 (Memory)
·
Abspeicherung veränderter Property-Werte bei Druck auf S5 >
5s zusammen mit allen anderen Werten im EEPROM
·
Falls Property-EEPROM-Speicher=$FF (unbeschrieben) --> lese
alle Default-Wert aus Si4735 aus und speichere in Property(n)
FM:
·
Si4735 Default-Werte:
·
Einstellung der manuellen Schrittweite auf 50 kHz (z.B für
Kabelempfang)
·
"max. Tune-Errors" auf 20 kHz (statt 30 kHz; Empfehlung
lt. Datenblatt)
·
Deemphasis auf 50µs (=Europa) anstelle 75µs (=USA) als
Default-Wert
·
50 Senderspeicher
·
AUTOSCAN bei Druck auf S2 für > 5
·
Auto-Scan des gesamten UKW-Bandes und Speicherung der gefundenen
Sender in M1....Mn (n max. 50)
·
Nach Abschluss des Scans: Speicherplatz M1 angewählt
·
Gerät dann im Speicher-Scrollmodus bzgl. Drehencoder-Funktion
·
Formatierung von FM-Frequenzen auf LCD und RS-232-Ausgabe als
"XXX.YY [Mhz]"
·
Anzeige von Sonderzeichen "ST" (="S" über
"T") für Stereo-Empfang in LCD-Zeile 2, Spalte 15
·
Anzeige von RDS-Empfang durch "R" in LCD-Zeile 2,
Spalte 16
·
Anzeige von Radiotext-Empfang durch Sonderzeichen "RT"
("R" über "T") in LCD-Zeile 2, Spalte 16
·
Automatische Anzeige von Radiotext in 1. LCD-Zeile:
·
statisch bei Radiotext-Länge < 17 Zeichen
·
"Ping-Pong" Scrolling (Links<->Rechts) bei Länge
17...24 Zeichen
·
wiederholtes Scrollen von links nach rechts bei Länge > 24
Zeichen
·
nach jeder Radiotext-Nachricht kurze Einblendung der FM-Frequenz
·
weitestgehende Implementierung des RDS-Zeichensatzes Europa durch
ASCII-Ersatz-Tabelle für EADOGM-Zeichensatz
·
PWM-Ausgang für analoges Zeigerinstrument bei FM anstelle
Feldstärke ("RSSI") verändert auf...
·
Stereo-Signalstärke (Si4735 Eigenschaft
"Stereo-Signal" = Response-Byte R3 Bit 0..6[%] in RSQ) :
·
0% (=Mono)...100% (=Stereo) --> 0...3,3V PWM-Ausgabe
·
oder Frequenz-Offset ("Ratio-Mitte") (Si4735
Eigenschaft "Frequency-Offset" = Response-Byte R7 Bit 0..7 [kHz] in
RSQ)
·
-128 kHz (0V PWM)..... +/-0 kHz (1,65V PWM)....+128 kHz (3,3V)
·
oder SNR (0...85 dB)
·
oder Feldstärke (0...85 dBµV)
·
Defaultwert: Stereo-Signalstärke
·
in Schritten durchschaltbar durch Druck auf S2 beim Einschalten
AM:
·
50 Sender-Speicher: 10 für LW, 10 für MW, 3x10 für Kurzwelle (3
Bandbereiche)
·
Anzahl KW-Bänder auf 14 Rundfunk-KW-Bänder erweitert;
entsprechend Wikipedia-Eintrag:
http://de.wikipedia.org/wiki/Kurzwellenrundfunk#Rundfunkb.C3.A4nder_im_Kurzwellenbereich
·
KW-Band wird bei Umschaltung im Klartext mit Frequenzgrenzen
angegeben
·
AUTOSCAN bei Druck auf S4 für > 5s:
·
Auto-Scan des eingestellten AM-Bandes und Speicherung der
gefundenen Sender in Mn....Mm (1...10=LW; 11...20=MW; 21...30 oder 31...40 oder
41...50 KW je nach gewählten Bandbereich)
·
Nach Abschluss des Scans Speicherplatz M1 (LW), M11 (MW) oder
M21/M32/M41 (je nach angewähltem KW-Bereich) angewählt
·
Gerät dann im Speicher-Scrollmodus bzgl. Drehencoder-Funktion
·
Sendernameneingabe: Beim separaten Speichern eines AM-Senders
wird der Sendername (max. 10 Zeichen) mit Drehencoder+Memory-Taste S5
eingegeben und nach Eingabe von 10 Zeichen automatisch mitgespeichert! (noch
nicht geprüft)
·
Schrittweite/Frequenzraster auf 9 kHz für LW/MW verändert
·
10 gültige LW und MW-Senderfrequenzen incl. Namen als
Default-Werte im EEPROM für Speicherplatz 1...10 und 11...20
RS-232:
·
neuer Befehl "j" + Steuerbyte + ENTER →
einmalige RDS-Datenausgabe im Klartext über RS-232
·
Auswahl des RDS-Infosegmentes über Bit 0...7 des eingegebenen
Steuerwertes
·
Bit 0...7 - Segmente beliebig kombinierbar
·
·
Bit 0 :
·
1 Satz Gruppen im FIFO-Speicher
·
aktuelle Gruppennummer+Typ (A/B)
·
Block A, B, C, D-Bytes
·
Blockerror-Byte (Si4735)
·
Bit 1 :
·
PI-Code (Hex und Binär)
·
TP/TA (Travel-Program; Travel-Announcement)
·
Music/Speech-Flag im Klartext
·
Programmtyp PTY (Nummer; 16-Zeichen-Klartext; PTY-Name-Ergänzung)
·
DI = Decoder-Information (Mono/Stereo; Kunstkopfstereophonie;
komrimiert/unkomprimert; Dynamischer oder statischer PTY)
·
Bit 2 :
·
PS = Sendername im Klartext
·
eingestellte Frequenz
·
AF = Alternativ-Frequenzen (ggf. mit Regionalisierung!; nicht
vorhanden bei Kabelempfang!)
·
Country-Code (z.zt. aus Platzmangel auskommentiert im
Source-Code)
·
Area-Coverage (z.zt. aus Platzmangel auskommentiert im
Source-Code)
·
Program Reference Nummer (z.zt. aus Platzmangel auskommentiert
im Source-Code)
·
Language (Klartext) (z.zt. aus Platzmangel auskommentiert im
Source-Code)
·
Bit 3:
·
lokale Uhrzeit formatiert „hhH:mmM“
·
Modified Julian Day-Number
·
Wochentag
·
Datum formatiert „Monday, TT.MM.JJJJ“
·
·
Bit 4 :
·
Radiotext-Zeichen-Länge
·
„Radiotext“
·
Bit 5 :
·
Emergency Warning System: EWS, EWS0...EWS4 (Hex) (z.zt. aus
Platzmangel auskommentiert im Source-Code)
·
Bit 6 :
·
EON-PS = EON-Sendername im Klartext
·
EON-PI-Code = Program Identification Code
·
EON-PIN-Code =
·
EON-TP/TA (EON-Travel Program/Travel
Announcement)
·
EON-Programmtyp EON-PTY (Nummer; 16-Zeichen-Klartext)
·
EON-AF und Mapped Frequencies (Alternativ-Frequenzen; zugeordnete
Frequenzen)
·
Bit 7 :
·
PIN-Code (hex + binär)
·
Linkage Actuator LA
·
Linkage Information (hex)
·
Language Code (hex)
·
Ext. Country Code (hex)
·
TMC-Identification (hex)
·
EWS-Channel (hex)
'kompiliert mit BASCOM V2.0.7.7.
'----------------------------------
'Ausstehende Korrekturen/Verbesserungen:
'---------------------------------------
'- beachte, daß angesteckter Programmieradapter Fehlfunktionen auslöst, da scheinbar Tasten gedrückt sind
'- Vergesse nicht abschließend $EEPROMHEX einzukommentieren
'- PWM-Werte über 1023 beschneiden
'- scroll PWM-Output mit Encoder beim Einschalten oder im Betrieb
'- PWM-Out auch in FM_Tune_Status_Freq_LCD (CALL-SUB)
'- kurze Frequenz-Anzeige in Radiotext auch bei stehendem Radiotext oder Ping-Pong-Scrolling
'- Prüfe AM-Sendernamen-Eingabe/Speicherung/Löschung/Einlesen
'- tausche kurzen und langen S5-Druck (Memory STORE/RECALL aus)
'- Prüfe Property-Verstellung
'- Prüfe RS232-Steuerung
'- prüfe, ob PTY-Name, Ländercode, Regionalcode, Language-Code (evtl. nicht im Kabel) richtig dekodiert werden
'- evtl. Band-Rollover doch wieder einführen für Scan???
'- FM-Bandstart alternativ auf 64MHz setzen. Mal gucken, was da los ist :-)
'- Amateurfunkbänder einbauen?
'- I2C-Befehle verkürzen mit I2CRECEIVE, I2CSEND
'Ausstehende Verbesserungen RDS:
'-------------------------------
'- Linefeed LF in Radiotext auswerten (bisher nur NOPs)
'- RT-Empfang kontinuierlich auch nach Erst-Dekodierung einer Nachricht, solange wie kein A/B-Flagwechsel?
'- PIN_code im Klartext auswerten?
'- TMC-Dekodierung implementieren (Gruppe 8)?
'Versionshistorie:
'-----------------
'V1.0.0.:
'--------
'- FM-Deemphasis auf "1"(=50µs für Europa) anstelle Default-Wert "2" (=75µs für USA etc.) !!!
'- Frequenzsuchraster FM : 50Khz (anstelle Default-Wert 100 khz )
'- Max. Tune-Error FM 20kHz (empfohlen lt. Datenblatt) anstelle Default-Wert 30 kHz
'-
Letzte eingestellte Frequenz/Band/AM-FM-Modus beim Einschalten aus
EEPROM einlesen und bei Veränderungen jeweils in EEPROM speichern
'- 50 FM-Speicher, 50 AM-Speicher + Namen
'-
S2/S4 länger als 2s gedrückt --> FM/AM-Bandscan und automatische
Abspeicherung der gefundenen Sender In Speicher 1...n (max. 30);
Speicher 1 dann aufrufen
'- Beim Speichern eines AM-Senders wird
Name (10 Zeichen) mit Drehencoder+Memory-Taste eingegeben und nach 10
Zeichen automatisch mitgespeichert
'- Falls Property-EEPROM-Speicher=$FF --> lese Default-Wert aus Si4735 aus und speichere in Property(n)
'- Einstellung der je acht Properties durch Drücken von S5 (Memory) länger als 2s
' - Auswahl der Property mit Drehencode
' - Bestätigen mit kurzem Tastendruck von S5 (Memory)
' - Variation der Property mit Drehencoder innerhalb der erlaubten Grenzen
' - Bestätigen und Abspeichern der Property mit kurzem Tastendruck von S5 (Memory)
'- FM-Anzeige:
' - Ergänzung "S" = Stereo , "R" = RDS-Daten vorhanden (LCD-Zeile 2, Spalte 15/16)
'- Ausgabe (sehr vieler) RDS-Informationen (meist) im Klartext über RS-232
'V1.0.1.:
'--------
'Anzeige der Betriebsspannung bei Start
'Anzeige der HW/FW/Rev. nach Powerup
'Anzahl KW-Bänder erweitert
'KW-Band bei Umschaltung im Klartext ausgeben
'Kommentare auf LCD bei allen Aktionen
'V1.0.2.:
'--------
'FM-Senderspeicher auf 50 erweitert
'AM-Senderspeicher auf 50 erweitert
'EEPROM enthält einige ausgewählte gültige LW,MW-Frequenzen und Namen
'EEPROM enthält gültige Default-Werte für Properties
'V1.0.3.:
'--------
'RDS: AF-Speicherung korrigiert
'RDS: Länder und Regionalcodes explizit
'RDS: Gruppe 1A und 1B-Dekodierung implementiert
'RDS: Language-Code im Klartext
'RDS: Datumsberechnung aus MJD implementiert
'RDS: Gruppe 10A-Dekodierung implementiert (PTYN)
'RDS: Gruppe 9A-Hex-Ausgabe implementiert (EWS)
'V1.0.7.:
'--------
'RDS: Inverses "R" für RDS+Radiotext-Empfang
'V1.0.8.:
'--------
'Codetabelle für Sonderzeichen, insbes. Umlaute
'RS232
Befehl "j" für einzelne RDS-Info-Teilbereiche jetzt mit Subvariable
--> jedes gesetzte Bit (0...6) = 1 Teilberich der gesamten RDS-Info
'Ping-Pong Scrollen bei Radiotext-Länge <25, sonst Scrollen von links n. rechts und Repeat
'bem Scrollen: Start und Ende länger stehen lassen (3x Schleifendurchlauf)
'geänderte PWM-Ausgabe (anstelle RSSI): Stereo-Signal (R3 Bit 0..6[%])
'PWM-Ausgabe Frequenz-Offset "Ratio-Mitte" (FM_RSQ_Status, R7 Bit0:7 [kHz]), wählbar durch Tastendruck S2 beim Einschalten
'Sonderzeichen "ST" für STEREO-Signal definiert, Ausgabe auf Zeile 2, Spalte 15
'Sonderzeichen "RT" für RADIOTEXT-Signal definiert, Ausgabe auf Zeile 2, Spalte 16; ersetzt inverses R
'V1.0.9.:
'--------
'RAM-Variablen optimiert
'EON-Dekodierung eingebaut
'V1.1.0.:
'--------
'IRS optimiert
'zugelassene Blockerrors testweise auf 2 = 3...5 korrigierbare Errors gesetzt
'über RS232 wird nur ein Datensatz ausgegeben
'falls bei Bandscan kein Sender gefunden wird --> kein Memory_Scroll-Modus
'alternative
PWM-Ausgabe Frequenz-Offset "Ratio-Mitte" (FM_RSQ_Status, R7 Bit0:7
[kHz]), wählbar durch Tastendruck S2 beim Einschalten
'alternative Frequenz-Schrittweite manuell: 10kHz (FM), 1kHz (AM), wählbar durch Tastendruck S3 beim Einschalten
'V1.1.1.:
'--------
'S2 beim Einschalten gedrückt: Toggelt alternative PWM-Ausgabe Frequenz-Offset "Ratio-Mitte"
'S3
beim Einschalten gedrückt: Toggelt alternative Frequenz-Schrittweite
manuell: 10kHz (FM), 1kHz (AM) / 50 kHz (FM) / 9/9/5 kHz (AM)
'EEPROM speichern und lesen der obigen Flags
'zugelassene Blockerrors wieder auf 1 = 1...2 korrigierbare Errors zurückgesetzt
'Betriebsspannungsmessung und Firmware-Anzeige aus Platzgründen auskommentiert
'EEPROM-Memory-Map:
'------------------
' 1 = Anzahl belegter FM-Senderspeicher($FF = unbelegt) "Fm_memorymax"
' 2...101 = 50 Gespeicherte AM-Frequenzen "Fm_memory(n)"
'102...201 = 50 Gespeicherte FM-Frequenzen "Am_memory(n)"
'202...751 = 50 Sendernamenspeicher f. AM-Sender; je 10+1 Bytes "Am_text(n)"
'995...999 = Anzahl belegter Senderspeicher in LW, MW, KW1, KW2, KW3
'1000 = Letzter eingestellter Modus (AM/FM)
'1001...1002 = Letzte Eingestellte FM-Frequenz
'1003...1004 = Letzte eingestellte AM-Frequenz
'1005 = Letztes eingestelltes AM-Band
'1006...1021 = 16 Bytes Tuning-Properties "Property_dat(n)"
'1022 = Flag für FM-PWM-Ausgabe
'1023 = Flag für manuelle Schrittweite
$regfile
=
"m328pdef.dat"
'ATMega328P-PU: 32k Flash 2k RAM 1k EEPROM
$crystal =
8000000
'8 MHz
$hwstack =
100
'je 2 Byte für Rücksprungadressen CALL/GOSUB/FUNCTION; je 34 Byte pro
(multiple) IRS
$swstack =
100
'je 2 Byte für (lokale Variable + Variablen, die an ein Unterprogramm
übergeben werden)
$framesize =
100
' (mit Byval übergebene + lokale Variable) + 24 Bytes für
Umwandlungsroutinen (PRINT/LCD, INPUT, FORMAT(FP-Variable), STR$
$map
'Report-File um die Label-Adressen erweitern
'$sim
'Befehle für Simulation, damit Wait-Zyklen nicht abgearbeitet werden
'$dbg
'zur Stackanalyse
'$prog &HFF , &HD7 , &HD7 ,
&HFD
'Fuse bytes.
$baud =
38400
'38.400 Baud über Hardware Rs-232 an FTDI
$lib
"I2C_TWI.LBX"
'nur bei Benutzung der Hardware I2C-Ports
'PIN-Configuration:
'------------------
'INPUT:
'------
'PB2 = Pin 16 Taster S2
'PB3 = Pin 17 Taster S3
'PB4 = Pin 18 Taster S4
'PB5 = Pin 19 Taster S5
'PC1 = Pin 24 Encoder
'PC2 = Pin 25 Encoder
'PC0 = Pin 23 ADC für Lautstärke-Poti
'PD0 = Pin 2 RxD
'*** Taster ***
Config Pinb.2 = Input : S2 Alias Pinb.2 : Set Portb.2 'PB2=S2 Pullup einschalten
Config Pinb.3 = Input : S3 Alias Pinb.3 : Set Portb.3 'PB2=S2 Pullup einschalten
Config Pinb.4 = Input : S4 Alias Pinb.4 : Set Portb.4 'PB2=S2 Pullup einschalten
Config Pinb.5 = Input : S5 Alias Pinb.5 : Set Portb.5 'PB2=S2 Pullup einschalten
'*** Encoder ***
Config
Pinc.1 = Input : Set
Portc.1
'Encoder-Portpins Pullups einschalten
Config Pinc.2 = Input : Set Portc.2
Config
Pinc.0 =
Input
'ADC0 für Lautstärke-Poti
Config Pind.0 =
Input
'RxD für Hardware RS-232
'OUTPUT:
'-------
'PB0 = Pin 14 Verkürzungsspule
'PB1 = Pin 15 Verkürzungsspule
'PC3 = Pin 26 Verkürzungsspule
'PC4 = Pin 27 I2C-SDA: Si4735 Data
'PC5 = Pin 28 I2C_SCL: Si4735 Clock
'PD1 = Pin 3 TxD
'PD2...PD7 = EADOGM162:RS,E,DB4...DB7
Config
Pinb.0 =
Output
'Spule MF
Config Pinc.3 =
Output
'Spule LF
Config Pinb.1 =
Output
'PWM1A-Ausgang für S-Meter
Config Pind.1 =
Output
'TxD für Hardware RS-232
'******************
'*** Konstanten ***
'******************
'*****************
'*** Variablen ***
'*****************
Dim
N As Byte , N1 As Byte , N2 As
Byte
'HilfsVariable Schleifenzähler
Dim I As Word , I1 As Word , I2 As
Word
'IndexVariable
Dim T As
Word
'Schleifendurchlaufzähler Main-Loop
Dim Lcdrefresh As
Byte
'Schleifenzähler; nach 5 Durchläufen x 200 Mainloop-Durchläufen
Frequenz und Tuingdetails erneuern
Dim D As
Byte
'Hilfs-Variable "Daten"
Dim Lo As Byte , Hi As
Byte
'Lo und High-Byte f. diverse Zwecke
Dim Text1 As String *
16
'allgemeiner Textausgabe-String
Dim Byte1 As Byte , Byte2 As Byte , Word1 As Word , Word2 As Word , Long1 As Long , Float1 As Single
'*** Poti, Taster, Encoder ***
Dim
Pot As
Word
'Poti-Wert aus ADC
Dim Dif As
Integer
'Differenz zum letzten Poti-Wert
Dim T1 As Word , T2 As Word , T3 As
Word , T4 As Word
'Verzögerungszähler für lang gedrückte Tasten
Dim Encoder1 As
Integer , Encoder1old As
Integer
'gelesene Encoder-Bits
Dim Code1 As Byte , Code1old As
Byte
'Encoder-Codes
'*** Frequenzen, Bänder, Schrittweiten ***
Dim
Am_fm_flag As
Byte
'Flag für AM-/FM-Modus: 1=AM, 0=FM
Dim Freq_fm As
Word
'FM-Frequenz
Dim Freq_am As
Word
'AM-Frequenz
Dim Freq As
Word
'Frequenz
Dim Band As
Byte
'AM-Frequenzband
Dim Band_start(17) As Word , Band_end(17) As
Word
'Band_start/-end-Frequenzen
Dim Band_name As String *
16
'Bandname
Dim Am_lower_limit As Word : Am_lower_limit =
149
'absolute AM-Grenzfrequenzen
Dim Am_upper_limit As Word : Am_upper_limit = 23000
Dim
Seek_step As
Byte
'Suchschrittweite in kHz
Dim Freq_step_fine_flag As
Byte
'Flag, ob FM-Step=10kHz, AM-Step=1 kHz (Einschalten S3 gedrückt)
'*** Senderspeicher ***
Dim
Am_memory(50) As
Word
'30 AM-Sendespeicher (Frequenz, 2 Byte)
Dim Am_memorypos As
Byte
'aktueller AM-Speicherplatz
Dim Am_memorymin As
Byte
'min. Speicherplatz in gewähltem Speicherbereich
Dim Am_memorymax As
Byte , Scan_memorymax As
Byte
'Anzahl benutzter Speicherplätze AM-Sender;
Dim Lw_memorymax As Byte , Mw_memorymax As Byte , Kw1_memorymax As Byte , Kw2_memorymax As Byte , Kw3_memorymax As Byte
Dim
Am_text(50) As String *
10
'AM-Sendernamen-Speicher a´ 10 Byte
Dim Am_textpos As
Byte
'Positionszeiger für AM-Sendernamen-Eingabe
Dim Am_textaktiv As
Bit
'Flag für AM-Sendernamen-Eingabe
Dim Fm_memory(50) As
Word
'30 FM-Sendespeicher (Frequenz, 2 Byte)
Dim Fm_memorypos As
Byte
'aktueller FM-Speicherplatz
Dim Fm_memorymax As
Byte
'Anzahl benutzter Speicherplätze FM-Sender
Dim Memory_aktiv_flag As
Bit
'im Speicher-Scroll-Modus
'*** Si4735 ***
Dim Rssi As
Word
'Signalstärke dBuv
Dim Snr As
Word
'SNR (dB)
Dim Stereo_signal As
Byte
'Stereo-Signal in %
Dim Freq_offset As
Byte
'+/- Frequenz-Abweichung in kHz
Dim Pwm_output As
Byte
'Flag für PWM-Ausgang (0=Stereo-Signal, 1=Freq.-Offset, 2=RSSI, 3=SNR)
Dim
C As
Long
'Antennten-Kapazität
Dim Fin As
Long
'Eingabe-Frequenz
Dim H As Byte , L As
Byte
'HilfsVariable High-/Low-Byte
Dim Vol As
Byte
'Volume
Dim Status As
Byte
'Statusbyte aus Si4735
Dim Bltf As
Bit
'Statusbyte für erreichen der Bandgrenze bei Suchlauf
Dim Valid As
Bit
'Flag für gültige Frequenz (über Pegel- und SNR-Schwelle)
Dim R1 As
Byte , R2 As Byte , R3 As Byte , R4 As
Byte '12* gelesene Response-Bytes
aus Si4735
Dim R5 As Byte , R6 As Byte , R7 As Byte , R8 As Byte
Dim R9 As Byte , R10 As Byte , R11 As Byte , R12 As Byte
Dim
Property_adr As
Word
'Property-Adresse
Dim Dat As Byte , Dat_word As
Word
'Datenbyte (u.a. Property-Low-Byte)
Dim Property_dat(16) As
Byte
'16 Byte Tuning-Parameter f. Si4735
Dim Property_adress(16) As Word
Dim Property_max(16) As Byte
Dim Property_min(16) As Byte
Dim Property_default(16) As Byte
Dim
Property_aktiv As
Byte
'Flag für Encoder-Eingabe Properties (1=Property-Scroll-Modus,
2=Property-Einstell-Modus)
'*** RDS-Variablen ***
Dim
Rds_flag As
Bit
'RDS-Signal vorhanden
Dim Rds_block_errors As Byte :
Rds_block_errors = 1
'max. zulässige RDS-Block-Fehler: 0=0 Errors, 1=1...2 errors
correctable, 2=3...5 errors correctable, 3=uncorrectable
Dim
Block_errors_block_a As Byte , Block_errors_block_b As Byte ,
Block_errors_block_c As Byte , Block_errors_block_d As
Byte 'Errors Block A,B,C,D
Dim
Service As
Byte
'Gruppennummer
Dim Tp As Byte , Ta As
Byte
'Flag für Travel-Program, Travel Announcement
Dim Pi As
Word
'16 bit Programm-Identification-Nummer
Dim Ms_flag As
Bit
'Music/Speech
Dim Di_counter As
Byte
'Decoder Information-Zähler modulo 4
Dim Di(4) As
Byte
'Decoder-Informationen
Dim Pty As Byte , Ptyn As
Byte
'Program-Type,Program-Type Name
Dim Pty_name As String * 8 , Pty_name_flag As Byte 'PTYN aus Gruppe 10A
Dim Ps_name As String * 8 , Ps_name_last As String * 8 'Sendername aus RDS, 8 Zeichen
Dim
Ps_counter As Byte , Ps_flag As
Bit
'Zähler für decodierte 2Byte-PS Blocks, Flag für komplette Dekodierung
Dim
Af_flag As
Byte
'Flag für gefundene AFs, 1=gefundene, 2=Liste fertig
Dim Af(25) As
Word
'Alternate Frequencies
Dim Freq_af As Word
Dim Af_max As
Byte
'Anzahl von AF
Dim Af_number As
Byte
'laufende Nummer AF
Dim Lw_mw_af As
Bit
'Flag für folgende LW-MW-Frequenz in Block D
Dim Method_b As
Bit
'Flag für AF-Methode B
Dim Reg_flag As
Bit
'Flag für Regionalprogramm/-Frequenzen
Dim Eon_flag As
Byte
'Flag für EON-Dekodierung: 0 oder $FF = nicht empfangen; 1= Start
empfangen, 2=vollständig empfangen
Dim Ps_eon As String *
8
'EON:PS
Dim Pty_eon As
Byte
'EON:PTY
Dim Tp_eon As Bit , Ta_eon As
Bit
'EON:TP/TA
Dim Pi_eon As Word , Pic1_eon As Byte , Pic2_eon As Byte 'EON:PI
Dim
Pin_code_eon As
Word
'EON:PIN
Dim Af_eon(12) As
Word
'EON: AF/Tuned-Freq. - Mapped Freq.
Dim Vc_counter_eon As
Word
'Zähler für Adress-Segment
Dim Link_info As
Word
'Linkage-Information
Dim La As
Bit
'Linkage Actuator-Flag
Dim Vc As
Byte
'Variant Code
Dim Ecc As
Byte
'Extended Country Code
Dim Lc As
Word
'Language Code
Dim Ews As Word , Ews0 As Byte , Ews1 As Byte , Ews2
As Byte , Ews3 As Byte , Ews4 As
Byte 'Emergency Warning System
Dim
Pin_code As
Word
'Program-Identification-Number
Dim Tmc_ident As
Word
'TMC-Idenfication
Dim Radiotext_on As Bit : Radiotext_on =
1
'Flag, ob RDS-Text angezeigt werden soll, oder nicht
Dim
Radiotext_present As
Bit
'Flag für Radiotext in RDS-Daten
Dim Radiotext_first_aqu As
Bit
'Flag für Radiotext Erstaquisition (Grupppe 2A oder 2B in RDS-Daten
enthalten)
Dim Radiotext_start_decode As
Byte
'Flag, daß RT-Dekodierung gestarrtet hat
Dim Segment As Byte ,
Position As
Byte
'Segment-Nummer des letzten empfangen egmentes
Dim Char_counter As
Byte
'Zeichenzähler
Dim Radiotext As String * 64 , Radiotext_new As String * 64 'Radiotext, max. 64 Zeichen
Dim
Radiotext_ab_flag As Byte , Radiotext_ab_flag_old As
Byte 'Toggle-Bit für neue
Radiotext-Info
Dim Radiotext_ready As
Bit
'Radiotext anzeigen --> Carriage Return oder alle Gruppen gesendet
in Radiotext
Dim Radiotext_display_pos As
Byte
'Aktuelle, rechte Stelle des RT
Dim Radiotext_length As Byte , End_position As Byte 'Länge des Radiotext-Strings
Dim
Radiotext_lf_pos As
Byte
'Position des nächsten LF
Dim Display_string As String *
16
'16-Byte String für LCD Zeile 1
Dim Scroll_counter As
Byte
'Verzögerungszähler für 1. und letztes Zeichen beim Scrolling
Dim
Direction As
Bit
'0=nach rechts, 1=nach links
Dim Replace_codes(127) As
Byte
'Sonderzeichen-Tabelle
Dim Rds_over_rs232_control As
Byte
'Control-Byte für RDS-Ausgabe An/Aus (an RS-232)
Dim Pos As
Byte
'Positionszeiger in Ausgabestring
Dim Ch As String *
1
'1 Zeichen für String
Dim Tx As String *
2
'1 Doppelzeichen für String
Dim Freq_string As String *
6
'Frequenzausgabe-String "108.45" für FM oder "1234" für AM
Dim
Minuten As Integer , Utc_min As
Byte
'Minuten
Dim Stunden As Integer , Utc_hour As
Byte
'Stunden
Dim Utc_offset As Byte
Dim Mjd As
Long
'Modified Julian Date
Dim Year As Integer , Month As Byte , Day As Byte , Wd As Long
Dim K As Byte , Ks As Single , Ms As Single , Ys As Single 'Hilfsvariablen
'*** RS-232 Variablen für I2C-Steuerung vom PC ***
Dim
Command As
Byte
'eingelesenes Kommando-Byte
Dim Bytesout As Byte
Dim Bytesin As Byte
Dim
Data_i2c(10) As
Byte
'zu lesende/schreibende I2C-Daten
'**********************************
'*** SUB-/FUNCTION Definitionen ***
'**********************************
Declare
Function Si4735_get_property(byval Prop_adr As Word) As
Word 'Hole Property-Wert Nr. N
(1...16)
Declare Sub
Si4735_get_status_byte()
'Status-Byte holen. Bit0 =
Declare Sub
Si4735_wait_for_seek_tune_cplt()
'Warte, bis Status-Bytet.0 = 1 = STC = Seek/Tune Complete --> bereit
zum nächsten Befehlsempfang
Declare Sub
Si4735_wait_for_clear_to_send()
'Warte bis Status-Byte.7 = CTS = "Clear to Send"
Declare Sub
Si4735_set_rx_volume()
'Property "Volume" setzen
Declare Sub Si4735_set_property(byval
Prop_adr As Word , Byval Prop_value_high As Byte , Byval Prop_value_low
As Byte) 'Property setzen
Declare
Sub
Si4735_print_property_lcd()
'Property-Wert Nr. N auf LCD ausgeben
Declare Sub
Si4735_init()
'Ruft Init=Powerup, Si4735_set_rx_volume, FM_Tune_Freq,
Am_tune_status_freq_print_lcd, Rds_init auf; Setzt Properties 1-8
Declare
Sub
Si4735_get_rev()
'Hole IC, Firmware und Rev. und schreibe auf LCD
Declare Sub Am_tune_freq()
Declare Sub Am_seek_freq_up()
Declare Sub Am_seek_freq_down()
Declare Sub Am_tune_status_freq_print_lcd()
Declare Sub Am_stop_seek_tune()
Declare Sub Am_rsq_status()
Declare
Sub
Am_seek_step()
'Setze AM-Frequenzschritt
Declare Sub Call_am_memory(am_memory_number As Byte)
Declare Sub Call_fm_memory(fm_memory_number As Byte)
Declare
Sub Write_ammemories_eeprom(stored_memories As Byte , Byval
Start_memory As Word) 'Schreibe
Anzahl gespeicherter Sender in AM-Bändern ins EEPROM
Declare Sub Read_ammemories_eeprom(stored_memories As Byte , Byval Start_memory As Word)
Declare Sub Fm_tune_freq()
Declare Sub Fm_seek_freq_up()
Declare Sub Fm_seek_freq_down()
Declare Sub Fm_tune_status_freq_print_lcd()
Declare Sub Fm_stop_seek_tune()
Declare Sub Fm_rsq_status()
Declare
Sub Lcd_freq(byval Fm_freq As Word , Byval Y_pos As Byte , Byval X_pos
As Byte) 'Drucke FM_Freq in
LCDPosition Y,X
Declare Sub
Lcd_scanning
'drucke "Scanning..." in untere LCD-Zeile, lösche "mxx " rechts
oben
Declare Sub
Eeprom_save()
'Frequenzdaten in EEPROM sichern
Declare Sub
Rds_init()
'RDS-Initialisierung
Declare Sub
Rds_reset()
'RDS-Variablen zurücksetzen nach SYNC-Lost oder neuem Sender
Declare
Sub
Rds_get_status_and_data()
'hole 1 RDS-Gruppe + RDS-Stausbytes R1...R14 aus Si4735
Declare Sub
Rds_decoding()
'Ausgabe RDS-Sendername und RDS-Zeit auf 2.Display-Zeile bzw. Radiotext
Declare Sub Rds_calc_af(af_index As Byte , Af_word As Word) 'Berechne Frequenz (FM/LW/MW) einer gültigen AF
Declare
Sub Rds_char_code(chr_code As
Byte)
'Ersetze RDS-ASCII-Code mit EADOGM-Code
Declare Sub
Make_freq_string(byval Af_freq As
Word) 'erzeuge
Freq_string für formatierte AM-/FM-Frequenz
Declare Sub
Radiotext_decoded()
'1x Radiotext-Message dekodiert
Declare Sub
Radiotext_scroll()
'Scrolle Radiotext um 1 Zeichen nach rechts
Declare Sub
Radiotext_start()
'Bringe Radiotext erneut in Anfangsposition
'Declare Sub
Blockerrors_service()
'Isoliere Blockerrors der 4 Blocks + Gruppennummer
Declare Sub
Clear_lcd_lowerline()
'untere LCD-Zeile löschen
Declare Sub
Clear_lcd_upperline()
'obere LCD-Zeile löschen
Declare Sub
Reset_flags()
'Eingabeflags zurücksetzen
Declare Sub Reset_encoder()
Declare Sub F_control()
Declare Sub Mam_control()
Declare Sub Mfm_control()
Declare Sub Pc_control_i2c()
Declare Sub Properties()
Declare
Sub
Rds_print_control()
'RDS-Ausgabe über RS-232 in Teilen ein- oder ausschalten (pro Bit 1
Segment, max. 8 Teilbereiche)
'**********************
'*** Initialisation ***
'**********************
Open
"com1:" For Binary As
#1
'Kanal 1/Com1 für RS-232 öffnen (38400 Baud, 8N1)
Config Scl =
Portc.5
'Entspricht Hardware-I2C; (evtl. andere I2C-Routine benutzen)
Config Sda = Portc.4
I2cinit
Config
Twi =
400000
'I2C-Bus mit 400kHz
Config Adc = Single , Prescaler = Auto ,
Reference = Off 'AD-Wandler für Volume-Poti Abfrage;
A_ref = ext = 3,3V
Start Adc
Config Timer1 = Pwm , Prescale =
8 , Pwm = 10 , Compare A Pwm = Clear
Down 'TIMER1 als 10bit-PWM-Ausgabe
für S-Meter (oder Stereo-Blend/Frequency-Offset)
Start Timer1
Pwm1a = 0
Config
Timer0 = Timer , Prescale =
8
'TIMER0 als Interruptquelle für Encoder-Abfrage
'On Ovf0 Tim0_isr Saveall
On Ovf0 Tim0_isr Nosave
Enable Timer0
Enable Interrupts
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2 , Chipset = Dogm162v3
Initlcd
Cursor Off Noblink
'Deflcdchar
0 , 1 , 14 , 14 , 1 , 11 , 13 , 14 ,
31
'Inverses "R"
Deflcdchar 0 , 24 , 20 , 24 , 20 , 20 , 7 , 2 ,
2 '"RT" =
Radiotext-Symbol
'Deflcdchar 7 , 6 , 8 , 6 , 1 , 14 , 4 , 4 ,
4
'"ST" = Stereo-Symbol (alternativ)
Deflcdchar 7 , 12 , 16 , 12 , 2 ,
12 , 7 , 2 ,
2
'"ST" = Stereo-Symbol
Deflcdchar 1 , 2 , 5 , 5 , 6 , 5 , 5 , 6 ,
8
'ß
Deflcdchar 2 , 32 , 4 , 14 , 4 , 32 , 14 , 32 , 32 '+/-
Deflcdchar 3 , 14 , 17 , 23 , 25 , 25 , 23 , 17 , 14 'Copyright
Deflcdchar 4 , 24 , 25 , 2 , 4 , 8 , 16 , 27 , 27 'Promille
Deflcdchar
5 , 4 , 14 , 21 , 4 , 4 , 4 , 4 ,
32
'Pfeil n. oben
Deflcdchar 6 , 32 , 4 , 2 , 31 , 2 , 4 , 32 ,
32
'Pfeil n. rechts
'Deflcdchar 7 , 4 , 4 , 4 , 4 , 21 , 14 , 4 ,
32
'Pfeil n. unten
'Deflcdchar 2 , 16 , 15 , 15 , 17 , 30 , 30 , 1 ,
31
'Inverses "S"
'Deflcdchar N , 32 , 16 , 8 , 4 , 2 , 1 , 32 ,
32
'\
'Deflcdchar N , 15 , 20 , 20 , 23 , 20 , 20 , 15 ,
32
'OE
'Deflcdchar N , 32 , 32 , 10 , 21 , 22 , 20 , 11 ,
32
'oe
Cls
'LCD-Einschalt-Meldung
'Cursor Off Noblink
'*** Band_start/-end-Frequenzen und Bandname ***
Restore Band_data
For N = 1 To 17
Read Band_start(n)
Read Band_end(n)
Next N
'*** Property-Grenzwerte einlesen ***
Restore Property_data
For
N = 1 To
16
'Tuning-Parameter f. Si4735 aus zurücklesen EEPROM-Adresse
1006...1023
Read
Property_adress(n)
'Property-Adressen, Min./Max.Werte aus Data-Zeilen einlesen
Read Property_min(n)
Read Property_max(n)
Read Property_default(n)
Next N
'*** Sonderzeichen-Ersatztabelle ab ASCII 128 für EADOGM-Zeichensatz vs. RDS-Zeichensatz laden ***
Restore Special_characters
For N = 1 To 127
Read Replace_codes(n)
Next N
'*** Clear Memory = Taste S5 ("Memory") beim Einschalten gedrückt ***
If
S5 = 0
Then
'Falls beim Einschalten S5 ("Memory") länger als 0,3s gedrückt -->
alle Tuning-Parameter+Senderspeicher löschen
D = 0
Writeeeprom D ,
0
'Anzahl gespeicherter AM-/FM-Sender = 0
Writeeeprom D
Writeeeprom D ,
995
'5xAM-Speicher
Writeeeprom D
Writeeeprom D
Writeeeprom D
Writeeeprom D
Text1 = Space(10)
For I = 202 To 741 Step
11
'AM-Senderspeichernamen löschen
Writeeeprom Text1 , I
Next I
For N = 1 To
16
'Tuning-Parameter mit Default-Wert füllen und ins EEPROM schreiben
Property_dat(n) = Property_default(n)
D = Property_default(n)
I = N + 1005
Writeeeprom D , I
Next N
End If
'*** letze Einstellwerte aus EEPROM einlesen und prüfen, ob gültig ***
Readeeprom
Am_fm_flag ,
1000
'letzen AM/FM Modus aus EEPROM zurücklesen
Readeeprom
Freq_fm
'letzte Frequenzen zurücklesen'
Readeeprom Freq_am
Readeeprom Band
If
Am_fm_flag > 1 Or Freq_fm < Band_start(17) Or Freq_fm >
Band_end(17) Or Freq_am < Band_start(1) Or Freq_am > Band_end(16)
Then
Am_fm_flag =
0
'Starte mit FM-Modus
Freq_fm =
10080
'FM-Default-Wert = 100.80 MHz
Freq_am =
549
'AM-Default-Frequenz= DLF
Band = 2
End If
If
Freq_am < Band_start(band) Or Freq_am > Band_end(band)
Then 'Falls AM-Frequenz außerhalb
Bandgrenzen...
Freq_am =
Band_start(band)
'--> AM-Frequenz auf Bandstart-Anfang
End If
Readeeprom
Fm_memorymax ,
1
'Anzahl gespeicherter FM-Sender aus EEPROM-Adresse 0 einlesen
If
Fm_memorymax > 50 Then Fm_memorymax =
0
'falls EEPROM-Speicher unbeschrieben --> Anzahl gespeicherter
FM-Sender=0 setzen
If Fm_memorymax > 0
Then
'falls FM-Senderspeicher EEPROM nicht leer --> FM-Senderspeicher
einlesen
For N = 1 To Fm_memorymax
I = N *
2
'EEPROM-Adresse für FM-Frequenz berechnen
I = I + 100
Readeeprom Freq ,
I
'FM-Speicherfrequenzen einlesen
Fm_memory(n) = Freq
Next N
End If
Readeeprom
Lw_memorymax ,
995
'5x genutzte AM-Speicher-Endadressen
Readeeprom Mw_memorymax , 996
Readeeprom Kw1_memorymax , 997
Readeeprom Kw2_memorymax , 998
Readeeprom Kw3_memorymax , 999
Call
Read_ammemories_eeprom(lw_memorymax ,
1)
'AM-Speicherfrequenzen und Speichernamen zurücklesen
Call Read_ammemories_eeprom(mw_memorymax , 11)
Call Read_ammemories_eeprom(kw1_memorymax , 21)
Call Read_ammemories_eeprom(kw2_memorymax , 31)
Call Read_ammemories_eeprom(kw3_memorymax , 41)
'*** letzte Tuningparameter (Properties) aus EEPROM einlesen ***
For
N = 1 To
16
'Tuning-Parameter f. Si4735 aus zurücklesen EEPROM-Adresse
1006...1023
I = N + 1005
Readeeprom Dat , I
Property_dat(n) = Dat
If Dat < Property_min(n) Or Dat > Property_max(n) Then
'eingelesener EEPROM-Wert außerhalb Wertebererich
Property_dat(n) = Property_default(n)
End If
Next N
Readeeprom
Pwm_output ,
1022
'Flag für PWM-Ausgabe FM einlsen
If Pwm_output > 3 Then
Pwm_output =
0
'auf Gültigkeit prüfen
Readeeprom Freq_step_fine_flag ,
1023
'Flag für manuelle Schrittweite einlesen
If Freq_step_fine_flag > 1 Then Freq_step_fine_flag = 0 'auf Gültigkeit prüfen
Lcd "DSP-Radio V1.1.1"
Home Lower
Lcd " Extended RDS"
Wait 1
'*** Ändere PWM-Ausgabe auf Freq-Offset, falls Taste S2 ("FM") beim Einschalten gedrückt ***
Cls
Lcd "PWM Analog-Out:" : Home Lower
If
S2 = 0
Then
'Falls beim Einschalten S2 ("FM") gedrückt --> PWM-Ausgabe aus
FM-Freq-Offset anstelle Stereo-Signal
Incr Pwm_output : If Pwm_output > 3 Then Pwm_output = 0
Writeeeprom Pwm_output ,
1022
'Flag für PWM-Ausgabe FM in EEPROM schreiben
End If
Select Case Pwm_output
Case 0 : Print "FM Stereo-Level"
Case 1 : Print "FM Freq-Offset"
Case 2 : Print "Feldstaerke"
Case 3 : Print "SNR"
End Select
If Pwm_output = 1 Then
Lcd "FM Freq-Offset"
Else
Lcd "FM Stereo-Level"
End If
Wait 2
If
S3 = 0
Then
'Falls beim Einschalten S3 ("Band") gedrückt --> manueller
Frequenzschritt
Toggle Freq_step_fine_flag.0
Writeeeprom Freq_step_fine_flag ,
1023
'Flag für manuelle Frequenzschrittweite iin EEPROM schreiben
End If
Cls
If Freq_step_fine_flag = 1 Then
Lcd "FM-Step:10 kHz"
Lowerline : Lcd "AM-Step: 1 kHz"
Else
Reset Freq_step_fine_flag
Lcd "FM-Step:50 kHz"
Lowerline : Lcd "AM-Step: 5 kHz"
End If
Wait 2
'(
Pot
= Getadc(14) : Pot =
Getadc(14)
'1.1V Bandgap-Referenz messen
Float1 = Pot : Float1 = Float1 / 1024 : Float1 = 1.1 / Float1
Cls : Lcd "Betriebsspannung"
Lowerline : Lcd " " ; Fusing(float1 , "#.#") ; " V" : Wait 1
Call
Si4735_get_rev()
'Hardware/Firmware Daten holen und anzeigen
')
'Vol =
45
'Default Volume Wert
'*** Si 4735 initialisieren ***
Call
Si4735_init
'--> Starte FM/AM-Modus in Si4735
'*****************
k
'*****************
'*** MAIN-LOOP ***
'*****************
'*****************
Do
'************ RS-332 Control***************************
'*** 1 Steuerzeichen einlesen und zu SUB verzweigen ***
'******************************************************
D = Inkey(#1)
Select Case D
Case 102 : Call
F_control
'"f", Freq
Case 109 : Call
Mam_control
'"m", Memory AM
Case 110 : Call
Mfm_control
'"n", Memory FM
Case 112 : Call
Properties
'"p", Property
Case 105 : Call
Pc_control_i2c
'"i", I2C command
Case 106 : Call
Rds_print_control
'"j": RDS output On (Sendername, Zeit, Radiotext ausgeben)
Case 107 : Rds_over_rs232_control =
0
'"k": RDS output Off
Case 114 : Print
Rssi
'"r": RSSI
Case 115 : Print
Snr
'"s": SNR
End Select
Waitms 1
'*************************
'*** Encoder auswerten ***
'*************************
'*** Encoder: Property-Anzeige/Einstell-Modus ***
If Encoder1old <> Encoder1 Then
Disable Timer0
If Property_aktiv <> 0
Then
'im Property-Einstell-Modus?
'Properties scrollen
If Property_aktiv = 1
Then
'im Property-Scroll-Modus?
If Encoder1 > 0 Then Incr
N
'Property-Adresse erhöhen oder verkleinern und auf Intervall 9...16
bringen
If Encoder1 < 0 Then Decr N
If N > 16 Then N =
9
'Property-Scroll nur im Intervall 1...8 (FM) oder 9...16 (AM)
If N = 0 Then N = 8
If N = 8 And Am_fm_flag = 1 Then N = 16
If N = 9 And Am_fm_flag = 0 Then N = 1
Elseif Property_aktiv = 2
Then
'im Property-Setz-Modus (Property_aktiv=2)? --> Je nach Property
Max./Min.Werte einhalten
Dat = Property_dat(n)
If Encoder1 > 0
Then
'Property-Wert erhöhen oder verkleinern und auf zulässiges Intervall
bringen
If Dat < Property_max(n) Then
Incr Dat
Else
Dat =
Property_min(n)
'Rollover
End If
End If
If Encoder1 < 0 Then
If Dat > Property_min(n) Then
Decr Dat
Else
Dat = Property_max(n)
End If
End If
Property_dat(n) = Dat
Property_adr =
Property_adress(n)
'Neuen Property-Wert setzen
Call Si4735_set_property(property_adr , &H00 , Dat)
End If
Call
Si4735_print_property_lcd
'Property auf LCD ausgeben
Call Reset_encoder
'*** Encoder: AM-Modus ***
Elseif Am_fm_flag = 1
Then
'im AM Modus?
' Disable timer0
If Am_textaktiv = 1
Then
'AM-Text Senderspeichernamen-Eingabe?
'Namenseingabe AM-Sender
Ch = Mid(am_text(am_memorypos) , Am_textpos ,
1) 'aktuelles Zeichen aus Am_text
isolieren
I = Asc(ch)
If Encoder1 > 0 Then Incr
I
'ASCII-Wert 1 erhöhen oder erniedrigen
If Encoder1 < 0 Then Decr I
If I = 126 Then I =
32
'Bei Überlauf auf "SPACE" zurücksetzen
If I = 31 Then I =
125
'Bei Unterlauf auf "~" zurücksetzen
Ch =
Chr(i)
'ASCII-Wert in Zeichen zurückverwandeln
Mid(am_text(am_memorypos) , Am_textpos , 1) =
Ch 'Zeichen in Am_text
zurückspeichern
I = Am_textpos + 6
Locate 2 , I
Lcd
Ch
'neues Zeichen ausgeben
Locate 2 , I
Call Reset_encoder
Elseif Memory_aktiv_flag = 1
Then
'im Memorymodus? --> Speicher durchscrollen
'Speicher-Scrolling
If Am_memorymax > 0
Then
'Scrolling nur, falls überhaupt mind. 1 Sender gespeichert
If Encoder1 > 0 Then Incr
Am_memorypos 'Speicherzeiger
+/- 1
If Encoder1 < 0 Then Decr Am_memorypos
If Am_memorypos > Am_memorymax Then Am_memorypos =
Am_memorymin 'Rollover bei
Überschreiten
If Am_memorypos < Am_memorymin Then Am_memorypos =
Am_memorymax 'Rollover bei
Unterschreiten
Call Call_am_memory(am_memorypos)
End If
Else
'sonst --> Frequenz je nach Band um 1/5/9 kHz erhöhen
'Frequenz-Erhöhung
Freq = Encoder1 *
5
'5 kHz-Default-Schrittweite
If Freq_step_fine_flag = 0 Then
If Band < 3 Then Freq = Encoder1 *
9 'Im Grobmodus: LW/MW
--> 9 kHz
Else
Freq =
Encoder1
'Im Feinmodus --> 1 KHz
End If
Freq_am = Freq_am + Freq
If Freq_am < Am_lower_limit Then Freq_am =
Am_lower_limit 'absolute
Frequenzgrenzen checken
If Freq_am > Am_upper_limit Then Freq_am = Am_upper_limit
Call
Am_tune_freq
'Frequenz einstellen
Call Am_tune_status_freq_print_lcd
Call Reset_encoder
End If
'*** Encoder: FM-Modus ***
Elseif Am_fm_flag = 0
Then
'im FM-Modus, dann...
' Disable
Timer0
'Encoder verändert --> Frequenz- oder Memory-Inc/Decr
If Memory_aktiv_flag = 1
Then
'im Speichermodus? --> Speicher durchscrollen
If Fm_memorymax > 0 Then
If Encoder1 > 0 Then Incr Fm_memorypos
If Encoder1 < 0 Then Decr Fm_memorypos
If Fm_memorypos > Fm_memorymax Then Fm_memorypos = 1
If Fm_memorypos < 1 Then Fm_memorypos = Fm_memorymax
Call Call_fm_memory(fm_memorypos)
End If
Else
'sonst --> FM-Frequnez um +/-50 kHz verändern
If Freq_step_fine_flag = 1
Then
'Frequenz-Schrittweite berechnen
Freq = Encoder1
Else
Freq = Encoder1 * 5
End If
Freq_fm = Freq_fm + Freq
If Freq_fm < Band_start(17) Then Freq_fm =
Band_end(17) 'FM-Bandgrenzen
checken --> Rollover
If Freq_fm > Band_end(17) Then Freq_fm = Band_start(17)
Call
Fm_tune_freq
'und einstellen
Call Fm_tune_status_freq_print_lcd
Call Reset_encoder
End If
End If
End If
'***********************************
'*** Display periodisch erneuern ***
'***********************************
'*** Frequenz, Tuning-Details und ggf. RDS/Radiotext auf Display***
If Property_aktiv = 0
Then
'falls gerade nicht im Property-Einstell-Modus und RDS-Data present...
Call
Rds_decoding()
'RDS-Loop; hole die letzten Gruppen aus FIFO-Speicher, sobald mind. 14
Gruppen present
End If
Incr
T
'Schleifenzähler für Mainloop bis 200
If T = 100 Then T = 0
If T = 25
Then
'bei T=50: Frequenz auf Display, falls Radiotext_ready=0
If Valid = 0
Then
'Bei noch ungültiger Frequenz...
If Am_fm_flag = 0
Then
'FM-Modus?
If Radiotext_ready = 1 Then
If Scroll_counter > 0
Then
'Verzögerungszähler
Decr Scroll_counter
Else
Call
Radiotext_scroll
'Scrolle Radiotext um 1 Zeichen weiter
End If
Else
Call
Fm_tune_status_freq_print_lcd
'--> FM-Fequenz Auf Display (wenn kein Radiotext decodiert)
End If
Else
'AM-Modus?
Call
Am_tune_status_freq_print_lcd
'--> Am-Status/Frequenz-ausgabe
End If
End If
End If
If T = 50
Then
'bei T=100: Tuning-Details und ggf. RDS auf Display
If Am_fm_flag = 0
Then
'FM-Modus
Call
Fm_rsq_status
'--> FM-Tuning-Details
If Radiotext_ready = 1
Then
'Radiotext-Anzeige
If Scroll_counter > 0
Then
'Verzögerungszähler
Decr Scroll_counter
Else
Call
Radiotext_scroll
'Scrolle Radiotext um 1 Zeichen weiter
End If
End If
Else
'AM-Modus
Call
Am_rsq_status
'-->AM-Tuningdetails auf LCD
End If
End If
If T = 0 Or T = 75 And Radiotext_ready = 1 Then
If Radiotext_ready = 1
Then
'Radiotext-Anzeige
If
Scroll_counter > 0
Then
'Verzögerungszähler
Decr Scroll_counter
Else
Call
Radiotext_scroll
'Scrolle Radiotext um 1 Zeichen weiter
End If
End If
End If
'******************************
'*** Tastendrücke auswerten ***
'******************************
'*** S2 = FM --> Seek-FM Up/Down oder Band-Scan FM ***
If S2 = 0 Then
Call
Reset_flags
'Eingabeflags zurücksetzen
Call Rds_reset
If Am_fm_flag = 1
Then
'falls noch nicht im FM-Modus...
Am_fm_flag =
0
' --> FM-Modus aktivieren
T1 = 0
Call Si4735_init
Else
T1 = 0
Waitms
5
'debounce
Do
Waitms 1
Incr T1
Loop Until S2 = 1
If T1 < 500
Then
'short (<500ms)--> Seekup
'FM-Seekup
Valid = 0
Call
Fm_seek_freq_up
'Stop bei Erreichen der Bandgrenze
Call Clear_lcd_lowerline
Waitms 500
Fm_tune_status_freq_print_lcd
Elseif T1 > 499 And T1 < 2000
Then
'long (500...2000ms) --> Seekdown
'FM-Seekdown
Valid = 0
Call Fm_seek_freq_down
Call Clear_lcd_lowerline
Waitms 500
Fm_tune_status_freq_print_lcd
Else
'very long (2000ms Scan FM-Band and Store 1...n)
'FM-Bandscan
Fm_memorymax = 0 : Fm_memorypos = 0 : Memory_aktiv_flag =
0 'Speicher auf Null setzen
Freq_fm =
Band_start(17)
'stelle Band_start FM ein (z.B. 87,50 MHz)
Call
Fm_tune_freq
'Tune auf Band_start
Bltf =
0
'Wraparound-Indikator
Cls : Lcd "FM-Bandscan" : Wait 1 : Cls
Do
'Schleife für kompletten Bandsuchlauf
Call
Fm_seek_freq_up
'FM-Suchmodus aufwärts starten
Call
Fm_tune_status_freq_print_lcd
'gefundene Frequenz aus Si4735 holen und anzeigen
Call
Fm_rsq_status
'RSSI und SNR anzeigen
Incr
Fm_memorymax
'Memoryzeiger + 1
Fm_memory(fm_memorymax) =
Freq_fm
'Frequenz abspeichern
Loop Until Bltf <> 0 Or Fm_memorymax =
50 'solange, bis Bandgrenze erreicht oder
30 Speicher voll
If Fm_memorymax > 0
Then
'Sender gefunden...
If Bltf = 1 Then Decr
Fm_memorymax 'Bei
Bandgrenze wird letzter Speicher doppelt belegt
Fm_memorypos =
1
'Zeiger auf 1. gefundenen Sender in Memory stellen
Memory_aktiv_flag = 1
Call Clear_lcd_lowerline
Freq_fm = Fm_memory(fm_memorypos)
Call Fm_tune_freq
Locate 1 ,
14
'"Mnn" in Zeile 1, Spalte 14 schreiben
Lcd "M" ; Fm_memorypos ; " "
End If
End If
End If
End If
'*** S3 = AM Band Up/Down ***
If S3 = 0 Then
Call
Reset_flags
'Eingabeflags zurücksetzen
Call Rds_reset
T2 = 0
Waitms
5
'debounce
Do
Waitms 1
Incr T2
Loop Until S3 = 1
If Am_fm_flag = 0
Then
'Falls noch nicht im AM-Modus --> AM-Modus starten
Am_fm_flag = 1
Call Si4735_init
Else
If T2 < 500
Then
'short-->nächst höheres Band / long--> nächst niedrigeres Band
Incr Band
Else
Decr Band
End If
End If
If Band > 16 Then Band =
1
'Bringe BAND auf Intervall 1...16
If Band = 0 Then Band =
16
'mit Rollover
Call
Am_stop_seek_tune
'Stoppe evtl. Tuning
Select
Case
Band
'Setze Anfang der Memmorybereichs
Case 1 : Am_memorypos = 1 : Am_memorymax = Lw_memorymax
Case 2 : Am_memorypos = 11 : Am_memorymax = Mw_memorymax
Case 3 To 6 : Am_memorypos = 21 : Am_memorymax = Kw1_memorymax
Case 7 To 10 : Am_memorypos = 31 : Am_memorymax = Kw2_memorymax
Case 11 To 16 : Am_memorypos = 41 : Am_memorymax = Kw3_memorymax
End Select
Am_memorymin =
Am_memorypos
'Halte min. Speicherplatz im Speicherbereioch fest
Band_name = Lookupstr(band , Band_names)
Cls : Lcd Band_name : Lowerline
Lcd Band_start(band) ; "-" ; Band_end(band) ; " kHz" : Wait 1
Cls
Freq_am = Band_end(band) : Hi = High(freq_am) : Lo =
Low(freq_am) 'Setze Suchlauf-Ende
auf Bandende
Call Si4735_set_property(&H3401 , Hi , Lo)
Freq_am = Band_start(band) : Hi = High(freq_am) : Lo =
Low(freq_am) 'Setze Suchlauf-Anfang
auf Anfang aktuelles Band
Call Si4735_set_property(&H3400 , Hi , Lo)
Call
Am_tune_freq
'Starte mit Band_start-Frequenz
Waitms 100
Call Am_tune_status_freq_print_lcd
If Band < 3
Then
'Setze Suchlauf-Schrittweite
Seek_step =
9
'9kHz in LW und MW
Else
Seek_step =
5
'1kHz in KW
End If
Call Am_seek_step()
End If
'*** S4 = AM Seek --> Seek-AM Up/Down oder Band-Scan FM ***
If S4 = 0 Then
Call
Reset_flags
'Eingabeflags zurücksetzen
Call Rds_reset
If Am_fm_flag = 1
Then
'schon im AM-Modus?
T3 = 0
Waitms
5
'debounce
Do
Waitms 1
Incr T3
Loop Until S4 = 1
If T3 < 500
Then
'short (<0,5s)
'AM-Seekup
Valid = 0
Call Am_seek_freq_up
Call Clear_lcd_lowerline
Waitms 500
Am_tune_status_freq_print_lcd
Elseif T3 > 499 And T3 < 2000
Then
'long (500...2000ms) --> Seekdown
'AM-Seekdown
Valid = 0
Call Am_seek_freq_down
Call Clear_lcd_lowerline
Waitms 500
Am_tune_status_freq_print_lcd
Else
'very long (>2000ms) Scan AM-Band and Store 1...n)
'AM-Band-Scan
If Band = 1
Then
'LW: von Speicher 1...10 füllen
Scan_memorymax =
0
'Speicher-Startposition - 1
Am_memorypos =
10
'Speicher-Maximum
Elseif Band = 2
Then
'MW: von Speicher 11...20 füllen
Scan_memorymax = 10
Am_memorypos = 20
Elseif Band > 2 And Band < 7
Then
'KW: Tropenbänder 3-6 = 120-60m von Speicher 21...30 füllen
Scan_memorymax = 20
Am_memorypos = 30
Elseif Band > 6 And Band < 11
Then
'KW: Bänder 7-10 = 49-25m von Speicher 31...40 füllen
Scan_memorymax = 30
Am_memorypos = 40
Elseif Band > 10 And Band < 17
Then
'KW: Bänder 11-16 = 22-11m von Speicher 41...50 füllen
Scan_memorymax = 40
Am_memorypos = 50
End If
Freq_am =
Band_start(band)
'stelle Band_start-Frequenz AM-Band ein
Call Am_tune_freq
Bltf =
0
'Wraparound-Flag zurücksetzen
Band_name = Lookupstr(band , Band_names)
Cls : Lcd "Scan " ; Band_name : Wait 1 : Cls
Do
Call
Am_seek_freq_up
'AM-Suchmodus aufwärts starten
Call
Am_tune_status_freq_print_lcd
'gefundene Frequenz aus Si4735 holen und anzeigen
Call
Am_rsq_status
'RSSI und SNR anzeigen
Incr
Scan_memorymax
'Memoryzeiger + 1
Am_memory(scan_memorymax) =
Freq_am 'Frequenz
abspeichern
Am_text(scan_memorymax) =
Space(10)
'Sendername löschen
Loop Until Bltf <> 0 Or Scan_memorymax =
Am_memorypos 'solange, bis
Bandgrenze erreicht
'
If Bltf = 1 Then Decr
Scan_memorymax
'Bei Bandgrenze wird letzter Speicher doppelt belegt
Am_memorypos = Am_memorypos -
9
'--> Zeiger auf Anfang des 10er-Speicerhblocks legen
If Valid = 0
Then
'letzter Sender ungültig --> kein Sender gefunden
Freq_am =
Band_start(band)
'Frequenz auf Bandanfang setzen
Else
Freq_am = Am_memory(am_memorypos)
End If
Call Clear_lcd_lowerline
Call Am_tune_freq
Call Am_tune_status_freq_print_lcd
If Valid = 0
Then
'falls M1 keine gültige Frequenz --> keine Frequenz gefunden
Memory_aktiv_flag = 0
Else
Memory_aktiv_flag = 1
Home Lower
Lcd "M" ; Am_memorypos ; " "
End If
End If
Else
'noch nicht im AM-Modus
Am_fm_flag =
1
'AM-Modus einschalten
T = 0
Call Si4735_init
End If
End If
'*** S5: Memory ***
'je einmal lang drücken (lang) toggelt Recall Modus an/aus
'Speicherauswahl im Recall-Modus mit Dreh-Encoder
'falls Recall-Modus aktiv und dann kurzer Tastendruck für "Store" --> Recall-Modus wird ausgeschaltet
'und Frequenz nicht (!) gespeichert
'2s drücken --> Property-Einstell-Modus starten (Scroll mit Encoder)
' --> kurz drücken --> gewählte Property mit Encoder verändern
' --> kurz drücken --> Property-Einstell-Modus beenden
'5s drücken --> alle Daten ins EEPROM speichern
If S5 = 0 Then
T4 = 0
Waitms
5
'debounce
Do
Waitms 1
Incr T4
Loop Until S5 = 1
If T4 > 5000
Then
'longer > 5000 ms --> alle Daten ins EEPROM
Call Rds_reset
Cls : Lcd "All data stored" : Lowerline : Lcd "into EEPROM" : Wait 2
Writeeeprom Fm_memorymax ,
1
'Anzahl belegter FM-Speicher ins EEPROM
Writeeeprom Lw_memorymax , 995
Writeeeprom Mw_memorymax , 996
Writeeeprom Kw1_memorymax , 997
Writeeeprom Kw2_memorymax , 998
Writeeeprom Kw3_memorymax , 999
Call Write_ammemories_eeprom(lw_memorymax , 1)
'Speichere alle AM-Senderspeicher ins EEPROM
Call Write_ammemories_eeprom(mw_memorymax , 11)
Call Write_ammemories_eeprom(kw1_memorymax , 21)
Call Write_ammemories_eeprom(kw2_memorymax , 31)
Call Write_ammemories_eeprom(kw3_memorymax , 41)
If Fm_memorymax > 0 Then
For N = 1 To
Fm_memorymax
'FM-Frequenzspeicher ins EEPROM
I = N * 2
I = I + 100
Freq = Fm_memory(n)
Writeeeprom Freq , I
Next N
End If
For N = 1 To
16
'Properties ins EEPROM
I = N + 1005
Dat = Property_dat(n)
Writeeeprom Dat , I
Next N
Elseif T4 > 2000
Then
'Sehr langer Tastendruck (>2s) --> Properties-Setz-Modus
Call Rds_reset
Property_aktiv =
1
'Property-Aktiv-Flag setzen
If Am_fm_flag = 0 Then N = 1 Else N =
9
'Property No.1/9 als Start (ja nach AM/FM-Modus)
Call
Si4735_print_property_lcd
'Property anzeigen
Elseif T4 >
500
Then
'Langer Tastendruck (>500ms)= MEMORY-Recall Modus einschalten
Call Rds_reset
If Memory_aktiv_flag = 0
Then
'noch nicht im Memorymodus?
If Am_fm_flag = 1
Then
'AM-Modus --> "M" auf Display
If Am_memorymax >= Am_memorypos
Then 'gültige Speicher?
Am_memorypos = Am_memorymin
Call Call_am_memory(am_memorypos)
Memory_aktiv_flag =
1
' --> Memorymodus aktiv setzen
End If
Else
'FM-Modus
If Fm_memorymax >= Fm_memorypos
Then 'gültige Speicher
Fm_memorypos = 1
Call Call_fm_memory(fm_memorypos)
Memory_aktiv_flag =
1
' --> Memorymodus aktiv setzen
End If
End If
Else
Memory_aktiv_flag =
0
'sonst: Memorymodus schon aktiv --> Memorymodus löschen
If Am_fm_flag = 1
Then
'AM-Modus
Home
Lower
'"Mnn"-Anzeige auf Display löschen
Lcd " "
Else
Locate 1 , 14
Lcd " "
End If
End If
Else
'kurzer Tastendruck (<500ms) --> STORE MEMORY/STORE PROPERTY
If Property_aktiv = 2
Then
'--> im Property-Setz-Modus?
Property_aktiv =
0
'Property-Modus wieder ausschalten
Call
Clear_lcd_lowerline
'2. LCD-Zeile wieder löschen
Elseif Property_aktiv = 1
Then
'im Property-Scroll-Modus?
Property_aktiv =
2
'--> in Property-Setz-Modus wechseln
Elseif Memory_aktiv_flag = 0
Then
'Memorymodus nicht aktiv
If Am_fm_flag = 1
Then
'AM-Modus?
If Am_textaktiv = 0
Then
'nicht im AM-Text-Eingabemodus?
'nächsten Speicher anwählen
Incr
Am_memorypos
'Speicherzähler+1 mit Rollover auf ersten Speicherplatz
If Am_memorypos > Am_memorymax Then Am_memorypos = Am_memorymin
Am_memory(am_memorypos) =
Freq_am
'Sender-Frequenz speichern (AM)
Am_text(am_memorypos) =
Space(10) 'Sendernamen
löschen
Home
Lower
'"Mnn" auf Display schreiben
Lcd "M" ; Am_memorymax ; " "
Am_textaktiv =
1
'Texteingabe für AM-Sendernamen aktivieren
Am_textpos = 1
Locate 2 ,
7
'Cursor vor Start der Am_text-Eingabe setzen
Cursor On
Blink
'Cursor anschalten
Else
'Texteingabemodus
Incr
Am_textpos
'Zeichenzähler+1
If Am_textpos = 11
Then
'letztes Zeichen erreicht?
Am_textaktiv =
0
'Am_text-Eingabeflag zurücksetzen
Cursor Off
Noblink
'Cursor wieder ausschalten
End If
End If
Else
'FM-Mode
Incr Fm_memorymax
If Fm_memorymax > 50 Then Fm_memorymax = 50 'Speicherzähler+1
und bei Überlauf auf max.Wert belassen setzen
Fm_memory(fm_memorymax) =
Freq_fm
'Sender-Frequenz speichern (AM)
Locate 1 , 14
Lcd "M" ; Fm_memorymax ; " "
End If
Elseif Memory_aktiv_flag = 1
Then
'sonst: Memorymodus schon aktiv -->
Memory_aktiv_flag =
0
'Memorymodus ausschalten
If Am_fm_flag = 1
Then
'AM-Modus --> LCD-Display "Mnn" löschen
Home Lower
Lcd " "
Else
Locate 1 ,
14
'LCD-Display "Mnn" löschen
Lcd " "
End If
End If
End If
End If
'*** Volume-Poti holen und setzen***
Pot =
Getadc(0)
'Hole Poti-ADC
Pot = Pot /
16
'schneide 4 LSB ab
Dif = Pot -
Vol
'Berechne Differenz zu aktuellem Vol-Wert
Dif = Abs(dif)
If Dif > 1
Then
'nur bei Veränderung-->
Vol
=
Pot
'setze neuen Volume-Wert
Call Si4735_set_rx_volume
End If
Loop
'**********************
'**********************
'*** Ende MAIN-LOOP ***
'**********************
'**********************
'*********************
'*********************
'*** SUBs und IRSs ***
'*********************
'*********************
'**************************************************************************
'*** Lese Si4734 Hardware-Code/-rev, Firmware, Lib und gebe auf LCD aus ***
'**************************************************************************
Sub Si4735_get_rev()
'*** POWERUP ***
I2cstart
I2cwbyte 34
I2cwbyte
&H01
'CMD = 0x01 = Powerup
'*** Set AM-/FM-Mode ***
If Am_fm_flag = 0 Then
I2cwbyte
&B00010000
'FM-Modus
Else
I2cwbyte
&B00010001
'AM-Modus
End If
'*** Set Analog-/Digital Outputs ***
I2cwbyte
&B00000101
'Analog Outputs On, Digital Outputs Off
I2cstop
Waitms
120
'110ms Wartezeit nach Powerup lt. Datenblatt
'*** GET REVISION ***
I2cstart
I2cwbyte 34
I2cwbyte
&H10
'CMD = 0x10 = Get_Rev.
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Read-Mode
I2crbyte Status , Ack
I2crbyte R1 , Ack
I2crbyte R2 , Ack
I2crbyte R3 , Ack
I2crbyte R4 , Ack
I2crbyte R5 , Ack
I2crbyte R6 , Ack
I2crbyte R7 , Nack
I2cstop
Cls
Lcd "Si47" ; R1 ; " Rev.:" ; R6
Lowerline : Lcd "FW:" ; R2 ; "." ; R3 ; " Lib:" ; R7
Wait 2
End Sub
'****************************
'*** Initialisiere SI4735 ***
'*** FM/AM-Modus starten ****
'****************************
Sub Si4735_init()
Cls
'*** POWERDOWN ***
I2cstart
I2cwbyte 34
I2cwbyte
&H11
'CMD 0x11=POWERDOWN
I2cstop
Waitms 1
'*** POWERUP ***
I2cstart
I2cwbyte 34
I2cwbyte
&H01
'CMD = 0x01 = Powerup
'*** Set AM-/FM-Mode ***
If Am_fm_flag = 0 Then
I2cwbyte
&B00010000
'FM-Modus
Else
I2cwbyte
&B00010001
'AM-Modus
End If
'*** Set Analog-/Digital Outputs ***
I2cwbyte
&B00000101
'Analog Outputs On, Digital Outputs Off
I2cstop
Waitms
120
'110ms Wartezeit nach Powerup lt. Datenblatt
'*** Lade und setze Properties ***
If Am_fm_flag = 0
Then
'Property-Indices für Schleife
N1 = 1 : N2 =
8
'FM
Else
N1 = 9 : N2 =
16
'AM
End If
For N = N1
To
N2
'Read back Properties 1...8
Property_adr = Property_adress(n)
Dat = Property_dat(n)
If Dat > Property_max(n)
Then
'Falls Property außerhalb Wertebereich...
Dat_word = Si4735_get_property(property_adr)
'lese eingestellten (Default-) Wert
Property_dat(n) =
Low(dat_word)
'und speichere in Property_dat(N)
Else
Call Si4735_set_property(property_adr , &H00 ,
Dat) 'sonst: Property setzen
End If
Next N
Call
Si4735_set_rx_volume
'Set Volume
If Am_fm_flag = 0
Then
'FM-Modus
Call
Si4735_set_property(&H1402 , &H00 ,
&H05) 'Setze
FM_Seek_Freq_Spacing Suchraster-FM auf 50kHz anstelle 100kHz (Default)
Call Si4735_set_property(&H1108 , &H00 ,
20) 'Setze
FM_Max_Tune_Error 20kHz anstelle 30kHz (Default)
Cls : Lcd " FM" : Lowerline
Call Lcd_freq(band_start(17) , 2 , 1)
Locate 2 , 7 : Lcd "-"
Call Lcd_freq(band_end(17) , 2 , 8)
Locate 2 , 14 : Lcd "MHz" : Wait 1
Cls
Call
Fm_tune_freq
'Set Frequency
Call
Fm_tune_status_freq_print_lcd
'Tune-Status auf Display
Call
Rds_init
'RDS initialisieren
Else
'AM-Modus einschalten
Band_name = Lookupstr(band , Band_names)
Cls : Lcd Band_name : Lowerline
Lcd Band_start(band) ; "-" ; Band_end(band) ; " kHz" : Wait 1
Cls
Call Am_tune_freq
Waitms 500
Call Am_tune_status_freq_print_lcd
End If
End Sub
'*******************************************************************************
'***
Si4735: Statusbyte
holen
***
'*** Bit 7 = CTS = Clear to send next
commands
***
'*** Bit 6 = ERR =
Error
***
'*** Bit 3 = RSQINT = Received Signal Quality measurement has been triggered ***
'***
Bit 2 = RDSINT =
RDS-Interrupt
***
'*** Bit 0 = STCINT = Seek/Tune
Complete
***
'*******************************************************************************
Sub
Si4735_get_status_byte()
'Abfrage, ob STC-Bit gesetzt (Seek/Tune Complete), also Si4735 bereit
zum Befehlsempfanf
I2cstart
I2cwbyte 34
I2cwbyte
&H14
'CMD $0x14 = Si4735_Get_status_byte
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Read-Mode
I2crbyte Status ,
Nack
'STATUS-Byte: D7=CTS, D6=ERR, D3=RSQINT, D2=RDSINT, D0=STCINT
I2cstop
' If Status.2 = 1 Then Rds_flag = 1 Else Rds_flag = 0
End Sub
'*******************************************
'*** Si4735: Warte bis Statusbit.0 STC=1 ***
'*** Bit 0 = STCINT = Seek/Tune Complete ***
'*******************************************
Sub Si4735_wait_for_seek_tune_cplt()
Do
Call Si4735_get_status_byte
Loop Until Status.0 = 1 Or S2 = 0 Or S3 = 0 Or S4 = 0 Or S5 = 0 Or Encoder1old <> Encoder1
End Sub
'*******************************************
'*** Si4735: Warte bis Statusbit.7 CTS=1 ***
'*** Bit 0 = CTS = Clear to send nxt cmd ***
'*******************************************
Sub Si4735_wait_for_clear_to_send()
Do
Call Si4735_get_status_byte
Loop Until Status.7 = 1
End Sub
'**************************
'*** Si4735: Set-Volume ***
'**************************
Sub Si4735_set_rx_volume()
Call Si4735_set_property(&H4000 , &H00 , Vol)
End Sub
'**************************************
'*** Si4735: Properties-Word setzen ***
'**************************************
Sub Si4735_set_property(byval Prop_adr As Word , Byval Prop_value_high As Byte , Byval Prop_value_low As Byte )
Local High_adr As Byte
Local Low_adr As Byte
Local High_value As Byte
Local Low_value As Byte
Call Si4735_wait_for_clear_to_send()
High_adr = High(prop_adr)
Low_adr = Low(prop_adr)
I2cstart
I2cwbyte 34
I2cwbyte
&H12
'CMD=0x12=Set Property
I2cwbyte &H00
I2cwbyte High_adr
I2cwbyte Low_adr
I2cwbyte Prop_value_high
I2cwbyte Prop_value_low
I2cstop
Waitms
15
'10ms t(complete) laut Datenblatt
End Sub
'*************************************
'*** Si4735: Properties-Word holen ***
'*************************************
Function Si4735_get_property(byval Prop_adr As Word) As Word
Local High_adr As Byte
Local Low_adr As Byte
Local High_value As Byte
Local Low_value As Byte
Call Si4735_wait_for_clear_to_send()
High_adr = High(prop_adr)
Low_adr = Low(prop_adr)
I2cstart
I2cwbyte 34
I2cwbyte
&H13
'CMD 0x13=CMD Si4735_get_property
I2cwbyte &H00
I2cwbyte High_adr
I2cwbyte Low_adr
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Read-Mode
I2crbyte Status ,
Ack
'STATUS-Byte: D7=CTS, D6=ERR, D3=RSQINT, D2=RDSINT, D0=STCINT
I2crbyte High_value ,
Ack
'Always $00
I2crbyte High_value ,
Ack
'High und Lowbyte der Property einlesen
I2crbyte Low_value , Nack
I2cstop
Waitms 1
Si4735_get_property = Makeint(low_value , High_value)
End Function
'*************************************************
'*** Gebe Property-Wert(n) auf LCD Zeile 2 aus ***
'*************************************************
Sub
Si4735_print_property_lcd()
'Property N auf LCD bringen (2. LCD-Zeile)
Local Property_string As String * 8
Property_string = Lookupstr(n , Property_names)
Home Lower
Dat = Property_dat(n)
Lcd "P" ; N ; " " ; Dat ; "
"
'"P nn Propertywert" in 2. Zeile schreiben
Locate 2 , 9 : Lcd Property_string
End Sub
'***********************************************
'*** Si4735: Suchschritt AM 1/5/9 kHz setzen ***
'***********************************************
Sub Am_seek_step()
Call Si4735_set_property(&H3402 , &H00 , Seek_step)
End Sub
'**************************************
'*** Si4735: AM-Frequenz einstellen ***
'**************************************
Sub Am_tune_freq()
If Freq_am > 500
Then
'Verkürzungsspulen setzen:
If Freq_am > 2000 Then
Portb.0 =
1
'SW
Portc.3 = 0
Else
Portb.0 =
0
'MW
Portc.3 = 1
End If
Else
Portb.0 =
0
'LW
Portc.3 = 0
End If
H = High(freq_am)
L = Low(freq_am)
I2cstart
I2cwbyte 34
I2cwbyte
&H40
'CMD 0x40 = Tune AM-Frequency
I2cwbyte &H00
I2cwbyte H
I2cwbyte L
I2cwbyte
&H00
'Tuning-Cap automatic
I2cstop
Waitms
85
'80ms bis Seet-Tune Complete lt. Datenblatt
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
End Sub
'*************************************
'*** Si4735: AM-Suchmodus aufwärts ***
'*************************************
Sub Am_seek_freq_up()
Call
Am_stop_seek_tune
'Cancel Seek
I2cstart
I2cwbyte 34
I2cwbyte
&H41
'CMD=0x41
I2cwbyte
&B00001000
'Bit3=Seek Up/Down; Bit2=Wrap/Stop bei Erreichen der Bandgrenze
I2cstop
Waitms
85
'80ms bis Seet-Tune Complete lt. Datenblatt
Call Clear_lcd_lowerline : Lowerline : Lcd "Scanning..."
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
End Sub
'************************************
'*** Si4735: AM-Suchmodus abwärts ***
'************************************
Sub Am_seek_freq_down()
Call
Am_stop_seek_tune
'Cancel Seek
I2cstart
I2cwbyte 34
I2cwbyte
&H41
'CMD=0x41
I2cwbyte
&B00000000
'Bit3=Seek Up/Down; Bit2=Wrap/Stop bei Erreichen der Bandgrenze
I2cstop
Waitms
85
'80ms bis Seet-Tune Complete lt. Datenblatt
Call Lcd_scanning
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
End Sub
'*****************************************
'*** Lese AM-Senderspeicher ins EEPROM ***
'*****************************************
Sub Read_ammemories_eeprom(stored_memories As Byte , Byval Start_memory As Word)
Local End_memory As Word
If Stored_memories >= Start_memory Then
End_memory =
Stored_memories
'Schleifenzähler-Endwert = Start + Anzahl Speicher -1
' End_memory = End_memory + Start_memory
' Decr End_memory
For I1 = Start_memory To End_memory
I = I1 * 2
Readeeprom Freq ,
I
'AM-Frequenz ins EEPROM
Am_memory(i1) = Freq
I = I1 * 11
I = I + 191
Readeeprom Text1 , I
Am_text(i1) =
Text1
'AM-Sendernamen ins EEPROM
Next I1
End If
End Sub
'**********************************************
'*** Speichere AM-Senderspeicher ins EEPROM ***
'**********************************************
Sub Write_ammemories_eeprom(stored_memories As Byte , Byval Start_memory As Word)
Local End_memory As Word
If Stored_memories >= Start_memory Then
End_memory =
Stored_memories
'Schleifenzähler-Endwert = Start + Anzahl Speicher -1
' End_memory = End_memory + Start_memory
' Decr End_memory
For I1 = Start_memory To End_memory
I = I1 * 2
Freq = Am_memory(i1)
Writeeeprom Freq , I
'AM-Frequenz ins EEPROM
I = I1 * 11
I = I + 191
Text1 = Am_text(i1)
Writeeeprom Text1 ,
I
'AM-Sendernamen ins EEPROM
Next I1
End If
End Sub
'*************************************
'*** Si4735: AM-Suchlauf abbrechen ***
'*************************************
Sub
Am_stop_seek_tune()
'Stopt aktuellen AM-Suchlauf
I2cstart
I2cwbyte 34
I2cwbyte
&H42
'CMD=0x42
I2cwbyte
&B00000011
'Bit1=1 Cancel Seek; Bit0=1 Clear Seek/Tune Interrupt Status Bits
I2cstop
Waitms 1
Call Lcd_scanning
Call Si4735_wait_for_clear_to_send
End Sub
'**************************************
'*** Si4735: FM-Frequenz einstellen ***
'**************************************
Sub Fm_tune_freq()
Call Rds_reset
Call
Fm_stop_seek_tune
'Cancel Seek
H = High(freq_fm)
L = Low(freq_fm)
I2cstart
I2cwbyte 34
I2cwbyte
&H20
'CMD=0x20
I2cwbyte
&H00
'Always $00
I2cwbyte H
I2cwbyte L
I2cwbyte
&H00
'Antenna-Cap=Automatic
I2cstop
Waitms
65
'60ms bis Seek-Tune-Complete laut Datenblatt
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
Cls
End Sub
'*************************************
'*** Si4735: FM-Suchmodus aufwärts ***
'*************************************
Sub Fm_seek_freq_up()
Call
Fm_stop_seek_tune
'Cancel Seek
I2cstart
I2cwbyte 34
I2cwbyte
&H21
'CMD=0x21
I2cwbyte
&B00001000
'Bit3=Seek Up/Down; Bit2=Wrap/Stop bei Erreichen der Bandgrenze
I2cstop
Waitms
65
'60ms bis Seet-Tune Complete lt. Datenblatt
Call Lcd_scanning
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
End Sub
'************************************
'*** Si4735: FM-Suchmodus abwärts ***
'************************************
Sub Fm_seek_freq_down()
Call
Fm_stop_seek_tune
'Cancel Seek
I2cstart
I2cwbyte 34
I2cwbyte
&H21
'CMD=0x21
I2cwbyte
&B00000000
'Bit3=Seek Up/Down; Bit2=Wrap/Stop bei Erreichen der Bandgrenze
I2cstop
Waitms
65
'60ms bis Seet-Tune Complete lt. Datenblatt
Call Lcd_scanning
Call
Si4735_wait_for_seek_tune_cplt
'Warte bis STC-Bit gesetzt
End Sub
'*************************************
'*** Si4735: FM-Suchlauf abbrechen ***
'*************************************
Sub Fm_stop_seek_tune()
Call Rds_reset
I2cstart
I2cwbyte 34
I2cwbyte
&H22
'CMD=0x22
I2cwbyte
&B00000011
'Bit1=1 Cancel Seek; Bit0=1 Clear Seek/Tune Interrupt Status Bits
I2cstop
Waitms 1
Call Si4735_wait_for_clear_to_send
End Sub
'*************************************************************
'*** Si4735: Frequenz/Tuningdetails FM in R1...R7 auslesen ***
'***
Frequenz auf LCD ausgeben, falls
gültig
***
'*************************************************************
Sub
Fm_tune_status_freq_print_lcd()
'Frequenz holen und ausgeben
Call
Si4735_get_status_byte
'
I2cstart
I2cwbyte
34
'Adresse Si4736 für Write
I2cwbyte
&H22
'CMD = 0x22 = FM_Tune_Status
' I2cwbyte
&B00000000
'D1=1 Cancel Seek; D0=1 Clear Seek/Tune Complete Interrupt Status
Indicator
I2cwbyte
&B00000011
'Original-Version --> Cancel Seek, Clear Seek-Tune-Complete
Interrupt Bit
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Adresse Si4735 für Read
I2crbyte Status ,
Ack
'Statusbyte (Bit 7=CTS)
I2crbyte R1 ,
Ack
'Bit7=kompletter Suchlauf (Bandlimit) nach FM_Seek; Valid_channel=Bit 0
I2crbyte R2 ,
Ack
'Frequenz
I2crbyte R3 ,
Ack
'Frequenz
I2crbyte R4 ,
Ack
'RSSI
I2crbyte R5 ,
Ack
'S/N
I2crbyte R6 , Ack
I2crbyte R7 ,
Nack
'Tuning-Capacitor
I2cstop
Bltf =
R1.7
'Statusbit für Erreichen der Bandgrenze bzw. Wraparound
Freq = 256 * R2
Freq = Freq + R3
Rssi = R4
Snr = R5
Valid = R1.0
If Valid = 1
Then
'Falls Frequenz Valid --> ausgelesene Frequenz in Freq_fm
übernehmen; Daten in EEPROM sichern
Freq_fm = Freq
Call Reset_encoder
Call Eeprom_save
End If
'
If Radiotext_ready = 0
Then
'falls keine RDS-Anzeige
Call
Lcd_freq(freq_fm , 1 ,
1)
'--> Frequenz-Anzeige
' End If
'
Pwm1a = Rssi *
12
'RSSI als PWM ausgeben
Waitms 1
Call Si4735_wait_for_clear_to_send
End Sub
'*****************************************
'*** Drucke FM_Freq in LCDPosition Y,X ***
'*****************************************
Sub Lcd_freq(byval Fm_freq As Word , Byval Y_pos As Byte , Byval X_pos As Byte)
Call
Make_freq_string(fm_freq)
'erzeuge Frequenz-String
Locate Y_pos ,
X_pos
'--> Frequenz in MHz + 2 Nachkommastellen auf Display
Lcd Freq_string
End Sub
'********************************************
'*** Erzeuge formatierten Frequenz-String ***
'********************************************
Sub Make_freq_string(byval Af_freq As Word)
Local Freq_int As Word
Local Freq_remainder As Word
Local Short_string As String * 2
If Af_freq > 6000
Then
'FM-Frequenz in 10 kHz-Einheiten
Freq_int = Af_freq / 100 : Freq_remainder = Af_freq Mod
100 'formatiere auf " 88.56" für
MHz-Ausgabe
Freq_string = Str(freq_int) : Short_string = Str(freq_remainder)
If Freq_int < 100 Then
Freq_string = " " + Freq_string
End If
Freq_string = Freq_string + "."
If Freq_remainder < 10 Then
Freq_string = Freq_string + "0"
End If
Freq_string = Freq_string + Short_string
Else
'AM-Frequenz in kHz
Freq_string = Str(af_freq)
End If
End Sub
'************************************************
'*** Drucke "Scanning..." in untere LCD-Zeile ***
'***
Lösche Mxx
Feld
***
'************************************************
Sub Lcd_scanning()
Cls
' Call Clear_lcd_lowerline
Lowerline : Lcd "Scanning..."
'
Locate 1 , 13 : Lcd "
"
'lösche letzte 4 Zeichen rechts oben
End Sub
'**************************************
'** RSSI und SNR holen und ausgeben ***
'**************************************
Sub Fm_rsq_status()
I2cstart
I2cwbyte 34
I2cwbyte
&H23
'CMD 0x23=FM_RSQ_STATUS
I2cwbyte
&B00000000
'Bit0=0 --> Interrupt Status Preserved
I2cstop
Waitms 1
I2cstart
I2cwbyte 35
I2crbyte Status ,
Ack
'Bit 7=CTS;
I2crbyte R1 ,
Ack
'div. Statusbits
I2crbyte R2 ,
Ack
'div. Statusbits; Bit0=Fm_freq_valid_flag Channel
I2crbyte R3 ,
Ack
'div. Statusbits; Bit7=Pilotton
I2crbyte R4 ,
Ack
'RSSI:0...127dBuV
I2crbyte R5 ,
Ack
'SNR:=9...127dB
I2crbyte R6 ,
Ack
'Stereo-Block_errors_block_nd 0...100%
I2crbyte
R7 ,
Nack
'Signed Frequency Offset
I2cstop
Rssi = R4
Snr = R5
'(
If Status.2 = 1 Then
Rds_flag =
1
'RDS_INT Flag setzen
Else
Rds_flag = 0
End If
')
Incr
Lcdrefresh
'nur bei jedem n. Schleifendurchlauf
If Lcdrefresh > 4 Then
Lcdrefresh = 0
'
If Radiotext_present = 0
Then
'falls keine Radiotext-Anzeige
If Radiotext_ready = 0
Then
'falls keine Radiotext-Anzeige
Call Clear_lcd_upperline
Call Lcd_freq(freq_fm , 1 ,
1)
'Frequenz auf Display
Locate 1 , 8
Lcd Rssi ; "
"
'RSSI und
Locate 1 , 11
Lcd Snr ; "
"
'SNR auf Display
If Memory_aktiv_flag = 1 Then
Locate 1 ,
14
'"Mnn" in Zeile 1, Spalte 14 schreiben
Lcd "M" ; Fm_memorypos
End If
End If
If Property_aktiv = 0 Then
Locate 2 ,
15
'STEREO-Anzeige-Symbol
If R3.7 = 1 Then Lcd Chr(7) Else Lcd "
" 'Pilotton
vorhanden -->Sonderzeichen für ST=Stereo
Locate 2 ,
16
'RDS/RADIOTEXT-Anzeige-Symbol
' If Radiotext_present = 1 Or Radiotext_ready = 1 Then
If Radiotext_present = 1 Then
Lcd
Chr(0);
'Sonderzeichen "RT" für Radiotext
Elseif Rds_flag = 1
Then
'"R" für nur RDS (ohne Radiotext)
Lcd "R";
Else
Lcd " ":
End If
End If
End If
Stereo_signal = R3 And
&B01111111
'Bit 0...6 von R3 = Stereo-Signal in %
Freq_offset =
R7
'Frequency-Offset in kHZ [-128...+128kHz]
Select Case Pwm_output
Case 0 : Pwm1a = Stereo_signal *
8
'PWM1A als Stereo-Signal setzen 0...100% = 0...1023
Case 1 : Pwm1a = Freq_offset *
4
'PWM1A als Freq_Offset setzen +/-128kHz = 0...1023
Case 2 : Pwm1a = Rssi *
12
'Signalstärke an PWM-Ausgang 0..85dBµV = 0...1023
Case 3 : Pwm1a = Snr *
12
'SNR 0...85dB = 0...1023
End Select
Waitms 1
Call Si4735_wait_for_clear_to_send
End Sub
'*************************************************************
'*** Si4735: Frequenz/Tuningdetails AM in R1...R7 auslesen ***
'***
Frequenz auf LCD ausgeben, falls
gültig
***
'*************************************************************
Sub Am_tune_status_freq_print_lcd()
I2cstart
I2cwbyte 34
I2cwbyte
&H42
'CMD=0x42
' I2cwbyte
&B00000000
'Bit1=0 Continue Seek; Bit0=Clear Seek/Tune Interrupt Status Bits
I2cwbyte
&B00000011
'Original-Version --> Cancel Seek, Clear Seek-Tune-Complete
Interrupt Bit
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Adresse Si4735 für Read
I2crbyte Status ,
Ack
'Statusbyte (Bit 7=CTS)
I2crbyte R1 ,
Ack
'Bit7=kompletter Suchlauf (Bandlimit) nach AM_Seek;
Fm_freq_valid_flag=Bit 0
I2crbyte R2 ,
Ack
'Frequenz
I2crbyte R3 ,
Ack
'Frequenz
I2crbyte R4 ,
Ack
'RSSI
I2crbyte R5 ,
Ack
'S/N
I2crbyte R6 ,
Ack
'Tuning-Capacitor
I2crbyte R7 ,
Nack
'Tuning-Capacitor
I2cstop
Bltf =
R1.7
'Statusbit für Erreichen der Bandgrenze
Freq = 256 * R2
Freq = Freq + R3
Rssi = R4
Snr = R5
C = 256 * R6
C = C + R7
C = C * 95
C = C / 1000
C = C + 7
Valid =
R1.0
'R1.0 = Valid AM-Frequency
Home Upper
Lcd Freq
If Freq < 10000 Then Lcd " "
If Freq < 1000 Then Lcd " "
Locate 1 , 13
Lcd C ; " "
If Valid = 1
Then
'Falls Frequenz Valid --> Frequenz übernehmen Daten in EEPROM sichern
Freq_am = Freq
Call Eeprom_save
End If
Pwm1a = Rssi *
12
'Signalstärke an PWM-Ausgang übergeben
Call Si4735_wait_for_clear_to_send
End Sub
'**************************************
'** RSSI und SNR holen und ausgeben ***
'**************************************
Sub Am_rsq_status()
I2cstart
I2cwbyte 34
I2cwbyte
&H43
'CMD 0x43
I2cwbyte
&B00000000
'Bit0=0 Interrupt Status preserved
I2cstop
Waitms 1
I2cstart
I2cwbyte 35
I2crbyte Status , Ack
I2crbyte R1 ,
Ack
'div. Statusbits
I2crbyte R2 ,
Ack
'div. Statusbits; Bit0=Fm_freq_valid_flag Channel
I2crbyte R3 , Ack
I2crbyte R4 ,
Ack
'RSSI:0...127dBuV
I2crbyte R5 ,
Nack
'SNR:=9...127dB
I2cstop
Rssi = R4
Snr = R5
' Incr Lcdrefresh
' If Lcdrefresh > 5 Then
' Lcdrefresh = 0
Locate 1 , 7
Lcd Rssi ; " "
Locate 1 , 10
Lcd Snr ; " "
' End If
If Am_textaktiv = 1
Then
'Im Texteingabemodus -->
I = Am_textpos + 6
Locate 2 , I
End If
Pwm1a = Rssi * 12
Waitms 1
Call Si4735_wait_for_clear_to_send
End Sub
'*************************************************
'*** Stelle AM-Speicher ein und bringe auf LCD ***
'*************************************************
Sub Call_am_memory(am_memory_number As Byte)
Home
Lower
'"Mnn" in 2. Zeile schreiben
Lcd "M" ; Am_memorypos ; " "
Freq_am =
Am_memory(am_memory_number)
'Frequenz aus Speicher-Array laden
Call Am_tune_freq
Call Am_tune_status_freq_print_lcd
Locate 2 , 7
Text1 =
Am_text(am_memory_number)
'Sendername in 2. Zeile ab Spalte 7 schreiben
Lcd Text1
Call Reset_encoder
End Sub
'*************************************************
'*** Stelle FM-Speicher ein und bringe auf LCD ***
'*************************************************
Sub Call_fm_memory(fm_memory_number As Byte)
Freq_fm = Fm_memory(fm_memory_number)
Call Fm_tune_freq
Call Fm_tune_status_freq_print_lcd
Locate 1 ,
14
'"Mnn" in Zeile 1, Spalte 14 schreiben
Lcd "M" ; Fm_memorypos ; " "
Call Reset_encoder
End Sub
'**********************************
'*** Si4735: RDS initialisieren ***
'**********************************
Sub Rds_init()
'RDS_INT wird gesetzt, wenn RDS-Sync = RDS-Signal vorhanden
Call Si4735_set_property(&H1500 , &H00 ,
&B00000100) 'Property=RDS_Int_Source; RDSINT-Set
bei... Bit2=RDS-SYNC, Bit1=RDS_SYNC_Lost, Bit0=RDS_Recv
Call Si4735_set_property(&H1501 , &H00 ,
14)
'Property=RDS_Int_FIFO_Count; DAT=14=min. Number of received Groups
before RDSRECV-Bit is set
Select Case Rds_block_errors
Case 0 : Call Si4735_set_property(&H1502 , &B00000000 ,
1) 'mur 1-2 korrigierbare
Blockfehler zulassen
Case 1 : Call Si4735_set_property(&H1502 , &B01010101 , 1)
Case 2 : Call Si4735_set_property(&H1502 , &B10101010 , 1)
Case 3 : Call Si4735_set_property(&H1502 , &B11111111 , 1)
End Select
Call Rds_reset()
End Sub
'****************************************************************
'*** Si4735: RDS-Status + RDS-Daten in Status, R1...R12 holen ***
'****************************************************************
Sub Rds_get_status_and_data()
I2cstart
I2cwbyte
34
'Adresse Si4735 für Write=34
I2cwbyte
&H24
'CMD $0x24 zur Adressierung RDS-Status-/Daten
' I2cwbyte
&B00000000
'Preserve RDS-Interrupt-Flag
I2cwbyte
&B00000001
'Preserve RDS-Interrupt-Flag
I2cstop
Waitms 1
I2cstart
I2cwbyte
35
'Adresse Si4735 für Read=35
I2crbyte Status ,
Ack
'Statusbyte einlesen:B7=CTS-Flag, B6=ERR-Flag, B3=RSQINT-Flag,
B2=RDSINT-Flag,
B0=STCINT-Flag
'
I2crbyte R1 ,
Ack
'Statusbyte einlesen:B2=RDS_SYNC_FOUND-Flag, B1=RDS_SYNC_LOST-Flag,
B0=RDS_RECV-Flag
I2crbyte R2 ,
Ack
'Statusbyte einlesen:B2=GRP_LOST-Flag, B0=RDS_SYNC-Flag
I2crbyte R3 ,
Ack
'RDS_FIFO_USED = Anzahl der verbleibenden Gruppen im RDS-FIFO-Speicher
I2crbyte R4 ,
Ack
'RDS-Gruppen in R4...R11 (8 Bytes)
I2crbyte R5 , Ack
I2crbyte R6 , Ack
I2crbyte R7 , Ack
I2crbyte R8 , Ack
I2crbyte R9 , Ack
I2crbyte R10 , Ack
I2crbyte R11 , Ack
I2crbyte R12 ,
Nack
'je 2 Bit für Anzahl der korrigierten RDS-Fehler in Gruppe A,B,C,D
I2cstop
Waitms 1
Call Si4735_wait_for_clear_to_send
End Sub
'****************************************************
'*** RDS-Dekodierung, LCD-Anzeige, RS-232-Anzeige ***
'****************************************************
Sub Rds_decoding()
Do
'Solange je eine Gruppe auf FIFO holen, bis FIFO leer
Call
Si4735_get_status_byte
'Statusbit 7 holen
If
Status.7 = 1
Then
'Falls CTS=1 (Si4735 bereit)...
Call
Rds_get_status_and_data
'hole RDS-Daten
If R2.0 = 1 Then Rds_flag = 1 Else Rds_flag = 0
'RDS-Flag = aktueller RDS-Sync-Status
If R3 > 0
Then
'FIFO-Speicher nicht leer (>0)
Block_errors_block_a = R12 And
&B11000000 'Anzahl RDS-Fehler
in Block A isolieren
Block_errors_block_b = R12 And
&B00110000 'Anzahl RDS-Fehler
in Block B isolieren
Block_errors_block_c = R12 And
&B00001100 'Anzahl RDS-Fehler
in Block C isolieren
Block_errors_block_d = R12 And
&B00000011 'Anzahl RDS-Fehler
in Block D isolieren
Service = R6 And
&B11111000
'Gruppennummer = Bit 7...4 + Typ = Bit 3 aus R6 isolieren
'*** GRUPPE 0A/0B (PI/TA/MS_Flag/DI/AF/PS=Sendername) ***
If Service = &B00000000 Or Service = &B00001000
Then 'Gruppe 0A/0B (Bit7..3/R6=0)
--> Sendername
If R7.4 = 1 Then Ta = 1 Else Ta =
0
'Travel-Announcement-Flag
If R7.3 = 1 Then Ms_flag = 1 Else Ms_flag =
0 'Music-Speech-Flag
Pos = R7 And
&B00000011
'Adresse für DI und PS-Namenszeichen isolieren Bit 0,1 in R7
Byte1 = Pos Xor
&B00000011
'Invertiere Adresse für DI-Adressierung
Incr
Byte1
'+1, da DI-Tabelle 1-based
Incr Di_counter : If Di_counter = 0 Then Di_counter =
4 'DI-Counter>=4 als
Zeichen für vollständig dekodierte DI
If R7.2 = 1
Then
'DI-Flag = Bit2 in R7
Di(byte1) = 1
Else
Di(byte1) = 0
End If
'PS-Name
Set
Ps_counter.pos
'Setze n=pos. Bit in PS-Counter
Pos = Pos *
2
'Programmname dekodieren und in Ps_name-String bringen
Pos = Pos + 1
Call
Rds_char_code(r10)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch =
Chr(r10)
'2 Zeichen aus R10 und R11 (Block D)
Mid(ps_name , Pos , 1 ) =
Ch
'in Ps_name-String
Call
Rds_char_code(r11)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r11)
Incr Pos
Mid(ps_name , Pos , 1 ) = Ch
If Ps_counter = &B00001111
Then
'Ausgabe auf LCD, wenn alle 4*2 Zeichensätzen durchlaufen
Home Lower
Lcd Ps_name
Ps_counter =
0
'Setze PS-Counter zurück
Ps_flag = 1
Ps_name_last = Ps_name
End If
'AF in Block C (R8,R9) nur in Gruppe 0A
If Service = &B00000000
Then
'Alternate Frequencies nur in Gruppe 0A!
'First 'AF-Byte
Lw_mw_af =
0
'LW/MW-Flag zurücksetzen
If R8 = 224
Then
'keine AF vorhanden
Af_flag =
0
'..> AF-Flag = 0
Elseif R8 > 224 And R8 < 250 And Af_flag <> 2
Then 'Startbyte: = n weitere
Alternate Frequencies vorhanden?
Af_flag =
1
'AF-Flag auf Empfang setzen
Af_number =
0
'laufender AF_Index
Af_max = R8 -
224
'Anzahl AFs = Start der AF-Liste
Elseif R8 > 0 And R8 < 205 And Af_flag = 1
Then 'Code zwischen 1...204 =>
gültige AF
If Af_number < 26 Then Incr Af_number 'Zähler nur
inkrementieren,solange <= 25
'
Word1 = Af(af_number)
Call Rds_calc_af(r8 ,
Word1)
'Dekodiere 1 AF
Af(af_number) = Word1
If Af_number >= Af_max Then Af_flag =
2 'Setze AF-Flag auf voll, falls
AF=AF_max
Elseif R8 = 250
Then
'LW/MW-Frequenz folgt
Lw_mw_af =
1
'--> Flag für Block D setzen, daß Frequenz = LM/AM-Frequenz ist
End If
'Second AF-Byte
If Af_number < 26 Then Incr Af_number
'Zähler nur inkrementieren,solange <= 25
' Word1 = Af(af_number)
Call Rds_calc_af(r9 ,
Word1)
'2. AF dekodieren
Af(af_number) = Word1
If Af_number >= Af_max Then Af_flag = 2 'Setze AF-Flag
auf voll, falls AF=AF_max
End If
End If
'*** GRUPPE 1A/1B (PI, Slow-labeling-codes etc.) ***
If Service = &B00010000 Or Service = &B00011000
Then 'Gruppe 1A/1B (Bit7..3/R6=0)
Pin_code = Makeint(r11 , R10)
If Service = &B00010000
Then
'Gruppe 1A --> div. Info-Bits
Word1 = Makeint(r9 , R8)
Word1 = Word1 And &B0000111111111111
If R8.7 = 1 Then La = 1 Else La = 0
'Linkage actuator
Vc = R8 And
&B01110000
'Variant-Code isolieren
Shift Vc , Right , 4
If Vc = 0
Then
'ECC
Ecc = R9
Elseif Vc = 1
Then
'TMC-Identification
Tmc_ident = Word1
Elseif Vc = 3
Then
'Language Code
Lc = Word1
Elseif Vc = 7
Then
'Emergency warning system
Ews = Word1
End If
End If
End If
'*** GRUPPE 2A/2B (Radiotext) ***
If Service = &B00100000 Or Service = &B00101000 And
Radiotext_on = 1 Then 'Gruppe 2A/2B
= Radiotext1 (bis zu 64/32 Zeichen!)
Radiotext_present = 1
Radiotext_ab_flag = R7 And &B00010000
'A/B-Toggle-Flag für neuen Text isolieren = Bit 4, Block B, R7
If Radiotext_first_aqu = 0
Then '1.
Durchlauf?
Radiotext_ab_flag_old = Radiotext_ab_flag Xor
&B00010000 'setzt A/B-Flag
künstlich auf aktuelles Toggeln
Radiotext_first_aqu = 1
End If
If Radiotext_ab_flag <> Radiotext_ab_flag_old
Then 'A/B Flag getoggelt? -->
neue Nachricht beginnt
Radiotext_ab_flag_old = Radiotext_ab_flag
Radiotext_start_decode =
1
'-->setze Flag auf neue Dekodierung
End If
Segment = R7 And
&B00001111
'Zeichenposition "POS" = 4*(Bit0...3) von R7
If Radiotext_start_decode = 1 And Segment = 0
Then 'Zeichenanfang gefunden?
Radiotext_start_decode =
2
'Flag auf Beginn Dekodierung setzen
Char_counter = 0
End If
If Radiotext_start_decode = 2
Then 'Bedingung zum Erstellen
des RT-Strings erfüllt
If Service = &B00100000
Then
'Gruppe 02A
Position = Segment
Shift Position , Left ,
2
'Position=Segment*4
If R8 = 13 And Radiotext_start_decode = 2
Then '=RETURN?
Call
Radiotext_decoded
'Aussprung in RT-Ready
Else
Incr Position : Incr Char_counter
'erhöhe Positions- und Gesamt-Zeichenzähler
Call
Rds_char_code(r8)
'RDS ASCII-Code in EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r8) '1. Zeichen in
Radiotext-String an richtige Position schreiben
If R9 = 13 And Radiotext_start_decode = 2 Then
Call Radiotext_decoded
Else
Incr Position : Incr Char_counter
'erhöhe Positions- und Gesamt-Zeichenzähler
Call Rds_char_code(r9) 'RDS
ASCII-Code in EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r9) '1. Zeichen in
Radiotext-String an richtige Position schreiben
If R10 = 13 And Radiotext_start_decode = 2 Then
Call Radiotext_decoded
Else
Incr Position : Incr Char_counter
Call Rds_char_code(r10) 'RDS ASCII-Code in
EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r10) '1. Zeichen in
Radiotext-String an richtige Position schreiben
If R11 = 13 And Radiotext_start_decode = 2 Then
Call Radiotext_decoded
Else
Incr Position : Incr Char_counter
Call Rds_char_code(r11) 'RDS ASCII-Code in EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r11) '1. Zeichen in
Radiotext-String an richtige Position schreiben
End If
End If
End If
End If
Else
'Gruppe 02B:
Position = Segment
Shift Position , Left ,
1
'Position=Segment*2
If R10 = 13 And Radiotext_start_decode = 2 Then
Call Radiotext_decoded
Else
Incr Position : Incr Char_counter
'erhöhe Positions- und Gesamt-Zeichenzähler
Call
Rds_char_code(r10)
'RDS ASCII-Code in EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r10) '1. Zeichen in
Radiotext-String an richtige Position schreiben
If R11 = 13 And Radiotext_start_decode = 2 Then
Call Radiotext_decoded
Else
Incr Position : Incr Char_counter
'erhöhe Positions- und Gesamt-Zeichenzähler
Call Rds_char_code(r11) 'RDS
ASCII-Code in EADOGM-Code umrechnen
Mid(radiotext_new , Position , 1) =
Chr(r11) '1. Zeichen in
Radiotext-String an richtige Position schreiben
End If
End If
End If
If Service = &B00100000 And Position = 64 And
Radiotext_start_decode = 2 Then Call
Radiotext_decoded 'nach 64/32
Zeichen automatisch CR=1 setzen
If Service = &B00101000 And Position = 32 And
Radiotext_start_decode = 2 Then Call
Radiotext_decoded 'Gruppe 02B
End If
End If
'*** GRUPPE 4A (UTC/MJD) ***
If Service = &B01000000
Then
'Gruppe 4A --> UTC-Zeit/Datum
Byte1 = R7 And
&B00000011
'MJD berechnen
Mjd = Byte1 : Shift Mjd , Left , 15
Word1 = Makeint(r9 , R8)
Shift Word1 , Right , 1
Long1 = Word1
Mjd = Mjd + Long1
Utc_offset = R11 And
&B00111111
'UTC-Offset berechnen
Lo =
R11
'Minuten berechnen
Shift Lo , Right , 6
Hi = R10 And &B00001111
Shift Hi , Left , 2
Utc_min = Hi + Lo
Minuten = Utc_min
Lo =
R10
'Stunden berechnen
Shift Lo , Right , 4
Hi = R9 And &B00000001
Shift Hi , Left , 4
Utc_hour = Hi + Lo
Stunden = Utc_hour
If R11.0 = 1
Then
'1/2-Stunden Addition
If R11.5 = 1 Then
Minuten = Minuten - 30
If Minuten < 0 Then
Minuten = Minuten + 60
Stunden = Stunden - 1
End If
Else
Minuten = Minuten + 30
If Minuten > 60 Then
Minuten = Minuten - 60
Stunden = Stunden + 1
End If
End If
End If
Shift Utc_offset , Right ,
1
'von 1/2-Stunden-Einheiten auf volle Stunden umrechnen
If R11.5 = 1 Then
Stunden = Stunden - Utc_offset
Else
Stunden = Stunden + Utc_offset
End If
If Stunden > 23 Then
Stunden = Stunden - 24
Decr Mjd
End If
If Stunden < 0 Then
Stunden = Stunden + 24
Incr Mjd
End If
Locate 2 ,
10
'Cursor auf Zeile 2, 10. Spalte setzen
Tx = Str(stunden)
If Stunden < 10 Then Tx = "0" + Tx
Lcd Tx ;
":";
'Stunden ":" Minuten auf Display ausgeben
Tx = Str(minuten)
If Minuten < 10 Then Tx = "0" + Tx
Lcd Tx
End If
'(
'*** GRUPPE 9A (EWS) ***
If Service = &B10010000
Then
'Gruppe 10A --> Erweiterung des PTY-Typs
If Ews <> &HFFFF
Then
'EWS-Daten isolieren
Ews0 = R7 And &B00011111
Ews1 = R8 : Ews2 = R9 : Ews3 = R10 : Ews4 = R11
End If
End If
')
'*** GRUPPE 10A (PTYN) ***
If Service = &B10100000
Then
'Gruppe 10A --> Erweiterung des PTY-Typs
If Pty_name_flag < 2
Then
'Solange Schleife noch nicht 2x durchlaufen ist
Incr
Pty_name_flag
'Setze Flag auf erkanntes PTYN
Byte1 = R7 And
&B00000001
'Isoliere Block C, Bit0 als HI/LO Schalter für Position in
8-Zeichen-String
Shift Byte1 , Left ,
3
'*4
Call
Rds_char_code(r8)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r8) : Pos = 1 + Byte1
Mid(pty_name , Pos , 1 ) = Ch
Call
Rds_char_code(r9)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r9) : Pos = 2 + Byte1
Mid(pty_name , Pos , 1 ) = Ch
Call
Rds_char_code(r10)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r10) : Pos = 3 + Byte1
Mid(pty_name , Pos , 1 ) = Ch
Call
Rds_char_code(r11)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r11) : Pos = 4 + Byte1
Mid(pty_name , Pos , 1 ) = Ch
End If
End If
'*** GRUPPE 14A (EON) ***
If Service = &B11100000
Then
'Gruppe 14A --> EON-Info
Tp_eon =
R7.4
'TP_EON
Pic1_eon =
R10
'Program Identification Code in Block D
Pic2_eon = R11
Vc_counter_eon = R7 And
&B00001111
'Variant-Code = Adressierung Datenbytes isolieren
If Eon_flag = &HFF Then Eon_flag =
0 'Start-Flag für
EON-Daten vorhanden setzen
If Eon_flag = 0 And Vc_counter_eon = 0 Then Eon_flag =
1 'EON-Dekodierung starten
If Eon_flag = 1 Then
'PS (Sendername) dekodieren
If Vc_counter_eon < 4 Then
Pos = Vc_counter_eon * 2
Incr Pos
Call
Rds_char_code(r8)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch =
Chr(r8)
'2 Zeichen aus R8 und R9 (Block C)
Mid(ps_eon , Pos , 1 ) =
Ch
'in Ps_name-String
Incr Pos
Call
Rds_char_code(r9)
'RDS ASCII-Code in EADOGM-Code umrechnen
Ch = Chr(r9)
Mid(ps_eon , Pos , 1 ) = Ch
'AF und Tuning-Freq./Mapped Freq.
Elseif Vc_counter_eon < 10 Then
Pos = Vc_counter_eon -
4
'Index = 2*(VC-4)+1
Shift Pos , Left , 1
Incr Pos
Lw_mw_af =
0
'Setze LW/MW-Flag auf Null
If R8 > 0 And R8 < 205
Then
'Code zwischen 1...204 => gültige AF
Call Rds_calc_af(r8 , Word1)
Af_eon(pos) = Word1
Elseif R8 = 250
Then
'LW/MW-Frequenz folgt
Lw_mw_af = 1
Af_eon(pos) =
0
'--> Flag setzen, daß nächste Frequenz = LM/AM-Frequenz ist
Else
Lw_mw_af = 0
Af_eon(pos) = 0
End If
Incr Pos
If R9 > 0 And R9 < 205
Then
'Code zwischen 1...204 => gültige AF
Call Rds_calc_af(r9 , Word1)
Af_eon(pos) = Word1
End If
'Linkage Information
Elseif Vc_counter_eon = 12 Then
Link_info = Makeint(r9 , R8)
'PTY_EON, TA
Elseif Vc_counter_eon = 13 Then
Pty_eon = R8 And &B11110000
Swap Pty_eon
Ta_eon = R9.0
'PIN_EON
Elseif Vc_counter_eon = 14 Then
Pin_code_eon = Makeint(r9 , R8)
Eon_flag =
2
'Flag auf voll dekodiert setzen
End If
End If
End If
'*** GRUPPE 14B (EON) ***
If Service = &B11101000
Then
'Gruppe 14B --> EON-Info
Ta_eon =
R7.3
'TA_EON
Tp_eon =
R7.4
'TP_EON
Pic1_eon =
R10
'Program Identification Code in Block D
Pic2_eon = R11
End If
If Rds_over_rs232_control.0 = 1
Then
'RDS-Infosegment 1
Print
'aktuelle Gruppennummer und Typ anzeigen
Byte1 = Service : Swap Byte1 : Byte1 = Byte1 And &B00001111
Print "Gruppennummer: " ; Byte1 ; : If Service.3 = 0 Then Print "A"
Else Print "B"
'Blöcke anzeigen
Print "BlockA: " ; Bin(r4) ; " " ; Bin(r5)
Print "BlockB: " ; Bin(r6) ; " " ; Bin(r7)
Print "BlockC: " ; Bin(r8) ; " " ; Bin(r9)
Print "BlockD: " ; Bin(r10) ; " " ; Bin(r11)
Print "Blockerrors: " ; Bin(r12)
End If
End If
End If
'*** Bei Tastendruck, Encoder, oder RS-232-Input --> Ende Radiotext-Dekodierung ***
'(
If S2 = 0 Or S3 = 0 Or S4 = 0 Or S5 = 0 Or Encoder1 <> Encoder1old Then
Call Rds_reset
Exit Do
End If
If Ischarwaiting(#1) = 1 Then Exit Do
')
Loop Until R3 = 1 Or R3 =
0
'Schleife, bis FIFO-Speicher leer
'*** div. RDS-Infos auf RS-232 ausgeben ***
Pi = Makeint(r5 ,
R4)
'Isoliere PI-Code aus BlockA = R4 + R5
If Rds_over_rs232_control.1 = 1 And Pi <> &HFFF Then 'RDS-Infosegment 2
Print
'PI-Code
Print "PI = $" ; Hex(pi) ; " = %" ; Bin(r4) ; " " ; Bin(r5)
'Travel-Program, Travel-Announcement
Print "TP = ";
If R6.2 = 1 Then
Tp = 1
Print "1 :"
;
'Verkehrsfunksender
Else
Tp = 0
Print "0 : No ";
End If
Print "Travel Program"
Print "TA = " ; Ta ; " : " ;
If Ta = 0 Then Print "No ";
Print "Travel-Announcement" ;
If Ta = 1 And Tp = 0 Then Print " on EON" Else
Print 'TA auf anderem Sender via EON
'Music/Speech
Print "Music or Speech: ";
If Ms_flag = 1
Then
'MS
Print "Music"
Elseif Ms_flag = 0 Then
Print "Speech"
End If
'PTY (Europa)
Pty = R6 And
&B00000011
'PTY-Bits isolieren
Shift Pty , Left , 3
Ptyn = R7 And &B11100000
Shift Ptyn , Right , 5
Pty = Pty Or Ptyn
Print "Program-Type: " ; Pty ; " = ";
'PTY im Klartext ausgeben (Europäische Kodierung)
'empfohlene Ausgabe für 16-Zeichen Anzeige
Text1 = Lookupstr(pty , Pty_codes)
Print Text1 ; " ";
'PTY_Name
If Pty_name_flag > 1
Then
'Klartext-Ergänzung des PTY
Print Pty_name
Pty_name_flag =
0
'Flag zurücksetzen
Else
Print
End If
'Decoder-Information
If Di_counter > 4 Then
Print "Decoder-Information: "
;
'DI
If Di(1) > 0 Then Print "Stereo," ; Else Print "Mono,";
If Di(2) > 0 Then Print " Binaural Transmission,";
If Di(3) > 0 Then Print " C" ; Else Print " Unc";
Print "ompressed Transmission";
If Di(4) > 0 Then Print ", Dynamic PTY or EON" Else Print ", Static
PTY"
End If
End If
If Rds_over_rs232_control.2 = 1
Then
'RDS-Infosegment 3
Print
If Ps_flag = 1
Then
'Ausgabe PS nur bei voll dekodiertem PS
Print "Program-Name: " ; Ps_name_last
Ps_flag = 0
End If
Call Make_freq_string(freq_fm)
Print "Frequenz: " ; Freq_string ; " MHz"
If Af_flag = 2 And Af_max > 0
Then
'Alternate Frequencies ausdrucken, wenn Liste vollständig
Word1 =
Af(1)
'AF1 zum Vergleich mit möglichen Frequenzpaaren in Methode B laden
Method_b = 0
If Af_max > 2
Then
'Prüfe auf Methode B
If Af(2) = Af(1) Or Af(3) = Af(1) Then
Method_b = 1
Else
Method_b = 0
Reg_flag =
0
'Regionalisierungs-Flag zurücksetzen
End If
End If
N =
1
'N=laufender Index für AF-Speicherstelle
N1 =
0
'N1=Index für tatsächlichen AF-Index (=N bei Methode A;
=Frequenzpaarnummer bei Methode B)
Do
If N1 = 0 And Method_b = 1 Then
Byte1 = Af_max / 2
Print "Frequenzpaare: " ; Byte1
Print "Tuned Frequency:
";
'Tuned-frequency bei Methode B (0. Paar)
Elseif N1 = 0 And Method_b = 0 Then
Print "Anzahl Alternativ-Frequenzen: " ; Af_max
Print "1. Altern. Frequ.: " ;
Else
'Methode A oder Methode B ab 1.Paar
If Method_b = 1 Then
Print N1 ;
Else
Print N;
End If
Print ". Altern. Frequ.: " ;
End If
If Method_b = 0
Then
'Methode A
Freq_af = Af(n)
Else
'Methode B
If N1 = 0
Then
'Hauptfrequenz bei Paarindex N1=0
Freq_af = Af(1)
Else
'AF-Paare dekodieren
N = N1 *
2
'N = 1.AF-Index für Frequenzpaar N1
N2 = N +
1
'N2= 2.AF-Index für Frequenzpaar N1
If Af(n) < Af(n2) Then Reg_flag = 0 Else Reg_flag =
1 'Teste auf Regional-Frequenz
If Af(n) = Af(1) Then Freq_af = Af(n2) 'Teste, welche Frequenz die AF,
und welche die Wiederholung der Hauptfrequenz ist
If Af(n2) = Af(1) Then Freq_af = Af(n)
End If
Incr
N
'damit >AF_max wird nach Erreichen des letzten Frequenzpaares
End If
Incr N : Incr
N1
'Paarindex erhöhen
' Word1 = Af(n)
Call Make_freq_string(freq_af)
'
If Af(n) < 1600
Then
'LW/MW-Frequenz
If Freq_af < 1600
Then
'LW/MW-Frequenz
Print Freq_string ; " kHz";
Else
'FM-Frequenz
Print Freq_string ; " MHz";
End If
If Reg_flag = 1 Then Print " Regional" Else Print
Loop Until N > Af_max
Af_flag =
0
'Flag wieder zurücksetzen, damit nächste AF-Liste bei Methode B geholt
werden kann
End If
'(
'PI-Codes (Europa)
Byte1 = R4 : Swap Byte1 : Byte1 = Byte1 And
&B00001111
'4 MSB von R4=BlockA isolieren
If Byte1 <> 0 Then
Decr
Byte1
'-1, da Tabelle 0-based
Print "Country-Code: ";
If Ecc = &HFF
Then
'keine ECC-Daten aus Gruppe1A
For N = 0 To 60 Step 15
Byte2 = Byte1 +
N
'Berechne Tabellenadrese
Text1 = Lookupstr(byte2 , Country_codes )
Print Text1 ; " or ";
Next N
Print
Else
'genau spezifiertes Land, weil ECC vorhanden
Byte2 = Ecc And
&B00001111
'4 LSB=Index isolieren
Byte2 = Byte2 * 15
Byte2 = Byte2 + Byte1
Text1 = Lookupstr(byte2 , Country_codes )
Print Text1
End If
Byte1 = R4 And
&B00001111
'4 LSB von R8=BlockC isolieren
Print "Area-Coverage-Code: ";
Select Case Byte1
Case 0 : Print "Local"
Case 1 : Print "International"
Case 2 : Print "National"
Case 3 : Print "Suparnational"
Case Else
Byte2 = Byte1 - 3
Print "Regional R" ; Byte2
End Select
Print "Program Reference Number: " ; R5
'Language Codes (Europe)
Print
If Lc <> &HFF Then
Print "Language: ";
If Lc < &H30 Then
Text1 = Lookupstr(lc , Language_codes )
Elseif Lc < &H40 Then
Text1 = "Reserved"
Elseif Lc = &H7D Then
Text1 = "Armenian"
Elseif Lc = &H7B Then
Text1 = "Azerbaijan"
Elseif Lc = &H79 Then
Text1 = "Belorussian"
Elseif Lc = &H71 Then
Text1 = "Georgian"
Elseif Lc = &H7D Then
Text1 = "Armenian"
Elseif Lc = &H63 Then
Text1 = "Macedonian"
Elseif Lc = &H60 Then
Text1 = "Moldavian"
Elseif Lc = &H56 Then
Text1 = "Russian"
Elseif Lc = &H54 Then
Text1 = "Serbo-Croat"
Elseif Lc = &H49 Then
Text1 = "Ukrainian"
Elseif Lc = &H40 Then
Text1 = "Background Sound"
End If
Print Text1
End If
End If
')
End If
If Rds_over_rs232_control.3 = 1 And Stunden <> &HFFFF
Then 'RDS-Infosegment 4
'Zeit + Datum
Print
Print "Local Time: " ;
If Stunden < 10 Then Print "0";
Print Stunden ; "h " ;
If Minuten < 10 Then Print "0";
Print Minuten ; "m"
Print "Modified Julian Date: " ; Mjd
Ys = Mjd : Ys = Ys - 15078.2 : Ys = Ys / 365.25 : Ys = Int(ys)
Ms = Mjd : Ms = Ms - 14956.1 : Ks = Ys * 365.25 : Ks = Int(ks) : Ms =
Ms - Ks : Ms = Ms / 30.6001 : Ms = Int(ms)
Float1 = Mjd : Float1 = Float1 - 14956 : Float1 = Float1 - Ks : Ks = Ms
* 30.6001 : Ks = Int(ks) : Float1 = Float1 - Ks
Day = Float1
If Ms = 14 Or Ms = 15 Then K = 1 Else K = 0
Year = Ys : Year = Year + K : Year = Year + 1900
K = K * 12
Month = Ms : Month = Month - 1 : Month = Month - K
Wd = Mjd + 2 : Wd = Wd Mod 7
Text1 = Lookupstr(wd , Day_names )
Print "Date: " ; Text1 ; ", " ; Day ; "." ; Month ; "." ; Year
End If
If Rds_over_rs232_control.4 = 1 And Radiotext_ready = 1
Then 'RDS-Infosegment 5
'Radiotext
Print
Print "Radiotext (Länge): " ; Radiotext_length
Print Left(radiotext ,
Radiotext_length)
'LF und CR werden automtisch bei RS-232 richtig interpretiert
End If
'(
If Rds_over_rs232_control.5 = 1 And Ews <> &HFFFF
Then
'RDS-Infosegment 6
'EWS
Print
Print "Emergency Warning: $" ; Hex(ews)
If Ews0 <> &HFF
Then
'EWS-Daten aus Gruppe 9A
Print "EWS0...EWS4 = $" ; Hex(ews0) ; " " ; Hex(ews1) ; " " ; Hex(ews2)
; " " ; Hex(ews3) ; " " ; Hex(ews4)
End If
End If
')
If Rds_over_rs232_control.6 = 1 And Eon_flag = 2 Then 'RDS-Infosegment 7, wenn EON voll dekodiert
'EON
Print
Eon_flag =
0
'EON-Flag zurücksetzen für Neudecodierung
Print "EON-Program-Name: " ; Ps_eon
'PI-Code
Pi_eon = Makeint(pic2_eon , Pic1_eon)
Print "PI-EON = $" ; Hex(pi_eon) ; " = %" ; Bin(pic1_eon) ; " " ; Bin(pic2_eon)
'PIN-Code
Print "PIN-EON = $" ; Hex(pin_code_eon)
'Travel-Program, Travel-Announcement
Print "EON-TP = " ; Tp_eon ; " : ";
If Tp_eon = 0 Then Print "No ";
Print "Travel Program"
Print "EON-TA = " ; Ta_eon ; " : ";
If Ta_eon = 0 Then Print "No ";
Print "Travel-Announcement";
If Ta_eon = 1 And Tp_eon = 0
Then
'TA auf anderem Sender via EON
Print " on EON"
Else
Print
End If
'EON_PTY
Text1 = Lookupstr(pty_eon , Pty_codes)
Print "EON-Program-Type: " ; Pty_eon ; " = " ; Text1
'EON_AF
For N = 0 To
5
'6 Frequenzpaare
Byte1 = N * 2 : Incr Byte1
Word1 = Af_eon(byte1)
If Af_eon(byte1) = Freq_fm
Then
'1. AF_EON aus Frequenzpaar = eingestellte Frequenz?
Incr
Byte1
'rechter Wert aus Frequenzpaar=mapped Frequency
Call Make_freq_string(word1)
Print "Mapped Frequency: " ; Freq_string ;
If Word1 < 1600 Then Print " kHz" Else Print "
MHz" '
Else
'AF-Methode A
If Word1 <> 0
Then
'linke AF aus AF-Paar
Call Make_freq_string(word1)
Print "Altern. Frequency: " ; Freq_string ;
If Word1 < 1600 Then Print " kHz " ; Else Print " MHz
"; '
End If
Incr Byte1
Word1 = Af_eon(byte1)
If Word1 <> 0
Then
'rechte AF aus AF-Paar
Call Make_freq_string(word1)
Print "Altern. Frequency: " ; Freq_string ;
If Word1 < 1600 Then Print " kHz" Else Print "
MHz" '
End If
End If
Next N
Eon_flag =
&HFF
'EON_Flag wieder zurücksetzen
End If
If Rds_over_rs232_control.7 = 1 And Pin_code <> &HFFFF
Then 'RDS-Infosegment 8
Print
Print "PIN-Code:
$" ; Hex(pin_code)
Print "Linkage actuator: $" ; La
Print "Linkage Information$" ; Hex(link_info)
Print "Language Code: $" ; Hex(lc)
Print "Ext. Country Code: $" ; Hex(ecc)
Print "TMC-Ident: $" ; Hex(tmc_ident)
Print "EWS-Channel: $" ; Hex(ews)
End If
Rds_over_rs232_control =
0
'Setze RS232-Ausgabe-Flag zurück
End Sub
'*************************************************
'*** Ersetze RDS-ASCII-Code mit EADOGM-Zeichencode
'*************************************************
Sub Rds_char_code(chr_code As Byte)
If Chr_code > 127
Then
'ASCII-Codes über 127?
Reset
Chr_code.7
' (Code - 127) = Tabellenindex
Incr Chr_code
Chr_code = Replace_codes(chr_code)
End If
End Sub
'*************************************
'*** Radiotext 1x fertig empfangen ***
'*************************************
Sub Radiotext_decoded()
If Char_counter = Position
Then
'Teste, ob Anzahl gezählter Zeichen = aktuelle Positionszähler
Radiotext_ready =
1
'Flag auf fertig dekodierten RT-String
Radiotext_start_decode =
3
'Flag auf fertig dekodierten RT-String
Radiotext =
Radiotext_new
'hole dekodierten String in "RADIOTEXT"-String
Radiotext_length =
Char_counter
'Aktuelle Position des letzten Zeichens/Zeichenzählers = Radiotext_Länge
Call
Radiotext_start
'
' Radiotext_lf_pos =
Charpos(radiotext ,
10)
'Position des nächsten LF
Home Upper : Lcd
Display_string
'RT-String in 1. Zeile LCD bringen
Else
Radiotext_start_decode =
1
'Dekodier-Status auf Anfang zurücksetzen
End If
End Sub
'******************************************************
'*** Starte Radiotext-Anzeige mit ersten 16 Zeichen ***
'******************************************************
Sub Radiotext_start()
Local Missing_spaces As Byte
Call
Clear_lcd_upperline
'Am Beginn 1s Frequenzanzeige
Call Fm_tune_status_freq_print_lcd
Wait 1
If Radiotext_length < 16
Then
'Radiotext kürzer als 16 Zeichen?
Radiotext = Left(radiotext ,
Radiotext_length) 'fülle RT mit
Spaces auf 16 Zeichen auf
Missing_spaces = 16 - Radiotext_length
Radiotext = Radiotext + Space(missing_spaces)
Radiotext_length = 16
End If
Radiotext_display_pos =
1
'Zähler für Postion nächstes 16-Zeichen-Segment
End_position = Radiotext_length -
14
'Letzte Zählerposition
Display_string =
Left(radiotext ,
16)
'Isoliere erste LCD-Zeile des Display_strings
Home Upper : Lcd
Display_string
'Drucke auf LCD aus
Scroll_counter = 2 :
Direction =
0
'2x stehen lassen, bevor weitergescrollt wird
End Sub
'******************************************
'*** Scrolle Radiotext-Lauftext auf LCD ***
'******************************************
Sub Radiotext_scroll()
Local Switch_position As Byte
Switch_position = End_position - 1
If Radiotext_length > 16
Then
'scrollen nur bei Länge>16
'Ping-Pong-Scrollen
If Radiotext_length < 25 Then
If Direction = 0
Then
'nach rechts
Incr Radiotext_display_pos
If Radiotext_display_pos = Switch_position Then Scroll_counter =
2 'rechtes Ende erreicht --> 2x
stehen lassen
If Radiotext_display_pos = End_position Then 'rechtes Ende
erreicht
Toggle
Direction
'Richtung umkehren
Else
Display_string = Mid(radiotext , Radiotext_display_pos ,
16) '16-Zeichen-String aus
Radiotext ausschneiden
End If
Else
'nach links
Decr Radiotext_display_pos
If Radiotext_display_pos = 1 Then Scroll_counter =
2 'rechtes Ende erreicht 6x stehen
lassen
If Radiotext_display_pos = 0
Then
'rechtes Ende erreicht
Toggle
Direction
'Richtung umkehren
Else
Display_string = Mid(radiotext , Radiotext_display_pos ,
16) '16-Zeichen-String aus
Radiotext ausschneiden
End If
End If
Home Upper
Lcd
Display_string
'drucke auf LCD aus
'normales Scrollen
Else
Incr Radiotext_display_pos
If Radiotext_display_pos = Switch_position Then Scroll_counter =
2 '2x stehen lassen
If Radiotext_display_pos = End_position
Then 'Scrolling beendet?
Call Radiotext_start
Else
Display_string = Mid(radiotext , Radiotext_display_pos ,
16) '16-Zeichen-String aus
Radiotext ausschneiden
Home Upper
Lcd
Display_string
'drucke auf LCD aus
End If
End If
End If
End Sub
'*********************************************
'*** Berechne Frequenz einer AF (FM/LW/MW) ***
'*********************************************
Sub Rds_calc_af(af_index As Byte , Af_word As Byte)
If Af_index = 250
Then
'LW/MW-Frequenz folgt im nächsten Byte
Lw_mw_af = 1 : Af_word = 0
Elseif Af_index > 0 And Af_index < 205
Then
'Code zwischen 1...204 => gültige AF
If Lw_mw_af = 0
Then
'FM-Frequenz
Af_word = Af_index +
875
'AF berechnen (in 100kHz-Einheiten)
Af_word = Af_word * 10
Else
'AM-Frequenz
Lw_mw_af =
0
'Flag wieder zurücksetzen
Af_word = 9 *
Af_index
'9kHz-Einheiten
If Af_index < 16
Then
'LW
Af_word = Af_word + 144
Else
'MW
Af_word = Af_word + 387
End If
End If
Else
'ungültige Frequenz --> 0 zurückgeben
Af_word = 0
End If
End Sub
'*******************************************************************
'*** RDS-Variablen zurücksetzen nach SYNC-Lost oder neuem Sender ***
'*******************************************************************
Sub Rds_reset()
Tp = &HFF : Ta =
&HFF
'Travel Program, Travel Announcement-Flag
Pi =
&HFFFF
'Programm-Identification Code
Di_counter = 0 :
Di(1) = &HFF : : Di(2) = &HFF : Di(3) = &HFF : Di(4) =
&HFF 'Decoder-Information-Zähler
Ps_name = Space(8) : Ps_name_last = Ps_name : Ps_flag = 0 : Ps_counter = 0
Af_flag = 0 : Af_max = 0 : Lw_mw_af =
0
'div. Startdaten für Alternate Frequencies
La =
0
'Linkage Actuator-Flag
Vc =
&HFF
'Variant Code
Ecc =
&HFF
'Extended Country Code
Lc =
&HFFFF
'Language Code
Ews = &HFFFF : Ews0 =
&HFF
'Emergency Warning System
Pin_code =
&HFFFF
'Program-Identification-Code
Tmc_ident =
&HFFFF
'TMC-Identification
Eon_flag = &HFF : Pin_code_eon = &HFFFF
Radiotext_present = 0
Radiotext_first_aqu = 0
Radiotext_start_decode = 0 : Radiotext_ready = 0
Minuten = &HFFFF : Stunden = &HFFFF : Utc_offset = &HFF :
Mjd = &HFFFFFFFF
'Zeitvariablen
'Modified Julian Date
Pty_name = Space(8) :
Pty_name_flag =
0
'PTYN aus Gruppe 10A
End Sub
'**********************************************************************************
'*** aktuell eingestellter Modus, Frequenz FM/AM und Band im EEPROM abspeichern ***
'**********************************************************************************
Sub
Eeprom_save()
'Frequenzdaten in EEPROM sichern
Writeeeprom Am_fm_flag , 1000
Writeeeprom Freq_fm
Writeeeprom Freq_am
Writeeeprom Band
End Sub
'********************************
'*** untere LCD-Zeile löschen ***
'********************************
Sub
Clear_lcd_lowerline()
'untere LCD-Zeile löschen
Home Lower
Lcd Space(16)
End Sub
'********************************
'*** untere LCD-Zeile löschen ***
'********************************
Sub
Clear_lcd_upperline()
'untere LCD-Zeile löschen
Home Upper
Lcd Space(16)
End Sub
'*******************************************
'*** Flags für Eingabemodus zurücksetzen ***
'*******************************************
Sub
Reset_flags()
'Eingabeflags zurücksetzen
Memory_aktiv_flag = 0
Property_aktiv = 0
Am_textaktiv = 0
Cursor Off
End Sub
'*****************************************************
'*** Encoderwerte nach Veränderung auf Null setzen ***
'*****************************************************
Sub
Reset_encoder()
'Encoder auf 0 zurücksetzen
Encoder1 = 0
Encoder1old = Encoder1
Enable Timer0
End Sub
'*****************************************************
'************** RS-232: Frequenz-Einstellung *********
'*****************************************************
Sub F_control()
Print "Tune"
Input Fin
If Am_fm_flag = 1
Then
'im AM-Modus?
If Fin >=
23000
Then
'prüfe, ob Frequenz oberhalb 23MHz
Am_fm_flag =
0
'--> schalte auf FM-Modus um
Call Si4735_init
End If
End If
If Am_fm_flag = 0
Then
'im FM-Modus?
' If Fin < 000
Then
'prüfe, ob Frequenz unterhalb 60MHz
'
Am_fm_flag =
1
'--> schalte auf AM-Modus um
' Call Si4735_init
' End If
End If
If Am_fm_flag = 1
Then
'setze AM-Frequenz
Freq_am = Fin
Call Am_tune_freq
Call Am_tune_status_freq_print_lcd
Else
'setze FM-Frequenz
Fin = Fin / 10
Freq_fm = Fin
Call Fm_tune_freq
Call Fm_tune_status_freq_print_lcd
End If
End Sub
'******************************************
'*** RS-232: Senderspeicher AM eingeben ***
'******************************************
Sub Mam_control()
Print "Memory AM"
Input
N
'Speicherplatz holen
Input
Fin
'Frequenz in kHz holen
Input
Text1
'Sendername holen
If N < 51 Then
If N > Am_memorymax Then Am_memorymax = N
Freq = Fin
Am_memory(n) = Freq
Text1 = Text1 + " "
Text1 = Left(text1 , 10)
Am_text(n) = Text1
End If
End Sub
'******************************************
'*** RS-232: Senderspeicher FM eingeben ***
'******************************************
Sub Mfm_control()
Print "Memory FM"
Input N
Input Fin
If N < 51 Then
If N > Fm_memorymax Then Fm_memorymax = N
Fin = Fin / 10
Freq = Fin
Fm_memory(n) = Freq
End If
End Sub
'*********************************
'*** RS-232: Property eingeben ***
'*********************************
Sub Properties()
Print "Property"
Input
N
'Property-Nummer holen
If N < 17 Then
Input
Dat
'Property-Wert
holen
'
Property_dat(n) = Dat
Property_adr = Property_adress(n)
Call Si4735_set_property(property_adr , &H00 , Dat) 'Property-Wert setzen
End If
End Sub
'*****************************
'*** RS-232: I2C-Kommando ***
'*****************************
Sub Pc_control_i2c()
Print #1 , "I2C"
Do
Get #1 ,
Command
'I2C write and read to SI4735
If Command = 67
Then
'"C"
Input #1 , Bytesout
Input #1 , Bytesin
For N = 1 To Bytesout
Inputhex #1 , Data_i2c(n)
Next N
I2cstart
I2cwbyte 34
For N = 1 To Bytesout
I2cwbyte Data_i2c(n)
Next N
I2cstop
If Bytesin > 0 Then
Waitms 1
I2cstart
I2cwbyte 35
While Bytesin > 1
Bytesin = Bytesin - 1
I2crbyte D ,
Ack
'Binärausgabe der gelesenen Bytes vom I2C-Bus
Print #1 , Bin(d)
Wend
I2crbyte D , Nack
Print #1 ,
Bin(d)
'Binärausgabe des letzten gelesenen Bytes vom I2C-Bus
I2cstop
End If
End If
If Command = 65
Then
'LCD Line 1
Input #1 , Text1
Home Upper
Lcd Text1
End If
If Command = 66
Then
'LCD Line 2
Input #1 , Text1
Home Lower
Lcd Text1
End If
Loop
End Sub
'*******************
'*** RDS-Ausgabe ***
'*******************
Sub Rds_print_control()
Print : Print "RDS-Data over RS-232 --> Enter Control Byte: ";
Input Rds_over_rs232_control :
Print
'
End Sub
'********************************************
'*** TIMER0-Interrupt für Encoder-Abfrage ***
'********************************************
Tim0_isr:
$asm
push r16
push r17
push r20
push r21
push r24
push r26
push r27
in r24,sreg
push r24
$end Asm
Code1 = Pinc
Code1 = Code1 And
&B00000110
'PC2 und PC1 isolieren
If Code1.2 < Code1old.2 Then
If Code1.1 = 1 Then Encoder1 = Encoder1 + 1
If Code1.1 = 0 Then Encoder1 = Encoder1 - 1
End If
Code1old = Code1
$asm
pop r24
Out Sreg , R24
pop r27
pop r26
pop r24
pop r21
pop r20
pop r17
pop r16
$end Asm
Return
End
'******************
'******************
'*** DATA-Werte ***
'******************
'******************
'******************
$eeprom
$eepromhex
'Intel HEX-Format für EEP-File für USBTiny-Programmer
'***EEPROMHEX-Direktive Auskommentieren bei Simulation oder Brennen mit Normal-Brenner!!!***
Data
0
'Leerbyte
Data
1
'Anzahl belegter FM-Senderspeicher
'10 LW-Speicherfrequenzen
Data
153%
'1.LW-Senderfrequenz
Data 162%
Data 177%
Data 183%
Data 198%
Data 207%
Data 216%
Data 234%
Data 252%
Data 279%
'10 MW-Speicherfrequenzen
Data
549%
'1.MW-Senderfrequenz
Data 621%
'Data 675%
Data 693%
Data 720%
Data 747%
Data 756%
'Data 801%
Data 810%
'Data 828%
Data 864%
'Data 1008%
'data 1215%
Data 1422%
Data 1440%
'Data 1593%
'10 KW-Speicerhfrequenzen, Bandbereich 1
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
'10 KW-Speicerhfrequenzen, Bandbereich 2
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
'10 KW-Speicerhfrequenzen, Bandbereich 3
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
'50 FM-Speicherfrequenzen
Data
10080%
'1.FM-Frequenz
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
Data 0%
'10 LW Speichernamen
Data
"DLF
"
'1.LW-Sendernamen
Data "France Int"
Data "DLR Kultur"
Data "Europe One"
Data "BBC4/BBCWS"
Data "DLF "
Data "MonteCarlo"
Data "RTL-Luxemb"
Data "Chaine 3 "
Data "Belarus 1 "
'10 MW Speichernamen
Data
"DLF
"
'2. MW-Sendernamen
Data "RTBF/Bel "
'Data "RadioMaria"
Data "BBC5/RUSSL"
Data "WDR2/VERA "
Data "Radio5 NL "
Data "DLF "
'Data "BR Plus "
Data "BBC Scotld"
'Data
"NDR Info
"
'oder "Radio10 NL"
Data "FranceBleu"
'Data "Gr.Nieuws "
'Data "V.o.Russia"
Data "DLF "
Data "RTL/China "
'Data "WDR2 "
'10 KW Speichernamen, KW-Bandbereich 1
Data
"
"
'1.KW-Sendername; Tropenbänder
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
'10 KW Speichernamen, KW-Bandbereich 2
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
'10 KW Speichernamen, KW-Bandbereich 3
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
Data " "
'Frei-Bytes 752-994
Data 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 , 65 , 66
Data
67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 ,
81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 91 , 92 , 93 , 94 ,
95 , 96 , 97 , 98 , 99
Data 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23
, 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32
Data 33 , 34 , 35 , 36
, 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 ,
51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 ,
65 , 66
Data 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 ,
78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 91 ,
92 , 93 , 94 , 95 , 96 , 97 , 98 , 99
Data 0 , 1 , 2 , 3 , 4 , 5
, 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20
, 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32
Data 33
, 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 ,
48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 ,
62 , 63 , 64 , 65 , 66
Data 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 ,
75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 ,
89 , 90 , 91 , 92 , 93 , 94
'Adresse 995:
Data
10
'Lw_memorymax = Position des höchsten LW-Speichers
Data
20
'Mw_memorymax = Position des höchsten MW-Speichers
Data
20
'Kw1_memorymax = Position des höchsten KW1-Speichers
Data
30
'Kw2_memorymax = Position des höchsten KW2-Speichers
Data
40
'Kw3_memorymax = Position des höchsten KW2-Speichers
'Adresse 1000
Data
0
'letzter Modus: AM/FM
Data
10080%
'letzte FM-Frequenz
Data
648%
'letzte AM-Frequenz
Data
2
'letztes AM-Band
'Adresse 1006
Data &H01 , &H31 ,
&H1E , &H40 , &H10 , &H04 , &H03 , &H14
'16 Property-Default-Werte ab 1006
Data &H00 , &H03 , &H40 , &H02 , &H10 , &H0A , &H05 , &H19
'Adresse 1022 = Flag für FM-PWM-Ausgabe
Data 0
'Adresse 1023 = Flag für manuelle Schrittweite
Data 0
$data
'Band-Bezeichnungen
Band_names:
Data " "
Data "Langwelle"
Data "Mittelwelle"
Data
"120m
Tropenband"
'KW-Bereich 1; AM-Speicher 21-30
Data "90m Tropenband"
Data "75m Tropenband"
Data "60m Tropenband"
Data
"49m
Europaband"
'KW-Bereich 2; AM-Speicher 31-40
Data "41m KW-Band"
Data "31m KW-Band"
Data "25m KW-Band"
Data
"21m
KW-Band"
'KW-Bereich 3: AM-Speicher 41-50
Data "19m KW-Band"
Data "16m KW-Band"
Data "15m KW-Band"
Data "13m KW-Band"
Data "11m KW-Band"
Band_data:
Data
153% ,
279%
'LW-Bandgrenzen
Data 522% ,
1710%
'MW-Bandgrenzen
Data 2300% ,
2495%
'KW-Band1 Bandgrenzen
Data 3200 % , 3400%
Data 3900% , 4000%
Data 4750% , 5060%
Data 5900% , 6200%
Data 7100% , 7450%
Data 9400% , 9900%
Data 11600% , 12100%
Data 13570% , 13870%
Data 15100% , 15800%
Data 17480% , 17900%
Data 18900% , 19020%
Data 21450% , 21850%
Data 25600% , 26100%
Data
8750% ,
10800%
'FM-Bandgrenzen
'Band_start(17) =
6400
'unterste FM-Grenze
'Call Si4735_set_property(&H1400 , 64 ,
00)
'auf 64 MHz setzen
'Property-Adressen N=1...16; max./min.-Werte; Default-Werte
Property_data:
Data
&H1100% , 1 , 2 ,
&H01
'FM-Deemphasis
Data &H1105% , 0 , 127 ,
&H31
'FM-Stereo-Schwelle
Data &H1106% , 0 , 127 ,
&H1E
'FM-Mono-Schwelle
Data &H1300% , 1 , 255 ,
&H40
'FM Mute-Geschwindigkeit
Data &H1302% , 0 , 31 ,
&H10
'FM Soft_Mute, max. Absenkung
Data &H1303% , 0 , 15 ,
&H04
'FM Soft_Mute, SNR-Schwelle
Data &H1403% , 0 , 127 ,
&H03
'FM Suchlauf, SNR-Schwelle
Data &H1404% , 0 , 127 ,
&H14
'FM Suchlauf, Signalstärke-Schwelle
Data &H3100% , 0 , 1 ,
&H00
'AM-Deemphasis
Data &H3102% , 0 , 4 ,
&H03
'AM-Bandbreite
Data &H3300% , 11 , 255 ,
&H40
'AM Soft-Mute Geschwindigkeit
Data &H3301% , 1 , 5 ,
&H02
'AM Soft-Mute Steilheit
Data &H3302% , 0 , 63 ,
&H10
'AM Soft_Mute, max. Absenkung
Data &H3303% , 0 , 63 ,
&H0A
'AM Soft_Mute, SNR-Schwelle
Data &H3403% , 0 , 63 ,
&H05
'AM Suchlauf, SNR-Schwelle
Data &H3404% , 0 , 63 ,
&H19
'AM Suchlauf, Signalstärke-Schwelle
'Property-Bezeichnungen (8 Zeichen f. LCD)
Property_names:
Data " "
Data "Deemphas"
Data "ST-Blend"
Data "MO-Blend"
Data "MuteRate"
Data "MuteAttn"
Data "Mute SNR"
Data "Seek SNR"
Data "SeekRSSI"
Data "Deemphas"
Data "Bndwidth"
Data "MuteRate"
Data "MuteSlop"
Data "MuteAttn"
Data "Mute SNR"
Data "Seek SNR"
Data "SeekRSSI"
Pty_codes:
'(
'RDS-PTY-Klartext-Bezeichnung (16-Zeichen-Code)
Data
"None"
'8-Character Anzeige " None "
Data
"News"
'8-Character Anzeige " News "
Data "Current
Affairs"
'8-Character Anzeige "Affairs "
Data
"Information"
'8-Character Anzeige " Info "
Data
"Sport"
'8-Character Anzeige " Sport "
Data
"Education"
'8-Character Anzeige "Educate "
Data
"Drama"
'8-Character Anzeige " Drama "
Data
"Culture"
'8-Character Anzeige "Culture "
Data
"Science"
'8-Character Anzeige "Science "
Data "Varied
Speech"
'8-Character Anzeige " Varied "
Data "Pop
Music"
'8-Character Anzeige " Pop M "
Data "Rock
Music"
'8-Character Anzeige " Rock M "
Data "Easy
Listening"
'8-Character Anzeige " Easy M "
Data "Light Classics
M"
'8-Character Anzeige "Light M "
Data "Serious
Classics"
'8-Character Anzeige "Classics"
Data "Other
Music"
'8-Character Anzeige "Other M "
Data "Weather &
Metr"
'8-Character Anzeige "Weather "
Data
"Finance"
'8-Character Anzeige "Finance "
Data "Children's
Progs"
'8-Character Anzeige "Children"
Data "Social
Affairs"
'8-Character Anzeige " Social "
Data
"Religion"
'8-Character Anzeige "Religion"
Data "Phone
In"
'8-Character Anzeige "Phone In"
Data "Travel &
Touring"
'8-Character Anzeige " Travel "
Data "Leisure &
Hobby"
'8-Character Anzeige "Leisure "
Data "Jazz
Music"
'8-Character Anzeige " Jazz "
Data "Country
Music"
'8-Character Anzeige "Country "
Data "National
Music"
'8-Character Anzeige "Nation M"
Data "Oldies
Music"
'8-Character Anzeige " Oldies "
Data "Folk
Music"
'8-Character Anzeige " Folk M "
Data
"Documentary"
'8-Character Anzeige "Document"
Data "Alarm
Test"
'8-Character Anzeige " TEST "
Data
"ALARM!"
'8-Character Anzeige " ALARM! "
')
'RDS-PTY-Klartext-Bezeichnung (8-Zeichen-Code)
Data "None"
Data "News"
Data "Affairs"
Data "Info"
Data "Sport"
Data "Educate"
Data "Drama"
Data "Culture"
Data "Science"
Data "Varied"
Data "Pop M"
Data "Rock M"
Data "Easy M"
Data "Light M"
Data "Classics"
Data "Other M"
Data "Weather"
Data "Finance"
Data "Children"
Data "Social"
Data "Religion"
Data "Phone In"
Data "Travel"
Data "Leisure"
Data "Jazz"
Data "Country"
Data "Nation M"
Data "Oldies"
Data "Folk M"
Data "Document"
Data "TEST"
Data "ALARM!"
'RDS-Ländercodes
'(
Country_codes:
Data "DE" , "DZ" , "AD" , "IL" , "IT" , "BE" , "RU" , "PS" , "AL" , "AT" , "HU" , "MT" , "DE" , "nn" , "EU"
Data "GR" , "CY" , "SM" , "CH" , "JO" , "FI" , "LU" , "BG" , "DK" , "GI" , "IQ" , "GB" , "LY" , "RO" , "FR"
Data "MA" , "CZ" , "PL" , "VA" , "SK" , "SY" , "TN" , "nn" , "LI" , "IS" , "MC" , "LT" , "YU" , "ES" , "NO"
Data "IE" , "TR" , "MK" , "nn" , "nn" , "nn" , "NL" , "LV" , "LB" , "nn" , "HR" , "nn" , "SE" , "BY" , "nn"
Data "MD" , "EE" , "nn" , "nn" , "nn" , "UA" , "nn" , "PT" , "SI" , "nn" , "nn" , "nn" , "nn" , "nn" , "BA"
')
'(
'RDS-Spachen-Kodierung
Language_codes:
Data
"unknown" , "Albanian" , "Breton" , "Catalan" , "Croatian" , "Welsh" ,
"Czech" , "Danish" , "German" , "English" , "Spanish" , "Esperanto" ,
"Estonian" , "Basque" , "French"
Data "Frisian" , "Irish" , "Gaelic"
, "Galician" , "Icelandic" , "Italian" , "Lappish" , "Latin" ,
"Latvian" , "Luxembourgian" , "Lithuanian" , "Hungarian" , "Maltese" ,
"Dutch" , "Norwegian" , "Occitan"
Data "Polish" , "Portugese" ,
"Romanian" , "Romansh" , "Serbian" , "Slovak" , "Slovene" , "Finnish" ,
"Swedish" , "Turkish" , "Flemish" , "Walloon" , " " , " " , " " , " "
')
Day_names:
Data "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" , "Sunday"
'RDS-Sonderzeichen ab ASCII 128
Special_characters:
Data
&HE0 , &H85 , &H82 , &H8A , &HE1 , &H8D ,
&HE2 , &H95 , &HE3 , &H97 , &H9C , &H80 ,
&H20 , &H00 , &HE9 , &H20
Data &H83 , &H84 ,
&H88 , &H89 , &H86 , &H8B , &H93 , &H94 ,
&H96 , &H81 , &H9B , &H87 , &H20 , &H20 ,
&H20 , &H20
Data &H9D , &H1F , &H03 , &H04 ,
&H20 , &H20 , &H20 , &H99 , &H19 , &HE4 ,
&HE5 , &H24 , &H08 , &H05 , &H06 , &H07
Data
&HF2 , &H20 , &H20 , &H02 , &H20 , &HE9 ,
&H6E , &H9A , &H75 , &H9F , &HF8 , &HDF ,
&HF6 , &HF5 , &H20 , &H12
Data &H41 , &H41 ,
&H90 , &H45 , &H49 , &H49 , &H4F , &H4F ,
&H55 , &H55 , &H52 , &H43 , &H53 , &H5A ,
&H44 , &H4C
Data &H41 , &H8E , &H45 , &H45 ,
&H49 , &H8B , &H93 , &H99 , &H95 , &H9A ,
&H72 , &H63 , &H73 , &H7A , &H64 , &H6C
Data
&HEC , &H8F , &H92 , &H99 , &H98 , &H59 ,
&HEC , &HEE , &H4E , &H6E , &H52 , &H43 ,
&H53 , &H5A , &H20 , &H20
Data &HED , &H83 ,
&H91 , &H94 , &H77 , &H79 , &HED , &HEF ,
&H6E , &H9A , &H72 , &H63 , &H73 , &H7A ,
&H20 , &H20