Subversion Repositories idreammicro-avr

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
52 jlesech 1
/**************************************************************************//**
2
 * \brief EEPROM 24C32/24C64 library.
3
 * \author Copyright (C) 2012  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20121102
6
 *
7
 * This file is part of the iDreamMicro library.
8
 *
9
 * This library is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU Lesser General Public License as published by the Free
11
 * Software Foundation, either version 3 of the License, or (at your option) any
12
 * later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program. If not, see http://www.gnu.org/licenses/
21
 ******************************************************************************/
22
 
23
/**************************************************************************//**
24
 * \file eeprom_24c32_24c64.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include "../eeprom_24c32_24c64.h"
32
 
33
#include <twi/twi.h>
34
 
35
#include <util/delay.h>
36
 
37
#include <assert.h>
38
#include <stdint.h>
39
#include <stdlib.h>
40
 
41
/******************************************************************************
42
 * Private macro definitions.
43
 ******************************************************************************/
44
 
45
/**************************************************************************//**
46
 * \def     EEPROM_24C32_24C64__ADDRESS
47
 * \brief   EEPROM 24C32/24C64 address. Given by datasheet.
48
 ******************************************************************************/
49
#define EEPROM_24C32_24C64__ADDRESS      0xA0
50
 
51
/**************************************************************************//**
52
 * \def     EEPROM_24C32_24C64__PAGE_SIZE
53
 * \brief   Size of a page in EEPROM memory.
54
 * This size is given by EEPROM memory datasheet.
55
 ******************************************************************************/
56
#define EEPROM_24C32_24C64__PAGE_SIZE    32
57
 
58
/******************************************************************************
59
 * Private function prototypes.
60
 ******************************************************************************/
61
 
62
/**************************************************************************//**
63
 * \fn static void eeprom_24c32_24c64__write_page(
64
 * uint16_t address,
65
 * uint8_t  length,
66
 * uint8_t* p_data)
67
 *
68
 * \brief Write a page in memory.
69
 *
70
 * \param       address Start address of data to write.
71
 * \param       length  Number of bytes to write.
72
 * \param[in]   p_data  Bytes to write.
73
 ******************************************************************************/
74
static
75
void
76
eeprom_24c32_24c64__write_page
77
(
78
    uint16_t    address,
79
    uint8_t     length,
80
    uint8_t*    p_data
81
);
82
 
83
/******************************************************************************
84
 * Private variable declarations.
85
 ******************************************************************************/
86
 
87
static uint8_t device_address = 0;
88
 
89
/******************************************************************************
90
 * Public function definitions.
91
 ******************************************************************************/
92
 
93
/**************************************************************************//**
94
 * \fn void eeprom_24c32_24c64__initialize(uint8_t hardware_address)
95
 *
96
 * \brief Initialize EEPROM 24C32/24C64.
97
 *
98
 * \param hardware_address Hardware address. Pins A0 to A2.
99
 ******************************************************************************/
100
void
101
eeprom_24c32_24c64__initialize
102
(
103
    uint8_t hardware_address
104
){
105
    // Compute device address.
106
    device_address = EEPROM_24C32_24C64__ADDRESS | ((hardware_address & 0x07) << 1);
107
 
108
    // We don't initialize TWI here: we may have several devices on the bus.
109
    // Initialize TWI.
110
    //twi__initialize(EEPROM_24C32_24C64__CLOCK_RATE);
111
}
112
 
113
/**************************************************************************//**
114
 * \fn void eeprom_24c32_24c64__write_byte(uint16_t address, uint8_t data)
115
 *
116
 * \brief Write a byte into memory.
117
 *
118
 * \param   address Address in memory.
119
 * \param   data    Byte to write.
120
 ******************************************************************************/
121
void
122
eeprom_24c32_24c64__write_byte
123
(
124
    uint16_t    address,
125
    uint8_t     data
126
){
127
    twi__start();
128
    twi__send_slaw(device_address);
129
    twi__send_data(address >> 8);
130
    twi__send_data(address & 0xFF);
131
    twi__send_data(data);
132
    twi__stop();
133
}
134
 
135
/**************************************************************************//**
136
 * \fn void eeprom_24c32_24c64__write_bytes(
137
 * uint16_t address,
138
 * uint16_t length,
139
 * uint8_t* p_data)
140
 *
141
 * \brief Write bytes into memory.
142
 *
143
 * \param       address Start address.
144
 * \param       length  Number of bytes to write.
145
 * \param[in]   p_data  Bytes to write.
146
 ******************************************************************************/
