summaryrefslogtreecommitdiff
path: root/m0EEPROM.cpp
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
}