This repository was archived by the owner on Jan 7, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathuart.hpp.in
More file actions
159 lines (129 loc) · 4.34 KB
/
Copy pathuart.hpp.in
File metadata and controls
159 lines (129 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// coding: utf-8
/* Copyright (c) 2009, Roboterclub Aachen e.V.
* All Rights Reserved.
*
* The file is part of the xpcc library and is released under the 3-clause BSD
* license. See the file `LICENSE` for the full license governing this code.
*/
// ----------------------------------------------------------------------------
{{ generation_block }}
/**
* @ingroup {{target.string}}
* @defgroup {{target.string}}_uart UART
*/
#ifndef XPCC_{{target.family | upper}}__UART{{ id }}_HPP
#define XPCC_{{target.family | upper}}__UART{{ id }}_HPP
#include "../../../device.hpp"
#include <xpcc/architecture/interface/uart.hpp>
#include "type_ids.hpp"
namespace xpcc
{
namespace {{target.family}}
{
/**
* (Non-)Buffered Uart{{ id }}
*
* This implementation uses a ringbuffer. The size of the ringbuffer
* can be changed in the `project.cfg` file.
*
* Just add add a value for `tx_buffer` and/or `rx_buffer` in the
* `parameters` section. The size can be any value between 1 and 254
* for buffered and 0 for non-buffered operation.
*
* Example:
* @code
* [parameters]
* uart.at90_tiny_mega.{{ id }}.tx_buffer = 20
* uart.at90_tiny_mega.{{ id }}.rx_buffer = 30
* @endcode
*
* @author Fabian Greif
* @author Niklas Hauser
* @ingroup {{target.string}}_uart
*/
class Uart{{ id }} : public ::xpcc::Uart
{
public:
static const TypeId::Uart{{ id }}Txd Tx;
static const TypeId::Uart{{ id }}Rxd Rx;
public:
// Expose jinja template parameters to be checked by e.g. drivers or application
static constexpr size_t RxBufferSize = {{ parameters.rx_buffer }};
static constexpr size_t TxBufferSize = {{ parameters.tx_buffer }};
public:
// start documentation inherited
template< class SystemClock, uint32_t baudrate,
uint16_t tolerance = xpcc::Tolerance::TwoPercent >
static xpcc_always_inline void
initialize()
{
// use double speed when necessary
constexpr uint32_t scalar = (baudrate * 16l > SystemClock::Uart) ? 8 : 16;
// calculate the fractional prescaler value
constexpr float pre_raw = static_cast<float>(SystemClock::Uart) / ( scalar * baudrate );
// respect the prescaler range of 1 to 4096
constexpr uint32_t pre_ceil = std::ceil(pre_raw) > 4096 ? 4096 : std::ceil(pre_raw);
constexpr uint32_t pre_floor = std::floor(pre_raw) < 1 ? 1 : std::floor(pre_raw);
// calculate the possible baudrates above and below the requested baudrate
constexpr uint32_t baud_lower = SystemClock::Uart / ( scalar * pre_ceil );
constexpr uint32_t baud_upper = SystemClock::Uart / ( scalar * pre_floor );
// calculate the half-point between the upper and lower baudrate
constexpr uint32_t baud_middle = (baud_upper + baud_lower) / 2;
// decide which prescaler value is closer to a possible baudrate
constexpr uint32_t prescaler = (baudrate < baud_middle) ? pre_ceil : pre_floor;
// check if within baudrate tolerance
constexpr uint32_t generated_baudrate = SystemClock::Uart / ( scalar * prescaler );
assertBaudrateInTolerance<
/* clostest available baudrate */ generated_baudrate,
/* desired baudrate */ baudrate,
tolerance >();
constexpr uint16_t ubrr = (prescaler - 1) | ((scalar == 8) ? 0x8000 : 0);
initialize(ubrr);
}
// MARK: write blocking
static void
writeBlocking(uint8_t data);
static void
writeBlocking(const uint8_t *data, std::size_t length);
static void
flushWriteBuffer();
// MARK: write
static bool
write(uint8_t data);
static std::size_t
write(const uint8_t *data, std::size_t length);
static bool
isWriteFinished();
// MARK: read
static bool
read(uint8_t& data);
static std::size_t
read(uint8_t *buffer, std::size_t length);
// MARK: discard
static std::size_t
discardReceiveBuffer();
static std::size_t
discardTransmitBuffer();
// end documentation inherited
// MARK: error
/**
* Check whether any errors occurred during receiving.
* Be aware that these indicate an error that occurred somewhere
* since resetting the Error Flags (with `acknowledgeErrorFlags()`), so
* you cannot tell which byte had the error.
*
* @return `0` if no errors occurred, otherwise a value that
* corresponds to the Error Flags in register A.
*/
static uint8_t
getErrorFlags();
/// Clears the error flags.
static void
acknowledgeErrorFlags();
protected:
static void
initialize(uint16_t ubrr);
};
} // namespace {{target.family}}
} // namespace xpcc
#endif // XPCC_{{target.family | upper}}__UART{{ id }}_HPP