/** @file debug.h
 * Module handling various debug functions
 *
 * The module provides a range of functions and tools to make debug more
 * convenient
 */

#ifndef _DEBUG_H_
#define _DEBUG_H_

//--includes--------------------------------------------------------------------

#include "../drv/usart.h"
#include "../drv/gpio.h"

#define DEBUG_TRACE 1
#define DEBUG_WARN 1
#define DEBUG_ERROR 1


//--type definitions------------------------------------------------------------

#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR
#define debug_init(usart, tx_port, tx_pin) _debug_init(usart, tx_port, tx_pin)
#else
#define debug_init(usart) do {} while (0)
#endif

#if DEBUG_TRACE
/**
 * Prints a trace message on the debug port. This function should return
 * immediately, provided that the message's length doesn't exceed 80 caracters
 * and that it isn't called in very quick succession. Otherwise, it will block
 * until the internal buffering system is ready to accept the message
 */
#define debug_trace(format, ...) _debug_print("T:", \
		format __VA_OPT__(,) __VA_ARGS__)
#else
#define debug_trace(format, ...) do {} while (0)
#endif

#if DEBUG_WARN
/**
 * Prints a warning message on the debug port. This function should return
 * immediately, provided that the message's length doesn't exceed 80 caracters
 * and that it isn't called in very quick succession. Otherwise, it will block
 * until the internal buffering system is ready to accept the message
 */
#define debug_warn(format, ...) _debug_print("W:", \
		format __VA_OPT__(,) __VA_ARGS__)
#else
#define debug_warn(format, ...) do {} while (0)
#endif

#if DEBUG_ERROR
/**
 * Prints an error message on the debug port. This function should return
 * immediately, provided that the message's length doesn't exceed 80 caracters
 * and that it isn't called in very quick succession. Otherwise, it will block
 * until the internal buffering system is ready to accept the message
 */
#define debug_error(format, ...) _debug_print("E:", \
		format __VA_OPT__(,) __VA_ARGS__)
#else
#define debug_error(format, ...) do {} while (0)
#endif


//--functions-------------------------------------------------------------------

#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR

/**
 * Initializes the debug system to use the given usart peripheral on the given
 * tx port, printing a banner if traces are enabled.
 * The usart doesn't need to be configured, neither does the tx port.
 *
 * This function shouldn't be called directly. Instead, use the debug_init macro
 */
void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port,
		enum GpioPin tx_pin);

/**
 * Prints a debug message on the debug port with the given header. This function
 * should return immediately, provided that the message's length doesn't exceed
 * 80 caracters and that it isn't called in very quick succession. Otherwise, it
 * will block until the internal buffering system is ready to accept the message
 *
 * This function shouldn't be called directly. Instead, use the debug macros
 */
void _debug_print(const char* restrict header,
		const char* restrict format, ...);

#endif

#endif //_DEBUG_H_

