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 
44 static const bool 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, };
45 
46 
52 static uint8_t usart_enhanced_id(uint32_t usart)
53 {
54  uint8_t to_return = USART_PERIPHERALS_NB;
55  switch (usart) {
56  case USART1:
57  to_return = 0;
58  break;
59  case USART2:
60  to_return = 1;
61  break;
62  case USART3:
63  to_return = 2;
64  break;
65  default:
66  to_return = USART_PERIPHERALS_NB;
67  break;
68  }
69  return to_return;
70 }
71 
72 bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity)
73 {
74  /* sanity check */
75  uint8_t id = usart_enhanced_id(usart);
76  if (id>=USART_PERIPHERALS_NB) {
77  return false;
78  }
79  if (databits<5 || databits>8) {
80  return false;
81  }
82  if (parity>USART_ENHANCED_PARITY_SPACE) {
83  return false;
84  }
85 
86  // save configuration for later use
87  usart_enhanced_databits[id] = databits;
88  usart_enhanced_parity[id] = parity;
89  // configure USART peripheral
90  if (8==databits && USART_ENHANCED_PARITY_NONE!=parity) { // the parity bit is additional to the data bits
91  usart_set_databits(usart, 9);
92  } else {
93  usart_set_databits(usart, 8);
94  }
95  usart_set_parity(usart, USART_PARITY_NONE); // set no parity since we will take care of it ourselves
96  // 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
97  return true;
98 }
99 
100 void usart_enhanced_send(uint32_t usart, uint8_t data)
101 {
102  /* sanity check */
103  uint8_t id = usart_enhanced_id(usart);
104  if (id>=USART_PERIPHERALS_NB) {
105  return;
106  }
107 
108  data &= ~(0xff<<usart_enhanced_databits[id]); // only keep the data bits
109  uint16_t output = data; // put value in output buffer
110  switch (usart_enhanced_parity[id]) {
111  case USART_ENHANCED_PARITY_NONE: // a mark is also decoded as idle/stop
113  output |= (1<<usart_enhanced_databits[id]); // add idle state
114  break;
116  if (!even_parity_lut[data]) {
117  output |= (1<<usart_enhanced_databits[id]);
118  }
119  // no need to clear a bit if the parity is even
120  break;
122  if (even_parity_lut[data]) {
123  output |= (1<<usart_enhanced_databits[id]);
124  }
125  // no need to clear a bit if the parity is odd
126  break;
128  // no need to clear the bit
129  break;
130  }
131  output |= (0xffff<<(usart_enhanced_databits[id]+1)); // set additional bits to idle (high)
132  usart_send(usart, output); // transmit character
133 }
134 
135 uint8_t usart_enhanced_recv(uint32_t usart)
136 {
137  /* sanity check */
138  uint8_t id = usart_enhanced_id(usart);
139  if (id>=USART_PERIPHERALS_NB) {
140  return 0xff;
141  }
142 
143  uint16_t input = usart_recv(usart); // read received character (also clears the error flags)
144  input &= ~(0xffff<<(usart_enhanced_databits[id]+1)); // only keep the data bits + parity bit
145  // check the parity
146  uint16_t parity = input&(1<<usart_enhanced_databits[id]); // only keep the parity bit
147  usart_enhanced_parity_errors[id] = false;
148  switch (usart_enhanced_parity[id]) {
150  usart_enhanced_parity_errors[id] = false;
151  break;
153  if (parity) {
155  } else {
157  }
158  break;
160  if (parity) {
162  } else {
164  }
165  break;
167  usart_enhanced_parity_errors[id] = !parity;
168  break;
170  usart_enhanced_parity_errors[id] = parity;
171  break;
172  }
173  input &= ~(0xffff<<(usart_enhanced_databits[id])); // only keep the data bits
174  return input;
175 }
176 
177 bool usart_enhanced_parity_error(uint32_t usart)
178 {
179  /* sanity check */
180  uint8_t id = usart_enhanced_id(usart);
181  if (id>=USART_PERIPHERALS_NB) {
182  return false;
183  }
184  return usart_enhanced_parity_errors[id];
185 }
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 const bool even_parity_lut[256]
know if there is an even number of 1&#39;s in a integer
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)