;***************************************************************** ;* Programme de d‚codage RDS pour carte mini-terminal * ;* * ;* * ;* - PI code (identificateur de la station) * ;* - PTY (Type de programme diffus‚) * ;* - M/S (Musique ou Speech ) * ;* - PSname (Nom de la station) * ;* - CT (l'heure de la station) * ;* TDA7330 : PE0=RDS CLOCK * ;* PE1=RDS Quality * ;* PE3=RDS DATA * ;* PE2=SW PUSHBUTTON1 with PULL-UP * ;* PE4=SW PUSHBUTTON2 with PULL-UP * ;* LCD : PB0-PB7 = DATA BUS * ;* PC3=E * ;* R/W=0 * ;* PC2=RS * ;* download: PD0/PD1: RS232 * ;*MB le 20-11-1999 * ;***************************************************************** ;***************************************************************** ;* D‚finition des adresses des registres * ;***************************************************************** DEB_PROG equ $F800 DEB_RAM equ $0000 DEB_REG equ $1000 PORTA equ DEB_REG DDRA equ DEB_REG+1 PORTE equ DEB_REG+$0A PORTC equ DEB_REG+3 PORTB equ DEB_REG+4 DDRC equ DEB_REG+7 INIT equ DEB_REG+$3D OPTION equ DEB_REG+$39 CSCTL equ DEB_REG+$5D ;***************************************************************** ;* D‚finition des variables * ;***************************************************************** org $0000 STOREG1 rmb 1 STOREG2 rmb 1 STOREG3 rmb 1 STOREG4 rmb 1 STOREG1X rmb 1 STOREG2X rmb 1 STOREG3X rmb 1 STOREG4X rmb 1 DATA1 rmb 1 DATA2 rmb 1 DATA3 rmb 1 DATA4 rmb 1 DATA5 rmb 1 DATA6 rmb 1 DATA7 rmb 1 DATA8 rmb 1 INTE rmb 1 SYNC_H rmb 1 SYNC_L rmb 1 STAT rmb 1 LCDINFO rmb 1 ;bits 0 … 3 : longueur du message … afficher (8max) ;bit 4: affichage sur 0->1Šre ligne 1->deuxiŠme ligne PI rmb 2 ; r‚serve 2 octets pour le PI code PIASCII rmb 4 ; r‚serve 4 octets pour l'affichage HEX->ASCII PSNAME rmb 8 ; r‚serve 8 octets pour le nom de la station LONGUEUR rmb 1 ; longueur du texte … afficher OFFSET rmb 1 ; d‚calage du curseur vers la droite BADQUALITY rmb 1 ; indicateur de mauvaise r‚ception FLAGNORDS rmb 1 ; message NO RDS d‚ja affich‚ ? (bit 0) CTBCD rmb 2 ; r‚serve 2 octets pour les heures/minutes hex CTASCII rmb 5 ; r‚serve 5 octets pour les heures/minutes en ASCII org $0F800 initlcd: fcb $38,$38,$38,$01,$02,$06,$0C,$10,$80 NOSIGNAL fcc " No RDS signal " TEXT1 fcc "RDS decoder for " TEXT2 fcc " mini-terminal " MST fcc "SM" PTYT fcc " No PTY " ;0 fcc " News " ;1 fcc "Affairs " ;2 fcc " Info " ;3 fcc " Sport " ;4 fcc "Educate " ;5 fcc " Drama " ;6 fcc "Culture " ;7 fcc "Science " ;8 fcc " Varied " ;9 fcc " Pop M " ;10 fcc " Rock M " ;11 fcc " Easy M " ;12 fcc "Light M " ;13 fcc "Classics" ;14 fcc "Other M " ;15 fcc "Weather " ;16 fcc "Finance " ;17 fcc "Children" ;18 fcc " Social " ;19 fcc "Religion" ;20 fcc "Phone In" ;21 fcc " Travel " ;22 fcc "Leisure " *23 fcc " Jazz " ;24 fcc "Country " ;25 fcc "Nation M" ;26 fcc " Oldies " ;27 fcc " Folk M " ;28 fcc "Document" ;29 fcc " TEST " ;30 fcc " Alarm !" ;31 ; ; ;***************************************************************** ;** Programme Principal ** ;***************************************************************** reset lds #$0FF ; Initialisation de la pile ldaa #$00 ; Initialisation du PORTA staa DDRA ; PA5=RDS CLOCK, PA7=RDS Quality, PA3=RDS DATA ldaa #$0ff ; Initialisation du PORTC (commandes/RS232) staa DDRC jsr INITAFF ; initialisation de l'affichage ldx #TEXT1 ldaa #$0F staa LCDINFO ldaa #$0 staa OFFSET jsr AFFICHAGE ldx #TEXT2 ldaa #$1F staa LCDINFO ldaa #$0 staa OFFSET jsr AFFICHAGE ldx #$0C8 BACKX jsr TEMPOX dex bne BACKX ldaa #%00000001 ; efface afficheur (DD-RAM) jsr VALC clr STAT ; initalisations diverses clr PI clr PI+1 clr BADQUALITY clr FLAGNORDS ldaa #$3A ; place les : ($3a) entre les heures et les minutes ldx #CTASCII staa 2,X BLOCK1 ldaa PORTE ; test de la qualit‚ du signal anda #$02 tsta bne SUIT ldaa BADQUALITY cmpa #10 ; niveau max de m‚diocrit‚ beq TEST inc BADQUALITY TEST cmpa #5 ; niveau de tol‚rance mauvais signal bne RDSSYNC jsr NORDS bra BLOCK1 SUIT ldaa BADQUALITY tsta ; niveau le meilleur=0 beq RDSSYNC dec BADQUALITY RDSSYNC jsr IGNORE3 ldaa SYNC_H ; V‚rification du syndrome A(partie haute) cmpa #$D8 ; qui doit ˆtre ‚gale … $D8 bne BLOCK1 ldaa SYNC_L ; V‚rification du syndrome A(partie basse) cmpa #$03 ; qui doit ˆtre egale … $03 bne BLOCK1 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ldaa STOREG2 ; Si le syndrome est correct staa DATA1 ; alors on sauvegarde les donn‚es ldaa STOREG3 ; re‡ues. staa DATA2 BLOCK2 jsr IGNORE2 jsr IGNORE3 ldaa SYNC_H ; V‚rification du syndrome B(partie haute) cmpa #$D4 ; qui doit ˆtre ‚gale … $D4 bne BLOCK1 ldaa SYNC_L ; V‚rification du syndrome B(partie basse) cmpa #$03 ; qui doit ˆtre ‚gale … $03 bne BLOCK1 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ldaa STOREG2 ; Si le syndrome est correct staa DATA3 ; alors on sauvegarde les donn‚es ldaa STOREG3 ; re‡ues staa DATA4 BLOCK3 jsr IGNORE2 jsr IGNORE3 ldaa SYNC_H ; V‚rification du syndrome C(partie haute) cmpa #$5C ; qui doit ˆtre ‚gale … $5C beq BLK3H ; Sinon cmpa #$CC ; V‚rification du syndrome C'(partie haute) beq BLK3H ; qui doit ˆtre ‚gale … $CC jmp BLOCK1 BLK3H ldaa SYNC_L ; Si le syndrome C ou C' est correct alors cmpa #$03 ; V‚rification du syndrome C(partie basse) beq BLK3L ; qui doit ˆtre ‚gale … $02 ou $03 cmpa #$02 beq BLK3L jmp BLOCK1 BLK3L ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ldaa STOREG2 ; Si le syndrome est correct staa DATA5 ; alors on sauvegarde les donn‚es ldaa STOREG3 ; re‡ues staa DATA6 BLOCK4 jsr IGNORE2 jsr IGNORE3 ldaa SYNC_H ; V‚rification du syndrome D(partie haute) cmpa #$58 ; qui doit ˆtre ‚gale … $58 beq BLK4H jmp BLOCK1 BLK4H ldaa SYNC_L ; V‚rification du syndrome D(partie basse) cmpa #$02 ; qui doit ˆtre ‚gale … $02 beq BLK4L jmp BLOCK1 BLK4L ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ror STOREG1 ror STOREG2 ror STOREG3 ror STOREG4 ldaa STOREG2 ; Si le syndrome est correct staa DATA7 ; on sauvegarde les donn‚es ldaa STOREG3 ; re‡ues staa DATA8 ;****************************************************************************** ;* synchronisation complete : les infos de la trame sont dans DATA1/DATA2 * ;* DATA3/DATA4, DATA5/DATA6 et DATA7/DATA8 * ;****************************************************************************** ;* interpretation et decodage des donn‚es RDS : PI code, Nom de la station... * ;****************************************************************************** ;* affichage du PI/PTY/MS code si diff‚rent de celui affich‚ (cas d'une nouvelle station) * ldx DATA1 cpx PI beq PSNAM ldaa #%00000001 ; efface afficheur (DD-RAM) jsr VALC clra staa FLAGNORDS ; affichage de NORDS possible clr STAT stx PI ldx #DATA1 ; adresse de la donn‚e … afficher jsr HEXASCII ldx #PIASCII ldaa #%00000100 ; 4 caractŠres … afficher sur la premiŠre ligne … droite staa LCDINFO ldaa #12 ; OFFSET=12 caractŠres (affichage en haut … droite) staa OFFSET jsr AFFICHAGE ;* affichage du type de programme PTY * PTY ldaa DATA3 anda #$03 ldab DATA4 andb #$E0 lsrd lsrd ; mul D x 4 addd #PTYT xgdx ; adresse de la donn‚e … afficher charg‚e dans X ldaa #%00010111 ; 8 caractŠres … afficher sur la deuxiŠme ligne … gche staa LCDINFO ldaa #0 ; OFFSET=0 caractŠre (affichage en bas … gauche) staa OFFSET jsr AFFICHAGE ;* affichage Music/Speech * MUSICSPEECH ldx #DATA3 brclr 0,X $F0 MSDISP ; V‚rification du groupe (0A) jmp PSNAM ; ce n'est pas un groupe 0A/0B MSDISP ldx #MST ldaa DATA4 anda #$08 tsta beq SPEECH inx SPEECH ldaa #%00000001 ; 1 caractŠre … afficher sur la premiŠre ligne staa LCDINFO ldaa #10 ; OFFSET=10 caractŠres (affichage au milieu) staa OFFSET jsr AFFICHAGE ;* affichage du nom de la station si diff‚rent de celui affich‚ * PSNAM ldx #DATA3 brclr 0,X $F0 NOMSTATION ; V‚rification du groupe (0A) jmp CLOCKTIME ; ce n'est pas un groupe 0A/0B NOMSTATION ;* les groupes 0A/0B contiennent le nom de la station ldab STAT ; le nom de la station est-il d‚ja affich‚ ? cmpa #$0F beq CLOCKTIME ; Oui ldy #STAT ldab DATA4 andb #3 cmpb #0 bne CHAR2 bset 0,Y $1 CHAR2 cmpb #1 ; on positionne les indicateurs de paire de caratŠres bne CHAR3 ; recues. bset 0,Y $2 CHAR3 cmpb #2 bne CHAR4 bset 0,Y $4 CHAR4 cmpb #3 bne CHAR5 bset 0,Y $8 CHAR5 lslb ; multiplie B par 2 clra addd #PSNAME xgdx ldab DATA7 stab 0,X ldab DATA8 inx stab 0,X ldaa STAT ; le nom de la station est-il re‡u completement ? cmpa #$0F beq AFFNOM jmp CLOCKTIME AFFNOM ldx #PSNAME ldaa #%00001000 staa LCDINFO ldaa #1 ; OFFSET=1 caractŠre staa OFFSET jsr AFFICHAGE ; On affiche alors les caracteres jmp CLOCKTIME ;* affichage Heure toutes les minutes * CLOCKTIME ldx #DATA3 ldaa 0,X anda #$F8 cmpa #$40 beq CTCALCUL ; Verification du groupe (4A) jmp RT ; ce n'est pas un groupe 4A CTCALCUL * les heures * ldx #DATA6 ; recuperation de l'heure universelle ldaa 0,X ldx #DATA7 ldab 0,X anda #$01 andb #$F0 lsrd lsrb lsrb lsrb stab CTBCD ldx #DATA8 ; recuperation de l'offset local ldaa 0,X ; exprime en demi-heures ! (+4 en France) anda #$1F lsra ; on divise par 2 pour avoir l'offset en heure brclr 0,X $20 WEST ldab CTBCD staa CTBCD subb CTBCD ; negative offset (West of zero degree longitude) tba bra STORE WEST adda CTBCD ; positive offset (East of zero degree longitude) STORE staa CTBCD * les minutes * ldx #DATA7 ldaa 0,X ldx #DATA8 ldab 0,X anda #$0F andb #$C0 lsld lsld staa CTBCD+1 ldy #CTBCD ; adresse de la donn‚e … afficher jsr BCDASCII ldx #CTASCII ldaa #%00010101 ; 5 caractŠres … afficher sur la deuxiŠme ligne … droite staa LCDINFO ldaa #10 ; OFFSET=10 caractŠres (affichage en bas … droite) staa OFFSET jsr AFFICHAGE ;* affichage du Radio Texte * RT jmp BLOCK1 ;On retourne au d‚but ;***************************************************************** ;* Sous-programmes * ;***************************************************************** TEMPOX pshy ldy #$06DA TEMPOX1 dey bne TEMPOX1 puly rts wait: ldy #$1800 wait1: dey bne wait1 rts INITAFF ldx #initlcd again: ldaa $00,X jsr VALC ; send the init table in the LCD jsr wait ; CONTROL register inx cpx #NOSIGNAL bne again rts ;INITAFF ldaa #%00111000 ; valide bus 8bits +double ligne ; jsr VALC ; ldaa #$01 ; efface l'afficheur ; jsr VALC ; ldaa #%00001100 ; allume l'ecran, curseur non visible ; jsr VALC ; ldaa #%00000110 ; decallage … droite du curseur ; jsr VALC ; ldaa #%00000001 ; efface afficheur (DD-RAM) ; jsr VALC ; rts AFFICHAGE psha pshb pshx pshy ldy #LCDINFO ldab 0,Y ; charge la longueur du message andb #$0F addb #1 stab LONGUEUR brset 0,Y $10 SUITE1 ; sur quelle ligne on affiche ? ; affichage sur la premiere ligne ldaa #%10000000 ; curseur … gauche, 1Šre ligne jsr VALC GORIGHT ldaa OFFSET beq AFF1 ldaa #%00010100 ; deplacement du curseur vers la droite jsr VALC dec OFFSET bne GORIGHT AFF1 ldaa 0,X ; contenu de l'adresse pointee par X dec LONGUEUR ; dans A beq FIN2 ; si LONGUEUR=0, fin du message jsr VALD inx bra AFF1 bra FIN2 * affichage sur la deuxiŠme ligne SUITE1 ldaa #%11000000 ; curseur … gauche, 2iŠme ligne jsr VALC GORIGHT2 ldaa OFFSET beq AFF1 ldaa #%00010100 ; d‚placement du curseur vers la droite jsr VALC dec OFFSET bne GORIGHT2 AFF2 ldaa 0,X ; idem avant dec LONGUEUR beq FIN2 ; si LONGUEUR=0, fin du message jsr VALD inx bra AFF2 FIN2 puly pulx pulb pula rts BCDASCII ; conversion 2 octets en BCD -> 4 caractŠres ASCII pour l'heure et minutes (… am‚liorer!) ldaa 0,Y ; contenu de l'adresse point‚e par X ds A (heure) tab clra ldx #10 idiv xgdx addb #$30 stab CTASCII xgdx addb #$30 stab CTASCII+1 ldaa 1,Y ; contenu de l'adresse point‚e par X ds A (minutes) tab clra ldx #10 idiv xgdx addb #$30 stab CTASCII+3 xgdx addb #$30 stab CTASCII+4 rts HEXASCII ; affichage 1 octet en HEX -> 2 caractŠres ASCII pour le PI code (… am‚liorer!) ldaa 0,X anda #$F0 lsra lsra lsra lsra cmpa #$0A blo ADD30 adda #$07 ADD30 adda #$30 staa PIASCII ldaa 0,X anda #$0F cmpa #$0A blo ADD301 adda #$07 ADD301 adda #$30 staa PIASCII+1 ldaa 1,X anda #$F0 clc lsra lsra lsra lsra cmpa #$0A blo ADD302 adda #$07 ADD302 adda #$30 staa PIASCII+2 ldaa 1,X anda #$0F cmpa #$0A blo ADD303 adda #$07 ADD303 adda #$30 staa PIASCII+3 rts VALC staa PORTB ; Validation des commandes ldaa #%00000000 ; E=0 RS=0 staa PORTC ldaa #%00001000 ; E=1 RS=0 staa PORTC ldaa #%00000000 ; E=0 RS=0 staa PORTC jsr TEMPO45 rts TEMPO120 pshx * tempo de 120æs n‚cessaire pour afficher les caract‚res ldx #33 TP120 dex bne TP120 pulx rts VALD staa PORTB ; Validation des donnees ldaa #%00000100 ; E=0 RS=1 staa PORTC ldaa #%00001100 ; E=1 RS=1 staa PORTC ldaa #%00000100 ; E=0 RS=1 staa PORTC jsr TEMPO120 rts TEMPO45 ; tempo de 4.5ms n‚cessaire pour envoyer les commandes pshx ldx #450/12 TP45 jsr TEMPO120 dex bne TP45 pulx rts TEMPO5 ; tempo de 5us qui sert … rien d'ailleur pshx ldx #1 TP5 dex bne TP5 pulx rts NORDS psha pshb ldaa FLAGNORDS ; le message est-il d‚j… affich‚ ? cmpa #1 beq PASS ldaa #%00000001 ; efface afficheur (DD-RAM) jsr VALC clr PI ldx #NOSIGNAL ldaa #%00001111 ; 16 caractŠres … afficher sur la premiŠre ligne … droite staa LCDINFO ldaa #1 ; OFFSET=1 caractŠre staa OFFSET jsr AFFICHAGE ldaa #01 staa FLAGNORDS ; on signale que l'on a affich‚ le message. PASS pulb pula rts ;***************************************************************** ;* routines de synchronisation RDS * ;***************************************************************** SYNCHRO ldx #PORTE brset 0,X $01 SYNCHRO BCL1 brclr 0,X $01 BCL1 ; On teste le bit 5 du port A (RDS CLOCK) rts IGNORE2 psha ; acquisition de 25 bits ldaa #25 BCLE jsr SYNCHRO ; synchronisation avec l'horloge jsr SHUFFLE deca tsta ; decremente le compteur bne BCLE pula rts IGNORE3 jsr SYNCHRO ; synchro avec l'horloge jsr SHUFFLE ; acquisition d'1bit et stockage dans STOREG4…1 jsr SYNDROME ; calcul du syndrome rts SHUFFLE clc ; on initialise le bit de retenue CARRY (C=0) psha ldaa #%00001000 anda PORTE ; on teste PA3 (=RDS Data) tsta bne SUIT2 bra SUITE3 SUIT2 sec ; si PA3=1 alors on met C=1 sinon C=0 SUITE3 rol STOREG4 ; on effectue 4 rotations succesives rol STOREG3 ; mettant la valeur de la retenue dans le premier rol STOREG2 ; bit D0 de STOREG4 et tout les autres bits etant rol STOREG1 ; d‚cal‚s vers la gauche. pula rts SYNDROME ;* routine de calcul du syndrome (provient de la note d'application MOTOROLA an495.pdf p15-16) psha pshb pshx TRY1 clr SYNC_H clr SYNC_L ; SYNC_H=SYNC_L=0 ldab STOREG4 ; on sauvegarde dans des registres temporaires stab STOREG4X ; les valeurs des registres STOREG4…1 dans ldab STOREG3 ; les registres STOREGX4…1 stab STOREG3X ldab STOREG2 stab STOREG2X ldab STOREG1 stab STOREG1X TRY2 ldaa STOREG2X ; LSB ldab STOREG1X ; MSB (2 bits) andb #3 ldx #DEB_RAM S03 brclr 7,X $01 S13 ; syndrome avec les 8 bits de storeg4x eora #$1B ; et donn‚es = 8bits de storeg2x eorb #$03 ; et 2 bits poids faible storeg1x S13 brclr 7,X $02 S23 eora #$8F eorb #$03 S23 brclr 7,X $04 S33 eora #$A7 eorb #$02 S33 brclr 7,X $08 S43 eora #$F7 S43 brclr 7,X $10 S53 eora #$EE eorb #$01 S53 brclr 7,X $20 S63 eora #$DC eorb #$03 S63 brclr 7,X $40 S73 eora #$01 eorb #$02 S73 brclr 7,X $80 S02 eora #$BB eorb #$01 S02 brclr 6,X $01 S12 ; syndrome avec les 8 bits de storeg3x eora #$76 eorb #$03 S12 brclr 6,X $02 S22 eora #$55 eorb #$03 S22 brclr 6,X $04 S32 eora #$13 eorb #$03 S32 brclr 6,X $08 S42 eora #$9F eorb #$03 S42 brclr 6,X $10 S52 eora #$87 eorb #$02 S52 brclr 6,X $20 S62 eora #$B7 S62 brclr 6,X $40 S72 eora #$6E eorb #$01 S72 brclr 6,X $80 FIN eora #$DC eorb #$02 FIN stab SYNC_L staa SYNC_H pulx pulb pula rts noirq rti org $FFD6 fdb noirq ;SCI fdb noirq ;SPI fdb noirq ;Pulse A IN fdb noirq ;Pulse A Overflow fdb noirq ;Timer Overflow fdb noirq ;Timer IC4/OC5 fdb noirq ;Timer OC4 fdb noirq ;Timer OC3 fdb noirq ;Timer OC2 fdb noirq ;Timer OC1 fdb noirq ;Timer IC3 fdb noirq ;Timer IC2 fdb noirq ;Timer IC1 fdb noirq ;Real-time Int fdb noirq ;IRQ Pin/handshake fdb noirq ;XIRQ Pin fdb noirq ;SWI fdb reset ;Illegal Opcode fdb reset ;COP Failure RST fdb reset ;CLOCK Fail RST fdb reset ;RESET