/*! @file AppDefs.h
 * @brief pin&gpio defines and function prototypes
*
* pin definitions are mainly described by 6 aspects:
*		SCU port number
*		SCU pin number
*		GPIO port number
*		GPIO pin number
*		alternate function index for GPIO mode
*		alternate function index for required mode, sometimes it is the same as GPIO mode
*/
#ifndef _APPDEFS_H_
#define _APPDEFS_H_

#include "bscdefs.h"
#include "lpc43xx.h"

// don't change the position to include this file!
#include "AppCfg.h"


#define ATR_RAMCODE	__attribute__((section("SECT_RAMCODE")))

#define CAMERA_OV7670	0	// an old but still popular sensor
#define CAMERA_YACBA21	1	// the knock-gate brick, the oldest Honeywell's sensor
#define CAMERA_PX6180	2	// a sensor from PixArt that has tough VSYNC timing

typedef enum _enum_Cameras
{
	camera_ov7670 = CAMERA_OV7670,
	camera_yacba21 = CAMERA_YACBA21,
	camera_px6180 = CAMERA_PX6180,
	camera_count,
}enum_Cameras;




// note : slave ID is shifted left by 1 !
#define I2C_SLAVE_0_ID_6180   0x38   // 6180
#define I2C_SLAVE_0_ID_7620   0x73   // 7620
#define I2C_SLAVE_0_ID_7670	  0x21
#define I2C_SLAVE_0_ID_6327   0x40   // 6327

#define TEST_NONE 		0
#define TEST_OVERRUN 	1	// test overrun by limiting lcd framebuffer switch rate
#define TEST_UNDERRUN	2	// test underrun by limiting receiving speed : use slower MCLK
// note: Though the 2 tests have completely different buffer usage, but it appears similar: low FPS!

/*! @name PinDefMacros
 * @brief pin definition macros. Every pin has up to 6 aspects, refer to comments for "IMGD0" pin
*/
///@{


typedef enum _enum_SGPSlice
{
	sliceA = 0,
	sliceB,
	sliceC,
	sliceD,
	
	sliceE,
	sliceF,
	sliceG,
	sliceH,
	
	sliceI,
	sliceJ,
	sliceK,
	sliceL,
	
	sliceM,
	sliceN,
	sliceO,
	sliceP,
	
	sliceCnt,
}enum_SGPSlice;

typedef enum _enum_SGPPin
{
	SGP0 = 0,
	SGP1,
	SGP2,
	SGP3,
	SGP4,
	SGP5,
	SGP6,
	SGP7,
	SGP8,
	SGP9,
	SGP10,
	SGP11,
	SGP12,
	SGP13,
	SGP14,
	SGP15,
}enum_SGPPin;

typedef enum _enum_SGPPinSlice
{
	pin0Slice = sliceA,
	pin1Slice = sliceI,
	pin2Slice = sliceE,
	pin3Slice = sliceJ,
	pin4Slice = sliceC,
	pin5Slice = sliceK,
	pin6Slice = sliceF,
	pin7Slice = sliceL,
	pin8Slice = sliceB,
	pin9Slice = sliceM,
	pin10Slice = sliceG,
	pin11Slice = sliceN,
	pin12Slice = sliceD,
	pin13Slice = sliceO,
	pin14Slice = sliceH,
	pin15Slice = sliceP,
}enum_SGPPinSlice;


//! 2D array presentation of pin muxing
typedef struct
{
	volatile unsigned int a2d[26][32];
}DS_PinMux2D;


#define SLCP0TO7_MASK	(1UL<<pin0Slice) | (1UL<<pin1Slice) | (1UL<<pin2Slice) | (1UL<<pin3Slice) | (1UL<<pin4Slice) | (1UL<<pin5Slice) | (1UL<<pin6Slice) | (1UL<<pin7Slice)


//					  DisPullDn | DisPullUp | NromalSlew| InputBufNCare	| DisGlitchFilter
#define SPNCFG_OUT_GNRC	0UL<<3 	| 1UL<<4 	| 0UL<<5 	| 0UL<<6 		| 1UL<<7

//					  DisPullDn | DisPullUp | HiSpdSlew | InputBufNCare	| DisGlitchFilter
#define SPNCFG_OUT_HSPD	0UL<<3 	| 1UL<<4 	| 1UL<<5 	| 0UL<<6 		| 1UL<<7


//					  DisPullDn | DisPullUp | N.C. 		| InputBufEn	| N.C.
#define SPNCFG_IN_GNRC	0UL<<3 	| 1UL<<4 	| 0UL<<5 	| 1UL<<6 		| 0UL<<7


//					  DisPullDn | EnPullUp  | N.C. 		| InputBufEn	| N.C.
#define SPNCFG_IN_PUP	0UL<<3 	| 0UL<<4 	| 0UL<<5 	| 1UL<<6 		| 0UL<<7

#define CAM_LDO_EN_H			LPC_GPIO_PORT->SET[GPT_LDO_EN] = 1UL<<GPN_LDO_EN
#define CAM_LDO_EN_L			LPC_GPIO_PORT->CLR[GPT_LDO_EN] = 1UL<<GPN_LDO_EN
#define CAM_CHIP_ENB_H		LPC_GPIO_PORT->SET[GPT_CHIP_ENB] = 1UL<<GPN_CHIP_ENB
#define CAM_CHIP_ENB_L		LPC_GPIO_PORT->CLR[GPT_CHIP_ENB] = 1UL<<GPN_CHIP_ENB

