# -------------------------------------------------------------------
# EEPROM TUTORIAL (c) Copyright 1997 Nat! & KKP
# -------------------------------------------------------------------
# These are some of the results/guesses that Klaus and Nat! found
# out about the Jaguar with a few helpful hints by other people,
# who'd prefer to remain anonymous.
#
# Since we are not under NDA or anything from Atari we feel free to
# give this to you for educational purposes only.
#
# Please note, that this is not official documentation from Atari
# or derived work thereof (both of us have never seen the Atari docs)
# and Atari isn't connected with this in any way.
#
# Please use this informationphile as a starting point for your own
# exploration and not as a reference. If you find anything inaccurate,
# missing, needing more explanation etc. by all means please write
# to us:
# nat@zumdick.ruhr.de
# or
# kp@eegholm.dk
#
# If you could do us a small favor, don't use this information for
# those lame flamewars on r.g.v.a or the mailing list.
#
# HTML soon ?
# -------------------------------------------------------------------
# $Id: eeprom.html,v 1.7 1997/11/16 18:14:40 nat Exp $
# -------------------------------------------------------------------
EEPROM tutorial:
=-=-=-=-=-=-=-=-=
This is just a little code, probably all you ever going to need to
access the EEPROM. This is written with PURE-ASM in mind in case
you're wondering about the slightly strange (and not 100% optimal)
register usage/wastage. Anyway this code runs fine on my Jaguar and
I am convinced I got the timing right.
This is coded for a 68000. For a 68030 be sure to put a NOP behind
all external hardware register accesses, because the 68030 has a
delayed write feature, where the NOP syncs. Then add a few NOPs for
timing purposed. One NOP -> 4 cycles,
CLOCK = EEPROM_CLOCK
RDATA = EEPROM_RDATA
WDATA = EEPROM_WDATA
STROBE = EEPROM_STROBE
; --------------------------------------------------------------
; read_whole_eeprom
; --------------------------------------------------------------
; Read EEPROM into 128 bytes of wordaligned buffer space (A0)
; wasting D1-D2 in the process
;
read_whole_eeprom:
MOVE.W D3,-(A7)
CLR.W D3 ; cell counter
.copy: MOVE.W D3,D0
JSR eeprom_read
MOVE.W D0,(A0)+
ADDQ.W #1,D3
CMP.W #$40,D3
BNE.B .copy
MOVE.W (A7)+,D3
RTS
; --------------------------------------------------------------
; write_whole_eeprom
; --------------------------------------------------------------
; Write complete EEPROM with 128 bytes of user data pointed to
; by A0, which contains of course an even address
; This can take up to 750ms even in successful writes
; wastes D1-D2
; returns in D0: 0: success
write_whole_eeprom:
BSR eeprom_unlock
MOVE.W D3,-(A7)
CLR.W D3
.copy:
MOVE.W (A0)+,D0 ;; get word
MOVE.W D3,D1 ;; get cell # in D1
BSR eeprom_write ;; write it down
BEQ .failed ;; timeout ->
ADDQ.W #1,D3 ;; try the next
CMP.W #$40,D3
BNE.B .copy
.failed:
MOVE D0,D3 ;; save write status
BSR eeprom_lock ;; lock cart again
MOVE D3,D0 ;; restore status
MOVE.W (A7)+,D3
SUB.W #1,D0 ;; make C-like status
RTS
; --------------------------------------------------------------
; eeprom_unlock
; --------------------------------------------------------------
; Unlock the EEPROM for writing
;
; D0: wasted
; D1: wasted
; D2: wasted
;
eeprom_unlock:
LEA CLOCK,A1
MOVE.W #$130,D0
BRA eeprom_w_cmd
; --------------------------------------------------------------
; eeprom_lock
; --------------------------------------------------------------
; Lock the EEPROM against writing
;
; D0: wasted
; D1: wasted
; D2: wasted
;
eeprom_lock:
LEA CLOCK,A1
MOVE.W #$100,D0
BRA eeprom_w_cmd
; --------------------------------------------------------------
; eeprom_write
; --------------------------------------------------------------
; D0: data
; D1: cell #
;
; retuens:
; D0: 0 = successful
; A1: wasted
; D2: wasted
eeprom_write:
LEA CLOCK,A1
MOVE D0,D2
MOVEQ #$3F,D0
AND D1,D0
ORI.W #$140,D0 ;; set prepare to write bits
BSR eeprom_w_cmd
MOVE D2,D0
BSR eeprom_w_data
bra eeprom_wait ;; you MUST pull CS down now
; --------------------------------------------------------------
; eeprom_read
; --------------------------------------------------------------
; Read a word from an EEPROM cell
;
; D0: cellnumber, returned data also in D0
; D1: wasted
; D2: wasted
;
module eeprom_read
LEA CLOCK,A1
AND.W #$3F,D0
ORI.W #$180,D0 ;; set prepare to read bits
BSR eeprom_w_cmd
; BRA eeprom_r_data ;; fall thru
; --------------------------------------------------------------
; eeprom_r_data
; --------------------------------------------------------------
; Read 16 bits of data over the serial line
; return them in D0
; wasting D1-D2
;
eeprom_r_data:
MOVEQ #0,D0
MOVEQ #$F,D2 ;; do 16 bits
.readbit: TST.W CLOCK-CLOCK(A1) ;; EEPROM has max 500ns time to
NOP ;; provide us with the data
NOP
MOVE.W RDATA-CLOCK(A1),D1
LSR.W #1,D1 ;; get LSB into X
ADDX.W D0,D0 ;; shift left and add X
DBF D2,.readbit
RTS
; --------------------------------------------------------------
; eeprom_w_data
; --------------------------------------------------------------
;
; write 16 bits of D0 data, wasting D1 in the process
;
eeprom_w_data::
MOVEQ #$F,D1 ;; wanna do 16 bits
BRA.B _writebit
; --------------------------------------------------------------
; eeprom_w_cmd
; --------------------------------------------------------------
; Initiate command mode by doing the CS ChipSelect
; then write 9 bits of D0 data onto the serial line,
; wasting D1 in the process
;
eeprom_w_cmd:
ROL.W #7,D0 ;; move 9th bit into MSB
TST.W STROBE-CLOCK(A1) ;; pull CS down
MOVEQ #8,D1 ;; wanna do 9 bits
_writebit:
.loop: ROL.W #1,D0 ;; get MSB into LSB
MOVE.W D0,WDATA-CLOCK(A1) ;; write it down #1#
;; wait 1us for EEPROM
DBF D1,.loop ;; 8 + 8 + 10 -> 28 > 13.3
RTS
; --------------------------------------------------------------
; eeprom_busy
; --------------------------------------------------------------
; Just check whether the damn thing is still busy. Not very
; useful this routine, but heck for completeness..
; returns: 1=ready 0=busy
eeprom_busy:
TST.W STROBE-CLOCK(A1) ;; pull CS down shortly
MOVEQ #1,D0 ;; wait for 500ns until
AND.W RDATA-CLOCK(A1),D0 ;; we read the data
RTS
; --------------------------------------------------------------
; eeprom_wait
; --------------------------------------------------------------
; Check whether the EEPROM is still busy writing. It must do this
; in a timespan of 10ms. Busy waiting. ARGH!
;
; wastes D1 in the process!!
; returns in D0: 1=ready 0: timeouted!!
eeprom_wait:
MOVE.W #5200,D1 ;; > 10ms timeout
TST.W STROBE-CLOCK(A1) ;; pull CS down
.loop: ;; inner loop:
MOVEQ #1,D0 ;; 4 + 12 + 10 -> 26 cycles
AND.W RDATA-CLOCK(A1),D0
DBNE D1,.loop
RTS
; #1# the PURE-ASM optimizes this!
$Id: eeprom.html,v 1.7 1997/11/16 18:14:40 nat Exp $