Forum: Projekte & Code RDS DECODER LCD TWI 2WIRE USART ATmega8 Assembler


von Bernhard S. (bernhard)



Lesenswert?

Geschätztes Forum

Ein kleines Beispiel eines RDS-Decoders.

Benötigt werden die Signale eines Rohdatendecoders Takt und Data.

Der RDS-Decoder kann die RDS-Daten auf dem Display darstellen,
die RDS-Gruppen am 2-Wire Ausgang zur Verfügung stellen (als Slave) und 
die RDS-Rohdaten, also den Datenstrom am USART / RS232-Ausgang zur 
weiteren Verarbeitung ausgeben.

Alle Funktionen sind gleichzeitig nutzbar.

Man könnte auch nur die LEDs nutzen für die Visualisierung der 
RDS-Datenqualität :-)

TMC hätte ich gern noch implementiert, vielleicht hat jemand von Euch 
schon damit Erfahrungen gesammelt?

Im Display werden u.a. folgende Informationen zur Verfügung gestellt:
- Stationsname
- Radiotext
- Alternativfrequenzen
- gesendete Gruppentypen
- Zeit
- Programm und Senderinformationen
- Statistik

LEDs:
- grün - RDS Daten sind fehlerfrei
- gelb - RDS Daten sind fehlerbehaftet (keine Synchronisation)
- rot  - ERROR im Programm

- blinken grün - Interrupt Error
- blinken gelb - schwerer Programmfehler, z.B. Stacküberlauf


Die RDS-Gruppen werden für TWI und das Display in je einem 256 Byte 
großen Puffer zwischengespeichert, d.h 32 Gruppen (ca. 3 Sekunden RDS 
Daten), ohne Datenverlust.


Der µC benötigt mindestens ca. 4MHz Prozessortakt, denn in den 
Interruptroutinen werden einige Berechnungen durchgeführt
(z.B. Prüfbitberechnung).

Programmaufbau:

Bei jedem RDS-Takt wird bei fallender Flanke ein externer Interrupt 
ausgeführt und der RDS-Data Pin abgefragt und ein Bit in den 
Zwischenpuffer geschoben und eine CRC-Prüfbitberechnung durchgeführt
und die Blöcke A+B+C+D gesammelt.

Wenn eine RDS-Gruppe fehlerfrei empfangen wurde, ist der Datenstrom 
synchronisiert und die 8 Datenbits (je 2 Bytes Block A, B C und D) 
werden in die 256 Byte großen Datenpuffer (Display / TWI) zur weiteren 
Verarbeitung zwischengespeichert.

Die LOOP-Schleife greift auf den Display-Datenpuffer zu, leert und 
verarbeitet ihn. Wird dieser Display-Datenpuffer nicht rechtzeitig 
geleert, entsteht Datenverlust, dann kommt es zu einer Fehlermeldung.

Der TWI-Datenpuffer lässt Datenverlust zu, die ältesten Daten werden 
überschrieben, was kann der Slave dazu, dass der Master die Daten nicht 
abruft... selber Schuld.

Das TWi Datenprotokoll ist relativ einfach gehlaten:
<Start MR> <AH> <AL> <BH>.....<DL> <Start MR> oder <STOPP>
Sind keine Daten mehr im TWI Puffer, dann sind alle Datenbites NULL.


Hier findet Ihr ev. noch weitere Informationen:

Beitrag "RDS CRC Prüfbit Berechnung"

Beitrag "RDS DECODER analog Schaltung ohne IC gesucht, für Rohdatengewinnung"

Beitrag "Si4735 RDS Radio UKW LW MW KW AM FM - TA TP AF GT TMC CT RT Pi PS ATmega8 Assembler"

Der Assemblercode ist nicht hochgradig optimiert, hier gibt es bestimmt 
noch Verbesserungsbedarf.

Für Anregungen und Hinweise bin ich sehr dankbar.

Bernhard

: Bearbeitet durch User
von Detlef K. (adenin)


Lesenswert?

SUPER :)
gleich mal eine Tip wie du den Code etwas schneller bekommst


alt:
1
RDS_GRUPPENTYP_A:
2
    ; CRC Kopie              
3
  mov temp3,temp5  ; CRC (berechnet)   
4
  mov temp4,temp6  ; CRC (berechnet)  
5
  ; "CRC"mit OFFSET_WORD_A verknüpfen  
6
    ldi  temp,low(OFFSET_WORD_A)
7
    eor  temp3,temp
8
    ldi  temp,high(OFFSET_WORD_A)
9
    eor  temp4,temp
10
  ; Vergleich mit empfangenem "CRC"  
11
  cp temp1,temp3   ; CRC(empfangen)  
12
  brne RDS_GRUPPENTYP_NO_A
13
  cp temp2,temp4   ; CRC(empfangen)  
