; PROGRAM: Dynamic RAM Basics (DRAM.SRC)
;
; works with "RAS before CAS" DRAMs
;
; Written December 29, 1993
; Revised February 24, 1996
; Upon power up or reset, this program starts sampling pin ra.0 and
; recording its state in sequential addresses of a 1Mb dynamic RAM.
; When the DRAM is full, the program plays back the recorded bits
; in a continuous loop.
device pins28,xt_osc,wdt_off,turbo,stackx,optionx
reset start
Sin = ra.0 ; Signal generator input
RAS = ra.1 ; DRAM row-address strobe
WR = ra.2 ; DRAM write line (0 = write)
Dout = ra.3 ; DRAM data line
CAS = rc.3 ; DRAM column-address strobe
adrb_lo = rb ; Low bits of address bus
adrb_hi = rc ; High bits of address bus
Din = rc.2 ; DRAM Q line
Sout = rc.5 ; Signal out to speaker
org 8 ; Start of available RAM
r_ctr ds 1 ; Refresh counter
row_lo ds 1 ; Eight LSBs of row address
row_hi ds 1 ; Two MSBs of row address
col_lo ds 1 ; Eight LSBs of column address
col_hi ds 1 ; Two MSBs of column address
flags ds 1 ; Holder for bit variable flag
flag = flags.0 ; Overflow flag for 20-bit address
org 0 ; Start of code space
start setb RAS ; Disable RAS and CAS before
setb CAS ; setting ports to output.
mov !ra,#1 ; Make ra.0 (Sin) an input.
mov !rb,#0 ; Make rb (low addresses) output.
mov !rc,#00000100b ; Make rc.2 (Din) an input.
clr flags ; Clear the variables.
clr row_lo
clr row_hi
clr col_lo
clr col_hi
call refresh ; Initialize DRAM.
:record call refresh ; Refresh the DRAM.
call write ; Write Sin bit to DRAM.
call inc_xy ; Increment row and col addresses.
jnb flag,:record ; Repeat until address overflows.
:play call refresh ; Refresh the DRAM.
call read ; Retrieve bit and write to Sout)
call inc_xy ; Increment row and col addresses.
JMP :play ; Loop until reset.
write mov adrb_lo,row_lo ; Put LSBs of row addr onto bus (rb).
AND adrb_hi,#11111100b ; Clear bits adrb_hi.0 and .1.
OR adrb_hi,row_hi ; Put MSBs of row addr onto bus (rc).
clrb RAS ; Strobe in the row address.
movb Dout,Sin ; Supply the input bit to the DRAM,
movb Sout,Sin ; and echo it to the speaker.
mov adrb_lo,col_lo ; Put LSBs of col addr onto bus (rb).
AND adrb_hi,#11111100b ; Clear bits adrb_hi.0 and .1.
OR adrb_hi,col_hi ; Put MSBs of col addr onto bus (rc).
clrb WR ; Set up to write.
clrb CAS ; Strobe in the column address.
setb WR ; Conclude the transaction by
setb RAS ; restoring WR, RAS, and CAS high
setb CAS ; (inactive).
ret
read mov adrb_lo,row_lo ; Put LSBs of row addr onto bus (rb).
AND adrb_hi,#11111100b ; Clear bits adrb_hi.0 and .1.
OR adrb_hi,row_hi ; Put MSBs of row addr onto bus (rc).
clrb RAS ; Strobe in the row address.
mov adrb_lo,col_lo ; Put LSBs of col addr onto bus (rb).
AND adrb_hi,#11111100b ; Clear bits adrb_hi.0 and .1.
OR adrb_hi,col_hi ; Put MSBs of col addr onto bus (rc).
clrb CAS ; Strobe in the column address.
movb Sout,Din ; Copy the DRAM data to the speaker.
setb RAS ; Conclude the transaction by restoring
setb CAS ; RAS and CAS high (inactive).
ret
; This routine implements a CAS-before-RAS refresh. The DRAM has an onboard
; counter to keep track of row addresses, so the status of the external
; address bus doesn't matter. The DRAM requires 512 row addresses be refreshed
; each 8 ms, so this routine must be called once every 125 microseconds.
; Changing the initial value moved into r_ctr will alter the refresh schedule.
; For example, to refresh the entire DRAM, move #0 into r_ctr (256 loops) and
; call the routine twice in a row (512).
refresh mov r_ctr,#8
:loop clrb CAS ; Activate column strobe.
clrb RAS ; Activate row strobe.
setb CAS ; Deactivate column strobe.
setb RAS ; Deactivate row strobe.
djnz r_ctr,:loop ; Repeat.
ret
; This routine increments a 20-bit number representing the 1,048,576 addresses
; of the DRAM. For convenience, the number is broken into two 10-bit numbers,
; which are each stored in a pair of byte variables. Note that wherever the
; routine relies on the carry bit to indicate a byte overflow, it uses
; the syntax "add variable,#1" not "inc variable." Inc does not set or clear
; the carry flag.
inc_xy add row_lo,#1 ; Add 1 to eight LSBs of row addr.
sc ; If carry, add 1 to MSB, else return.
ret
inc row_hi ; Increment MSBs of row address.
sb row_hi.2 ; If we've overflowed 10 bits, clear
ret ; row_ hi and add 1 to column
clr row_hi ; address, else return.
add col_lo,#1
sc ; If carry, add 1 to MSB, else return.
ret
inc col_hi ; Increment MSBs of col address.
sb col_hi.2 ; If we've overflowed 10 bits, clear
ret ; col_ hi and set the flag to signal
clr col_hi ; main program that we've reached the
setb flag ; end of available memory, then return.
ret