Subversion Repositories idreammicro-avr

Rev

Rev 38 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
12 jlesech 1
/**************************************************************************//**
2
 * \brief USART0 library
3
 * \author Copyright (C) 2011  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20090426
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 usart0_m128.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include "../usart0.h"
32
 
33
#include <usart/usart.h>
34
 
35
#include <useful/bits.h>
36
 
37
#include <avr/interrupt.h>
38
#include <avr/io.h>
39
 
40
#include <assert.h>
25 jlesech 41
#include <stdbool.h>
12 jlesech 42
#include <stdint.h>
43
#include <stdlib.h>
44
 
45
/******************************************************************************
46
 * Private variable declarations.
47
 ******************************************************************************/
48
 
49
static usart__rx_complete_callback_t*           p_rx_complete           = NULL;
50
static usart__tx_complete_callback_t*           p_tx_complete           = NULL;
51
static usart__data_register_empty_callback_t*   p_data_register_empty   = NULL;
52
 
53
static usart__configuration_t configuration =
54
{
55
    .mode       = USART__MODE__ASYNCHRONOUS,
56
    .baudrate   = USART__BAUDRATE__9600,
57
    .data_size  = USART__DATA_SIZE__8_BITS,
58
    .stop_size  = USART__STOP_SIZE__1_BIT,
59
    .parity     = USART__PARITY__DISABLED
60
};
61
 
62
static bool double_speed_is_set = false;
63
 
64
/******************************************************************************
65
 * Private function prototypes.
66
 ******************************************************************************/
67
 
68
/**************************************************************************//**
69
 *
70
 ******************************************************************************/
71
static inline
72
uint16_t
73
usart0__compute_ubrr
74
(
75
    void
76
);
77
 
78
/******************************************************************************
79
 * Public function definitions.
80
 ******************************************************************************/
81
 
82
/**************************************************************************//**
83
 * \fn void usart0__initialize(usart__configuration_t* p_configuration)
84
 *
85
 * \brief Initialize USART0.
86
 *
87
 * \param[in] p_configuration   USART configuration. If null, default settings
88
 *                              will be used.
89
 *
90
 * Default settings:
91
 * - baudrate = 9600 bps;
92
 * - 8 data bits;
93
 * - 1 stop bit;
94
 * - no parity.
95
 ******************************************************************************/
96
void
97
usart0__initialize
98
(
41 jlesech 99
    const usart__configuration_t* p_configuration
12 jlesech 100
){
101
    // If p_configuration is not null, use it!
102
    if (NULL != p_configuration)
103
    {
104
        configuration = *p_configuration;
105
    }
106
 
107
    // Set mode.
108
    usart0__set_mode(configuration.mode);
109
 
110
    // Set baud rate.
111
    usart0__set_baudrate(configuration.baudrate);
112
    usart0__set_double_speed(false);
113
 
114
    // Configure settings.
115
    usart0__set_data_size(configuration.data_size);
116
    usart0__set_stop_size(configuration.stop_size);
117
    usart0__set_parity(configuration.parity);
118
}
119
 
120
/**************************************************************************//**
121
 * \fn void usart0__set_baudrate(usart__baudrate_t baudrate)
122
 *
123
 * \brief Set USART0 baudrate.
124
 *
125
 * \param baudrate baudrate to set (in bauds per second)
126
 ******************************************************************************/
127
void
128
usart0__set_baudrate
129
(
130
    usart__baudrate_t baudrate
131
){
132
    configuration.baudrate = baudrate;
133
 
134
    uint16_t ubrr = usart0__compute_ubrr();
135
    UBRR0H = (uint8_t)(ubrr >> 8);
136
    UBRR0L = (uint8_t)ubrr;
137
}
138
 
139
/**************************************************************************//**
140
 * \fn void usart0__set_mode(usart__mode_t usart_mode)
141
 *
142
 * \brief Set USART0 mode.
143
 *
144
 * \param usart_mode Mode to set.
145
 ******************************************************************************/
146
void
147
usart0__set_mode
148
(
149
    usart__mode_t usart_mode
150
){
151
    // Check the preconditions.
152
    assert(USART__MODE__INVALID > usart_mode);
153
 
154
    configuration.mode = usart_mode;
155
 
156
    switch (usart_mode)
157
    {
158
        case USART__MODE__ASYNCHRONOUS:
159
        {
15 jlesech 160
            BIT__RST(UCSR0C, UMSEL0);
12 jlesech 161
        }
162
        break;
163
 
164
        case USART__MODE__SYNCHRONOUS:
165
        {
166
            BIT__SET(UCSR0C, UMSEL0);
167
        }
168
        break;
169
 
170
        case USART__MODE__MASTER_SPI:
171
        case USART__MODE__INVALID:
172
        default:
173
        break;
174
    }
175
}
176
 
