usart_enhanced.c
Go to the documentation of this file.
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* standard libraries */
#include <stdint.h> // standard integer types
/* STM32 (including CM3) libraries */
#include <libopencm3/stm32/usart.h> // USART utilities
/* own libraries */
#include "usart_enhanced.h" // utilities for USART enhancements
#define USART_PERIPHERALS_NB 3
static uint8_t usart_enhanced_databits[USART_PERIPHERALS_NB];
static enum usart_enhanced_parity_t usart_enhanced_parity[USART_PERIPHERALS_NB];
static bool usart_enhanced_parity_errors[USART_PERIPHERALS_NB];
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, };
static uint8_t usart_enhanced_id(uint32_t usart)
{
uint8_t to_return = USART_PERIPHERALS_NB;
switch (usart) {
case USART1:
to_return = 0;
break;
case USART2:
to_return = 1;
break;
case USART3:
to_return = 2;
break;
default:
to_return = USART_PERIPHERALS_NB;
break;
}
return to_return;
}
bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity)
{
/* sanity check */
uint8_t id = usart_enhanced_id(usart);
if (id>=USART_PERIPHERALS_NB) {
return false;
}
if (databits<5 || databits>8) {
return false;
}
if (parity>USART_ENHANCED_PARITY_SPACE) {
return false;
}
// save configuration for later use
usart_enhanced_databits[id] = databits;
usart_enhanced_parity[id] = parity;
// configure USART peripheral
if (8 == databits && USART_ENHANCED_PARITY_NONE != parity) { // the parity bit is additional to the data bits
usart_set_databits(usart, 9);
} else {
usart_set_databits(usart, 8);
}
usart_set_parity(usart, USART_PARITY_NONE); // set no parity since we will take care of it ourselves
// 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
return true;
}
void usart_enhanced_send(uint32_t usart, uint8_t data)
{
/* sanity check */
uint8_t id = usart_enhanced_id(usart);
if (id >= USART_PERIPHERALS_NB) {
return;
}
data &= ~(0xff << usart_enhanced_databits[id]); // only keep the data bits
uint16_t output = data; // put value in output buffer
switch (usart_enhanced_parity[id]) {
case USART_ENHANCED_PARITY_NONE: // a mark is also decoded as idle/stop
case USART_ENHANCED_PARITY_MARK:
output |= (1 << usart_enhanced_databits[id]); // add idle state
break;
case USART_ENHANCED_PARITY_EVEN:
if (!usart_enhanced_even_parity_lut[data]) {
output |= (1 << usart_enhanced_databits[id]);
}
// no need to clear a bit if the parity is even
break;
case USART_ENHANCED_PARITY_ODD:
if (usart_enhanced_even_parity_lut[data]) {
output |= (1 << usart_enhanced_databits[id]);
}
// no need to clear a bit if the parity is odd
break;
case USART_ENHANCED_PARITY_SPACE:
// no need to clear the bit
break;
}
output |= (0xffff << (usart_enhanced_databits[id] + 1)); // set additional bits to idle (high)
usart_send(usart, output); // transmit character
}
uint8_t usart_enhanced_recv(uint32_t usart)
{
/* sanity check */
uint8_t id = usart_enhanced_id(usart);
if (id >= USART_PERIPHERALS_NB) {
return 0xff;
}
uint16_t input = usart_recv(usart); // read received character (also clears the error flags)
uint8_t data = input & ~(0xffff << usart_enhanced_databits[id]); // only keep the data bits
// check the parity
uint16_t parity = input & (1 << usart_enhanced_databits[id]); // only keep the parity bit
usart_enhanced_parity_errors[id] = false;
switch (usart_enhanced_parity[id]) {
case USART_ENHANCED_PARITY_NONE:
usart_enhanced_parity_errors[id] = false;
break;
case USART_ENHANCED_PARITY_EVEN:
if (parity) {
usart_enhanced_parity_errors[id] = !usart_enhanced_even_parity_lut[data];
} else {
usart_enhanced_parity_errors[id] = usart_enhanced_even_parity_lut[data];
}
break;
case USART_ENHANCED_PARITY_ODD:
if (parity) {
usart_enhanced_parity_errors[id] = usart_enhanced_even_parity_lut[data];
} else {
usart_enhanced_parity_errors[id] = !usart_enhanced_even_parity_lut[data];
}
break;
case USART_ENHANCED_PARITY_MARK:
usart_enhanced_parity_errors[id] = !parity;
break;
case USART_ENHANCED_PARITY_SPACE:
usart_enhanced_parity_errors[id] = parity;
break;
}
return data;
}
bool usart_enhanced_parity_error(uint32_t usart)
{
/* sanity check */
uint8_t id = usart_enhanced_id(usart);
if (id >= USART_PERIPHERALS_NB) {
return false;
}
return usart_enhanced_parity_errors[id];
}
usart_enhanced_send
void usart_enhanced_send(uint32_t usart, uint8_t data)
send data over the enhanced USART using the configuration
Definition: usart_enhanced.c:96
USART_ENHANCED_PARITY_SPACE
space parity
Definition: usart_enhanced.h:44
USART_PERIPHERALS_NB
#define USART_PERIPHERALS_NB
number of available USART peripherals
Definition: usart_enhanced.c:33
usart_enhanced_parity_t
usart_enhanced_parity_t
enhanced USART setting for the additional parity bit
Definition: usart_enhanced.h:26
usart_enhanced_id
static uint8_t usart_enhanced_id(uint32_t usart)
get index of corresponding enhanced USART configurations
Definition: usart_enhanced.c:48
usart_enhanced_parity
static enum usart_enhanced_parity_t usart_enhanced_parity[USART_PERIPHERALS_NB]
configured enhanced USART parity
Definition: usart_enhanced.c:37
USART_ENHANCED_PARITY_EVEN
even parity
Definition: usart_enhanced.h:32
usart_enhanced_config
bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity)
configure enhanced USART
Definition: usart_enhanced.c:68
USART_ENHANCED_PARITY_NONE
no parity
Definition: usart_enhanced.h:28
usart_enhanced_recv
uint8_t usart_enhanced_recv(uint32_t usart)
receive data over the enhanced USART using the configuration
Definition: usart_enhanced.c:131
USART_ENHANCED_PARITY_MARK
mark parity
Definition: usart_enhanced.h:40
usart_enhanced_databits
static uint8_t usart_enhanced_databits[USART_PERIPHERALS_NB]
configured enhanced USART word size
Definition: usart_enhanced.c:35
usart_enhanced_parity_error
bool usart_enhanced_parity_error(uint32_t usart)
get the parity status of the received data
Definition: usart_enhanced.c:172
usart_enhanced_parity_errors
static bool usart_enhanced_parity_errors[USART_PERIPHERALS_NB]
last enhanced USART parity error status
Definition: usart_enhanced.c:39
usart_enhanced.h
library for enhanced USART communication (API)
USART_ENHANCED_PARITY_ODD
odd parity
Definition: usart_enhanced.h:36
usart_enhanced_even_parity_lut
const bool usart_enhanced_even_parity_lut[256]
know if there is an even number of 1&#39;s in a integer
Definition: usart_enhanced.c:41