REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
EEPROM25AA02.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3//
4// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
5
6#include "EEPROM25AA02.h"
7
8const SPISettings functions::EEPROM25AA02::DEFAULT_SPI_SETTINGS{4'000'000, MSBFIRST, SPI_MODE0};
9
11 // Set write enable by sending 0b0000'0110 and cycling chip select
12 // See datasheet for details
14}
15
17 // Unset write enable by sending 0b0000'0100 and cycling chip select
18 // Possibly unnecessary, datasheet says it is reset after successful write
19 // See datasheet for details
20 transfer8(COMMAND_WRITE_DISABLE);
21}
22
23size_t functions::EEPROM25AA02::read(size_t address, size_t length, uint8_t *buffer) const {
24 if (!_is_address_valid(address) || !_is_address_valid(address + length - 1))
25 return 0;
26
27 // Begin SPI communication
28 begin_communication();
29
30 auto spi = get_raw_spi();
31 // Send READ command B00000011
32 spi.transfer(COMMAND_READ);
33 // Send byte offset / address
34 spi.transfer(address);
35 // Read data
36 spi.transfer(nullptr, buffer, length);
37
38 // Release address and stop SPI transaction
39 end_communication();
40
41 return length;
42}
43
44bool functions::EEPROM25AA02::read8(size_t address, uint8_t *data_out) const {
45 return read(address, 1, data_out) == 1;
46}
47
48bool functions::EEPROM25AA02::read16(size_t address, uint16_t *data_out) const {
49 return read(address, 2, (uint8_t *)data_out) == 2;
50}
51
52bool functions::EEPROM25AA02::read32(size_t address, uint32_t *data_out) const {
53 return read(address, 4, (uint8_t *)data_out) == 4;
54}
55
56size_t functions::EEPROM25AA02::write(size_t address, size_t length, const uint8_t *buffer) const {
57 set_write_enable();
58
59#ifdef ANABRID_PEDANTIC
60 auto read_status = read_status_register();
61 if (!read_status.is_write_enabled())
62 return false;
63#endif
64
65 begin_communication();
66 auto spi = get_raw_spi();
67
68 // Check if the last byte of the buffer can fit in the EEPROM
69 const auto last_byte = address + length - 1;
70 if (!_is_address_valid(last_byte))
71 return false;
72
73 auto page_start = address;
74 auto page_end = std::min(
75 last_byte,
76 page_start | ADRESS_MASK); // Write till we hit the end of the current page or the end of the buffer
77
78 while (true) {
79 set_write_enable();
80 begin_communication();
81
82 // Write current page to chip
83 spi.transfer(COMMAND_WRITE);
84 spi.transfer(page_start);
85 spi.transfer(buffer + page_start - address, nullptr, page_end - page_start + 1);
86
87 end_communication();
88
89 // Move to the next page
90 page_start = page_end + 1;
91 if (page_start > last_byte)
92 break; // The whole buffer was written and we are done
93
94 page_end = std::min(
95 last_byte,
96 page_start | ADRESS_MASK); // Write till we hit the end of the current page or the end of the buffer
97
98 // Wait for chip to handle input, before we write more data. Abort write if we timeout
99 if (!await_write_complete())
100 return false;
101 }
102
103 if (!await_write_complete())
104 return false;
105
106#ifdef ANABRID_PEDANTIC
107 uint8_t written_data[length];
108
109 if (!read(address, length, written_data))
110 return false;
111 return memcmp(written_data, buffer, length) == 0;
112#endif
113
114 return length;
115}
116
117bool functions::EEPROM25AA02::write8(size_t address, uint8_t data) const {
118 set_write_enable();
119
120#ifdef ANABRID_PEDANTIC
121 auto read_status = read_status_register();
122 if (!read_status.is_write_enabled())
123 return false;
124#endif
125 // Send WRITE command, byte offset and then data
126 begin_communication();
127 auto spi = get_raw_spi();
128 spi.transfer(COMMAND_WRITE);
129 spi.transfer(address);
130 spi.transfer(data);
131 end_communication();
132
133 if (!await_write_complete())
134 return false;
135
136#ifdef ANABRID_PEDANTIC
137 uint8_t written_data;
138 if (!read8(address, &written_data))
139 return false;
140 return written_data == data;
141#endif
142 return true;
143}
144
145bool functions::EEPROM25AA02::write16(size_t address, uint16_t data) const {
146 uint8_t buffer[2];
147 *(uint16_t *)buffer = data;
148 return write(address, 2, buffer);
149}
150
151bool functions::EEPROM25AA02::write32(size_t address, uint32_t data) const {
152 uint8_t buffer[4];
153 *(uint32_t *)buffer = data;
154 return write(address, 4, buffer);
155}
156
158 begin_communication();
159 auto spi = get_raw_spi();
160 spi.transfer(COMMAND_READ_STATUS_REGISTER);
161 auto data = spi.transfer(0);
162 end_communication();
163 return Status(data);
164}
165
167 // According to datasheet, internal write times are up to 5ms,
168 // and it's recommended to poll the write_in_progress flag
169 uint8_t tries = 0;
170 do {
171 delay(1);
172 if (tries++ > 20)
173 return false;
174 } while (read_status_register().is_write_in_progress());
175 return true;
176}
177
179 set_write_enable();
180
181 begin_communication();
182 auto spi = get_raw_spi();
183 spi.transfer(COMMAND_WRITE_STATUS_REGISTER);
184 spi.transfer(static_cast<uint8_t>(status) & 0b0000'1100);
185 end_communication();
186
187 return await_write_complete();
188}
uint8_t transfer8(uint8_t data_in) const
bool await_write_complete() const
void set_write_enable() const
static const SPISettings DEFAULT_SPI_SETTINGS
Definition EEPROM25AA02.h:8
bool read8(size_t address, uint8_t *data_out) const
Reads one byte at the specified address into the provided pointer. Returns 0 on failure.
bool read16(size_t address, uint16_t *data_out) const
Reads two bytes starting at the specified address into the provided pointer. Returns 0 on failure.
Status read_status_register() const
void unset_write_enable() const
bool write16(size_t address, uint16_t data) const
Writes two bytes starting at the specified address Returns 0 on failure.
bool write_status_register(const Status status) const
size_t read(size_t address, size_t length, uint8_t *buffer) const
Reads the specified number of bytes starting at address into the specified buffer....
bool read32(size_t address, uint32_t *data_out) const
Reads four bytes starting at the specified address into the provided pointer. Returns 0 on failure.
size_t write(size_t address, size_t length, const uint8_t *buffer) const
Writes the specified number of bytes starting at address into the specified buffer....
bool write32(size_t address, uint32_t data) const
Writes four bytes starting at the specified address Returns 0 on failure.
static constexpr uint8_t COMMAND_WRITE_ENABLE
bool write8(size_t address, uint8_t data) const
Writes one byte at the specified address Returns 0 on failure.
utils::status status
Definition daq.h:21
uint32_t
Definition flasher.cpp:195