177
/**************************************************************************//**
178
 * \fn void usart0__set_data_size(usart__data_sizet data_size)
179
 *
180
 * \brief Set USART0 data size.
181
 *
182
 * \param data_size data size (in bits)
183
 ******************************************************************************/
184
void
185
usart0__set_data_size
186
(
187
    usart__data_size_t data_size
188
){
189
    configuration.data_size = data_size;
190
 
191
    switch (data_size)
192
    {
193
        case USART__DATA_SIZE__5_BITS:
194
        {
15 jlesech 195
            BIT__RST(UCSR0B, UCSZ02);
196
            BIT__RST(UCSR0C, UCSZ01);
197
            BIT__RST(UCSR0C, UCSZ00);
12 jlesech 198
        }
199
        break;
200
 
201
        case USART__DATA_SIZE__6_BITS:
202
        {
15 jlesech 203
            BIT__RST(UCSR0B, UCSZ02);
204
            BIT__RST(UCSR0C, UCSZ01);
12 jlesech 205
            BIT__SET(UCSR0C, UCSZ00);
206
        }
207
        break;
208
 
209
        case USART__DATA_SIZE__7_BITS:
210
        {
15 jlesech 211
            BIT__RST(UCSR0B, UCSZ02);
12 jlesech 212
            BIT__SET(UCSR0C, UCSZ01);
15 jlesech 213
            BIT__RST(UCSR0C, UCSZ00);
12 jlesech 214
        }
215
        break;
216
 
217
        case USART__DATA_SIZE__8_BITS:
218
        {
15 jlesech 219
            BIT__RST(UCSR0B, UCSZ02);
12 jlesech 220
            BIT__SET(UCSR0C, UCSZ01);
221
            BIT__SET(UCSR0C, UCSZ00);
222
        }
223
        break;
224
 
225
        case USART__DATA_SIZE__9_BITS:
226
        {
227
            BIT__SET(UCSR0B, UCSZ02);
228
            BIT__SET(UCSR0C, UCSZ01);
229
            BIT__SET(UCSR0C, UCSZ00);
230
        }
231
        break;
232
 
233
        default:
234
        break;
235
    }
236
}
237
 
238
/**************************************************************************//**
239
 * \fn void usart0__set_stop_size(usart__stop_size_t stop_size)
240
 *
241
 * \brief Set USART0 stop size.
242
 *
243
 * \param stop_size stop size (in bits)
244
 ******************************************************************************/
245
void
246
usart0__set_stop_size
247
(
248
    usart__stop_size_t stop_size
249
){
250
    configuration.stop_size = stop_size;
251
 
252
    if (USART__STOP_SIZE__1_BIT == stop_size)
253
    {
15 jlesech 254
        BIT__RST(UCSR0C, USBS0);
12 jlesech 255
    }
256
    else
257
    {
258
        BIT__SET(UCSR0C, USBS0);
259
    }
260
}
261
 
262
/**************************************************************************//**
263
 * \fn void usart0__set_parity(usart__parity_t parity)
264
 *
265
 * \brief Set USART0 parity.
266
 *
267
 * \param parity parity to set
268
 ******************************************************************************/
269
void
270
usart0__set_parity
271
(
272
    usart__parity_t parity
273
){
274
    configuration.parity = parity;
275
 
276
    switch (parity)
277
    {
278
        case USART__PARITY__DISABLED:
279
        {
15 jlesech 280
            BIT__RST(UCSR0C, UPM01);
281
            BIT__RST(UCSR0C, UPM00);
12 jlesech 282
        }
283
        break;
284
 
285
        case USART__PARITY__EVEN:
286
        {
287
            BIT__SET(UCSR0C, UPM01);
15 jlesech 288
            BIT__RST(UCSR0C, UPM00);
12 jlesech 289
        }
290
        break;
291
 
292
        case USART__PARITY__ODD:
293
        {
294
            BIT__SET(UCSR0C, UPM01);
295
            BIT__SET(UCSR0C, UPM00);
296
        }
297
        break;
298
 
299
        default:
300
        break;
301
    }
302
}
303
 
304
/**************************************************************************//**
305
 * \fn void usart0__set_double_speed(bool double_speed)
306
 *
307
 * \brief Set double speed.
308
 *
309
 * \param   double_speed    True to set double speed, false otherwise.
310
 ******************************************************************************/
311
void
312
usart0__set_double_speed
313
(
314
    bool double_speed
315
){
316
    double_speed_is_set = double_speed;
317
 
318
    if (double_speed_is_set)
319
    {
320
        BIT__SET(UCSR0A, U2X0);
321
    }
322
    else
323
    {
15 jlesech 324
        BIT__RST(UCSR0A, U2X0);
12 jlesech 325
    }
326
}
327
 
328
/**************************************************************************//**
329
 * \fn void usart0__enable_receiver(void)
330
 *
331
 * \brief Enable USART 0 receiver.
332
 ******************************************************************************/
333
void
334
usart0__enable_receiver
335
(
336
    void
337
){
338
    BIT__SET(UCSR0B, RXEN0);
339
}
340
 
341
/**************************************************************************//**
342
 * \fn void usart0__disable_receiver(void)
343
 *
344
 * \brief Disable USART 0 receiver.
345
 ******************************************************************************/
346
void
347
usart0__disable_receiver
348
(
349
    void
350
){
15 jlesech 351
    BIT__RST(UCSR0B, RXEN0);
12 jlesech 352
}
353
 
354
/**************************************************************************//**
355
 * \fn void usart0__enable_transmitter(void)
356
 *
357
 * \brief Enable USART 0 transmitter.
358
 ******************************************************************************/
359
void
360
usart0__enable_transmitter
361
(
362
    void
363
){
364
    BIT__SET(UCSR0B, TXEN0);
365
}
366
 
367
/**************************************************************************//**
368
 * \fn void usart0__disable_transmitter(void)
369
 *
370
 * \brief Disable USART 0 transmitter.
371
 ******************************************************************************/
372
void
373
usart0__disable_transmitter
374
(
375
    void
376
){
15 jlesech 377
    BIT__RST(UCSR0B, TXEN0);
12 jlesech 378
}
379
 
380
/**************************************************************************//**
381
 * \fn uint8_t usart0__receive_byte(void)
382
 *
383
 * \brief Receive a byte on USART0.
384
 *
385
 * \return received byte
386
 ******************************************************************************/
387
uint16_t
388
usart0__receive_byte
389
(
390
    void
391
){
392
    // Wait for data to be received.
393
    while (!(UCSR0A & (1 << RXC0)));
394
 
395
    // Get received data.
396
    uint16_t received_byte = UDR0;
397
 
398
    if (USART__DATA_SIZE__9_BITS == configuration.data_size)
399
    {
400
        // If 9-bit data size, get 9th bit.
401
        uint8_t resh = UCSR0B;
402
        resh = (resh >> 1) & 0x01;
403
        received_byte = (resh << 8) | received_byte;
404
    }
405
 
406
    // Return received data from buffer.
407
    return received_byte;
408
}
409
 
410
/**************************************************************************//**
411
 * \fn usart0__transmit_byte(uint8_t byte_to_transmit)
412
 *
413
 * \brief Transmit a byte on USART0.
414
 *
415
 * \param byte_to_transmit byte to transmit
416
 ******************************************************************************/
417
void
418
usart0__transmit_byte
419
(
420
    uint16_t byte_to_transmit
421
){
422
    // Wait for empty transmit buffer.
423
    while (!(UCSR0A & (1 << UDRE0)));
424
 
425
    if (USART__DATA_SIZE__9_BITS == configuration.data_size)
426
    {
427
        // If 9-bit data size, copy 9th bit to TXB80.
428
        UCSR0B &= ~(1 << TXB80);
429
        if (byte_to_transmit & 0x0100)
430
        {
431
            UCSR0B |= (1 << TXB80);
432
        }
433
    }
434
 
435
    // Put data into transmit buffer, sends the data.
436
    UDR0 = byte_to_transmit;
437
}
438
 
439
/**************************************************************************//**
440
 * \fn void usart0__flush(void)
441
 *
442
 * \brief Flush USART0 receiver buffer.
443
 ******************************************************************************/
444
void
445
usart0__flush
446
(
447
    void
448
){
449
    uint8_t dummy = 0;
450
    while (UCSR0A & (1 << RXC0))
451
    {
452
        dummy = UDR0;
453
    }
454
}
455
 
456
/**************************************************************************//**
457
 * \fn void usart0__enable_rx_complete_interrupt(void)
458
 *
459
 * \brief Enable USART 0 receive complete interrupt.
460
 ******************************************************************************/
461
void
462
usart0__enable_rx_complete_interrupt
463
(
464
    void
465
){
466
    BIT__SET(UCSR0B, RXCIE0);
467
    sei();
468
}
469
 
470
/**************************************************************************//**
471
 * \fn void usart0__disable_rx_complete_interrupt(void)
472
 *
473
 * \brief Disable USART 0 receive complete interrupt.
474
 ******************************************************************************/
475
void
476
usart0__disable_rx_complete_interrupt
477
(
478
    void
479
){
15 jlesech 480
    BIT__RST(UCSR0B, RXCIE0);
12 jlesech 481
    sei();
482
}
483
 
484
/**************************************************************************//**
485
 * \fn void usart0__set_rx_complete_callback(
486
 * const usart__rx_complete_callback_t* p_callback)
487
 *
488
 * \brief Set a callback to call when receive byte complete interrupt is generated.
489
 *
490
 * \param[in]   p_callback  Callback to set.
491
 ******************************************************************************/
