Subversion Repositories idreammicro-avr

Rev

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

Rev Author Line No. Line
17 jlesech 1
/**************************************************************************//**
2
 * \brief TWI library
3
 * \author Copyright (C) 2009  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20090501
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 twi.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include <twi/twi.h>
32
#include <useful/bits.h>
33
 
34
#include <avr/io.h>
35
#include <util/twi.h>
36
 
37
#include <assert.h>
38
#include <stdint.h>
39
#include <stdlib.h>
40
 
41
/******************************************************************************
42
 * Private macros.
43
 ******************************************************************************/
44
 
45
/**************************************************************************//**
46
 * \def     TWI__MAX_FREQUENCY
47
 * \brief   Max frequency of TWI bus.
48
 ******************************************************************************/
49
#define TWI__MAX_FREQUENCY  400000
50
 
51
/******************************************************************************
52
 * Private types.
53
 ******************************************************************************/
54
 
55
/**************************************************************************//**
56
 * \enum    twi__prescaler_values
57
 * \brief   Available TWI bus prescaler values.
58
 *
59
 * \typedef twi__prescaler_value_t
60
 * \brief   TWI bus prescaler value.
61
 ******************************************************************************/
62
typedef enum twi__prescaler_values
63
{
64
    TWI__PRESCALER_VALUE__1,
65
    TWI__PRESCALER_VALUE__4,
66
    TWI__PRESCALER_VALUE__16,
67
    TWI__PRESCALER_VALUE__64,
68
    TWI__PRESCALER_VALUE__INVALID
69
} twi__prescaler_value_t;
70
 
71
/**************************************************************************//**
72
 * \struct  twi__prescaler_configuration
73
 * \brief   TWI bus prescaler configuration.
74
 *
75
 * \typedef twi__prescaler_configuration_t
76
 * \brief   TWI bus prescaler configuration.
77
 ******************************************************************************/
78
typedef struct twi__prescaler_configuration
79
{
80
    uint8_t value;
81
    uint8_t bits;
82
} twi__prescaler_configuration_t;
83
 
84
/******************************************************************************
85
 * Private constant definitions.
86
 ******************************************************************************/
87
 
88
/**************************************************************************//**
89
 * \var     prescaler_configurations
90
 * \brief   Available prescaler configurations.
91
 ******************************************************************************/
92
static const twi__prescaler_configuration_t prescaler_configurations[] =
93
{
94
    [TWI__PRESCALER_VALUE__1] =
95
    {
96
        .value  = 1,
97
        .bits   = 0
98
    },
99
    [TWI__PRESCALER_VALUE__4] =
100
    {
101
        .value  = 4,
102
        .bits   = _BV(TWPS0)
103
    },
104
    [TWI__PRESCALER_VALUE__16] =
105
    {
106
        .value  = 16,
107
        .bits   = _BV(TWPS1)
108
    },
109
    [TWI__PRESCALER_VALUE__64] =
110
    {
111
        .value  = 64,
112
        .bits   = _BV(TWPS1) | _BV(TWPS0)
113
    }
114
};
115
 
116
/******************************************************************************
117
 * Private function prototypes.
118
 ******************************************************************************/
119
 
120
/**************************************************************************//**
121
 * \fn static inline uint8_t twi__compute_bit_rate(
122
 * uint32_t f_scl,
123
 * uint8_t  prescaler_value)
124
 *
125
 * \brief
126
 *
127
 * \param   f_scl           SCL frequency.
128
 * \param   prescaler_value Prescaler value.
129
 ******************************************************************************/
130
static inline
131
uint8_t
132
twi__compute_bit_rate
133
(
134
    uint32_t    f_scl,
135
    uint8_t     prescaler_value
136
);
137
 
138
/******************************************************************************
139
 * Public function definitions.
140
 ******************************************************************************/
141
 
142
/**************************************************************************//**
143
 * \fn void twi__initialize(uint32_t frequency)
144
 *
145
 * \brief Initialize TWI.
146
 *
147
 * \param   frequency   TWI frequency (up to 400 kHz).
148
 ******************************************************************************/
