NV-DIR

From CPCWiki - THE Amstrad CPC encyclopedia!
Jump to: navigation, search

This source deals with the non volatile memory of the SYMBiFACE II and the CPC Booster. Compatible with the MAXAM assembler.

org &9000 ; File ----> NV-DIR.MAX
nolist    ; Version -> 1.0 (30.12.2006) english!
          ; Lines ---> 477

;Part of the FutureView IV release, please look there for further informations.

;This file containt the source code to calculate a checksum over the DIRectory
;of the nvRAM of the Symbiface and/or the EEPROM of the CPC-Booster Plus.
;This source code is a part of the FutureView IV.



;-----------------;
; All code by TFM ;
; of  Future-Soft ;
;-----------------;
; This  code  was ;
; tested.  Please ;
; copy  this file ;
; as it is!!! TFM ;
;-----------------;



;--- --- --- Example how to work with the EEPROM o.t. CPC Booster+ --- --- ---;

 LD   HL,EE_BUFFER ;Space for the &200 Bytes EEPROM of the CPC Booster+
 CALL READ_EE      ;Read &200 Bytes EEPROM from CB (CPC Booster+)

 LD   HL,EE_BUFFER ;Pointer to &200 Bytes of EEPROM buffer
 CALL TST_CHCK_EE  ;Test if Checksum of the EEPROM is correct

 JP   Z,EE_DIR_OK  ;Go there if Checksum is correct!

;Checksum is NOT correct!

 LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer
 CALL INIT_DIR_EE  ;Initialize DIRectory of the EEPROM

;There is NO need to create/install a NEW checksum,
;because the checksum and DIR are all zero bytes.

 JP   EE_EXIT      ;Write new DIR and DATA into the CP EEPROM, then Exit!

;Delete last line of code, if you want to manage newly installed DIR/DATA.


;EEPROM Checksum was tested correct!

EE_DIR_OK

;NOW you can MANAGE your CB EEPROM in different ways...

;1. - READ an Entry (of 16 Bytes)
;(remove semicolons of the following 5 lines to use this function)
;
; LD   A,&09        ;A contains the Product-ID (range between &01 and &FE).
; LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer (source)
; LD   DE,ENTRY_BUF ;16 Byte buffer for ONE 16 Byte Entry of the CB EEPROM
; CALL RED_ENT_EE   ;Read 16 Byte Entry from CB EEPROM with the ID stored in A

;... or ...

;2. - WRITE an Entry (of 16 Bytes)
;(remove semicolons of the following 8 lines to use this function)
;
; LD   A,&12        ;A contains YOUR Product-ID (range between &01 and &FE).
; LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM target buffer
; LD   DE,ENTRY_BUF ;source buffer of ONE 16 Byte Entry for the CB EEPROM
; CALL WRT_ENT_EE   ;Write 16 Byte Entry to CB EEPROM (ID prev. stored in A)
;
; LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer
; CALL MAKE_CHK_EE  ;Create and install NEW checksum after WRITE

;... or ...

;3. - ERASE an Entry (of 16 Bytes)
;(remove semicolons of the following 7 lines to use this function)
;
; LD   A,&02        ;A contains YOUR Product-ID (range between &01 and &FE).
; LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer
; CALL ERA_ENT_EE   ;Erase ONE Entry (16 Bytes) in the DIR of the CB EEPROM
;
; LD   HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer
; CALL MAKE_CHK_EE  ;Create and install NEW checksum after ERASE


;Finally you have to write back Checksum and Data from RAM to the CB EEPROM.

EE_EXIT LD HL,EE_BUFFER ;Pointer to &200 Bytes EEPROM buffer

 CALL WRITE_EE ;Write RAM to EEPROM of CB
 RET



;--- --- --- Example how to work with the nvRAM of the Symbiface --- --- --- ;

 LD   HL,NV_BUFFER ;Space for &72 Bytes of the &80 Bytes nvRAM of the Symbiface
 CALL READ_NV      ;Read &72 Bytes nvRAM from SF (without clock data)

 LD   HL,NV_BUFFER ;Pointer to &72 Bytes of nvRAM buffer
 CALL TST_CHCK_NV  ;Test if Checksum of the nvRAM is correct

 JP   Z,NV_DIR_OK  ;Go there if Checksum is correct!