#define CAM_SCTDMAREQNUM	1	// DMA AHB master can only access memory
#define CAM_SCTDMAPERIPNUM	8UL
#define CAM_DMAMUXNUM		2

#define CAM_MAX_PIXEL_PER_LINE	640

#define MCLK_ON		1
#define MCLK_OFF	0



#define MS2TICK(n) (1000 / MICROSEC_PER_TICK * n)

typedef enum
{
	CAMDATAFMT_YUV422 = 0,
	CAMDATAFMT_RGB565 = 4,
	CAMDATAFMT_RGB422 = 7,
}enum_YACBDataFormat;

#define SHARERAM __attribute__((section("SECT_SHARERAM"), zero_init))
#define IRAM1_SECT __attribute__((section("SECT_IRAM1"), zero_init))
#define AHBRAM __attribute__((section("SECT_AHBRAM"), zero_init))
#define SDRAMRAW __attribute__((section("SECT_SDRAMRAW"), zero_init))

typedef struct _DS_DMALLI
{
	void *pvSrc;
	void *pvDst;
	struct _DS_DMALLI *pNextLLI;
	unsigned int ctrlReg;
}DS_DMALLI;

#if LCD_PANEL == LCD_PANEL_MCB4300
	//! width of LCD
	#define CAM_LCD_W		240
	//! height of LCD
	#define CAM_LCD_H		320

	#if CAM_PREVIEW_W > CAM_LCD_H
		#error "preview width must <= capture height"
	#endif
	#if CAM_PREVIEW_H > CAM_LCD_W
		#error "preview height must <= capture width"
	#endif

#else
	#error "By now only MCB4300's LCD panel is supported"
#endif

#define CAP_BUF_SIZE	(CAM_CAP_W * CAM_CAP_H * 2)


// Sanity checks

#if FRABUF_Q_CAPACITY > 50 || FRABUF_Q_CAPACITY < 1
#error "LCD frame buffers must be 1 - 50"
#endif

#if LCD_PANEL == LCD_PANEL_MCB4300
	#if CAM_PREVIEW_W > CAM_LCD_H
		#error "preview width must <= capture height"
	#endif
	#if CAM_PREVIEW_H > CAM_LCD_W
		#error "preview height must <= capture width"
	#endif
#endif

#if CAM_CAP_W > 640
#error "Capture width must <=640"
#endif

#if CAM_CAP_W & 15
#error "Capture width must can be divided by 16 ---- i.e., align to 16"
#endif

#if CAM_PREVIEW_W > CAM_CAP_W
#error "preview width must <= capture width"
#endif
#if CAM_PREVIEW_H > CAM_CAP_H
#error "preview height must <= capture height"
#endif

#if CAM_SKIP_FRAME != 0 && CAM_SKIP_FRAME != 1
#error "CAM_SKIP_FRAME must be 0 or 1"
#endif

// if buffer overrun test is not defined, then default to test none
#ifndef TEST_MODE
#define TEST_MODE	TEST_NONE
#endif


/*! @brief main control block for driving the camera
* Brief description continued.
* this block contains most parameters required for operation, some members are
* not mandatory but just for test.
*/

#if 0 == IS_TWIN_RXBUF
#define RCV_BUF_CNT 1
#else
#define RCV_BUF_CNT 2
#endif

typedef union
{
	//! buffer pair for 64 bit. note that this also makes the union alined to 8
	volatile unsigned long long aa64[RCV_BUF_CNT][CAP_BUF_SIZE/8];	//! buffer pair for 64 bit
	volatile unsigned long		aa32[RCV_BUF_CNT][CAP_BUF_SIZE/4];	//! buffer pair for 32 bit
	volatile unsigned short 	aa16[RCV_BUF_CNT][CAP_BUF_SIZE/2];	//! buffer pair for 16 bit
	volatile unsigned char		aa08[RCV_BUF_CNT][CAP_BUF_SIZE/1];	//! buffer pair for 8 bit
}US_RcvBuf;

typedef struct
{
	VUI32 m0CycCnt;		// Cycle counter of M0's main while(1) loop.	
	VUI32 sgpIrqCntInPrevFra;
	VUI32 sgpIntPerFra;
	US_RcvBuf *pRcvDbBuf;
	VUI32 rcvTglBit;
	VUI32 *pBuf, *pBufEnd;
	// SGPIO transfers per image. Note that each SGPIO transfer is 32 bytes
	// this means image size in byte must be integer times of 32, i.e., 32, 64, 96, ...
	VUI32 vsyncCnt;  //! JustForTest: VSync pulse count	
	VUI32 vsyncEffCnt;


	// these 2 counters are key to synchronize camera receiver and lcd refresher	
	VUI32 freeRxBufCnt;	// if >0, previous image is consumed, camera is allow to receiving new incoming frames
	VUI32 rdyRxBufCnt;	// if >0, at least one incoming frame is received, new image ready to consume
	// both above counters are required because it costs some time to fill a receiving buffer and process the received image.
	
	volatile BOOL32 test;	// !0 = display color ribbons
}DS_CamCB;



/*! @defgroup YACBA21 camera register low level access routines
  * @brief camera low level register access routines, do not call them directly
  * @{
  */
void DelayTicks(unsigned int cnt);


extern unsigned int ReadI2CRegister(uint8_t SlaveID, uint8_t Addr,uint8_t *Data);
extern unsigned int WriteI2CRegister(uint8_t SlaveID, uint8_t Addr,uint8_t Data);
extern signed int OV7670RefreshColor(void);
extern signed int OV7670RefreshGray(void);
extern void CamInit(void);	// should return value in practical use

//! @}

#endif