149
void twi__initialize
150
(
151
    uint32_t frequency
152
){
153
    // Check the preconditions.
154
    assert(TWI__MAX_FREQUENCY >= frequency);
155
 
156
    uint16_t bit_rate = UINT16_MAX;
157
    twi__prescaler_value_t prescaler_value = TWI__PRESCALER_VALUE__1;
158
 
159
    // Compute bit rate and prescaler value.
160
    do
161
    {
162
        bit_rate = twi__compute_bit_rate
163
        (
164
            frequency,
165
            prescaler_configurations[prescaler_value].value
166
        );
167
    } while (UINT8_MAX < bit_rate && TWI__PRESCALER_VALUE__INVALID > prescaler_value++);
168
 
169
    // Set bit rate.
170
    TWBR = bit_rate;
171
 
172
    // Set prescaler value.
173
    TWSR = prescaler_configurations[prescaler_value].bits;
174
}
175
 
176
/**************************************************************************//**
177
 * \fn twi__error_t twi__start(void)
178
 *
179
 * \brief
180
 ******************************************************************************/
181
twi__error_t
182
twi__start
183
(
184
        void
185
){
186
        // Send start condition.
187
        TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
188
 
189
        // Wait for TWINT flag set. This indicates that the START condition has
190
        // been transmitted.
191
        while (!(TWCR & (1 << TWINT)));
192
 
193
        // Check value of TWI Status Register. Mask prescaler bits.
194
        if (TWSR & TW_NO_INFO != TW_START)
195
        {
196
                // If status is different from START (TW_START), return error.
197
                return TWI__ERROR__ERROR;
198
        }
199
 
200
        return TWI__ERROR__NONE;
201
}
202
 
203
/**************************************************************************//**
204
 * \fn twi__error_t twi__repeat_start(void)
205
 *
206
 * \brief
207
 ******************************************************************************/
208
twi__error_t
209
twi__repeat_start
210
(
211
        void
212
){
213
        // TODO: check if TWSTO must be set.
214
        // Send start condition.
215
        TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA) | (1 << TWSTO);
216
 
217
        // Wait for TWINT flag set. This indicates that the START condition has
218
        // been transmitted.
219
        while (!(TWCR & (1 << TWINT)));
220
 
221
        // Check value of TWI Status Register. Mask prescaler bits.
222
        if (TWSR & TW_NO_INFO != TW_REP_START)
223
        {
224
                //  If status different from START (TW_REP_START), return error.
225
                return TWI__ERROR__ERROR;
226
        }
227
 
228
        return TWI__ERROR__NONE;
229
}
230
 
231
/**************************************************************************//**
232
 * \fn twi__error_t twi__send_slar(uint8_t sla)
233
 *
234
 * \brief
235
 *
236
 * \param   sla
237
 ******************************************************************************/
238
twi__error_t
239
twi__send_slar
240
(
241
    uint8_t sla
242
){
243
        // Load SLA into TWDR register.
244
        TWDR = sla | TW_READ;
245
 
246
        // Clear TWINT bit in TWCR to start transmission of address.
247
        TWCR = (1 << TWINT) | (1 << TWEN);
248
 
249
        // Wait for TWINT flag set. This indicates that the SLA+W (TW_WRITE) has
250
        // been transmitted, and ACK/NACK has been received.
251
        while (!(TWCR & (1 << TWINT)));
252
 
253
        // Check value of TWI Status Register. Mask prescaler bits. If status
254
        // different from MT_SLA_ACK (TW_MR_SLA_ACK), return error.
255
        if (TWSR & TW_NO_INFO != TW_MR_SLA_ACK)
256
        {
257
                return TWI__ERROR__ERROR;
258
        }
259
 
260
        return TWI__ERROR__NONE;
261
}
262
 
263
/**************************************************************************//**
264
 * \fn twi__error_t twi__send_slaw(uint8_t sla)
265
 *
266
 * \brief
267
 *
268
 * \param   sla
269
 ******************************************************************************/
270
twi__error_t
271
twi__send_slaw
272
(
273
    uint8_t sla
274
){
275
        // Load SLA into TWDR register.
276
        TWDR = sla | TW_WRITE;
277
 
278
        // Clear TWINT bit in TWCR to start transmission of address.
279
        TWCR = (1 << TWINT) | (1 << TWEN);
280
 
281
        // Wait for TWINT flag set. This indicates that the SLA+W (TW_WRITE) has
282
        // been transmitted, and ACK/NACK has been received.
283
        while (!(TWCR & (1 << TWINT)));
284
 
285
        // Check value of TWI Status Register. Mask prescaler bits. If status
286
        // different from MT_SLA_ACK (TW_MT_SLA_ACK), return error.
287
        if (TWSR & TW_NO_INFO != TW_MT_SLA_ACK)
288
        {
289
                return TWI__ERROR__ERROR;
290
        }
291
 
292
        return TWI__ERROR__NONE;
293
}
294
 
