/**
 * \file
 *
 * \brief Console driver interface.
 *
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
 * - Supported devices:  All devices
 * - AppNote:
 *
 * \author               Atmel Corporation: http://www.atmel.com \n
 *                       Support and FAQ: http://support.atmel.no/
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 * Atmel AVR product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
#ifndef CONSOLE_DRIVER_H_INCLUDED
#define CONSOLE_DRIVER_H_INCLUDED

#include <ring.h>
#include <stddef.h>

/**
 * \brief The size of the console ring buffer in bytes.
 */
#define CONSOLE_BUF_SIZE	64

/**
 * \brief Buffer holding input or output data for a console.
 */
struct console_buffer {
	/** \brief Ring buffer state */
	struct ring_head ring;
	/** \brief Ring buffer data */
	char data[CONSOLE_BUF_SIZE];
};

/**
 * \brief Add a character to the console ring buffer.
 *
 * \param buf The console buffer.
 * \param c The character to be added to \a buf.
 *
 * \pre \a buf must have room for at least one character
 */
static inline void console_buf_insert_char(struct console_buffer *buf, char c)
{
	buf->data[ring_get_head(&buf->ring, CONSOLE_BUF_SIZE)] = c;
	ring_insert_entries(&buf->ring, 1);
}

/**
 * \brief Extract a character from the console ring buffer.
 *
 * \param buf The console buffer.
 * \return The oldest unseen character in \a buf
 *
 * \pre \a buf must contain at least one character
 */
static inline char console_buf_extract_char(struct console_buffer *buf)
{
	unsigned long tail = ring_get_tail(&buf->ring, CONSOLE_BUF_SIZE);
	ring_extract_entries(&buf->ring, 1);
	return buf->data[tail];
}

/**
 * \brief Get the number of unused character slots in the console ring
 * buffer.
 *
 * \param buf The console buffer.
 * \return The number of characters that can be inserted into \a buf
 * before it is full.
 */
static inline unsigned long console_buf_unused(struct console_buffer *buf)
{
	return ring_entries_unused(&buf->ring, CONSOLE_BUF_SIZE);
}

/**
 * \brief Get the number of unused character slots in the console ring
 * buffer before it wraps.
 *
 * \param buf The console buffer.
 * \return The number of characters that can be inserted into \a buf
 * before it is full or wraps around to the beginning.
 */
static inline unsigned long console_buf_unused_before_end(
		struct console_buffer *buf)
{
	return ring_entries_unused_before_end(&buf->ring, CONSOLE_BUF_SIZE);
}

/**
 * \brief Get the number of used character slots in the console ring
 * buffer.
 *
 * \param buf The console buffer.
 * \return The number of characters that can be extracted from \a buf
 * before it is empty.
 */
static inline unsigned long console_buf_used(struct console_buffer *buf)
{
	return ring_entries_used(&buf->ring, CONSOLE_BUF_SIZE);
}

/**
 * \brief A console driver.
 *
 * A console driver is responsible for emptying the console buffer and
 * producing something the user can see, for example by pushing the
 * characters out over a serial line.
 */
struct console_driver {
	/** \brief Commit the console output buffer. */
	void (*tx_commit)(struct console_driver *drv);
	/** \brief Make room for more characters in the console output buffer */
	void (*tx_make_room)(struct console_driver *drv, size_t goal);

	/**
	 * \brief The console buffer holding characters for
	 * transmission through this driver.
	 *
	 * \todo This really belongs in struct console.
	 */
	struct console_buffer tx_buf;
};

#endif /* CONSOLE_DRIVER_H_INCLUDED */
