/**************************************************************************//**
 * @file display.h
 * @brief Display device interface
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2013 Energy Micro AS, http://www.energymicro.com</b>
 *******************************************************************************
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 * 4. The source and compiled code may only be used on Energy Micro "EFM32"
 *    microcontrollers and "EFR4" radios.
 *
 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
 * obligation to support this Software. Energy Micro AS is providing the
 * Software "AS IS", with no express or implied warranties of any kind,
 * including, but not limited to, any implied warranties of merchantability
 * or fitness for any particular purpose or warranties against infringement
 * of any proprietary rights of a third party.
 *
 * Energy Micro AS will not be liable for any consequential, incidental, or
 * special damages, or any other relief, or for any claim by any third party,
 * arising from your use of this Software.
 *
 *****************************************************************************/
#ifndef _DISPLAY_H_
#define _DISPLAY_H_

#include <stdbool.h>
#include <stdint.h>
#include "emstatus.h"
#include "displayconfigall.h"

/***************************************************************************//**
 * @addtogroup Drivers
 * @{
 ******************************************************************************/

/***************************************************************************//**
 * @addtogroup Display
 * @brief Display device driver stack library. See @ref display_doc for
 *       more information.
 * @{
 ******************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 ********************************  DEFINES  ************************************
 ******************************************************************************/

/** EMSTATUS codes of the display interface. */
#define DISPLAY_EMSTATUS_OK                                        (0) /**< Operation successful. */
#define DISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY (DISPLAY_EMSTATUS_BASE | 1) /**< Not enough memory. */
#define DISPLAY_EMSTATUS_OUT_OF_RANGE      (DISPLAY_EMSTATUS_BASE | 2) /**< Parameters out of range. */
#define DISPLAY_EMSTATUS_INVALID_PARAMETER (DISPLAY_EMSTATUS_BASE | 3) /**< Invalid parameter. */
#define DISPLAY_EMSTATUS_NOT_SUPPORTED     (DISPLAY_EMSTATUS_BASE | 4) /**< Feature/option not supported. */
#define DISPLAY_EMSTATUS_NOT_INITIALIZED   (DISPLAY_EMSTATUS_BASE | 5) /**< Feature/option not supported. */


/*******************************************************************************
 ********************************   ENUMS   ************************************
 ******************************************************************************/

/** Display device colour modes. */
typedef enum DISPLAY_ColourMode_t
{
  DISPLAY_COLOUR_MODE_MONOCHROME,         /**< White = pixel bit value = 0,
                                               Black = pixel bit value = 1 */
  DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE, /**< Black = pixel bit value = 0,
                                               White = pixel bit value = 1 */
} DISPLAY_ColourMode_t;


/** Display device address modes. */
typedef enum DISPLAY_AddressMode_t
{
  DISPLAY_ADDRESSING_BY_ROWS_ONLY,        /**< Display device is addressed by
                                             rows only. I.e. a full line of
                                             pixel data is required to update
                                             a single pixel. */
  DISPLAY_ADDRESSING_BY_ROWS_AND_COLUMNS  /**< Display device is addressed by
                                             both rows and columns. I.e. single
                                             pixel updates is supported. */
} DISPLAY_AddressMode_t;


/** Pixel matrix handle. */
typedef void* DISPLAY_PixelMatrix_t;


/*******************************************************************************
 *******************************   STRUCTS   ***********************************
 ******************************************************************************/

/** Display geometry specification. */
typedef struct DISPLAY_Geometry_t
{
  unsigned int   width;   /**< Pixel width of display. */
  unsigned int   stride;  /**< Total line width of display including pixels and
                               controls words. */
  unsigned int   height;  /**< Pixel height of display. */
} DISPLAY_Geometry_t;


/* Forward declaration of struct DISPLAY_Device_t in order to reference it
   inside the typdef. */
struct DISPLAY_Device_t;

/**
 * Display device data structure, including a specification of how the
 * display device behaves.
 */
typedef struct DISPLAY_Device_t
{
  char*                 name;        /**< Name of the display device. */
  DISPLAY_Geometry_t    geometry;    /**< Geometry of the display device. */
  DISPLAY_ColourMode_t  colourMode;  /**< Colour mode of the display device. */
  DISPLAY_AddressMode_t addressMode; /**< Address mode of the display device. */

  /** Turn power on display on or off. */
  EMSTATUS (*pDisplayPowerOn) (struct DISPLAY_Device_t* device,
                               bool                     on);

  /** Allocates a pixelMatrix buffer in the format specified by the geometry
      (DISPLAY_Geometry_t) of the display device. */
  EMSTATUS (*pPixelMatrixAllocate) (struct DISPLAY_Device_t* device,
                                    unsigned int  width,
#ifdef EMWIN_WORKAROUND
                                    unsigned int  userStride,
#endif
                                    unsigned int  height,
                                    DISPLAY_PixelMatrix_t  *pixelMatrix
                                    );
  
  /** Frees a pixelMatrix buffer */
  EMSTATUS (*pPixelMatrixFree) (struct DISPLAY_Device_t* device,
                                DISPLAY_PixelMatrix_t pixelMatrix);
  
  /** Copies the contents of the specified pixelMatrix buffer to the display
      device. */
  EMSTATUS (*pPixelMatrixDraw) (struct DISPLAY_Device_t* device,
                                DISPLAY_PixelMatrix_t pixelMatrix,
                                unsigned int startColumn,
                                unsigned int width,
#ifdef EMWIN_WORKAROUND
                                unsigned int userStride,
#endif
                                unsigned int startRow,
                                unsigned int height);
  
  /** Clears a pixelMatrix buffer by setting all pixels to black. */
  EMSTATUS (*pPixelMatrixClear) (struct DISPLAY_Device_t* device,
                                 DISPLAY_PixelMatrix_t pixelMatrix,
                                 unsigned int width,
                                 unsigned int height
                                 );
  
  /** Refreshes the display device driver after system change, like changing
      a clock frequency of some related device. */
  EMSTATUS (*pDriverRefresh) (struct DISPLAY_Device_t* device);
  
} DISPLAY_Device_t;


/**
 * Display device driver init function pointer type.
 * The displayconfig.h file includes a table that contains the default
 * display devices to initialize.
 */
typedef EMSTATUS (*pDisplayDeviceDriverInitFunction_t) (void);


/*******************************************************************************
 **************************    FUNCTION PROTOTYPES    **************************
 ******************************************************************************/

EMSTATUS DISPLAY_Init          (void);
EMSTATUS DISPLAY_DriverRefresh (void);
EMSTATUS DISPLAY_DeviceGet     (int               displayDeviceNo,
                                DISPLAY_Device_t* device);

#ifdef __cplusplus
}
#endif

/** @} (end group Display) */
/** @} (end group Drivers) */

#endif  /*  _DISPLAY_H_  */
