{ Unit :Eeprom File :EEPROM.PAS Author :Ivan Beltrame (ivan.beltrame@nline.it) Date :5 August 1997 Rev. :1.00b Note :This unit provide to read and write in 93xx EEPROM. 93xx chip are present in many circuit board to storage of a password,to retain some data in non volatile memory,or to limit the 'life' of a device. It is very easy to use it but this version has a little 'bug' : *timing !* Since I'm a TP6 beginner I'm not able to implement a *compact* and *serious* "delay" routine that run over microsecond or nanosecond, then I have used "FastWait" unit by Southern Software from the SWAG archive (not included in this source). Use of this unit it's free, but comments on my programming mode (self-made) will be apreciated. Important :I decline any responsibilities or liabilities resulting from the use of these informations (source and schematics). ------------------------------------------------------ Pin connections of the parallel port vs chip: LPTx chip v v ____________ 2 K ! o ! 16(C2) ---\/\/\---! 1(CS) 8 !------> +5 Volt 2 K ! ! 2 (D0) ---\/\/\---! 2(CK) 7 !--x 2 K ! ! 1 (C0) ---\/\/\---! 3(DI) 6 !--x 100 ohm ! ! 11(S7) ---\/\/\---! 4(DO) 5 !---*---> GND !____________! I I 18(GND) ____________________________I 9306 9346 } Unit Eeprom; interface var PData :word; { may be $378 or $278 or $3BC } procedure LptInit; { initialize LPTx wires and port registers } procedure Eral; { reset all registers in the chip } procedure Wral(EEfill :word); { write all reg. with EEfill value } procedure EraseLoc(Erase_Loc :byte); { reset a register } procedure EEwrite(WrLoc :byte; WrValue :word); { write in a register } function EEvalue(Loc :byte) :word; { return a register's value } { Notice: Eral procedure sets all registers at $FFFF; EraseLoc sets selected location to $FFFF. } implementation uses crt, FastWait; { also available in SWAG -- TIMING.SWG} var Weight :word; s :byte; PStatus :word; PControl :word; procedure CK; { Generate a clock pulse in the CK wire } { Produce un impulso di clock sul filo CK } begin Wait(2); { ritardo dopo il dato (2 mS) } port[PData] := port[PData] or 1; { CK = 1 } Wait(4); { tempo di CK alto (4 mS) } port[PData] := port[PData] and 254; { CK = 0 } Wait(6); { tempo di CK basso (6 mS) } end; procedure CSon; { Abilita il chip (Chip Select on) *e lo lascia abilitato* } { Enable the chip (Chip Select on) *and it remain still enabled* } begin Wait(4); { ritardo dal precedente CSon } port[PControl] := port[PControl] or 4; { CS = 1 } CK; { un CK a vuoto (necessario) } end; procedure CSoff; { Disabilita il chip (Chip Select off) *e lo lascia disabilitato* } { Disable the chip (Chip Select off) *and it remain still disabled* } begin port[PControl] := port[PControl] and 251; { CS = 0 } end; procedure DI1; { Attiva il filo DI (Data Input) del chip } { Brought DI wire (Data Input) high } begin port[PControl] := port[PControl] and 30; { DI = 1 } end; procedure DI0; { Disattiva il filo DI (Data Input) del chip } { Brought DI wire (Data Input) low } begin port[PControl] := port[PControl] or 1; { DI = 0 } end; procedure LptInit; begin PStatus := PData + 1; PControl := PData + 2; CSoff; { evita confusioni } DI0; { evita confusioni } end; procedure EEcmd(EEcode :word;EEloc :byte); { Invia il codice operativo al chip } { Send operating code to the chip } begin CSon; EEcode := EEcode + EEloc; { Codice operativo = Operazione + Locazione } for s:= 8 downto 0 do begin { invia stringa di bit seriali sul filo DI } Weight := 1 shl(s); if EEcode < Weight then begin DI0; CK; end else begin EEcode := EEcode - Weight; DI1; CK; end; end; end; procedure Ewen; { Ordine di abilitazione alla scrittura/cancellazione al chip } { Enable command for writing/erasing operations to the chip } const EwenCode = 304; begin EEcmd(EwenCode,0); { il campo EELoc deve essere = 0 } DI0; { ripristina DI = 0 (evita confusioni) } CSoff; { disabilita il chip dopo il comando } end; procedure Ewds; { Ordine di disabilitazione alla scrittura/cancellazione al chip } { Disable command for writing/erasing operations to the chip } const EwdsCode = 256; begin EEcmd(EwdsCode,0); { il campo EELoc deve essere = 0 } CSoff; { disabilita il chip dopo il comando } end; procedure Eral; { Ordine di cancellazione totale al chip. Tutte le loc diventeranno $FFFF } { Erase all command to the chip. All locations become $FFFF } const EralCode = 288; begin Ewen; { abilita il chip alla cancellazione totale } EEcmd(EralCode,0); { il campo EELoc deve essere = 0 } CSoff; { disabilita il chip dopo il comando } Ewds; { disab. il chip alla cancellazione totale } end; procedure Wral(EEfill :word); { Ordine di riempimento delle loc del chip con un valore 'EEfill' } { Fill all locations with 'EEfill' value } const WralCode = 272; begin Eral; { "ERAL" necessario per affidabilita' } Ewen; { abilita il chip alla scrittura } EEcmd(WralCode,0); { comando "WRAL" } for s:= 15 downto 0 do begin { invia stringa di bit seriali } Weight := 1 shl(s); { per specificare il dato di } if EEfill < Weight then { riempimento } begin DI0; CK; end else begin EEfill := EEfill - Weight; DI1; CK; end; end; DI0; { ripristina DI = 0 (evita confusioni) } CSoff; { Disabilita il chip } Ewds; { disab. il chip alla scrittura } end; procedure EraseLoc(Erase_Loc :byte); { Ordine di resettare una locazione; il suo valore diventera' $FFFF } { Reset command for a single location; it become $FFFF } const EraseCode = 448; begin Ewen; { abilita il chip alla cancellazione } EEcmd(EraseCode,Erase_Loc); { il campo Erase_Loc deve avere il } DI0; { ripristina DI = 0 (evita confusioni) } CSoff; { numero della locazione da resettare } Ewds; { disab. il chip alla cancellazione } end; procedure EEwrite(WrLoc :byte; WrValue :word); { Ordine di scrivere un dato 'WrValue' alla loc 'WrLoc' } { Writing command; it will write a 'WrValue' in a 'WrLoc' location } const WrCode = 320; begin Ewen; { abilita il chip alla scrittura } EEcmd(WrCode,WrLoc); { comando di scrittura alla loc WrLoc } for s:= 15 downto 0 do begin { invia stringa di bit seriali sul DI } Weight := 1 shl(s); if WrValue < Weight then begin DI0; CK; end else begin WrValue := WrValue - Weight; DI1; CK; end; end; DI0; { ripristina DI = 0 (evita confusioni) } CSoff; { disabilita il chip } Ewds; { disabilita il chip alla scrittura } end; function EEvalue(Loc :byte) :word; { Ritorna il valore letto nella 'Loc' } { It return a Loc's value } const ReadCode = 384; var Value :byte; EEval :word; begin EEvalue := 0; EEval := 0; EEcmd(ReadCode,Loc); { comando di lettura alla 'Loc' } for s := 0 to 15 do begin CK; { invia impulso di clock } wait(5); Value := port[PStatus]; { legge sul filo DO il livello logico } if Value < 128 then EEval := EEval + (1 shl(15 - s)); { poiche' quando il filo "S7" della porta e' a "1" il peso 7 del byte } { di stato e' a "0" potremmo dire di avere un "1" quando Value < 128. } { Se ad ogni ciclo incrementiamo o decrementiamo i pesi di EEval a } { seconda del valore di DO, ci ritroveremo col dato della locazione. } end; DI0; { ripristina DI = 0 (evita confusioni) } CSoff; { disabilita il chip } EEvalue := EEval; end; End. { There are some examples } { program EEpromTest; uses EEprom; var j :byte; h :word; begin PData := $378; { You must specify the parallel port in use } LptInit; { initialize LPTx wires and port regs } writeln('Reading test on EEPROM 9306'); writeln; for j := 0 to 15 do { this "for"cicle put on "h" } begin { the "j" location } h := EEvalue(j); { of the EEPROM chip } write (h,' '); { } end; readln; Eral; { this procedure sets all regs } { in the EEPROM chip = 65535 } readln; h := 100; Wral(h); { this procedure sets all regs } { in the EEPROM chip = "h" } readln; j := 5; EraseLoc(j); { this procedure sets the "j" } { reg in the EEPROM = 65535 } readln; j := 10; h := 1500; EEwrite(j,h); { this procedure sets the reg } { "j" = "h" in the EEPROM } { Notice : in certain cases it } { is necessary to perform an } { EaseLoc(j) before of EEwrite(j,.... } end.