14
  brne RDS_GRUPPENTYP_NO_A
15
  ; ERGEBNIS
16
  LDS temp4,(adr_RDS_DATA3)    ; aus SRAM laden  
17
  LDS temp3,(adr_RDS_DATA2)
18
  STS(adr_RDS_GRUPPE_AH_ROH),temp4   ; im SRAM ablegen  
19
  STS(adr_RDS_GRUPPE_AL_ROH),temp3
20
  ldi temp1,1  ; RÜCKGABEWERT  
21
  ret
22
RDS_GRUPPENTYP_NO_A:

neu:
1
RDS_GRUPPENTYP_A:
2
  ; Lowbyte "CRC"mit OFFSET_WORD_A verknüpfen  
3
  ldi  temp,low(OFFSET_WORD_A)
4
  eor  temp,temp5
5
  cp   temp,temp1   ; CRC(empfangen)  
6
  brne RDS_GRUPPENTYP_NO_A
7
  ; Highbyte "CRC"mit OFFSET_WORD_A verknüpfen  
8
  ldi  temp,high(OFFSET_WORD_A)
9
  eor  temp,temp6
10
  cp   temp,temp2   ; CRC(empfangen)  
11
  brne RDS_GRUPPENTYP_NO_A
12
  ; ERGEBNIS
13
  LDS  temp,(adr_RDS_DATA3)    ; aus SRAM laden  
14
  STS  (adr_RDS_GRUPPE_AH_ROH),temp   ; im SRAM ablegen  
15
  LDS  temp,(adr_RDS_DATA2)
16
  STS  (adr_RDS_GRUPPE_AL_ROH),temp
17
  ldi  temp1,1  ; RÜCKGABEWERT  
18
  ret
19
RDS_GRUPPENTYP_NO_A:
Vorteile:
-du sparst das kopieren der berechneten CRC
-der Programmteil wird bereits verlassen, wenn das erste Byte des CRC 
nicht stimmt
-du sparst Register temp3 und tmp4

von Detlef K. (adenin)


Lesenswert?

noch ein Tipp :)

alt:
1
RDS_SAMPLING:
2
  ; SAMPLING            
3
  sbic (DATA_PIN),(DATA_PIN_NR)  ; Sprung, wenn Bit clear
4
  rjmp RDS_SAMPLING_HIGH
5
RDS_SAMPLING_LOW:
6
  CLC ; clear CARRY  
7
  rjmp RDS_SAMPLING_W
8
RDS_SAMPLING_HIGH:
9
  SEC  ; set CARRY    
10
RDS_SAMPLING_W:

neu
1
RDS_SAMPLING:
2
  ; SAMPLING            
3
  CLC ; clear CARRY  
4
  sbic (DATA_PIN),(DATA_PIN_NR)  ; Sprung, wenn Bit clear
5
  SEC  ; set CARRY    
6
RDS_SAMPLING_W:

von Bernhard S. (bernhard)


Lesenswert?

@Detlef

> SUPER :)
> gleich mal eine Tip wie du den Code etwas schneller bekommst

Ich danke Dir :-)

Gruß


Bernhard

von Bernhard S. (bernhard)


Lesenswert?


von Mike (prophaganda)


Lesenswert?

Auch wenn der Beitrag schon sehr alt ist, möchte ich dazu mal als 
Neuling eine Frage setllen:
Geschrieben ist der Code für einen ATmega8.
Ließe sich der auch auf einen Arduino Nano (ATmega 328) verwenden?

So alt das Projekt auch ist, ist es für mich gerade aktuell...

Vielen Dank schon mal.

von Bernhard S. (bernhard)


Lesenswert?

Mike schrieb:
> Ließe sich der auch auf einen Arduino Nano (ATmega 328) verwenden?

Prinzipell ja, aber der ATmega hat einige Besonderheiten ;-)

von Mike (prophaganda)


Lesenswert?

Vielen Dank.
Nur zur Vorwarnung für mich (nicht dass ich hinterher geschockt umfalle 
;) ): Um welche Besonderheiten geht es?

Allgemein für den Hintergrund:
Es gibt unmassen Schaltpläne für RDS-Decoder - nur mit dem Nachteil, 
dass man da nen PIC programmieren muss - und mit dem Arduino wäre es 
sicher etwas einfacher (denke ich mal so leichtsinnigerweise).
Dann würde ich dann mir das Material (Arduino, TDA7330, Display) zulegen 
und das mal in Angriff nehmen.
Ich bin noch Fan von eher älteren Radios (vor Allem RFT / REMA).
Jedoch würde ich Denen gerne diese zusätzliche Anzeige spendieren.

: Bearbeitet durch User
von Christian S. (roehrenvorheizer)


Lesenswert?

