Subversion Repositories idreammicro-avr

Rev

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

Rev Author Line No. Line
45 jlesech 1
/**************************************************************************//**
2
 * \brief EEPROM 24C512 library.
3
 * \author Copyright (C) 2012  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20121031
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_24c512.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include "../eeprom_24c512.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_24C512__ADDRESS
47
 * \brief   EEPROM 24C512 address. Given by datasheet.
48
 ******************************************************************************/
49
#define EEPROM_24C512__ADDRESS      0xA0
50
 
51
/**************************************************************************//**
52
 * \def     EEPROM__PAGE_SIZE
53
 * \brief   Size of a page in EEPROM memory.
54
 * This size is given by EEPROM memory datasheet.
55
 ******************************************************************************/
56
#define EEPROM_24C512__PAGE_SIZE    128
57
 
58
/******************************************************************************
59
 * Private function prototypes.
60
 ******************************************************************************/
61
 
62
/**************************************************************************//**
63
 *
64
 ******************************************************************************/
46 jlesech 65
static
45 jlesech 66
void
67
eeprom_24c512__write_page
68
(
69
    uint16_t    address,
70
    uint8_t     length,
71
    uint8_t*    p_data
46 jlesech 72
);
45 jlesech 73
 
74
/******************************************************************************
75
 * Private variable declarations.
76
 ******************************************************************************/
77
 
78
static uint8_t device_address = 0;
79
 
80
/******************************************************************************
81
 * Public function definitions.
82
 ******************************************************************************/
83
 
84
/**************************************************************************//**
85
 * \fn void eeprom_24c512__initialize(uint8_t hardware_address)
86
 *
87
 * \brief Initialize EEPROM 24C512.
88
 *
89
 * \param hardware_address Hardware address. Pins A0 to A2.
90
 ******************************************************************************/
91
void
92
eeprom_24c512__initialize
93
(
94
    uint8_t hardware_address
95
){
96
    // Compute device address.
97
    device_address = EEPROM_24C512__ADDRESS | (hardware_address << 1);
98
 
99
    // We don't initialize TWI here: we may have several devices on the bus.
100
    // Initialize TWI.
101
    //twi__initialize(EEPROM_24C512__CLOCK_RATE);
102
}
103
 
104
/**************************************************************************//**
105
 * \fn void eeprom_24c512__write_byte(uint16_t address, uint8_t data)
106
 *
107
 * \brief Write a byte into memory.
108
 *
109
 * \param   address Address in memory.
110
 * \param   data    Byte to write.
111
 ******************************************************************************/
112
void
113
eeprom_24c512__write_byte
114
(
115
    uint16_t    address,
116
    uint8_t     data
117
){
118
    twi__start();
119
    twi__send_slaw(device_address);
120
    twi__send_data(address >> 8);
121
    twi__send_data(address & 0xFF);
122
    twi__send_data(data);
123
    twi__stop();
124
}
125
 
126
/**************************************************************************//**
127
 * \fn void eeprom_24c512__write_bytes(
128
 * uint16_t address,
129
 * uint16_t length,
130
 * uint8_t* p_data)
131
 *
132
 * \brief Write bytes into memory.
133
 *
134
 * \param       address Start address.
135
 * \param       length  Number of bytes to write.
136
 * \param[in]   p_data  Bytes to write.
137
 ******************************************************************************/