295
/**************************************************************************//**
296
 * \fn twi__error_t twi__send_data(uint8_t data)
297
 *
298
 * \brief
299
 *
300
 * \param   data    Data to send.
301
 ******************************************************************************/
302
twi__error_t
303
twi__send_data
304
(
305
        uint8_t data
306
){
307
        // Load data into TWDR register.
308
        TWDR = data;
309
 
310
        // Clear TWINT bit in TWCR to start transmission of data.
311
        TWCR = (1 << TWINT) | (1 << TWEN);
312
 
313
        // Wait for TWINT flag set. This indicates that the data has been
314
        // transmitted, and ACK/NACK has been receiver.
315
        while (!(TWCR & (1 << TWINT)));
316
 
317
        // Check value of TWI status register. Mask prescaler bits. If status
318
        // different from MT_DATA_ACK (TW_MT_DATA_ACK), return error.
319
        if (TWSR & TW_NO_INFO != TW_MT_DATA_ACK)
320
        {
321
                return TWI__ERROR__ERROR;
322
        }
323
 
324
        return TWI__ERROR__NONE;
325
}
326
 
327
/**************************************************************************//**
328
 * \fn twi__error_t twi__receive_data_ack(uint8_t* p_data)
329
 *
330
 * \brief
331
 *
332
 * \param   p_data
333
 ******************************************************************************/
334
twi__error_t
335
twi__receive_data_ack
336
(
337
        uint8_t* p_data
338
){
339
        // Check the preconditions.
340
        assert(NULL != p_data);
341
 
342
        TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA);
343
 
344
        while (!(TWCR & (1 << TWINT)));
345
 
346
        if ((TWSR & TW_NO_INFO) != TW_MR_DATA_ACK)
347
        {
348
                return TWI__ERROR__ERROR;
349
        }
350
 
351
        *p_data = TWDR;
352
 
353
        return TWI__ERROR__NONE;
354
}
355
 
356
/**************************************************************************//**
357
 * \fn twi__error_t twi__receive_data_nack(uint8_t* p_data)
358
 *
359
 * \brief
360
 *
361
 * \param   p_data
362
 ******************************************************************************/
363
twi__error_t
364
twi__receive_data_nack
365
(
366
        uint8_t* p_data
367
){
368
        // Check the preconditions.
369
        assert(NULL != p_data);
370
 
371
        TWCR = (1 << TWEN) | (1 << TWINT);
372
 
373
        while (!(TWCR & (1 << TWINT)));
374
 
375
        if ((TWSR & TW_NO_INFO) != TW_MR_DATA_NACK)
376
        {
377
                return TWI__ERROR__ERROR;
378
        }
379
 
380
        *p_data = TWDR;
381
 
382
        return TWI__ERROR__NONE;
383
}
384
 
385
/**************************************************************************//**
386
 * \fn void twi__stop(void)
387
 *
388
 * \brief Stop TWI.
389
 ******************************************************************************/
390
void
391
twi__stop
392
(
393
        void
394
){
395
        // Transmit stop operation.
396
        TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
397
 
398
        // Wait for stop.
399
        while (TWCR & (1 << TWSTO));
400
}
401
 
402
/******************************************************************************
403
 * Private function definitions.
404
 ******************************************************************************/
405
 
406
/**************************************************************************//**
407
 * \fn static inline uint8_t twi__compute_bit_rate(
408
 * uint32_t f_scl,
409
 * uint8_t  prescaler_value)
410
 *
411
 * \brief
412
 *
413
 * \param   f_scl           SCL frequency.
414
 * \param   prescaler_value Prescaler value.
415
 ******************************************************************************/
416
static inline
417
uint8_t
418
twi__compute_bit_rate
419
(
420
    uint32_t    f_scl,
421
    uint8_t     prescaler_value
422
){
423
    uint8_t bit_rate = (F_CPU - 16 * f_scl) / (2 * f_scl * prescaler_value);
424
 
425
    return bit_rate;
426
}