Subversion Repositories idreammicro-avr

Rev

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