; Aufgabe Nr.: Speichermodul fuer uP- Praktikum II ; Autor: Joerg Vollandt ; erstellt am : 21.05.1994 ; letzte Aenderung am : 02.08.1994 ; Bemerkung : Routinen fuer die Speicherverwaltung ; ; Dateiname : mem1.asm ; ;===================================================================== ; Definitionen der Funktionen des Seichermoduls ;INIT_MEM Initialisieren des Speichermoduls ;DEINIT_MEM Deinitialisieren des Speichermoduls ;CLEAR_MEM Speicher loeschen ;RESET_MEM Speicher zum lesen zuruecksetzen ;PUT_ELEMENT_MEM Element anf naechste freie Position schreiben ;GET_ELEMENT_MEM Element von akt. Position lesen ;WR_MEM_PC Speicher auf dem PC speichern. ;RD_MEM_PC Speicher vom PC laden. ;------------------------------------------------------------------------------ ;Messagedefinitionen ;1.Dateityp (Bit 0 und Bit 1) Msg_PC_To_Net equ 00b ;direkte Eingabe von Hex-Messages fr das Netz Msg_Frs_Datei equ 01b ;Frstischdatei Msg_Rob_Teach_Datei equ 10b ;Roboter-Teach-In-Datei Msg_Frs_Teach_Datei equ 11b ;Frstisch-Teach-In-Datei ;2.Aktion (Bit 2 und Bit 3) Msg_PC_Get equ 0000b ;Rekordanfrage an PC Msg_PC_Put equ 0100b ;Rekordspeichern Slave=>PC, Rekordausgabe PC=>Slave Msg_PC_Reset equ 1000b ;PC Datei ffnen zum Lesen Msg_PC_Rewrite equ 1100b ;PC Datei ffnen zum Schreiben ;3.Slaveadresse Slave=>PC ; Msg_From_PC PC=>Slave Msg_From_PC equ 00000000b ;Antwort auf Anfrage EOF_Record equ 0ffffh ; PC_Slave_Adr equ 0eh ; ;------------------------------------------------------------------------------ ; Speicherdefinitionen SEGMENT DATA CHECKSUMME DW ? SEGMENT XDATA POINTER DW ? ; fuer Test NEXT_FREE DW ? RD_POINTER DW ? BLOCKNR DW ? MEM_ANF DB 1000 DUP (?) ; Speichergroesse in Bytes MEM_ENDE ;--------------------------------------------------------------------- SEGMENT CODE ;--------------------------------------------------------------------- ; Funktion : Initialisieren des Speichermoduls ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; INIT_MEM: PUSH PSW PUSH_DPTR MOV DPTR,#MEM_ANF SET_16 NEXT_FREE SET_16 RD_POINTER MOV CHECKSUMME,#0 MOV CHECKSUMME+1,#0 CLR READY CLR CRC POP_DPTR POP PSW RET ;--------------------------------------------------------------------- ; Funktion : Deinitialisieren des Speichermoduls ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; DEINIT_MEM: RET ;--------------------------------------------------------------------- ; Funktion : Speicher loeschen ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; CLEAR_MEM: PUSH PSW PUSH_DPTR MOV DPTR,#MEM_ANF SET_16 NEXT_FREE SET_16 RD_POINTER MOV CHECKSUMME,#0 MOV CHECKSUMME+1,#0 CLR READY CLR CRC POP_DPTR POP PSW RET ;--------------------------------------------------------------------- ; Funktion : Speicher zum lesen zuruecksetzen ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; RESET_MEM: PUSH_DPTR MOV DPTR,#MEM_ANF SET_16 RD_POINTER POP_DPTR RET ;--------------------------------------------------------------------- ; Funktion : Speicher von MEM_ANF bis NEXT_FREE auf dem PC speichern. ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; WR_MEM_PC: PUSH_ALL ; MOV A,#MSG_PC_REWRITE+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_REWRITE MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; Datei oeffnen MOV B,#8 SEND_NET ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; Header zusammenstellen MOV B,#8 MOV DPTR,#0 SET_16 BLOCKNR ; Blocknr.=0 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH GET_16 NEXT_FREE SUBB_DPTR MEM_ANF MOV R3,DPL ; Anzahl Bytes MOV R4,DPH LCALL CHECK_SUM MOV R5,CHECKSUMME ; Pruefsumme MOV R6,CHECKSUMME+1 SEND_NET ; Header senden MOV DPTR,#MEM_ANF SET_16 POINTER ; Zeiger auf MEM_ANF setzen WR_MEM_MSG: LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JNC WR_MEM_MSG1 LJMP WR_MEM_CLOSE ; keine Bytes mehr -> close datei WR_MEM_MSG1: LCALL ACC_RD_MEM ; Byte aus MEM lesen MOV R3,A ; Message aufbauen LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JNC WR_MEM_MSG2 LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben WR_MEM_MSG2: LCALL ACC_RD_MEM ; Byte aus MEM lesen MOV R4,A ; Message aufbauen LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JNC WR_MEM_MSG3 LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben WR_MEM_MSG3: LCALL ACC_RD_MEM ; Byte aus MEM lesen MOV R5,A ; Message aufbauen LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JNC WR_MEM_MSG4 LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben WR_MEM_MSG4: LCALL ACC_RD_MEM ; Byte aus MEM lesen MOV R6,A ; Message aufbauen LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JNC WR_MEM_MSG5 LJMP WR_MEM_REST ; keine Bytes mehr -> Rest schreiben WR_MEM_MSG5: LCALL ACC_RD_MEM ; Byte aus MEM lesen MOV R7,A ; Message aufbauen PUSH_DPTR GET_16 BLOCKNR INC DPTR SET_16 BLOCKNR ; Blocknr.=+1 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH POP_DPTR ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr MOV B,#8 SEND_NET ; Message senden LJMP WR_MEM_MSG ; naechste Message WR_MEM_REST: PUSH_DPTR ; nicht volle MSG schreiben GET_16 BLOCKNR INC DPTR SET_16 BLOCKNR ; Blocknr.=+1 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH POP_DPTR ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr MOV B,#8 SEND_NET ; Message senden WR_MEM_CLOSE: ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; Datei schlieen MOV B,#8 MOV R1,#(EOF_RECORD#256) MOV R2,#(EOF_RECORD/256) SEND_NET POP_ALL RET ;--------------------------------------------------------------------- ; Funktion : Speicher vom PC laden. ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; RD_MEM_PC: PUSH_ALL ; MOV A,#MSG_PC_RESET+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_RESET MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; Datei oeffnen MOV B,#8 SEND_NET ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_GET MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; Header laden MOV B,#8 MOV DPTR,#0 SET_16 BLOCKNR ; Blocknr.=0 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH SEND_NET ; Header anfordern POP_ALL RET GET_FROM_PC: PUSH_ALL CJNE R1,#0,GET_NO_HEADER1 ; wenn Blocknr.=0, dann CJNE R2,#0,GET_NO_HEADER1 ; Header LJMP GET_HEADER GET_NO_HEADER1: LJMP GET_NO_HEADER GET_HEADER: CJNE R3,#0,GET_NOT_EMPTY_JMP ; testen ob 0 Bytes in Datei CJNE R4,#0,GET_NOT_EMPTY_JMP LJMP GET_EMPTY GET_NOT_EMPTY_JMP: LJMP GET_NOT_EMPTY GET_EMPTY: ; Datei leer LCALL INIT_MEM ; Speicherreset ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; und Datei schlieen MOV B,#8 MOV R1,#(EOF_RECORD#256) MOV R2,#(EOF_RECORD/256) SEND_NET POP_ALL SETB READY LCD 40H,"Teachin- Datei leer. " RET GET_NOT_EMPTY: ; Datei nicht leer MOV DPL,R3 ; Groesse nach DPTR MOV DPH,R4 ADD_DPTR MEM_ANF SET_16 NEXT_FREE ; neues Speicherende setzen MOV CHECKSUMME,R5 ; neue Checksumme laden MOV CHECKSUMME+1,R6 PUSH_DPTR GET_16 BLOCKNR INC DPTR SET_16 BLOCKNR ; Blocknr.=+1 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH POP_DPTR ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_GET MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr MOV B,#8 SEND_NET ; 1. Block anfordern MOV DPTR,#MEM_ANF SET_16 POINTER ; Zeiger auf MEM_ANF setzen POP_ALL RET GET_NO_HEADER: GET_16 POINTER ; Schreibzeiger laden MOV A,R3 LCALL ACC_WR_MEM ; in den Speicher schreiben LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei JNC GET_MORE2 LJMP GET_CLOSE ; wenn nicht Datei schliessen GET_MORE2: MOV A,R4 LCALL ACC_WR_MEM ; in den Speicher schreiben LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei JNC GET_MORE3 LJMP GET_CLOSE ; wenn nicht Datei schliessen GET_MORE3: MOV A,R5 LCALL ACC_WR_MEM ; in den Speicher schreiben LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei JNC GET_MORE4 LJMP GET_CLOSE ; wenn nicht Datei schliessen GET_MORE4: MOV A,R6 LCALL ACC_WR_MEM ; in den Speicher schreiben LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei JNC GET_MORE5 LJMP GET_CLOSE ; wenn nicht Datei schliessen GET_MORE5: MOV A,R7 LCALL ACC_WR_MEM ; in den Speicher schreiben LCALL CHECK_RD_POINTER ; pruefen ob noch Bytes in der Datei JNC GET_MORE6 LJMP GET_CLOSE ; wenn nicht Datei schliessen GET_MORE6: SET_16 POINTER GET_16 BLOCKNR INC DPTR SET_16 BLOCKNR ; Blocknr.=+1 setzen MOV R1,DPL ; Blocknr. MOV R2,DPH ; MOV A,#MSG_PC_GET+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_GET MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr MOV B,#8 SEND_NET ; naechsten Block anfordern POP_ALL RET GET_CLOSE: ; MOV A,#MSG_PC_PUT+MY_SLAVE_ADR1*16 MOV A,MY_SLAVE_ADR SWAP A ; *16 ADD A,#MSG_PC_PUT MOVB ACC.0,P3.5 ; Datei fuer Roboter oder Fraese SETB ACC.1 MOV R0,A MOV A,#PC_Slave_Adr ; und Datei schlieen MOV B,#8 MOV R1,#(EOF_RECORD#256) MOV R2,#(EOF_RECORD/256) SEND_NET MOV R0,CHECKSUMME MOV A,CHECKSUMME+1 LCALL CHECK_SUM CJNE A,CHECKSUMME+1,GET_CRC_ERROR MOV A,R0 CJNE A,CHECKSUMME,GET_CRC_ERROR POP_ALL CLR CRC SETB READY LCD 40H,"Teachin- Datei fehlerfrei geladen. " RET GET_CRC_ERROR: POP_ALL SETB CRC SETB READY LCD 40H,"FEHLER bei Laden der Teachin- Datei. " RET ;--------------------------------------------------------------------- ; Funktion : Testen ob DPTR zum LESEN auf belegten Speicher zeigt. ; C=0 ==> MEM_ANF <= DPTR < NEXT_FREE ; C=1 ==> sonst ; Aufrufparameter : DPTR = Pointer ; Ruechgabeparameter : - ; Veraenderte Register : PSW ; Stackbedarf : ; Zeitbedarf : ; CHECK_RD_POINTER: PUSH PSW PUSH ACC MOV A,#((MEM_ANF-1)/256) CJNE A,DPH,CH_RD1 ; Test ob Pointer >= MEM_ANF CH_RD1: JC CH_RD_OK1 CJNE A,DPH,CH_RD_ERROR ; MOV A,#((MEM_ANF-1)#256) CJNE A,DPL,CH_RD2 CH_RD2: JC CH_RD_OK1 LJMP CH_RD_ERROR ; CH_RD_OK1: PUSH_DPTR MOV DPTR,#(NEXT_FREE+1) MOVX A,@DPTR POP_DPTR CJNE A,DPH,CH_RD3 ; Test ob Pointer < NEXT_FREE CH_RD3: JC CH_RD_ERROR CJNE A,DPH,CH_RD_OK2 ; PUSH_DPTR MOV DPTR,#NEXT_FREE MOVX A,@DPTR POP_DPTR CJNE A,DPL,CH_RD4 CH_RD4: JC CH_RD_ERROR CJNE A,DPL,CH_RD_OK2 LJMP CH_RD_ERROR ; CH_RD_OK2: POP ACC POP PSW CLR C ; o.k. RET CH_RD_ERROR: POP ACC POP PSW SETB C ; Fehler RET ;--------------------------------------------------------------------- ; Funktion : Testen ob DPTR zum SCHREIBEN auf belegten Speicher zeigt. ; C=0 ==> MEM_ANF <= DPTR <= NEXT_FREE ; C=1 ==> sonst ; Aufrufparameter : DPTR = Pointer ; Ruechgabeparameter : - ; Veraenderte Register : PSW ; Stackbedarf : ; Zeitbedarf : ; CHECK_WR_POINTER: PUSH PSW PUSH ACC MOV A,#((MEM_ANF-1)/256) CJNE A,DPH,CH_WR1 ; Test ob Pointer >= MEM_ANF CH_WR1: JC CH_WR_OK1 CJNE A,DPH,CH_WR_ERROR ; MOV A,#((MEM_ANF-1)#256) CJNE A,DPL,CH_WR2 CH_WR2: JC CH_WR_OK1 LJMP CH_WR_ERROR ; CH_WR_OK1: PUSH_DPTR MOV DPTR,#(NEXT_FREE+1) MOVX A,@DPTR POP_DPTR CJNE A,DPH,CH_WR3 ; Test ob Pointer <= NEXT_FREE CH_WR3: JC CH_WR_ERROR CJNE A,DPH,CH_WR_OK2 ; PUSH_DPTR MOV DPTR,#NEXT_FREE MOVX A,@DPTR POP_DPTR CJNE A,DPL,CH_WR4 CH_WR4: JNC CH_WR_OK2 LJMP CH_WR_ERROR ; CH_WR_OK2: POP ACC POP PSW CLR C ; o.k. RET CH_WR_ERROR: POP ACC POP PSW SETB C ; Fehler RET ;--------------------------------------------------------------------- ; Funktion : Testen ob DPTR < MEM_ENDE. ; C=0 ==> DPTR < MEM_ENDE ; C=1 ==> sonst ; Aufrufparameter : DPTR = Pointer ; Ruechgabeparameter : - ; Veraenderte Register : PSW ; Stackbedarf : ; Zeitbedarf : ; CHECK_EOM_POINTER: PUSH PSW PUSH ACC MOV A,#(MEM_ENDE/256) CJNE A,DPH,CH_EOM3 ; Test ob Pointer < MEM_ENDE CH_EOM3: JC CH_EOM_ERROR CJNE A,DPH,CH_EOM_OK2 ; MOV A,#(MEM_ENDE#256) CJNE A,DPL,CH_EOM4 CH_EOM4: JC CH_EOM_ERROR CJNE A,DPL,CH_EOM_OK2 LJMP CH_EOM_ERROR ; CH_EOM_OK2: POP ACC POP PSW CLR C ; o.k. RET CH_EOM_ERROR: POP ACC POP PSW SETB C ; Fehler RET ;--------------------------------------------------------------------- ; Funktion : ACC in den Speicher schreiben, DPTR increminieren. ; Aufrufparameter : ACC = Wert, DPTR = Pointer ; Ruechgabeparameter : - ; Veraenderte Register : DPTR ; Stackbedarf : ; Zeitbedarf : ; ACC_WR_MEM: MOVX @DPTR,A INC DPTR RET ;--------------------------------------------------------------------- ; Funktion : ACC aus dem Speicher lesen, DPTR increminieren. ; Aufrufparameter : DPTR = Pointer ; Ruechgabeparameter : ACC = Wert ; Veraenderte Register : ACC, DPTR ; Stackbedarf : ; Zeitbedarf : ; ACC_RD_MEM: MOVX A,@DPTR INC DPTR RET ;--------------------------------------------------------------------- ; Funktion : Pruefsumme ueber den Speicher bilden. ; Aufrufparameter : - ; Ruechgabeparameter : - ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; CHECK_SUM: PUSH PSW PUSH ACC PUSH_DPTR MOV CHECKSUMME,#0 MOV CHECKSUMME+1,#0 MOV DPTR,#MEM_ANF ; Pointer auf MEM_ANF setzen CHECK_SUM1: LCALL CHECK_RD_POINTER ; Pointer in DPTR!!! JC CHECK_SUM_ENDE LCALL ACC_RD_MEM ; Byte aus MEM lesen ADD A,CHECKSUMME MOV CHECKSUMME,A MOV A,#0 ADDC A,CHECKSUMME+1 MOV CHECKSUMME+1,A LJMP CHECK_SUM1 CHECK_SUM_ENDE: POP_DPTR POP ACC POP PSW RET ;--------------------------------------------------------------------- ; Funktion : Element in den Speicher auf die naechste frei Position schreiben. ; Aufrufparameter : ACC = Wert ; Ruechgabeparameter : C=0 ==> o.k., C=1 ==> Speicherueberlauf ; Veraenderte Register : - ; Stackbedarf : ; Zeitbedarf : ; PUT_ELEMENT_MEM: PUSH PSW GET_16 NEXT_FREE LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE JC GET_ELEMENT_ERROR ; wenn nicht Fehler LCALL CHECK_WR_POINTER ; testen ob MEM_ANF <= DPTR <= NEXT_FREE JC PUT_ELEMENT_ERROR ; wenn nicht Fehler LCALL ACC_WR_MEM ; Byte aus MEM lesen SET_16 NEXT_FREE PUT_EL_OK1: POP PSW CLR C RET PUT_ELEMENT_ERROR: POP PSW SETB C RET RET ;--------------------------------------------------------------------- ; Funktion : Element von der akt. Position aus dem Speicher lesen. ; Aufrufparameter : - ; Ruechgabeparameter : ACC = Wert ; C=0 ==> o.k., C=1 ==> Schreib- gleich Lesezeiger ; oder Lesezeiger ausserhalb des gueltigen Bereiches ; Veraenderte Register : ACC, PSW ; Stackbedarf : ; Zeitbedarf : ; GET_ELEMENT_MEM: PUSH PSW GET_16 RD_POINTER LCALL CHECK_EOM_POINTER ; testen ob DPTR < MEM_ENDE JC GET_ELEMENT_ERROR ; wenn nicht Fehler LCALL CHECK_RD_POINTER ; testen ob MEM_ANF <= DPTR < NEXT_FREE JC GET_ELEMENT_ERROR ; wenn nicht Fehler LCALL ACC_RD_MEM ; Byte aus MEM lesen SET_16 RD_POINTER GET_EL_OK1: POP PSW CLR C RET GET_ELEMENT_ERROR: POP PSW SETB C RET ;===================================================================== ; END ;---------------------------------------------------------------------