forked from haraldwolff/avr-fw-modules
88 lines
1.5 KiB
C
Executable File
88 lines
1.5 KiB
C
Executable File
#include <sys/i2ceeprom.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/assert.h>
|
|
|
|
#include <hwo/i2c.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define DEVICE(x) ((x >> 16)&0x07)
|
|
#define PAGE(x) (x >> 7)
|
|
#define PAGEBASE(x) (x & 0xFF80)
|
|
#define PAGEOFFSET(x) (x & 0x007F)
|
|
|
|
struct i2cee_state {
|
|
uint16_t offset;
|
|
uint16_t len;
|
|
uint8_t *p;
|
|
};
|
|
|
|
static int i2cee_save_cb(void *p,int n,int ch){
|
|
switch (n){
|
|
case 0:
|
|
return (((struct i2cee_state*)p)->offset >> 8) & 0xFF;
|
|
case 1:
|
|
return (((struct i2cee_state*)p)->offset) & 0xFF;
|
|
default:
|
|
if ( (n-2) < ((struct i2cee_state*)p)->len )
|
|
return ((struct i2cee_state*)p)->p[n-2];
|
|
return -1;
|
|
};
|
|
};
|
|
|
|
int i2cee_save(int32_t base,void *p,int16_t len){
|
|
uint8_t *b = p;
|
|
uint16_t ilen,slen;
|
|
int32_t offset = base;
|
|
struct i2cee_state
|
|
state;
|
|
uint8_t n;
|
|
int r;
|
|
|
|
MUTEXED(&i2c.mutex);
|
|
|
|
slen = 0;
|
|
|
|
while (len){
|
|
|
|
if (!(i2cee.emask & (1<<DEVICE(offset))))
|
|
return -ENOFILE;
|
|
|
|
ilen = 128 - PAGEOFFSET(offset);
|
|
if (ilen > len) {
|
|
ilen = len;
|
|
};
|
|
|
|
state.offset = offset;
|
|
state.len = ilen;
|
|
state.p = b;
|
|
|
|
r = i2c_transfer_ex( 0xA0 + (DEVICE(offset) << 1), i2cee_save_cb, &state);
|
|
noassert(r);
|
|
|
|
if ((r >= 0) && (r != (ilen+2))){
|
|
return -ESHORT;
|
|
};
|
|
|
|
for (n=0;n<10;n++){
|
|
r = i2c_transfer( 0xA0 + (DEVICE(offset) << 1), (void*)&offset, 2);
|
|
if (r >= 0) {
|
|
break;
|
|
} else if (r == -EFAIL) {
|
|
wait_ms(1);
|
|
continue;
|
|
} else {
|
|
noassert(r);
|
|
return r;
|
|
};
|
|
};
|
|
assert(r);
|
|
|
|
len -= ilen;
|
|
b += ilen;
|
|
offset += ilen;
|
|
slen += ilen;
|
|
};
|
|
return slen;
|
|
}; |