CuVoodoo STM32F1 firmware template
usart_enhanced.c
Go to the documentation of this file.
1 /* This program is free software: you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation, either version 3 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
23 /* standard libraries */
24 #include <stdint.h> // standard integer types
25 
26 /* STM32 (including CM3) libraries */
27 #include <libopencm3/stm32/usart.h> // USART utilities
28 
29 /* own libraries */
30 #include "usart_enhanced.h" // utilities for USART enhancements
31 
33 #define USART_PERIPHERALS_NB 3
34 
40 
41 const bool usart_enhanced_even_parity_lut[256] = { true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false, true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true, };
42 
48 static uint8_t usart_enhanced_id(uint32_t usart)
49 {
50  uint8_t to_return = USART_PERIPHERALS_NB;
51  switch (usart) {
52  case USART1:
53  to_return = 0;
54  break;
55  case USART2:
56  to_return = 1;
57  break;
58  case USART3:
59  to_return = 2;
60  break;
61  default:
62  to_return = USART_PERIPHERALS_NB;
63  break;
64  }
65  return to_return;
66 }
67 
68 bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity)
69 {
70  /* sanity check */
71  uint8_t id = usart_enhanced_id(usart);
72  if (id>=USART_PERIPHERALS_NB) {
73  return false;
74  }
75  if (databits<5 || databits>8) {
76  return false;
77  }
78  if (parity>USART_ENHANCED_PARITY_SPACE) {
79  return false;
80  }
81 
82  // save configuration for later use
83  usart_enhanced_databits[id] = databits;
84  usart_enhanced_parity[id] = parity;
85  // configure USART peripheral
86  if (8 == databits && USART_ENHANCED_PARITY_NONE != parity) { // the parity bit is additional to the data bits
87  usart_set_databits(usart, 9);
88  } else {
89  usart_set_databits(usart, 8);
90  }
91  usart_set_parity(usart, USART_PARITY_NONE); // set no parity since we will take care of it ourselves
92  // we could also lower the number of stop bits when less than 8 bits are used, for higher throughput, but this is not a good idea since most UART transceiver parse 8 bits even is less is used
93  return true;
94 }
95 
96 void usart_enhanced_send(uint32_t usart, uint8_t data)
97 {
98  /* sanity check */
99  uint8_t id = usart_enhanced_id(usart);
100  if (id >= USART_PERIPHERALS_NB) {
101  return;
102  }
103 
104  data &= ~(0xff << usart_enhanced_databits[id]); // only keep the data bits
105  uint16_t output = data; // put value in output buffer
106  switch (usart_enhanced_parity[id]) {
107  case USART_ENHANCED_PARITY_NONE: // a mark is also decoded as idle/stop
109  output |= (1 << usart_enhanced_databits[id]); // add idle state
110  break;
112  if (!usart_enhanced_even_parity_lut[data]) {
113  output |= (1 << usart_enhanced_databits[id]);
114  }
115  // no need to clear a bit if the parity is even
116  break;
118  if (usart_enhanced_even_parity_lut[data]) {
119  output |= (1 << usart_enhanced_databits[id]);
120  }
121  // no need to clear a bit if the parity is odd
122  break;
124  // no need to clear the bit
125  break;
126  }
127  output |= (0xffff << (usart_enhanced_databits[id] + 1)); // set additional bits to idle (high)
128  usart_send(usart, output); // transmit character
129 }
130 
131 uint8_t usart_enhanced_recv(uint32_t usart)
132 {
133  /* sanity check */
134  uint8_t id = usart_enhanced_id(usart);
135  if (id >= USART_PERIPHERALS_NB) {
136  return 0xff;
137  }
138 
139  uint16_t input = usart_recv(usart); // read received character (also clears the error flags)
140  uint8_t data = input & ~(0xffff << usart_enhanced_databits[id]); // only keep the data bits
141  // check the parity
142  uint16_t parity = input & (1 << usart_enhanced_databits[id]); // only keep the parity bit
143  usart_enhanced_parity_errors[id] = false;
144  switch (usart_enhanced_parity[id]) {
146  usart_enhanced_parity_errors[id] = false;
147  break;
149  if (parity) {
151  } else {
153  }
154  break;
156  if (parity) {
158  } else {
160  }
161  break;
163  usart_enhanced_parity_errors[id] = !parity;
164  break;
166  usart_enhanced_parity_errors[id] = parity;
167  break;
168  }
169  return data;
170 }
171 
172 bool usart_enhanced_parity_error(uint32_t usart)
173 {
174  /* sanity check */
175  uint8_t id = usart_enhanced_id(usart);
176  if (id >= USART_PERIPHERALS_NB) {
177  return false;
178  }
179  return usart_enhanced_parity_errors[id];
180 }
void usart_enhanced_send(uint32_t usart, uint8_t data)
send data over the enhanced USART using the configuration
#define USART_PERIPHERALS_NB
number of available USART peripherals
usart_enhanced_parity_t
enhanced USART setting for the additional parity bit
static uint8_t usart_enhanced_id(uint32_t usart)
get index of corresponding enhanced USART configurations
static enum usart_enhanced_parity_t usart_enhanced_parity[USART_PERIPHERALS_NB]
configured enhanced USART parity
bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity)
configure enhanced USART
uint8_t usart_enhanced_recv(uint32_t usart)
receive data over the enhanced USART using the configuration
static uint8_t usart_enhanced_databits[USART_PERIPHERALS_NB]
configured enhanced USART word size
bool usart_enhanced_parity_error(uint32_t usart)
get the parity status of the received data
static bool usart_enhanced_parity_errors[USART_PERIPHERALS_NB]
last enhanced USART parity error status
library for enhanced USART communication (API)
const bool usart_enhanced_even_parity_lut[256]
know if there is an even number of 1&#39;s in a integer