; MICROCHIP DRAM Driver Routines, November 24, 2004 ; Copyright (c) 2004, Tom Napier ; Use a 20 MHz or 19.6608 MHz crystal with a 16C55. ; Use either a 16k or 64k DRAM. ; These routines assume that 16384 RAM locations (2048 bytes) ; are used and therefore all 128 rows need to be refreshed. ; If a single register byte address is used (ADRHI = 0) ; only 16 rows need be refreshed. ; The read/write routines presented here operate on four bits ; at a time. This compromises between maximum speed and ; minimum in-line code size. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Input/Output STATUS EQU 3 PORTA EQU 5 PORTB EQU 6 ; Port A DTI EQU 0 ; Data in from RAM DTO EQU 1 ; Data out to RAM RAS EQU 2 ; RAS (active low) CAS EQU 3 ; CAS (active low) ; Port B 7-Bit RAM address and WE (Bit 7) WE EQU 7 ; Port C Available to application ; Registers used by DRAM routines COUNT EQU 8 ; Loop counter for start-up RDAT EQU 9 ; Memory I/O data register ADRLO EQU 10 ; Memory I/O address low ADRHI EQU 11 ; Memory I/O address high RADD EQU 12 ; Row address CADD EQU 13 ; Column address + WE RFSH EQU 14 ; Refresh address counter ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Code to be incorporated in your program's startup MOVLW 1 TRIS PORTA ; BSF high three bits of A to output MOVLW 0 TRIS PORTB ; BSF port B to output BSF PORTA,RAS ; RAS high BSF PORTA,CAS ; CAS high BSF PORTB,WE ; WE high ; 150 uS start-up delay CLRF COUNT STR1 DECFSZ COUNT,1 GOTO STR1 ; Cycle RAS 10 times MOVLW 10 MOVWF COUNT STR2 BCF PORTA,RAS BSF PORTA,RAS DECFSZ COUNT,1 GOTO STR2 GOTO YOURS ; Continue with your program YOURS ; Dummy to keep assembler happy ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; DRAM read/write/refresh routines ; Refresh all 128 rows. ; Should be called at least once every 2 mS. ; Holds WE bit high. REFSH MOVLW 128 MOVWF PORTB REF1 BCF PORTA,RAS BSF PORTA,RAS INCFSZ PORTB,1 GOTO REF1 RETLW 0 ; Refresh one row only. ; Should be called every 15 uS on average if bulk refresh not used. ; Can be used as a macro without the RETLW instruction. SREF INCF RFSH,1 MOVLW 80H IORWF RFSH,0 MOVWF PORTB BCF PORTA,RAS BSF PORTA,RAS RETLW 0 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Compute row and column addresses from byte address. ; RADD and CADD have WE bit set high. GETAD SWAPF ADRHI,0 ; Low nibble to high W ANDLW 0F0H ; Mask high four bits IORLW 80H ; Set WE high MOVWF RADD ; Save high nibble of row address SWAPF ADRLO,0 ; High nibble to low W ANDLW 0FH ; Mask low four bits IORWF RADD,1 ; Complete row address SWAPF ADRLO,0 ; Low nibble to high W MOVWF CADD BSF STATUS,0 ; For high WE bit RRF CADD,1 MOVLW 0F8H ANDWF CADD,1 ; Set bit address low RETLW 0 ; Read RAM byte in address register ADRHI/LO to register RDAT. READM CALL GETAD ; Set up row and column addresses CALL SREF ; Do a refresh CALL RNIBB ; Read lower nibble CALL SREF ; Do a refresh CALL RNIBB ; Read upper nibble RETLW 0 ; Write byte in register RDAT to RAM address in register ADRHI/LO. ; RDAT is unchanged. WRITM CALL GETAD CALL SREF ; Do a refresh CALL WNIBB ; Write lower nibble CALL SREF ; Do a refresh CALL WNIBB ; Write upper nibble RETLW 0 ; Read one nibble from DRAM and OR it with upper nibble of RDAT. ; Toggle the bit address from low to high nibble. ; If called twice, RDAT contains the complete byte. ; Takes its row and column addresses from RADD and CADD. RNIBB MOVF RADD,0 MOVWF PORTB ; Row address ready BCF PORTA,RAS ; Latch row address MOVF CADD,0 MOVWF PORTB ; Initial column address ready MOVLW 0F0H ANDWF RDAT,1 ; Clear lower nibble of input byte BCF PORTA,CAS ; Latch column address INCF PORTB,1 ; Ready next address during RAM access BTFSC PORTA,DTI ; Test RAM bit BSF RDAT,0 ; Update bit 0 of byte BSF PORTA,CAS ; Back to initial state BCF PORTA,CAS INCF PORTB,1 BTFSC PORTA,DTI BSF RDAT,1 ; Update bit 1 of byte BSF PORTA,CAS BCF PORTA,CAS INCF PORTB,1 BTFSC PORTA,DTI BSF RDAT,2 ; Update bit 2 of byte BSF PORTA,CAS BCF PORTA,CAS INCF PORTB,1 BTFSC PORTA,DTI BSF RDAT,3 ; Update bit 3 of byte BSF PORTA,CAS BSF PORTA,RAS ; Reset RAS SWAPF RDAT,1 ; Swap nibbles MOVLW 4 XORWF CADD,1 ; Toggle bit count RETLW 0 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Write nibble in register RDAT to RAM. ; Swaps RDAT nibbles so calling twice writes complete byte. ; Takes its row and column addresses from RADD and CADD. WNIBB MOVF RADD,0 MOVWF PORTB ; Row address ready BCF PORTA,RAS ; Latch row address MOVF CADD,0 ANDLW 7FH ; Set WE low MOVWF PORTB ; Initial column address ready MOVLW 8 ; To raise CAS and clear DTO MOVWF PORTA ; Set RAS low, CAS high, data low BTFSC RDAT,0 ; Test bit to write BSF PORTA,DTO ; Set bit to write a one BCF PORTA,CAS ; Lower CAS to write bit MOVWF PORTA ; Reset CAS and DTO INCF PORTB,1 ; Prepare next address BTFSC RDAT,1 BSF PORTA,DTO BCF PORTA,CAS MOVWF PORTA INCF PORTB,1 BTFSC RDAT,2 BSF PORTA,DTO BCF PORTA,CAS MOVWF PORTA INCF PORTB,1 BTFSC RDAT,3 BSF PORTA,DTO BCF PORTA,CAS MOVWF PORTA BSF PORTB,WE ; Reset WE BSF PORTA,RAS ; Reset RAS SWAPF RDAT,1 ; Ready for next nibble MOVLW 4 XORWF CADD,1 ; Toggle bit count RETLW 0 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - END