EEPROM Library - libeerw.a
(usage- you have to figure it out for now)
EEPROM Header - eerw.h
(usage- #include "eerw.h")

Features (and shortcomings)-
>read 8bit,16bit,32bit
>write 8bit,16bit,32bit
>read block up to 256bytes
>write block up to 256bytes
>normal avr gcc call/return register usage
>all eeprom register modifications done
>  with irq's disabled, to prevent any eeprom
>  reading from irq's 'corrupting' eeprom
>  registers
>all-in-one function for read/write, using
>  either of the 2 common eeprom register
>  address locations
>irq's re-enabled between read/write of each
>  byte, to give irq's a chance to run
>writing eeprom data will be skipped for each
>  byte which will not be changed
>read/write of >8bit are not 'atomic'
>no check of flash programming in progress
>block read/write limited to 256bytes
>code size- 52 words (always the same, even if
>  only reading eeprom)
>it may not work

below is the libray source followed by the
header file used in your program


/*-----------------------------------------------------------------------------------------------------------
___ ___ _____ __ _ ___ ___ ___ _ _____ __ ___ ___ _ _ ___ ___ ___
| __| __| _ \ \ / / | | |_ _| _ ) _ \ /_\ | _ \ \ / / / __|/ _ \| | | | _ \/ __| __|
| _|| _|| /\ \/\/ / | |__ | || _ \ / / _ \| /\ V / \__ \ (_) | |_| | / (__| _|
|___|___|_|_\ \_/\_/ |____|___|___/_|_\/_/ \_\_|_\ |_| |___/\___/ \___/|_|_\\___|___|

by Curt Van Maanen
AVR Freaks member- curtvm
-----------------------------------------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------------------------------------
___ _ _ ___ _ _ _ ___ ___ ___
|_ _| \| |/ __| | | | | | \| __/ __|
| || .` | (__| |_| |_| | |) | _|\__ \
|___|_|\_|\___|____\___/|___/|___|___/

-----------------------------------------------------------------------------------------------------------*/
#include <avr/io.h>

/*-----------------------------------------------------------------------------------------------------------
___ _ _ _ _ ___ _____ ___ ___ _ _ ___
| __| | | | \| |/ __|_ _|_ _/ _ \| \| |/ __|
| _|| |_| | .` | (__ | | | | (_) | .` |\__ \
|_| \___/|_|\_|\___| |_| |___\___/|_|\_||___/

-----------------------------------------------------------------------------------------------------------*/
.section .text

.global ee_read_32bit
.global ee_read_16bit
.global ee_read_8bit
.global ee_read_block

.global ee_write_32bit
.global ee_write_16bit
.global ee_write_8bit
.global ee_write_block


/*-----------------------------------------------------------------------------------------------------------
C register usage for values passed to non-block functions-

r25:r24 = eeprom address

r23:r22:r21:r20 = data input for write 32bit
r23:r22 = data input for write 16bit
r22 = data input for write 8bit

r25:r24:r23:r22 = return data for read 32bit
r25:r24 = return data for read 16bit
r24 = return data for read 8bit

r25 bit7 = read/write bit - read = 0, write = 1
r25 bit6 = eecr register (0=0x003F,1=0x003C)
r25 bit5,4 = read/write count -1 (0-3 for count of 1-4)

write functions will use data indirect addressing (XH:XL) as the data input
read functions will use data indirect addressing (XH:XL) as the return data
-----------------------------------------------------------------------------------------------------------*/

ee_write_8bit: //data input= r22
ee_write_16bit: //data input= r22 to r23
ee_read_32bit: //return data= r22 to r25
ldi XL,22
rjmp ee_nb
ee_write_32bit: //data input= r20 to r23
ldi XL,20
rjmp ee_nb
ee_read_16bit: //data return= r24 to r25
ee_read_8bit: //data return= r24
ldi XL,24
ee_nb:
ldi XH,0 //all above functions need XH=0
mov r19,r25 //get r25 into r19
swap r19 //get count into low nibble
andi r19,0x03 //mask off unneeded bits
rjmp ee_all

/*-----------------------------------------------------------------------------------------------------------
C register usage for values passed to block functions-

r25:r24 = eeprom address

r23:r22 = target address for block functions

r20 = count for block functions

r25 bit7 = read/write bit - read = 0, write = 1
-----------------------------------------------------------------------------------------------------------*/
ee_write_block:
ee_read_block:
movw XL,r22
mov r19,r20
ee_all:
movw r30,r24 //addr(r25:r24)-> r31:r30
in r18,0x3f //save SREG(I bit wanted)

push YL //save call-saved registers r28,r29
push YH
ldi YL,0x3F //assume EECR is 0x003F
sbrc r25,6 //if r25 bit6 clear, skip next
ldi YL,0x3C //else bit6 set, EECR is 0x003C
ldi YH,0 //Y = points to EECR

ee_check_rdy0:
cli //irq's off
ldd r0,Y+0 //get EECR
sbrs r0,1 //if EEPE set, not ready
rjmp ee_read_prev //else EEPE clear, continue
ee_check_rdy1:
out 0x3f,r18 //restore irq status
rjmp ee_check_rdy0 //repeat (irq's can run after rjmp)

ee_read_prev:
std Y+3,r31 //r31->EEARH
std Y+2,r30 //r30->EEARL
inc r1 //r1=1 (EERE)
std Y+0,r1 //EERE
ldd r0,Y+1 //EEDR-> r0

//_check_rw:
sbrs r31,7 //if bit7 set, skip next
rjmp ee_read //else is clear, so read

//_write0:
ld r24,X+ //get data
cp r0,r24 //compare to data already in eeprom
breq ee_next1 //if the same, no need to write, so go to next byte

//_write1:
std Y+1,r24 //r24-> EEDR
lsl r1 //r1=2
lsl r1 //r1=4
std Y+0,r1 //EECR write enable
lsr r1 //r1=2
std Y+0,r1 //write
rjmp ee_next1 //skip next

ee_read: //read
st X+,r0 //store ee data
ee_next1:
eor r1,r1
adiw r30,1 //next address (Z +1)
subi r19,1 //dec byte count
brpl ee_check_rdy1 //if plus(>=0), do again
//ee_done:
out 0x3f,r18 //restore irq status
pop YH
pop YL
ret

/*--end----------------------------------------------------------------------------------------------------*/













#if E2END <= 0xFFF

#ifndef _EERW_H_
#define _EERW_H_ 1

/*-----------------------------------------------------------------------------------------------------------
___ ___ _____ __ _ _ ___ _ ___ ___ ___ ___ ___ _ ___
| __| __| _ \ \ / / | || | __| /_\ | \| __| _ \ | __|_ _| | | __|
| _|| _|| /\ \/\/ / | __ | _| / _ \| |) | _|| / | _| | || |__| _|
|___|___|_|_\ \_/\_/ |_||_|___/_/ \_\___/|___|_|_\ |_| |___|____|___|

by Curt Van Maanen
AVR Freaks member- curtvm

eerw.h
-----------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------
___ _ _ _ _ ___ _____ ___ ___ _ _ ___ ___ ___ _____ ___ _______ _____ ___ ___
| __| | | | \| |/ __|_ _|_ _/ _ \| \| | | _ \ _ \/ _ \_ _/ _ \_ _\ \ / / _ \ __/ __|
| _|| |_| | .` | (__ | | | | (_) | .` | | _/ / (_) || || (_) || | \ V /| _/ _|\__ \
|_| \___/|_|\_|\___| |_| |___\___/|_|\_| |_| |_|_\\___/ |_| \___/ |_| |_| |_| |___|___/

do not use directly, use macros below

-----------------------------------------------------------------------------------------------------------*/

//C function prototypes - read
uint8_t ee_read_8bit (const uint8_t* addr);
uint16_t ee_read_16bit (const uint8_t* addr);
uint32_t ee_read_32bit (const uint8_t* addr);
void ee_read_block (const uint8_t* addr,uint8_t* target, uint8_t count);

//C function prototypes - write
void ee_write_8bit (const uint8_t* addr, uint8_t data);
void ee_write_16bit (const uint8_t* addr, uint16_t data);
void ee_write_32bit (const uint8_t* addr, uint32_t data);
void ee_write_block (const uint8_t* addr, uint8_t* target, uint8_t count);

/*-----------------------------------------------------------------------------------------------------------
___ ___ ___ ___ _ _ ___ ___
| \| __| __|_ _| \| | __/ __|
| |) | _|| _| | || .` | _|\__ \
|___/|___|_| |___|_|\_|___|___/

-----------------------------------------------------------------------------------------------------------*/

#define EE_2B 0x1000 //2byte read/write count
#define EE_4B 0x3000 //4byte read/write count
#define EE_WR 0x8000 //write bit

//figure out what address EECR is at
#undef _MMIO_BYTE //temporarily undefine so we can get address of EECR
#define _MMIO_BYTE(mem_addr) mem_addr //new define to get only mem address
#if (EECR == 0x3F) //if EECR==0x3F
#define EE_CR 0 //no bit6 set for eeprom high address
#elif (EECR == 0x3C) //else if EECR==0x3C
#define EE_CR 0x4000 //set bit6 of eeprom address
#else //else EECR is not known
#error "EECR is not at the 2 known locations, eerw library cannot be used"
#endif
#undef _MMIO_BYTE //undefine
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) //get back to original define