147
void
148
eeprom_24c32_24c64__write_bytes
149
(
150
    uint16_t    address,
151
    uint16_t    length,
152
    uint8_t*    p_data
153
){
154
    // Check the preconditions.
155
    assert(NULL != p_data);
156
 
157
    // Write first page if not aligned.
158
    uint8_t not_aligned_length = 0;
159
    uint8_t page_offset = address % EEPROM_24C32_24C64__PAGE_SIZE;
160
    if (page_offset > 0)
161
    {
162
        not_aligned_length = EEPROM_24C32_24C64__PAGE_SIZE - page_offset;
163
        eeprom_24c32_24c64__write_page(address, not_aligned_length, p_data);
164
        length -= not_aligned_length;
165
    }
166
 
167
    if (length > 0)
168
    {
169
        address += not_aligned_length;
170
        p_data += not_aligned_length;
171
 
172
        // Write complete and aligned pages.
173
        uint16_t page_count = length / EEPROM_24C32_24C64__PAGE_SIZE;
174
        for (uint16_t i = 0; i < page_count; i++)
175
        {
176
            eeprom_24c32_24c64__write_page(address, EEPROM_24C32_24C64__PAGE_SIZE, p_data);
177
            address += EEPROM_24C32_24C64__PAGE_SIZE;
178
            p_data += EEPROM_24C32_24C64__PAGE_SIZE;
179
            length -= EEPROM_24C32_24C64__PAGE_SIZE;
180
        }
181
 
182
        if (length > 0)
183
        {
184
            // Write remaining uncomplete page.
185
            eeprom_24c32_24c64__write_page(address, EEPROM_24C32_24C64__PAGE_SIZE, p_data);
186
        }
187
    }
188
}
189
 
190
/**************************************************************************//**
191
 * \fn uint8_t eeprom_24c32_24c64__read_byte(uint16_t address)
192
 *
193
 * \brief Read a byte in memory.
194
 *
195
 * \param address   Address to read.
196
 *
197
 * \return Read byte.
198
 ******************************************************************************/
199
uint8_t
200
eeprom_24c32_24c64__read_byte
201
(
202
    uint16_t address
203
){
204
    uint8_t data = 0;
205
 
206
    twi__start();
207
    twi__send_slaw(device_address);
208
    twi__send_data(address >> 8);
209
    twi__send_data(address & 0xFF);
210
    twi__repeat_start();
211
    twi__send_slar(device_address);
212
    twi__receive_data_nack(&data);
213
    twi__stop();
214
 
215
    return data;
216
}
217
 
218
/**************************************************************************//**
219
 * \fn void eeprom_24c32_24c64__read_bytes(
220
 * uint16_t address,
221
 * uint16_t length,
222
 * uint8_t* p_data)
223
 *
224
 * \brief Read bytes in memory.
225
 *
226
 * \param       address Start address of data to read.
227
 * \param       length  Number of bytes to read.
228
 * \param[in]   p_data  Buffer to fill with read bytes.
229
 ******************************************************************************/
230
void
231
eeprom_24c32_24c64__read_bytes
232
(
233
    uint16_t    address,
234
    uint16_t    length,
235
    uint8_t*    p_data
236
){
237
    // Check the preconditions.
238
    assert(NULL != p_data);
239
 
240
    twi__start();
241
    twi__send_slaw(device_address);
242
    twi__send_data(address >> 8);
243
    twi__send_data(address & 0xFF);
244
    twi__repeat_start();
245
    twi__send_slar(device_address);
246
    for (uint16_t i = 0; i < length - 1; i++)
247
    {
248
        twi__receive_data_ack(p_data + i);
249
    }
250
    twi__receive_data_nack(p_data + length - 1);
251
    twi__stop();
252
}
253
 
254
/******************************************************************************
255
 * Private function definitions.
256
 ******************************************************************************/
257
 
258
/**************************************************************************//**
259
 * \fn static void eeprom_24c32_24c64__write_page(
260
 * uint16_t address,
261
 * uint8_t  length,
262
 * uint8_t* p_data)
263
 *
264
 * \brief Write a page in memory.
265
 *
266
 * \param       address Start address of data to write.
267
 * \param       length  Number of bytes to write.
268
 * \param[in]   p_data  Bytes to write.
269
 ******************************************************************************/
270
static
271
void
272
eeprom_24c32_24c64__write_page
273
(
274
    uint16_t    address,
275
    uint8_t     length,
276
    uint8_t*    p_data
277
){
278
    // Check the preconditions.
279
    assert(NULL != p_data);
280
 
281
    twi__start();
282
    twi__send_slaw(device_address);
283
    twi__send_data(address >> 8);
284
    twi__send_data(address & 0xFF);
285
    for (uint8_t i = 0; i < length; i++)
286
    {
287
        twi__send_data(p_data[i]);
288
    }
289
    twi__stop();
290
 
291
    // Write cycle time (tWR). See EEPROM memory datasheet for more details.
292
    _delay_ms(10);
293
}