;Checksum is NOT correct!

 LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer
 CALL INIT_DIR_NV  ;Initialize DIRectory of the nvRAM

 LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer
 CALL MAKE_CHK_NV  ;Create and install NEW checksum

 JP   NV_EXIT      ;Write new DIR and DATA into the SF nvRAM, then Exit!

;Delete last line of code, if you want to manage newly installed DIR/DATA.


;nvRAM Checksum was tested correct!

NV_DIR_OK

;NOW you can MANAGE your SF nvRAM in different ways...

;1. - READ an Entry (of 16 Bytes)
;(remove semicolons of the following 5 lines to use this function)
;
; LD   A,&09        ;A contains the Product-ID (range between &01 and &FE).
; LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer (source)
; LD   DE,ENTRY_BUF ;16 Byte buffer for ONE 16 Byte Entry of the SF nvRAM
; CALL RED_ENT_NV   ;Read 16 Byte Entry from SF nvRAM with the ID stored in A

;... or ...

;2. - WRITE an Entry (of 16 Bytes)
;(remove semicolons of the following 8 lines to use this function)
;
; LD   A,&12        ;A contains YOUR Product-ID (range between &01 and &FE).
; LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM target buffer
; LD   DE,ENTRY_BUF ;source buffer of ONE 16 Byte Entry for the SF nvRAM
; CALL WRT_ENT_NV   ;Write 16 Byte Entry to SF nvRAM (ID prev. stored in A)
;
; LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer
; CALL MAKE_CHK_NV  ;Create and install NEW checksum after WRITE

;... or ...

;3. - ERASE an Entry (of 16 Bytes)
;(remove semicolons of the following 7 lines to use this function)
;
; LD   A,&02        ;A contains YOUR Product-ID (range between &01 and &FE).
; LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer
; CALL ERA_ENT_NV   ;Erase ONE Entry (16 Bytes) in the DIR of the SF nvRAM
;
; LD   HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer
; CALL MAKE_CHK_NV  ;Create and install NEW checksum after ERASE


;Finally you have to write back Checksum and Data from RAM to the SF nvRAM.

NV_EXIT LD HL,NV_BUFFER ;Pointer to &72 Bytes nvRAM buffer

 CALL WRITE_NV ;Write RAM to nvRAM of SF (without clock)
 RET



; --- --- --- Subroutines for EEPROM management / CPC Booster+ --- --- --- ;

;Read &0200 Bytes CPC Booster+ EEPROM (DIR and Data)
;
;In;
;HL = Buffer for &200 Bytes
;
;Out;
;&200 Bytes (Checksum, Data) have been read to old HL
;
;(Changed Registers AF, BC, HL)

READ_EE XOR A,A:LD BC,&FF0C:OUT (C),A:INC C:OUT (C),A
READ_E1 INC C:INI:INC B:DEC C:INC A:OUT (C),A:JR NZ,READ_E1

 INC A:DEC C:OUT (C),A:INC C:DEC A

READ_E2 INC C:INI:INC B:DEC C:INC A:OUT (C),A:JR NZ,READ_E2:RET


;Test Checksum of EEPROM (CPC Booster+)
;
;In;
;HL = Buffer-Start of &200 Bytes EEPROM (previously read with READ_EE)
;
;Out;
;Zero-Flag is SET if Checksum is correct, else Zero is cleared.
;
;(Changed Registers AF, BC, DE, HL)

TST_CHCK_EE LD E,(HL):INC HL:LD D,(HL):INC HL:PUSH DE ;old checksum

 LD A,&0F:LD DE,&0000

TST_CHCK_EL LD C,(HL):INC HL:LD B,(HL):INC HL:EX DE,HL:ADD HL,BC:EX DE,HL

 DEC A:JR NZ,TST_CHCK_EL:POP HL:XOR A,A:SBC HL,DE:RET