/*-----------------------------------------------------------------------------------------------------------
___ _ _ _ _ ___ _____ ___ ___ _ _ __ __ _ ___ ___ ___ ___
| __| | | | \| |/ __|_ _|_ _/ _ \| \| | | \/ | /_\ / __| _ \/ _ \/ __|
| _|| |_| | .` | (__ | | | | (_) | .` | | |\/| |/ _ \ (__| / (_) \__ \
|_| \___/|_|\_|\___| |_| |___\___/|_|\_| |_| |_/_/ \_\___|_|_\\___/|___/

use these macros to access the eeprom functions

-----------------------------------------------------------------------------------------------------------*/

//eeprom read macros
#define EE_RD_8(addr) \
ee_read_8bit ((const uint8_t*)(addr|EE_CR));

#define EE_RD_16(addr) \
ee_read_16bit ((const uint8_t*)(addr|EE_CR|EE_2B));

#define EE_RD_32(addr) \
ee_read_32bit ((const uint8_t*)(addr|EE_CR|EE_4B));

#define EE_RD_BLK(addr,target,count) \
ee_read_block ((const uint8_t*)(addr|EE_CR), (uint8_t*)target, (uint8_t)count);


//eeprom write macros
#define EE_WR_8(addr,data) \
ee_write_8bit((const uint8_t*)(addr|EE_CR|EE_WR),(uint8_t)data);

#define EE_WR_16(addr,data) \
ee_write_16bit ((const uint8_t*)(addr|EE_CR|EE_WR|EE_2B),(uint16_t)data);

#define EE_WR_32(addr,data) \
ee_write_32bit ((const uint8_t*)(addr|EE_CR|EE_WR|EE_4B),(uint32_t)data);

#define EE_WR_BLK(addr,target,count) \
ee_write_block ((const uint8_t*)(addr|EE_CR|EE_WR),(uint8_t*)target,(uint8_t)count);


#endif // _EE_RW_H_

#else
#error "EEPROM size > 0xFFF, eerw library cannot be used"
#endif // E2END <= 0xFFF