/*!
 * \file alcd.c
 * \brief
 *    A target independent Alpharithmetic LCD driver
 *
 * Author: Christos Choutouridis AEM: 8997
 * email : <cchoutou@ece.auth.gr>
 *
 */

#ifndef __alcd_h__
#define __alcd_h__

#ifdef __cplusplus
extern "C" {
#endif

#include "jiffies.h"
#include "driver_types.h"
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <time.h>


/*
 * General Defines
 */
#define ALCD_CLOCK       (CLOCK)

/*!
 *  ----------------------------------------------------
 *      Hitachi HD44780 - Samsung KS0066U
 *  ----------------------------------------------------
 *
 *
 *  Entry Mode Set -----> 0  0  0  0      0  1  I/D  S
 *  ----------------------------------------------------
 *  I/D = 1 -->Inciment Curs     I/D = 0 Decriment
 *  S = 1 -->Display shift       S = 0 Not
 *
 *
 *  DispOnOffControll -->  0  0  0  0     1  D  C  B
 *  -------------------------------------------------
 *  D = Display On
 *  C = Cursor On
 *  B = Blinking On
 *
 *
 *  Cursor/Display Shift --> 0  0  0  1   S/C R/L  x  x
 *  ---------------------------------------------------
 *  S/C = 1 -->Display Shift  S/C = 0 -->Cursor Shift
 *  R/L = 1 -->Shift Right     R/L = 0 -->Shift left
 *
 *
 *  FunctionSet     ------>  0  0  1 DL   N   F   x  x
 *  ---------------------------------------------------
 *  DL = 1 -->8bit         DL = 0 -->4bit
 *  N = 1 -->2 lines       N = 0 -->1 line
 *  F = 1 -->5x10 dots     F = 0 -->5x8 dots
 *
 */
//#define LCD_LINES                   (4)
//#define LCD_ROWS                    (16)

#define LCD_CLRSCR                  (0x01)      /*!< Clear Srean Command Number */
#define LCD_RETHOME                 (0x02)      /*!< Cursor home Un-Shift display DDRam as is */

#define LCD_ENTRYMODE               (0x06)      /*!< Inc Cursor, Don't shift display */
#define LCD_DISP_ON                 (0x0C)      /*!< No Cursos and Blink */
#define LCD_DISP_OFF                (0x08)
#define LCD_CUR_DISP                (0x14)      /*!< Cursor shift right */
#define LCD_FUNSET_2L8              (0x28)      /*!< 4bit, 2lines, 5x8 dots */
#define LCD_FUNSET_1L8              (0x20)      /*!< 4bit, 1lines, 5x8 dots */
#define LCD_FUNSET_1L10             (0x24)      /*!< 4bit, 1lines, 5x10 dots */

#define LCD_SETCGRAMADDR            (0x40)

#define LCD_DDRAMMask               (0x80)      /*!< DDRAM ------------> 1   ADD[7..0] */
#define LCD_BFMask                  (0x80)      /*!< IR    ------------> BF   AC[6..0] */
#define LCD_ACMask                  (0x7f)      /*!<    ____________________________| */

#define LCD_SHIFT_RIGHT             (0x1C)
#define LCD_SHIFT_LEFT              (0x18)

typedef enum {
   ALCD_1Line_5x8 = LCD_FUNSET_1L8,
   ALCD_1Line_5x10 = LCD_FUNSET_1L10,
   ALCD_2Lines_5x8 = LCD_FUNSET_2L8
} alcd_funset_en;

/*!
 * Alpharithmetic LCD Cursor
 */
typedef volatile struct
{
   uint8_t     x;
   uint8_t     y;
}alcd_cursor_t;


/*!
 * Alpharithmetic LCD Pin assignements.
 * Each one can be called xx.DB4(1); or xx.DB4(0); in order to set
 * or clear the corresponding pin.
 *
 * \note These pointers MUST to be assigned from main application.
 */
typedef volatile struct
{
   //drv_pinout_ft  db0;
   //drv_pinout_ft  db1;
   //drv_pinout_ft  db2;
   //drv_pinout_ft  db3;
   drv_pinout_ft  db4;     /*!< Pointer for DB4 pin */
   drv_pinout_ft  db5;     /*!< Pointer for DB5 pin */
   drv_pinout_ft  db6;     /*!< Pointer for DB6 pin */
   drv_pinout_ft  db7;     /*!< Pointer for DB7 pin */
   drv_pinout_ft  rs;      /*!< Pointer for RS pin */
   drv_pinout_ft  en;      /*!< Pointer for EN pin */
   drv_pinout_ft  bl;      /*!< Pointer for Back Light pin*/
}alcd_io_t;

/*!
 * Alpharithmetic LCD Public Data struct
 */
typedef volatile struct
{
   alcd_io_t      io;      //!< Link to IO struct
   alcd_cursor_t  c;       //!< Link to Cursor struct
   uint8_t        lines;   //!< The lines of attached lcd
   uint8_t        columns; //!< The columns of attached lcd
   //uint8_t        bus;     //!< Bus length, 4 or 8 bit
   drv_status_en  status;  //!< alcd driver status
}alcd_t;


/*
 *  ============= PUBLIC ALCD API =============
 */

/*
 * Link and Glue functions
 */
void alcd_link_db4 (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_db5 (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_db6 (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_db7 (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_rs (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_en (alcd_t *alcd, drv_pinout_ft pfun);
void alcd_link_bl (alcd_t *alcd, drv_pinout_ft pfun);

int alcd_putchar (alcd_t *alcd, int ch);

/*
 * Set functions
 */
void alcd_set_lines (alcd_t *alcd, int lines);
void alcd_set_columns (alcd_t *alcd, int columns);

/*
 * User Functions
 */
void alcd_deinit (alcd_t *alcd);                /*!< For compatibility */
drv_status_en alcd_init (alcd_t *alcd, alcd_funset_en fs);         /*!< For compatibility */

void alcd_backlight (alcd_t *alcd, uint8_t on); /*!< For compatibility */
void alcd_enable (alcd_t *alcd, uint8_t on);    /*!< For compatibility */
void alcd_cls (alcd_t *alcd);                   /*!< For compatibility */
void alcd_shift (alcd_t *alcd, int pos);        /*!< For compatibility */
void alcd_createChar (alcd_t *alcd, uint8_t location, uint8_t charmap[]);

#ifdef __cplusplus
}
#endif

#endif //#ifndef __alcd_h__