;Initialize DIRectory of the EEPROM
;
;In;
;HL = Buffer for &200 Bytes EEPROM (previously read with READ_EE)
;
;(Changed Registers AF, BC, DE, HL)

INIT_DIR_EE XOR A,A:LD (HL),A:LD D,H:LD E,L:INC DE:LD BC,&001F:LDIR:RET


;Calculate and Install new Checksum for CB EEPROM buffer
;
;In;
;HL = Start of buffer of &200 Bytes EEPROM (previously read with READ_EE)
;
;(Changed Registers AF, BC, DE, HL)

MAKE_CHK_EE PUSH HL:INC HL:INC HL:LD A,&0F:LD DE,&0000

MAKE_CHK_EL LD C,(HL):INC HL:LD B,(HL):INC HL:EX DE,HL:ADD HL,BC:EX DE,HL

 DEC A:JR NZ,MAKE_CHK_EL:POP HL:LD (HL),E:INC HL:LD (HL),D:RET


;Read 16 Byte Entry from CB EEPROM with given Product-ID
;
;In;
; A = contains the Product-ID (in the range between &01 and &FE).
;HL = Pointer to &200 Bytes EEPROM source buffer (must have been read before!)
;DE = Pointer to 16 Byte target buffer for ONE 16 Byte entry of the CB EEPROM
;
;Out;
;Zero-Flag set ------> Entry was found and copied to DE (16 Bytes)
;Zero-Flag cleared --> An Entry with that Product-ID was NOT found!
;
;(Changed Registers AF, BC, DE, HL)

RED_ENT_EE PUSH HL:INC HL:INC HL:LD B,&1E
GLP_ENT_EE CP A,(HL):JR Z,GEX_ENT_EE:INC HL:DJNZ GLP_ENT_EE:POP HL:RET
GEX_ENT_EE LD A,&20:SUB A,B:ADD A,A:ADD A,A:ADD A,A ;(DIR Nr. 2..31)*8

 LD B,&00:LD C,A:POP HL:ADD HL,BC:ADD HL,BC:LD BC,&0010:LDIR:XOR A,A:RET


;Write 16 Byte Entry to CB EEPROM buffer (identified through given Product-ID)
;(Routine OVERWRITES old entry with the SAME Product-ID)
;
;In;
; A = YOUR Product-ID (range between &01 and &FE).
;HL = Pointer to &200 Bytes EEPROM target buffer (must have been read before!)
;DE = Pointer to source buffer of ONE 16 Byte Entry of the CB EEPROM
;
;Out;
;Zero-Flag set ------> Entry was written to CB EEPROM buffer (16 Bytes)
;Zero-Flag cleared --> NO free Entry anymore!
;
;(Changed Registers AF, BC, DE, HL)

WRT_ENT_EE PUSH HL:INC HL:INC HL:LD B,&1E
WLP_ENT_EE CP A,(HL):JR Z,WEX_ENT_EE:INC HL:DJNZ WLP_ENT_EE

 LD BC,&FFE2:ADD HL,BC:LD B,&1E:LD C,A:XOR A,A

WL2_ENT_EE CP A,(HL):JR Z,WEY_ENT_EE:INC HL:DJNZ WL2_ENT_EE:POP HL:RET
WEY_ENT_EE LD (HL),C
WEX_ENT_EE LD A,&20:SUB A,B:ADD A,A:ADD A,A:ADD A,A ;(DIR Nr. 2..31)*8

 LD B,&00:LD C,A:POP HL:ADD HL,BC:ADD HL,BC
 EX DE,HL:LD BC,&0010:LDIR:XOR A,A:RET


;Erase ONE Entry in the DIR of the CB EEPROM (named by given Product-ID)
;
;In;
; A = contains the Product-ID (in the range between &01 and &FE).
;HL = Pointer to &200 Bytes EEPROM buffer (must have been read before!)
;
;Out;
;Zero-Flag set ------> Entry was found and ERASED in DIR
;Zero-Flag cleared --> An Entry with the given Product-ID was NOT found!
;
;(Changed Registers AF, BC, HL)

