/** 
 * \file lcd.h
 * \brief LCD ST7920 header file
 * \details File contain functions declarations and structures for LCD controller ST7920 (one master, one slave/LCD).
			Screen resolution: 128x40 pixels
			Rows/Columns: 4/16 (ASCII), 4/8 (Chinese)
			Graphic mode: yes
 *
 * \author Juraj Golej
 * \version 1.0
 *
 * \todo [lcd] Cursor control
 */


#ifndef LCD_H_
#define LCD_H_

#include "sam.h"
#include <inttypes.h>
#include <stdbool.h>
#include <drivers/timer/timer.h>
#include <drivers/spi/spi.h>
#include <utils/circbuffer/circbuff.h>
#include <utils/assert/arm_assert.h>
#include <utils/retcode/retcode.h>
#include "lcd_cfg.h"

/** 
 * \brief ST7920 LCD controller instruction list enumeration
 * \note LCD_CMD_TXT_xxx are for text mode, LCD_CMD_IMG_xxx are for image mode
 */
enum LCD_CMD {
	LCD_CMD_TXT			= 0x30,	///< Text mode
	LCD_CMD_TXT_CLEAR	= 0x01,	///< Clear screen
	LCD_CMD_TXT_HOME	= 0x02,	///< Go to home position
	LCD_CMD_TXT_MOVR	= 0x06,	///< Writing to the right (European standard)
	LCD_CMD_TXT_DISPON	= 0x0C,	///< Display ON
	LCD_CMD_TXT_DISPOFF	= 0x08,	///< Display OFF
	LCD_CMD_TXT_CURSON	= 0x0F, ///< Cursor ON
	LCD_CMD_TXT_CURSOFF	= 0x08, ///< Cursor OFF
	LCD_CMD_IMG			= 0x34,	///< Image mode
	LCD_CMD_IMG_DISPON	= 0x36,	///< Display ON
	LCD_CMD_IMG_DISPOFF	= 0x34,	///< Display OFF
	LCD_CMD_IMG_HOME	= 0x80,	///< Go to home position
}; /* enum LCD_CMD */

/** 
 * \brief Instruction or data enumeration
 */
enum LCD_RS {
	LCD_RS_INSTRUCTION = 0b11111000,	///< Instruction
	LCD_RS_DATA = 0b11111010,			///< Data
}; /* enum LCD_RS */

/** 
 * \brief LCD mode enumeration
 */
enum LCD_MODE {
	LCD_MODE_TEXT,	///< Text mode
	LCD_MODE_IMAGE,	///< Image mode
}; /* enum LCD_MODE */

/**
 * \brief LCD Initialization
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EInvalidParameter Initialization problem (check definitions on configuration file)
 *
 * \note Call this function before anything else
 */
enum retCode LCD_init();

/**
 * \brief Go to home position (only TEXT mode)
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in TEXT mode
 */
enum retCode LCD_home();	

/**
 * \brief Clear screen
 */
void LCD_clear();	

/**
 * \brief Go to selected position
 * 
 * \param[in] row Row (0 to 3)
 * \param[in] column Column (0 to 8)
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in TEXT mode
 */
enum retCode LCD_goto(const uint8_t row, const uint8_t column);	

/**
 * \brief Send one char
 * 
 * \param[in] data Data
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in TEXT mode
 */
enum retCode LCD_putc(const uint8_t data);		

/**
 * \brief Send string
 * 
 * \param[in] data Pointer on string
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in TEXT mode
 *
 * \note String must be terminated by '\0'
 */
enum retCode LCD_puts(const uint8_t* data);	

/**
 * \brief Set graphic mode
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in TEXT mode
 */
enum retCode LCD_setGraphicMode();

/**
 * \brief Set text mode
 * 
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in IMAGE mode
 */
enum retCode LCD_setTextMode();

/**
 * \brief Show image
 * 
 * \param[in] image Pointer on image array
 *
 * \return \b enum \b retCode Return code value
 * \retval ENone everything OK
 * \retval EDenied LCD isn't in IMAGE mode
 */
enum retCode LCD_show_image(const uint8_t* image);

#endif /* LCD_H_ */