Subversion Repositories idreammicro-avr

Rev

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