blob: 10761a7afff92b3ab386a9334f8a76efe118cbbb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// m0EEPROM.cpp - implementation of eeprom memory library
//
#include "Arduino.h"
#include "Wire.h"
#include "RingBuffer.h" // for SERIAL_BUFFER_SIZE
#include "m0EEPROM.h
#define PAGE_SIZE 64 // page size of the 24LC256 in bytes
// get the uint log based 2 of the number.
uint8_t log2uint(uint32_t v) {
uint32_t z = 0;
while (v >>=1) z++;
return z;
}
// read a byte from the specified address in eeprom memory
uint8_t eeprom::read_byte(uint16_t address) {
uint8_t rdata = 0xFF;
Wire.beginTransmission(_device_address);
Wire.write((int)(address >> 8)); // MSB
Wire.write((int)(address & 0xFF)); // LSB
Wire.requestFrom(_device_address,1);
if (Wire.available()) rdata = Wire.read();
return rdata;
}
// write a single byte of data to the given address in eeprom memory
void eeprom::write_byte(uint16_t address, uint8_t value) {
Wire.beginTransmission(_device_address);
Wire.write((int)(address >> 8)); // MSB
Wire.write((int)(address & 0xFF)); // LSB
Wire.write(data);
Wire.endTransmission();
delay(6); // at least 5ms for quiescence
}
// read a structure of arbitrary size from address.
// the size of the structure must be less than 64K-address.
// returns a byte array of memory specified. The byte array data
// must be preallocated to the expected size.
uint8_t* eeprom::read_bytes(uint16_t start_address, uint8_t* data, uint16_t size) {
unsigned char i=0;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,num_chars);
while(Wire.available()) data[i++] = Wire.read();
}
// write a structure of arbitrary size to memory at address.
// the size of the structure must be less than 64K-address.
// The structure is passed as a byte array.
void eeprom::write_bytes(uint16_t address, uint8_t* data, uint16_t size) {
// Uses Page Write for 24LC256
// Allows for EEPROM_PAGE_SIZE byte page boundary
// Splits string into max BUFFER_SIZE byte writes
// uint8_t counter=0;
unsigned int address;
uint32_t first_page_len;
unsigned int num_writes;
// unsigned int data_len=0;
unsigned char first_write_size;
unsigned char last_write_size;
unsigned char write_size;
// get the amount of memory to write in the first page of eeprom
uint8_t page_bits = log2uint(EEPROM_PAGE_SIZE);
first_page = ((start_address >> page_bits) +1) * EEPROM_PAGE_SIZE -startaddress;
// get the size of the first write based on the I2C buffer size
uint8_t buffer_bits = log2uint(SERIAL_BUFFER_SIZE);
if (first_page > SERIAL_BUFFER_SIZE){
first_write_size = first_page - (first_page >> buffer_bits) * SERIAL_BUFFER_SIZE;
if (first_write_size == 0) first_write_size = SERIAL_BUFFER_SIZE;
}
else
first_write_size = first_page;
// now get the size of the last write in the final page
// and the total number of pages to write.
if (size > first_write_size){
last_write_size = (size - first_write_size) % SERIAL_BUFFER_SIZE;
num_writes = ((data_len - first_write_size) >> (buffer_bits)) + 2;
}
else
num_writes = 1;
// Write loop
uint8_t i = 0;
for (uint32_t page = 0; page < num_writes; ++page){
if(page==0)
write_size = first_write_size;
else if (page == (num_writes-1))
write_size = last_write_size;
else write_size = SERIAL_BUFFER_SIZE;
// I2C handshake and comms happens here
Wire.beginTransmission(_device_address);
Wire.write((int)((address) >> 8)); // MSB
Wire.write((int)((address) & 0xFF)); // LSB
for (uint8_t counter=0; counter<write_size; ++counter,++i){
Wire.write(data[i]);
}
Wire.endTransmission();
address += write_size;
delay(6); // needs 5ms for page write
}
|