ERA_ENT_EE INC HL:INC HL:LD B,&1E
ELP_ENT_EE CP A,(HL):JR Z,EEX_ENT_EE:INC HL:DJNZ ELP_ENT_EE:RET
EEX_ENT_EE XOR A,A:LD (HL),A:RET


;Write RAM buffer back to CPC Booster+ EEPROM (DIR and Data)
;
;In;
;HL = Pointer to Buffer of &200 Bytes in RAM
;
;Out;
;&200 Bytes (Checksum, Data) have been written from RAM to EEPROM(CPC Booster+)
;
;(Changed Registers AF, BC, DE, HL)

WRITE_EE LD DE,&0001:LD BC,&FF0C:OUT (C),D:INC C:OUT (C),D
WRITE_E1 INC C:LD A,(HL):OUT (C),A:INC HL:DEC C

 INC D:OUT (C),D:JR NZ,WRITE_E1
 DEC C:OUT (C),E:INC C

WRITE_E2 INC C:LD A,(HL):OUT (C),A:INC HL:DEC C

 INC D:OUT (C),D:JR NZ,WRITE_E2:RET



; --- --- --- Subroutines for the nvRAM management / Symbiface --- --- --- ;

;Read Symbiface nvRAM (DIR and Data)
;(read nvRAM-Bytes &000E-&007F, no clock data)
;
;In;
;HL = Buffer for &72 Bytes
;
;Out;
;&72 Bytes (Checksum, Data) have been read to old HL
;
;(Changed Registers AF, BC, HL)

READ_NV LD BC,&FD15:LD A,&0E
READ_NL OUT (C),A:DEC C:INI:INC B:INC C:INC A:OR A,A:JP P,READ_NL:RET


;Test Checksum of nvRAM (Symbiface)
;
;In;
;HL = Buffer-Start of &72 Bytes nvRAM (previously read with READ_NV)
;
;Out;
;Zero-Flag is SET if Checksum is correct, else Zero is cleared.
;
;(Changed Registers AF, BC, DE, HL)

TST_CHCK_NV LD E,(HL):INC HL:LD D,(HL):LD BC,&0061:ADD HL,BC:PUSH DE ;old checksum

 LD A,&08:LD DE,&0000

TST_CHCK_NL LD C,(HL):INC HL:LD B,(HL):INC HL:EX DE,HL:ADD HL,BC:EX DE,HL

 DEC A:JR NZ,TST_CHCK_NL:POP HL:XOR A,A:SBC HL,DE:RET


;Initialize DIRectory of the nvRAM
;(protect Clock Data [nvRAM-Bytes &00-&0D])
;(protect DIRectory [nvRAM-Bytes &70-&77])
;(set Millenium [nvRAM-Byte &32] to &14)
;
;In;
;HL = Buffer for &72 Bytes nvRAM (previously read with READ_NV)
;
;(Changed Registers AF, BC, DE, HL)

INIT_DIR_NV XOR A,A:LD (HL),A:LD D,H:LD E,L:INC DE:LD BC,&0071:LDIR

 LD DE,&FFF8:ADD HL,DE:LD (HL),D:LD E,&F9:ADD HL,DE:LD (HL),D
 LD DE,&FFC2:ADD HL,DE:LD A,&14:LD (HL),A:RET


;Calculate and Install new Checksum for SF nvRAM buffer
;
;In;
;HL = Start of buffer of &72 Bytes nvRAM (previously read with READ_NV)
;
;(Changed Registers AF, BC, DE, HL)

MAKE_CHK_NV PUSH HL:LD BC,&0062:ADD HL,BC

 LD A,&08:LD DE,&0000

MAKE_CHCK_NL LD C,(HL):INC HL:LD B,(HL):INC HL:EX DE,HL:ADD HL,BC:EX DE,HL

 DEC A:JR NZ,MAKE_CHCK_NL:POP HL:LD (HL),E:INC HL:LD (HL),D:RET


;Read 16 Byte Entry from SF nvRAM with given Product-ID
;
;In;
; A = contains the Product-ID (in the range between &01 and &FE).
;HL = Pointer to &72 Bytes nvRAM source buffer (must have been read before!)
;DE = Pointer to 16 Byte target buffer for ONE 16 Byte entry of the SF nvRAM
;
;Out;
;Zero-Flag set ------> Entry was found and copied to DE (16 Bytes)
;Zero-Flag cleared --> An Entry with that Product-ID was NOT found!
;
;(Changed Registers AF, BC, DE, HL)