138
void
139
eeprom_24c512__write_bytes
140
(
141
    uint16_t    address,
142
    uint16_t    length,
143
    uint8_t*    p_data
144
){
145
    // Check the preconditions.
146
    assert(NULL != p_data);
147
 
148
    // Write first page if not aligned.
149
    uint8_t not_aligned_length = 0;
150
    uint8_t page_offset = address % EEPROM_24C512__PAGE_SIZE;
151
    if (page_offset > 0)
152
    {
153
        not_aligned_length = EEPROM_24C512__PAGE_SIZE - page_offset;
154
        eeprom_24c512__write_page(address, not_aligned_length, p_data);
155
        length -= not_aligned_length;
156
    }
157
 
158
    if (length > 0)
159
    {
160
        address += not_aligned_length;
161
        p_data += not_aligned_length;
162
 
163
        // Write complete and aligned pages.
164
        uint16_t page_count = length / EEPROM_24C512__PAGE_SIZE;
165
        for (uint16_t i = 0; i < page_count; i++)
166
        {
167
            eeprom_24c512__write_page(address, EEPROM_24C512__PAGE_SIZE, p_data);
168
            address += EEPROM_24C512__PAGE_SIZE;
169
            p_data += EEPROM_24C512__PAGE_SIZE;
170
            length -= EEPROM_24C512__PAGE_SIZE;
171
        }
172
 
173
        if (length > 0)
174
        {
175
            // Write remaining uncomplete page.
176
            eeprom_24c512__write_page(address, EEPROM_24C512__PAGE_SIZE, p_data);
177
        }
178
    }
179
}
180
 
181
/**************************************************************************//**
182
 * \fn uint8_t eeprom_24c512__read_byte(uint16_t address)
183
 *
184
 * \brief Read a byte in memory.
185
 *
186
 * \param address   Address to read.
187
 *
188
 * \return Read byte.
189
 ******************************************************************************/
190
uint8_t
191
eeprom_24c512__read_byte
192
(
193
    uint16_t address
194
){
195
    uint8_t data = 0;
196
 
197
    twi__start();
198
    twi__send_slaw(device_address);
199
    twi__send_data(address >> 8);
200
    twi__send_data(address & 0xFF);
201
    twi__stop();
202
 
203
    twi__start();
204
    twi__send_slar(device_address);
205
    twi__receive_data_nack(&data);
206
    twi__stop();
207
 
208
    return data;
209
}
210
 
211
/**************************************************************************//**
212
 * \fn void eeprom_24c512__read_bytes(
213
 * uint16_t address,
214
 * uint16_t length,
215
 * uint8_t* p_data)
216
 *
217
 * \brief Read bytes in memory.
218
 *
219
 * \param       address Start address of data to read.
220
 * \param       length  Number of bytes to read.
221
 * \param[in]   p_data  Buffer to fill with read bytes.
222
 ******************************************************************************/
223
void
224
eeprom_24c512__read_bytes
225
(
226
    uint16_t    address,
227
    uint16_t    length,
228
    uint8_t*    p_data
229
){
230
    // Check the preconditions.
231
    assert(NULL != p_data);
232
 
233
    twi__start();
234
    twi__send_slaw(device_address);
235
    twi__send_data(address >> 8);
236
    twi__send_data(address & 0xFF);
237
    twi__stop();
238
 
239
    twi__start();
240
    twi__send_slar(device_address);
241
    for (uint16_t i = 0; i < length - 1; i++)
242
    {
243
        twi__receive_data_ack(p_data + i);
244
    }
245
    twi__receive_data_nack(p_data + length - 1);
246
    twi__stop();
247
}
248
 
249
/******************************************************************************
250
 * Private function definitions.
251
 ******************************************************************************/
252
 
253
/**************************************************************************//**
254
 * \fn static void eeprom_24c512__write_page(
255
 * uint16_t address,
256
 * uint8_t  length,
257
 * uint8_t* p_data)
258
 *
259
 * \brief Write a page in memory.
260
 *
261
 * \param       address Start address of data to write.
262
 * \param       length  Number of bytes to write.
263
 * \param[in]   p_data  Bytes to write.
264
 ******************************************************************************/
46 jlesech 265
static
45 jlesech 266
void
267
eeprom_24c512__write_page
268
(
269
    uint16_t    address,
270
    uint8_t     length,
271
    uint8_t*    p_data
272
){
273
    // Check the preconditions.
274
    assert(NULL != p_data);
275
 
276
    twi__start();
277
    twi__send_slaw(device_address);
278
    twi__send_data(address >> 8);
279
    twi__send_data(address & 0xFF);
280
    for (uint8_t i = 0; i < length; i++)
281
    {
282
        twi__send_data(p_data[i]);
283
    }
284
    twi__stop();
285
 
286
    // Write cycle time (tWR). See EEPROM memory datasheet for more details.
287
    _delay_ms(10);
288
}