; Programm Magnetic Card Reader
; CPU AT89C2051
; (c)1999 Bauer Karl
;
;Assembler; AS Vers. 1.41 von Alfred Arnold
;
; Passende Magnetkartenleser:
;  ddm hopt+schuler 
;  Handdurchzugsleser Best Nr. 832 0 1 xxx 0
;  1, 2, 3 Spur Leser sind verfügbar
;    Mehr Informationen siehe Datenblatt (im Archiv dabei)
;
;Baudrate PC <=> uC 57600 Baud, Protokoll XOn/XOff, 8N1
;
;
  CPU 8051
  INCLUDE stddef51.inc
;            standart include datei...
;
;************************
; Informationen
;************************
;
;
;********************************************************************
; Definitionen
;********************************************************************
  org 30h ;startadresse Code 30h

;Portdefinitionen
LED_ISO_Track_1 equ P3.2
LED_ISO_Track_2 equ P3.3
LED_ISO_Track_3 equ P3.4

ISO1_Data_Pin equ P1.2
ISO1_Clock_Pin equ P1.3

ISO2_Data_Pin equ P1.4
ISO2_Clock_Pin equ P1.5

ISO3_Data_Pin equ P1.6
ISO3_Clock_Pin equ P1.7

;Variablen zur Ablaufsteuerung


;Konstanten
InfoMsg: db "Magnetic Card Reader",10,13
         db "(c)1999 Bauer Karl",10,13
         db "e-mail: karbauer@bigfoot.de",10,13
         db "Version 1.0",10,13
         db 10,13,"Controlling the Reader Interface:",10,13
         db "---------------------------------",10,13
         db "PC => uC the Number 1 the Magnetic Card Reader Interface Switch to ISO Track 1",10,13
         db "PC => uC the Number 2 the Magnetic Card Reader Interface Switch to ISO Track 2",10,13
         db "PC => uC the Number 3 the Magnetic Card Reader Interface Switch to ISO Track 3",10,13
         db "Moving a Magnetic Card in the Reader the uC => PC the Bits of the Card (010100010101...)",10,13
         db 0
;
ReadyMsg: db "Magnetic Card Reader",10,13
          db ">>> More Information with ? <<<",10,13
          db 0
;********************************************************************
; Subroutinen start
;********************************************************************

; serielle Schnittstellen initialisieren
;Serial Port at 57600Baud => 11.0592Mhz Quartz
;Mode				= 1  /8-bit UART
;Serial Port Interrupt		= Enabled
;Receive			= Enabled
;Timer 1 is being used to generate baud rates.
init_serial: mov SCON, #050h
             ;Timer 1 is being used to generate baud rates.
             orl PCON, #80H ;<= wenn Aktiviert dann Baudrate = x2
             mov TMOD, #020h
             mov TH1, #0FFh
             setb TCON.6         ;TCON.6
             setb ES             ;IE.4
             clr RI              ;SCON.0
             ret


; SendData sendet ein Zeichen in A ueber die serielle Schnittstelle
; TI muss bei der Initialisierung GESETZT werden
; TI wird hardwaremaessig gesetzt, wenn ein Zeichen vollstaendig gesendet
; ist. TI muss vor dem Schreiben in SBUF geloescht werden.
senddata: push PSW                     ; Flags retten
          push IE
          clr IE.4                  ; serint abschalten
          mov SBUF, A                 ; Zeichen senden
 pb_wait: jnb TI, pb_wait             ; warten bis gesendet
          clr TI                      ; Sendeflag loeschen
          pop IE                    ; serint wiederherstellen
          pop PSW
          ret


; Send Message via Serial
; DPTR -> Message
SendMessage:
  CLR A
  MOVC A, @A+DPTR
  CJNE A, #00h, LoopM2
  RET
LoopM2:
  CALL SendData
  INC DPTR
  SJMP SendMessage
  ret

;		Very short delay
delay:		push	acc
		mov	a,r0
		push	acc
		mov	r0,#80
delay0:		mov	a,#127
delay1:		dec	a
		cjne	a,#0,delay1
		dec	r0
		cjne	r0,#0,delay0
		pop	acc
		mov	r0,a
		pop	acc
		ret


; ----------------------------------------
; Pause (0,25 s.)
; ----------------------------------------
ShortDelay:    
  MOV    R0, #0FFH
Loop0:    
  NOP
  MOV    R1, #0FFH
Loop1:    
  NOP
  DJNZ   R1, Loop1
  DJNZ   R0, Loop0
  RET


;Zeichenauswertung
ser_char_auswert:
          pc_val1: cjne A, #'1', pc_val2
                call sw_to_track_ISO1
               jmp ser_ausw_exit

          pc_val2: cjne A, #'2', pc_val3
                call sw_to_track_ISO2
              jmp ser_ausw_exit

          pc_val3: cjne A, #'3', pc_val4
                call sw_to_track_ISO3
              jmp ser_ausw_exit

          pc_val4: cjne A, #'?', pc_val5
               mov DPTR, #InfoMsg
               call SendMessage
              jmp ser_ausw_exit

          pc_val5:

        ser_ausw_exit: ret



