/* 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/>.
 *
 */
/** library for enhanced USART communication (API)
 *  @file usart_enhanced.h
 *  @author King Kévin <kingkevin@cuvoodoo.info>
 *  @date 2018
 *  @details the USART peripherals only support 8 or 9-bit word and even or odd parity (included in the data bits). The library adds support for 5 to 8-bit words, none/even/odd/mark/space parity (on top of the data bits)
 *  @note since parity is handled in software, the parity error (PE) flag is unused and should be replaced by the value return by usart_enhanced_parity_error
 *  @remark 9-bit raw communication is not supported since this is not common and can be done without this library
 */
#pragma once

/** enhanced USART setting for the additional parity bit*/
enum usart_enhanced_parity_t {
	/** no parity */
	USART_ENHANCED_PARITY_NONE,
	/** even parity
	 *  @note the number of 1's is even
	 */
	USART_ENHANCED_PARITY_EVEN,
	/** odd parity
	 *  @note the number of 1's is odd
	 */
	USART_ENHANCED_PARITY_ODD,
	/** mark parity
	 *  @note the parity bit is 1
	 */
	USART_ENHANCED_PARITY_MARK,
	/** space parity
	 *  @note the parity bit is 0
	 */
	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
 *  @param[in] usart USART peripheral base address
 *  @param[in] databits word size in bits (5 to 8)
 *  @param[in] parity additional parity bit
 *  @return if the input settings are valid and the configuration is successful
 */
bool usart_enhanced_config(uint32_t usart, uint8_t databits, enum usart_enhanced_parity_t parity);
/** send data over the enhanced USART using the configuration
 *  @param[in] usart USART peripheral base address
 *  @param[in] data data to be sent
 *  @note uses usart_send
 */
void usart_enhanced_send(uint32_t usart, uint8_t data);
/** receive data over the enhanced USART using the configuration
 *  @param[in] usart USART peripheral base address
 *  @return data received
 *  @note uses usart_recv
 */
uint8_t usart_enhanced_recv(uint32_t usart);
/** get the parity status of the received data
 *  @param[in] usart USART peripheral base address
 *  @return if there is a parity error
 *  @note the check only applies to the last data retrieved using usart_enhanced_recv
 */
bool usart_enhanced_parity_error(uint32_t usart);