492
void
493
usart0__set_rx_complete_callback
494
(
495
    const usart__rx_complete_callback_t*  p_callback
496
){
497
    // Check the preconditions.
498
    assert(NULL != p_callback);
499
 
500
    p_rx_complete = p_callback;
501
}
502
 
503
/**************************************************************************//**
504
 *
505
 ******************************************************************************/
506
void
507
usart0__enable_tx_complete_interrupt
508
(
509
    void
510
){
511
    BIT__SET(UCSR0B, TXCIE0);
512
    sei();
513
}
514
 
515
/**************************************************************************//**
516
 *
517
 ******************************************************************************/
518
void
519
usart0__disable_tx_complete_interrupt
520
(
521
    void
522
){
15 jlesech 523
    BIT__RST(UCSR0B, TXCIE0);
12 jlesech 524
    sei();
525
}
526
 
527
/**************************************************************************//**
528
 *
529
 ******************************************************************************/
530
void
531
usart0__set_tx_complete_callback
532
(
533
    const usart__tx_complete_callback_t*  p_callback
534
){
535
    // Check the preconditions.
536
    assert(NULL != p_callback);
537
 
538
    p_tx_complete = p_callback;
539
}
540
 
541
/**************************************************************************//**
542
 *
543
 ******************************************************************************/
544
void
545
usart0__enable_data_register_empty_interrupt
546
(
547
    void
548
){
549
    BIT__SET(UCSR0B, UDRIE0);
550
    sei();
551
}
552
 
553
/**************************************************************************//**
554
 *
555
 ******************************************************************************/
556
void
557
usart0__disable_data_register_empty_interrupt
558
(
559
    void
560
){
15 jlesech 561
    BIT__RST(UCSR0B, UDRIE0);
12 jlesech 562
    sei();
563
}
564
 
565
/**************************************************************************//**
566
 *
567
 ******************************************************************************/
568
void
569
usart0__set_data_register_empty_callback
570
(
571
    const usart__data_register_empty_callback_t*  p_callback
572
){
573
    // Check the preconditions.
574
    assert(NULL != p_callback);
575
 
576
    p_data_register_empty = p_callback;
577
}
578
 
579
/******************************************************************************
580
 * Private function definitions.
581
 ******************************************************************************/
582
 
583
/**************************************************************************//**
584
 * \fn static uint16_t usart0__compute_ubrr(void)
585
 *
586
 * \brief Compute ubrr value.
587
 *
588
 * \return ubrr value.
589
 ******************************************************************************/
590
static inline
591
uint16_t
592
usart0__compute_ubrr
593
(
594
    void
595
){
596
    uint16_t ubrr = 0;
597
 
598
    switch (configuration.mode)
599
    {
600
        case USART__MODE__ASYNCHRONOUS:
601
        {
602
            if (!double_speed_is_set)
603
            {
38 jlesech 604
                ubrr = F_CPU / (16 * usart__baudrate_values[configuration.baudrate]) - 1;
12 jlesech 605
            }
606
            else
607
            {
38 jlesech 608
                ubrr = F_CPU / (8 * usart__baudrate_values[configuration.baudrate]) - 1;
12 jlesech 609
            }
610
        }
611
        break;
612
 
613
        case USART__MODE__SYNCHRONOUS:
614
        {
38 jlesech 615
            ubrr = F_CPU / (2 * usart__baudrate_values[configuration.baudrate]) - 1;
12 jlesech 616
        }
617
        break;
618
 
619
        case USART__MODE__MASTER_SPI:
620
        break;
621
 
622
        default:
623
        break;
624
    }
625
 
626
    return ubrr;
627
}
628
 
629
/******************************************************************************
630
 * Interrupt vectors.
631
 ******************************************************************************/
632
 
633
/**************************************************************************//**
634
 * \fn ISR(USART_RX_vect)
635
 ******************************************************************************/
636
ISR(USART0_RX_vect)
637
{
638
    if (NULL != p_rx_complete)
639
    {
640
        p_rx_complete();
641
    }
642
}
643
 
644
/**************************************************************************//**
645
 * \fn ISR(USART_TX_vect)
646
 ******************************************************************************/
647
ISR(USART0_TX_vect)
648
{
649
    if (NULL != p_tx_complete)
650
    {
651
        p_tx_complete();
652
    }
653
}
654
 
655
/**************************************************************************//**
656
 * \fn ISR(USART_UDRE_vect)
657
 ******************************************************************************/
658
ISR(USART0_UDRE_vect)
659
{
660
    if (NULL != p_data_register_empty)
661
    {
662
        p_data_register_empty();
663
    }
664
}