/*
 * uart.h
 *
 * Universal Serial (UART) Library v1.1
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 *
 * Copyright (c) 2023 Georgy Moshkin <https://georgymoshkin.com>
 * All rights reserved.
 *
 * Changelog:
 *
 * v1.1 (2026-4-13)
 *   - Added COM_SetTimeout() function
 *   - Removed timeOut from COM_Init() parameters
 *   - Changed timeOut type to uint32_t for correct wrap-around of HAL_GetTick()
 *   - Removed zeroing of RX buffer before HAL_UART_Receive_DMA() call
 *   - Replaced {asm("nop");} with __NOP();
 *   - Replaced uint8_t pointers with void pointers
 *
 * v1.0 (2023-11-14)
 *   - Initial release
 *
 */


#ifndef UART_H_
#define UART_H_

#include "stdbool.h"
#include "string.h"
#include "stdint.h"
#include "main.h"

#define COM_MAX_NUM 8

#if defined(STM32F0) || defined(STM32L4) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32U5)
    #define MY_ISR(p)     p->huartPtr->Instance->ISR
    #define MY_ISR_TC     USART_ISR_TC
#elif defined(STM32F1) || defined(STM32F4)
    #define MY_ISR(p)     p->huartPtr->Instance->SR
    #define MY_ISR_TC     USART_SR_TC
#else
    #error "You can add macros above for MY_ISR / MY_ISR_TC"
#endif

#define COM_CMD_NONE  0
#define COM_CMD_READY 1

typedef struct
{
	UART_HandleTypeDef* huartPtr;
	uint8_t* rxBufPtr;
	uint16_t rxBufSize;
	uint16_t rxPos;
	uint32_t timeOut;
	bool rxFail;
    void (*_rs485tx) (void);
    void (*_rs485rx) (void);
    uint8_t com_cmd_ready; // 0 = no command, 1 = command available
    uint8_t com_cmd_byte;  // command byte
} COM_TPort;

// Set current serial port number
extern void COM_Select(uint8_t n);

// Set current serial port timeout
extern void COM_SetTimeout(uint32_t t);

// Initialize serial port library
extern void COM_Init(uint8_t n,			// Serial port number
		UART_HandleTypeDef *huartPtr,	// HAL serial port handle
		volatile uint8_t *rxBufPtr,		// RX buffer
		uint16_t rxBufSize				// RX buffer size
		);

// Set RS-485 transceiver chip callback functions for current port
extern void COM_SetCallbacks485(void (*f485tx)(void), void (*f485rx)(void));

// TX functions (for currently selected serial port):

// Transmit data to serial port and return immediately
extern void COM_WriteFast(void *pData, uint16_t Size);

// Transmit data to serial port and wait for completion
extern void COM_Write(void *pData, uint16_t Size);

// RX functions (for currently selected serial port):

// Try to read single byte from serial port and return immediately
extern bool COM_ReadByteFast(void *b);

// Try to read single byte from serial port with timeout
extern bool COM_ReadByte(void *b);

// Try to read multiple bytes from serial port and return immediately
extern bool COM_ReadFast(void *destBuffer, uint16_t needLen);

// Try to read multiple bytes from serial port with timeout
extern bool COM_Read(void *destBuffer, uint16_t needLen);

// Check if failure (read timeout) flag was set during read operation
bool COM_RxFail(void);

// Clean RX failure flag
void COM_CleanRxFail(void);

void COM_StartCmd(void);
uint8_t COM_ReadCmd(uint8_t expectedCmd);
uint8_t COM_ReadCmdEx(uint8_t expectedCmd,
                      uint8_t payloadSize,
                      void* payload);

#endif /* UART_H_ */
