Subversion Repositories idreammicro-avr

Rev

Rev 54 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
54 jlesech 1
/**************************************************************************//**
2
 * \brief EEPROM 24C04/24C08/24C16 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_24c04_24c16.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include "../eeprom_24c04_24c16.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_24C04_24C16__ADDRESS
47
 * \brief   EEPROM 24C04/24C08/24C16 address. Given by datasheet.
48
 ******************************************************************************/
49
#define EEPROM_24C04_24C16__ADDRESS      0xA0
50
 
51
/**************************************************************************//**
52
 * \def     EEPROM_24C04_24C16__PAGE_SIZE
53
 * \brief   Size of a page in EEPROM memory.
54
 * This size is given by EEPROM memory datasheet.
55
 ******************************************************************************/
56
#define EEPROM_24C04_24C16__PAGE_SIZE    16
57
 
58
/******************************************************************************
59
 * Private function prototypes.
60
 ******************************************************************************/
61
 
62
/**************************************************************************//**
63
 * \fn static void eeprom_24c04_24c16__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_24c04_24c16__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_24c04_24c16__initialize(uint8_t hardware_address)
95
 *
96
 * \brief Initialize EEPROM 24C04/24C08/24C16.
97
 *
98
 * \param hardware_address Hardware address. Pins A1 to A2.
99
 ******************************************************************************/
100
void
101
eeprom_24c04_24c16__initialize
102
(
103
    uint8_t hardware_address
104
){
105
    // Compute device address.
106
    device_address = EEPROM_24C04_24C16__ADDRESS | ((hardware_address & 0x06) << 1);
107
 
108
    // We don't initialize TWI here: we may have several devices on the bus.
109
    // Initialize TWI.
110
    //twi__initialize(EEPROM_24C04_24C16__CLOCK_RATE);
111
}
112
 
113
/**************************************************************************//**
114
 * \fn void eeprom_24c04_24c16__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_24c04_24c16__write_byte
123
(
124
    uint16_t    address,
125
    uint8_t     data
126
){
127
    twi__start();
128
    twi__send_slaw(device_address | ((address & 0x30) >> 7));
129
    twi__send_data(address & 0xFF);
130
    twi__send_data(data);
131
    twi__stop();
132
}
133
 
134
/**************************************************************************//**
135
 * \fn void eeprom_24c04_24c16__write_bytes(
136
 * uint16_t address,
137
 * uint16_t length,
138
 * uint8_t* p_data)
139
 *
140
 * \brief Write bytes into memory.
141
 *
142
 * \param       address Start address.
143
 * \param       length  Number of bytes to write.
144
 * \param[in]   p_data  Bytes to write.
145
 ******************************************************************************/
146
void
147
eeprom_24c04_24c16__write_bytes
148
(
149
    uint16_t    address,
150
    uint16_t    length,
151
    uint8_t*    p_data
152
){
153
    // Check the preconditions.
154
    assert(NULL != p_data);
155
 
156
    // Write first page if not aligned.
157
    uint8_t not_aligned_length = 0;
158
    uint8_t page_offset = address % EEPROM_24C04_24C16__PAGE_SIZE;
159
    if (page_offset > 0)
160
    {
161
        not_aligned_length = EEPROM_24C04_24C16__PAGE_SIZE - page_offset;
162
        eeprom_24c04_24c16__write_page(address, not_aligned_length, p_data);
163
        length -= not_aligned_length;
164
    }
165
 
166
    if (length > 0)
167
    {
168
        address += not_aligned_length;
169
        p_data += not_aligned_length;
170
 
171
        // Write complete and aligned pages.
172
        uint16_t page_count = length / EEPROM_24C04_24C16__PAGE_SIZE;
173
        for (uint16_t i = 0; i < page_count; i++)
174
        {
175
            eeprom_24c04_24c16__write_page(address, EEPROM_24C04_24C16__PAGE_SIZE, p_data);
176
            address += EEPROM_24C04_24C16__PAGE_SIZE;
177
            p_data += EEPROM_24C04_24C16__PAGE_SIZE;
178
            length -= EEPROM_24C04_24C16__PAGE_SIZE;
179
        }
180
 
181
        if (length > 0)
182
        {
183
            // Write remaining uncomplete page.
55 jlesech 184
            eeprom_24c04_24c16__write_page(address, length, p_data);
54 jlesech 185
        }
186
    }
187
}
188
 
189
/**************************************************************************//**
190
 * \fn uint8_t eeprom_24c04_24c16__read_byte(uint16_t address)
191
 *
192
 * \brief Read a byte in memory.
193
 *
194
 * \param address   Address to read.
195
 *
196
 * \return Read byte.
197
 ******************************************************************************/
198
uint8_t
199
eeprom_24c04_24c16__read_byte
200
(
201
    uint16_t address
202
){
203
    uint8_t data = 0;
204
 
205
    twi__start();
206
    twi__send_slaw(device_address | ((address & 0x30) >> 7));
207
    twi__send_data(address & 0xFF);
208
    twi__repeat_start();
209
    twi__send_slar(device_address);
210
    twi__receive_data_nack(&data);
211
    twi__stop();
212
 
213
    return data;
214
}
215
 
216
/**************************************************************************//**
217
 * \fn void eeprom_24c04_24c16__read_bytes(
218
 * uint16_t address,
219
 * uint16_t length,
220
 * uint8_t* p_data)
221
 *
222
 * \brief Read bytes in memory.
223
 *
224
 * \param       address Start address of data to read.
225
 * \param       length  Number of bytes to read.
226
 * \param[in]   p_data  Buffer to fill with read bytes.
227
 ******************************************************************************/
228
void
229
eeprom_24c04_24c16__read_bytes
230
(
231
    uint16_t    address,
232
    uint16_t    length,
233
    uint8_t*    p_data
234
){
235
    // Check the preconditions.
236
    assert(NULL != p_data);
237
 
238
    twi__start();
239
    twi__send_slaw(device_address | ((address & 0x30) >> 7));
240
    twi__send_data(address & 0xFF);
241
    twi__repeat_start();
242
    twi__send_slar(device_address);
243
    for (uint16_t i = 0; i < length - 1; i++)
244
    {
245
        twi__receive_data_ack(p_data + i);
246
    }
247
    twi__receive_data_nack(p_data + length - 1);
248
    twi__stop();
249
}
250
 
251
/******************************************************************************
252
 * Private function definitions.
253
 ******************************************************************************/
254
 
255
/**************************************************************************//**
256
 * \fn static void eeprom_24c04_24c16__write_page(
257
 * uint16_t address,
258
 * uint8_t  length,
259
 * uint8_t* p_data)
260
 *
261
 * \brief Write a page in memory.
262
 *
263
 * \param       address Start address of data to write.
264
 * \param       length  Number of bytes to write.
265
 * \param[in]   p_data  Bytes to write.
266
 ******************************************************************************/
267
static
268
void
269
eeprom_24c04_24c16__write_page
270
(
271
    uint16_t    address,
272
    uint8_t     length,
273
    uint8_t*    p_data
274
){
275
    // Check the preconditions.
276
    assert(NULL != p_data);
277
 
278
    twi__start();
279
    twi__send_slaw(device_address | ((address & 0x30) >> 7));
280
    twi__send_data(address & 0xFF);
281
    for (uint8_t i = 0; i < length; i++)
282
    {
283
        twi__send_data(p_data[i]);
284
    }
285
    twi__stop();
286
 
287
    // Write cycle time (tWR). See EEPROM memory datasheet for more details.
288
    _delay_ms(10);
289
}