;Routinen zum Umschalten der ISO Tracks die Gelesen werden Sollen

sw_to_track_ISO1: clr LED_ISO_Track_1
                  setb LED_ISO_Track_2
                  setb LED_ISO_Track_3
                 ret

sw_to_track_ISO2: setb LED_ISO_Track_1
                  clr LED_ISO_Track_2
                  setb LED_ISO_Track_3
                 ret

sw_to_track_ISO3: setb LED_ISO_Track_1
                  setb LED_ISO_Track_2
                  clr LED_ISO_Track_3
                 ret

LED_post_test: call sw_to_track_ISO1
               call ShortDelay
               call sw_to_track_ISO2
               call ShortDelay
               call sw_to_track_ISO3
               call ShortDelay
               call sw_to_track_ISO2
               call ShortDelay
               call sw_to_track_ISO1
               call ShortDelay
               call sw_to_track_ISO2
               call ShortDelay
               call sw_to_track_ISO3
              ret

read_magnetic_data: jnb LED_ISO_Track_1, read_ISO1_data
                    jnb LED_ISO_Track_2, read_ISO2_data
                    jnb LED_ISO_Track_3, read_ISO3_data
                   ret
               

read_ISO1_data: jb ISO1_Clock_Pin, read_ISO1_exit ; falls kein takt weiter mit der hauptschleife
                jnb ISO1_Data_Pin, ser_tx_ISO1_1
                 mov A, #'0' ;sendet eine 0 wenn die datenleitung high level hat 
                 call SendData
                 jnb ISO1_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
                 jmp read_ISO1_exit
     ser_tx_ISO1_1:
                 mov A, #'1' ;sendet eine 1 wenn die datenleitung low level hat 
                 call SendData
                 jnb ISO1_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
     read_ISO1_exit:
                jmp read_ser
               ret


read_ISO2_data: jb ISO2_Clock_Pin, read_ISO2_exit ; falls kein takt weiter mit der hauptschleife
                jnb ISO2_Data_Pin, ser_tx_ISO2_1
                 mov A, #'0' ;sendet eine 0 wenn die datenleitung high level hat 
                 call SendData
                 jnb ISO2_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
                 jmp read_ISO2_exit
     ser_tx_ISO2_1:
                 mov A, #'1' ;sendet eine 1 wenn die datenleitung low level hat 
                 call SendData
                 jnb ISO2_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
     read_ISO2_exit:
                jmp read_ser
               ret


read_ISO3_data: jb ISO3_Clock_Pin, read_ISO3_exit ; falls kein takt weiter mit der hauptschleife
                jnb ISO3_Data_Pin, ser_tx_ISO3_1
                 mov A, #'0' ;sendet eine 0 wenn die datenleitung high level hat 
                 call SendData
                 jnb ISO3_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
                 jmp read_ISO3_exit
     ser_tx_ISO3_1:
                 mov A, #'1' ;sendet eine 1 wenn die datenleitung low level hat 
                 call SendData
                 jnb ISO3_Clock_Pin, $ ;warten bis Clock pin wieder high level hat
     read_ISO3_exit:
                jmp read_ser
               ret


;********************************************************************
; Subroutinen ende
;********************************************************************


;********************************************************************
; Hauptprogramm start
;********************************************************************

on_reset: call init_serial      ;Initalisiere Serielle Schnittstelle
          mov DPTR, #ReadyMsg   ;Startmeldung
          call SendMessage      ;Sende Text
          call LED_post_test    ; LED Test und Schaltungtest
   main_loop: jmp read_magnetic_data ;Pruefen ob Date zum Einelesen und falls ja, Einlesen
   read_ser: jnb RI, main_loop         ; warte bis Zeichen da, wenn kein Zeiche jmp zu main_loop
             mov A, SBUF               ; Zeichen holen und in ACC Copy
             clr RI                    ; Int zuruecksetzen
             call ser_char_auswert
             jmp main_loop
          reti


;********************************************************************
; Hauptprogramm ende
;********************************************************************


;********************************************************************
; Interrupt einsprungadressen
;********************************************************************
   org 0000h           ; System reset      RST
    jmp on_reset            ;reset init

   org 0003H           ; external interrupt 0 vector
    reti

   org 0013H           ; external interrupt 1 vector
    reti

   org 000BH           ; timer 0 overflow vector
    reti                    ; undefined

   org 001BH          ; timer 1 overflow vector
    reti                    ; undefined

   org 0023H           ; serial I/O interrupt vector
    reti              ; Serial interrupt

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
end
;
; jetzt ende gesamter Qelltext !
;

