Subversion Repositories idreammicro-avr

Rev

Rev 17 | Details | Compare with Previous | 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
(
47 jlesech 184
    void
17 jlesech 185
){
47 jlesech 186
    // Send start condition.
187
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
17 jlesech 188
 
47 jlesech 189
    // Wait for TWINT flag set. This indicates that the START condition has
190
    // been transmitted.
191
    while (!(TWCR & (1 << TWINT)));
17 jlesech 192
 
47 jlesech 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;
17 jlesech 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
(
47 jlesech 211
    void
17 jlesech 212
){
47 jlesech 213
    // TODO: check if TWSTO must be set.
214
    // Send start condition.
215
    TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA) | (1 << TWSTO);
17 jlesech 216
 
47 jlesech 217
    // Wait for TWINT flag set. This indicates that the START condition has
218
    // been transmitted.
219
    while (!(TWCR & (1 << TWINT)));
17 jlesech 220
 
47 jlesech 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;
17 jlesech 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
){
47 jlesech 243
    // Load SLA into TWDR register.
244
    TWDR = sla | TW_READ;
17 jlesech 245
 
47 jlesech 246
    // Clear TWINT bit in TWCR to start transmission of address.
247
    TWCR = (1 << TWINT) | (1 << TWEN);
17 jlesech 248
 
47 jlesech 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)));
17 jlesech 252
 
47 jlesech 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
    }
17 jlesech 259
 
47 jlesech 260
    return TWI__ERROR__NONE;
17 jlesech 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
){
47 jlesech 275
    // Load SLA into TWDR register.
276
    TWDR = sla | TW_WRITE;
17 jlesech 277
 
47 jlesech 278
    // Clear TWINT bit in TWCR to start transmission of address.
279
    TWCR = (1 << TWINT) | (1 << TWEN);
17 jlesech 280
 
47 jlesech 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)));
17 jlesech 284
 
47 jlesech 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
    }
17 jlesech 291
 
47 jlesech 292
    return TWI__ERROR__NONE;
17 jlesech 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
(
47 jlesech 305
    uint8_t data
17 jlesech 306
){
47 jlesech 307
    // Load data into TWDR register.
308
    TWDR = data;
17 jlesech 309
 
47 jlesech 310
    // Clear TWINT bit in TWCR to start transmission of data.
311
    TWCR = (1 << TWINT) | (1 << TWEN);
17 jlesech 312
 
47 jlesech 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;
17 jlesech 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
(
47 jlesech 337
    uint8_t* p_data
17 jlesech 338
){
47 jlesech 339
    // Check the preconditions.
340
    assert(NULL != p_data);
17 jlesech 341
 
47 jlesech 342
    TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA);
17 jlesech 343
 
47 jlesech 344
    while (!(TWCR & (1 << TWINT)));
17 jlesech 345
 
47 jlesech 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;
17 jlesech 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
(
47 jlesech 366
    uint8_t* p_data
17 jlesech 367
){
47 jlesech 368
    // Check the preconditions.
369
    assert(NULL != p_data);
17 jlesech 370
 
47 jlesech 371
    TWCR = (1 << TWEN) | (1 << TWINT);
17 jlesech 372
 
47 jlesech 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;
17 jlesech 383
}
384
 
385
/**************************************************************************//**
386
 * \fn void twi__stop(void)
387
 *
388
 * \brief Stop TWI.
389
 ******************************************************************************/
390
void
391
twi__stop
392
(
47 jlesech 393
    void
17 jlesech 394
){
47 jlesech 395
    // Transmit stop operation.
396
    TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
397
 
398
    // Wait for stop.
399
    while (TWCR & (1 << TWSTO));
17 jlesech 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
}