Zur Portierung muß man die Registernamen und IRQnamen anpassen, sowie 
bei den Timern genau darauf achten, daß das gleiche passiert, wie im 
ursprünglich verwendeten µC. Hierzu ist ein genauerer Blick in beide 
Datenblätter zusammen mit etwas Erfahrung nötig. Oder man lernt dies bei 
dieser Gelegenheit.

mfg

von Mike (prophaganda)


Lesenswert?

OK, würde mich als Neuanfänger evtl. da doch etwas überfordern...
Evtl. blöde Frage:
Wenn ich jetzt ein UNO3-Bord nehme, den 328 gegen einen 8 ersetze 
(Pincompatibel sind sie ja) müsste das dann meines Erachtens 
funktionieren... oder liege ich da falsch?

Zum wirklichen Lernen würden dann (wenn ich hiermit erstmal ein für mich 
nützliches Startprojekt erfolgreich am Laufen habe) folgen... Idee'n 
gibt es genug ;)

Beitrag #7258325 wurde von einem Moderator gelöscht.
von Peter (Gast)


Lesenswert?

Hübsches Projekt, aber kann der Prozessor nicht den rds Rohdaten decoder 
gleich mit machen?

So hoch sind die Frequenzen doch nicht. Klar muss man das Signal vor den 
ganzen Filtern angreifen, aber da muss man den Rohdatendecoder auch hin 
setzen.

Wäre das noch möglich?

von Mike (prophaganda)


Lesenswert?

Die Filterung der Frequenzen und soweit ich mich da mal eingelesen habe 
da auch noch mit der Phasenlage im ATmel zu zaubern, dürfte wohl nicht 
möglich sein... und wenn, dann nur mit extrem hohem 
programmiertechnischem Aufwand, der in keinem Verhältnis steht.
Da ist es sinvoller eine Platine mit nem TDA7330: 
https://pdf1.alldatasheet.com/datasheet-pdf/view/25129/STMICROELECTRONICS/TDA7330.html
zu basteln, zumal die Ringsrumbeschaltung minimal ist.
Das lässt sich mühelos auf einer Lochrasterplatine "zusammenbraten" ;)

@Bernhard D.
Beim Datenblatt zum TDA7330 ist mir aufgefallen, dass der einen Ausgang 
(PIN 14) für Anzeige "RDS-Qualität" hat.
Dafür hast Du am ATmega die grüne LED "RDS-OK" eingebunden.
Wäre es dann bei Verwendung des TDA7330 sinnvoller, statt der LED am 
Atmega dann die LED am TDA zu betreiben?

von Bernd (Gast)


Lesenswert?

Mike schrieb:
> Geschrieben ist der Code für einen ATmega8.
> Ließe sich der auch auf einen Arduino Nano (ATmega 328) verwenden?
Vermutlich schon. Der ATmega328 müsste die 32k-Flash-Variante des 
ATmega8 sein.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bernd schrieb:
> Vermutlich schon. Der ATmega328 müsste die 32k-Flash-Variante des
> ATmega8 sein.

Der ATmega328 ist die 32K-Flash-Variante des ATmega88, nicht des uralten 
ATmega8.

von Peter (Gast)


Lesenswert?

Na wenn es nur an der Geschwindigkeit vom Prozessor liegt dann kann man 
ja auch auf einen ARM Prozessor ausweichen.
Ist dann halt 3v3 und nicht 5v.

von Mike (prophaganda)


Lesenswert?

@bernhard
Mal die Frage:
Welche Fuses hast Du eigentlich gesetzt?

von Mike (prophaganda)


Angehängte Dateien:

Lesenswert?

Sooo,
ich habe jetzt (auf einem Breadboard) soweit die reine Decoder-Schaltung 
(ohne Rohdatendecoder) aufgebaut.
Ich habe jedoch ein 20x4-Deisplay verwendet.
Die ensprechenden Zeilen habe ich in der RDSLCD_LCD_ini.asm 
auskommentiert und dafür die beiden zeilen für 16x4 kommentiert.
Ber irgendwie scheinen wohl trotzdem nicht alle 20Zeichen pro Zeile 
genutzt zu werden.
Aber das ist aktuell noch nicht wirklich das eigentliche Problem.

Das Zweite ist:
Auch wenn ich keine Daten (aufgrund fehlenden Rohdatendekoders empfange) 
müsste doch das Display auf die anderen Anzeigen umschalten, wenn ich 
den Menü-Taster betätige. Das passiert jedoch nicht...
Zum Anderen:
Wenn die Daten fehlen, müsste doch eigentlich die gelbe LED für 
"RDS-Error" leuchten... - Die bleibt jedoch dunkel.
Beim Starten des Dekoders läuft die "Test-Ampel" jedoch sauber durch.
Habe ich was übersehen und falsch verstanden?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.