# ------------------------------------------------------------------- # 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 $