RED_ENT_NV LD BC,&0063:PUSH HL:ADD HL,BC:LD B,&06
GLP_ENT_NV CP A,(HL):JR Z,GEX_ENT_NV:INC HL:DJNZ GLP_ENT_NV:POP HL:RET
GEX_ENT_NV LD A,&06:SUB A,B:ADD A,A:ADD A,A:ADD A,A:ADD A,A ;(DIR Nr.0-5)*16

 INC A:INC A:LD B,&00:LD C,A:POP HL:ADD HL,BC:LD BC,&0010:LDIR:XOR A,A:RET


;Write 16 Byte Entry to SF nvRAM buffer (identified through given Product-ID)
;(Routine OVERWRITES old entry with the SAME Product-ID)
;
;In;
; A = YOUR Product-ID (range between &01 and &FE).
;HL = Pointer to &72 Bytes nvRAM target buffer (must have been read before!)
;DE = Pointer to source buffer of ONE 16 Byte Entry of the SF nvRAM
;
;Out;
;Zero-Flag set ------> Entry was written to SF nvRAM buffer (16 Bytes)
;Zero-Flag cleared --> NO free Entry anymore!
;
;(Changed Registers AF, BC, DE, HL)

WRT_ENT_NV LD BC,&0063:PUSH HL:ADD HL,BC:LD B,&06
WLP_ENT_NV CP A,(HL):JR Z,WEX_ENT_NV:INC HL:DJNZ WLP_ENT_NV

 LD BC,&FFFA:ADD HL,BC:LD B,&06:LD C,A:XOR A,A

WL2_ENT_NV CP A,(HL):JR Z,WEY_ENT_NV:INC HL:DJNZ WL2_ENT_NV:POP HL:RET
WEY_ENT_NV LD (HL),C
WEX_ENT_NV LD A,&06:SUB A,B:ADD A,A:ADD A,A:ADD A,A:ADD A,A ;(DIR Nr.0-5)*16

 INC A:INC A:LD B,&00:LD C,A:POP HL
 ADD HL,BC:EX DE,HL:LD BC,&0010:LDIR:XOR A,A:RET


;Erase ONE Entry in the DIR of the SF nvRAM (named by given Product-ID)
;
;In;
; A = contains the Product-ID (in the range between &01 and &FE).
;HL = Pointer to &72 Bytes nvRAM buffer (must have been read before!)
;
;Out;
;Zero-Flag set ------> Entry was found and ERASED in DIR
;Zero-Flag cleared --> An Entry with the given Product-ID was NOT found!
;
;(Changed Registers AF, BC, HL)

ERA_ENT_NV LD BC,&0063:ADD HL,BC:LD B,&06
ELP_ENT_NV CP A,(HL):JR Z,EEX_ENT_NV:INC HL:DJNZ ELP_ENT_NV:RET
EEX_ENT_NV XOR A,A:LD (HL),A:RET


;Write RAM buffer back to Symbiface nvRAM (DIR and Data)
;
;In;
;HL = Buffer of &72 Bytes in RAM
;
;Out;
;&72 Bytes (Checksum, Data) have been written from RAM to nvRAM (Symbiface)
;
;(Changed Registers AF, BC, HL)

WRITE_NV LD BC,&FD15:LD A,&0E
WRITE_NL OUT (C),A:DEC C:INC B:OUTI:INC C:INC A:OR A,A:JP P,WRITE_NL:RET



; --- --- --- Buffers / Space for Data --- --- --- ;

EE_BUFFER DS &0200,&00 ;&200 Byte buffer for CPC Booster+ EEPROM

NV_BUFFER DS &72,&00   ;&72 Byte buffer for Symbiface nvRAM

ENTRY_BUF DS &10,&00   ;16 Byte buffer for ONE 16 Byte Entry (CB or SF)



LIST
DUMP