USART: put parity LUT in header so others can use it

This commit is contained in:
King Kévin 2018-07-11 08:20:51 +02:00
parent 7b0922b614
commit 8e710f21c4
2 changed files with 25 additions and 24 deletions

View File

@ -38,11 +38,7 @@ static enum usart_enhanced_parity_t usart_enhanced_parity[USART_PERIPHERALS_NB];
/** last enhanced USART parity error status */ /** last enhanced USART parity error status */
static bool usart_enhanced_parity_errors[USART_PERIPHERALS_NB]; static bool usart_enhanced_parity_errors[USART_PERIPHERALS_NB];
/** know if there is an even number of 1's in a integer 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, };
* @remark a look-up is a lot faster than making the calculation and doesn't does a lot of (flash) space
*/
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, };
/** get index of corresponding enhanced USART configurations /** get index of corresponding enhanced USART configurations
* @param[in] usart USART peripheral base address * @param[in] usart USART peripheral base address
@ -87,7 +83,7 @@ bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced
usart_enhanced_databits[id] = databits; usart_enhanced_databits[id] = databits;
usart_enhanced_parity[id] = parity; usart_enhanced_parity[id] = parity;
// configure USART peripheral // configure USART peripheral
if (8==databits && USART_ENHANCED_PARITY_NONE!=parity) { // the parity bit is additional to the data bits if (8 == databits && USART_ENHANCED_PARITY_NONE != parity) { // the parity bit is additional to the data bits
usart_set_databits(usart, 9); usart_set_databits(usart, 9);
} else { } else {
usart_set_databits(usart, 8); usart_set_databits(usart, 8);
@ -101,26 +97,26 @@ void usart_enhanced_send(uint32_t usart, uint8_t data)
{ {
/* sanity check */ /* sanity check */
uint8_t id = usart_enhanced_id(usart); uint8_t id = usart_enhanced_id(usart);
if (id>=USART_PERIPHERALS_NB) { if (id >= USART_PERIPHERALS_NB) {
return; return;
} }
data &= ~(0xff<<usart_enhanced_databits[id]); // only keep the data bits data &= ~(0xff << usart_enhanced_databits[id]); // only keep the data bits
uint16_t output = data; // put value in output buffer uint16_t output = data; // put value in output buffer
switch (usart_enhanced_parity[id]) { switch (usart_enhanced_parity[id]) {
case USART_ENHANCED_PARITY_NONE: // a mark is also decoded as idle/stop case USART_ENHANCED_PARITY_NONE: // a mark is also decoded as idle/stop
case USART_ENHANCED_PARITY_MARK: case USART_ENHANCED_PARITY_MARK:
output |= (1<<usart_enhanced_databits[id]); // add idle state output |= (1 << usart_enhanced_databits[id]); // add idle state
break; break;
case USART_ENHANCED_PARITY_EVEN: case USART_ENHANCED_PARITY_EVEN:
if (!even_parity_lut[data]) { if (!usart_enhanced_even_parity_lut[data]) {
output |= (1<<usart_enhanced_databits[id]); output |= (1 << usart_enhanced_databits[id]);
} }
// no need to clear a bit if the parity is even // no need to clear a bit if the parity is even
break; break;
case USART_ENHANCED_PARITY_ODD: case USART_ENHANCED_PARITY_ODD:
if (even_parity_lut[data]) { if (usart_enhanced_even_parity_lut[data]) {
output |= (1<<usart_enhanced_databits[id]); output |= (1 << usart_enhanced_databits[id]);
} }
// no need to clear a bit if the parity is odd // no need to clear a bit if the parity is odd
break; break;
@ -128,7 +124,7 @@ void usart_enhanced_send(uint32_t usart, uint8_t data)
// no need to clear the bit // no need to clear the bit
break; break;
} }
output |= (0xffff<<(usart_enhanced_databits[id]+1)); // set additional bits to idle (high) output |= (0xffff << (usart_enhanced_databits[id] + 1)); // set additional bits to idle (high)
usart_send(usart, output); // transmit character usart_send(usart, output); // transmit character
} }
@ -136,14 +132,14 @@ uint8_t usart_enhanced_recv(uint32_t usart)
{ {
/* sanity check */ /* sanity check */
uint8_t id = usart_enhanced_id(usart); uint8_t id = usart_enhanced_id(usart);
if (id>=USART_PERIPHERALS_NB) { if (id >= USART_PERIPHERALS_NB) {
return 0xff; return 0xff;
} }
uint16_t input = usart_recv(usart); // read received character (also clears the error flags) uint16_t input = usart_recv(usart); // read received character (also clears the error flags)
input &= ~(0xffff<<(usart_enhanced_databits[id]+1)); // only keep the data bits + parity bit uint8_t data = input & ~(0xffff << usart_enhanced_databits[id]); // only keep the data bits
// check the parity // check the parity
uint16_t parity = input&(1<<usart_enhanced_databits[id]); // only keep the parity bit uint16_t parity = input & (1 << usart_enhanced_databits[id]); // only keep the parity bit
usart_enhanced_parity_errors[id] = false; usart_enhanced_parity_errors[id] = false;
switch (usart_enhanced_parity[id]) { switch (usart_enhanced_parity[id]) {
case USART_ENHANCED_PARITY_NONE: case USART_ENHANCED_PARITY_NONE:
@ -151,16 +147,16 @@ uint8_t usart_enhanced_recv(uint32_t usart)
break; break;
case USART_ENHANCED_PARITY_EVEN: case USART_ENHANCED_PARITY_EVEN:
if (parity) { if (parity) {
usart_enhanced_parity_errors[id] = !even_parity_lut[input&0xff]; usart_enhanced_parity_errors[id] = !usart_enhanced_even_parity_lut[data];
} else { } else {
usart_enhanced_parity_errors[id] = even_parity_lut[input&0xff]; usart_enhanced_parity_errors[id] = usart_enhanced_even_parity_lut[data];
} }
break; break;
case USART_ENHANCED_PARITY_ODD: case USART_ENHANCED_PARITY_ODD:
if (parity) { if (parity) {
usart_enhanced_parity_errors[id] = even_parity_lut[input&0xff]; usart_enhanced_parity_errors[id] = usart_enhanced_even_parity_lut[data];
} else { } else {
usart_enhanced_parity_errors[id] = !even_parity_lut[input&0xff]; usart_enhanced_parity_errors[id] = !usart_enhanced_even_parity_lut[data];
} }
break; break;
case USART_ENHANCED_PARITY_MARK: case USART_ENHANCED_PARITY_MARK:
@ -170,15 +166,14 @@ uint8_t usart_enhanced_recv(uint32_t usart)
usart_enhanced_parity_errors[id] = parity; usart_enhanced_parity_errors[id] = parity;
break; break;
} }
input &= ~(0xffff<<(usart_enhanced_databits[id])); // only keep the data bits return data;
return input;
} }
bool usart_enhanced_parity_error(uint32_t usart) bool usart_enhanced_parity_error(uint32_t usart)
{ {
/* sanity check */ /* sanity check */
uint8_t id = usart_enhanced_id(usart); uint8_t id = usart_enhanced_id(usart);
if (id>=USART_PERIPHERALS_NB) { if (id >= USART_PERIPHERALS_NB) {
return false; return false;
} }
return usart_enhanced_parity_errors[id]; return usart_enhanced_parity_errors[id];

View File

@ -44,6 +44,12 @@ enum usart_enhanced_parity_t {
USART_ENHANCED_PARITY_SPACE, USART_ENHANCED_PARITY_SPACE,
}; };
/** know if there is an even number of 1's in a integer
* @note this look up table is only useful for up to 8-bit words, else use __builtin_parity
* @remark a look-up is a lot faster than making the calculation and doesn't use a lot of (flash) memory
*/
extern const bool usart_enhanced_even_parity_lut[256];
/** configure enhanced USART /** configure enhanced USART
* @param[in] usart USART peripheral base address * @param[in] usart USART peripheral base address
* @param[in] databits word size in bits (5 to 8) * @param[in] databits word size in bits (5 to 8)