/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#ifndef _LPCLIB_H
#define _LPCLIB_H

/** @addtogroup lpc_prg_lib */
/** @{ */

/**
*	Structure holding info about the the CPU HW.
*/

typedef struct {

	unsigned int	has_rco;		//!< Frequency of the RC osc, in Hz
	unsigned int	sio_div;		//!< SIO prescaler from CPU clock
	unsigned int	mem_ctr;		//!< Vector mapping control reg address
	unsigned int	mem_mon;		//!< Vector mapping for monitor mode
	unsigned int	mem_usr;		//!< Vector mapping for user mode

} LPC_CHIP_CPU;

/**
*	Structure holding info about the FLASH.
*/

typedef struct {

	unsigned int	rom_len;		//!< Size of the FLASH [KB]
	unsigned int	num_sec;		//!< Number of FLASH sectors
	const int		sec_siz[];		//!< Size of the sectors, in [KB]

} LPC_CHIP_ROM;

/**
*	Structure holding info about the (main) RAM.
*/

typedef struct {

	unsigned int	ram_beg;		//!< Start address of the RAM
	unsigned int	ram_len;		//!< Size of the RAM [KB]

} LPC_CHIP_RAM;

/**
*	Structure describing a chip.
*/

typedef struct {

	unsigned int		code;		//!< Chip ID
	const char			*name;		//!< The name of the chip
	const char			*mask;		//!< The mask revison string (or NULL)
	const LPC_CHIP_CPU	*cpu;		//!< CPU info
	const LPC_CHIP_ROM	*rom;		//!< FLASH info
	const LPC_CHIP_RAM	*ram;		//!< RAM info

} LPC_CHIP;

/**
*	File I/O descriptor.
*/

typedef	struct {

	struct s_hexio			*stat;	//!< The opaque internal state
	const struct s_hfunc	*func;	//!< Function table
	void					*data;	//!< Pointer to a data buffer
	unsigned int			rlen;	//!< Length of the data/record
	unsigned int			addr;	//!< Address associated with the data/record
	unsigned int			line;	//!< Line (record) number

} LPC_IO;

/**
*	File type specific function table.
*/

typedef	struct s_hfunc {

	/*
	*	An internal link field, not used in the user structures.
	*/

	struct s_hfunc	*link;

	/*
	*	The name of the file type.
	*/

	char	const	*name;

	/*
	*	Pointer to a function that opens the file for reading.
	*	It should return a negative error code if there was an error,
	*	0 otherwise. It should allocate the memory it needs to handle
	*	the given file (i.e. all internal state) and set the 'stat'
	*	field of the 'recp' parameter to that. The treatment of all
	*	fields of the received LPC_IO structure is implementation
	*	dependent.
	*/

	int		(*open)( LPC_IO *recp, const char *name );

	/*
	*	Reads a data record from the hexfile. The file must have been
	*	opened for reading by calling the function described by the 'open'
	*	field of this struture.
	*	Returns a negative error code if there was an error.
	*	Returns 0 if there was no error and the last record of the file
	*	was read. Returns a greater than 0 value if a record was read
	*	and there are still records in the file. The interpretation of the
	*	fields of the LPC_IO parameter at input are implementation dependent.
	*	At output, the 'addr' field must be set to the start adress of the
	*	record,
	*	Returns HEXERR_DONE if an end record was read (or EOF was reched),
	*	in that case the addr field of the record structure is set to whatever
	*	address the end record specified.
	*	Returns HEXERR_OK if a data record was read.
	*/

	int		(*read)( LPC_IO *recp );

	int		(*create)( LPC_IO *recp, const char *name );

	int		(*write)( LPC_IO *recp );
	int		(*close)( LPC_IO *recp );

} LPC_IO_FUNC;

/**
*	Opaque pointer to the LPC library internal state
*/

typedef	struct s_lpc *LPC;

/**
*	Signal control modes
*/

typedef enum {

	LPC_MODE_pDTR = 0,		//!< DTR with positive polarity
	LPC_MODE_nDTR = 1,		//!< DTR with negative polarity
	LPC_MODE_pRTS = 2,		//!< RTS with positive polarity
	LPC_MODE_nRTS = 3		//!< RTS with negative polarity

} LPC_CONTROL_MODE;

/**
*	Log types.
*/

typedef enum {

	LPC_LOG_TIMESTAMP = 0,	//!< Have a delta time for each entry
	LPC_LOG_ERROR,			//!< Log errors (always on)
	LPC_LOG_SERIAL,			//!< Log serial events
	LPC_LOG_TARGET,			//!< Log target activity
	LPC_LOG_FILEIO,			//!< Log access to files
	LPC_LOG_NUMLOG			//!< Number of types of logs

} LPC_LOG_TYPE;

/**
*	Target control
*/

typedef enum {

	LPC_RES_ASSERT = 0,		//!< Assert the reset signal
	LPC_RES_NEGATE,			//!< Negate the reset signal
	LPC_ISP_ASSERT,			//!< Assert the ISP signal
	LPC_ISP_NEGATE			//!< Negate the ISP signal

} LPC_CONTROL;

/**
*	Error codes
*/

typedef enum {

	LPC_ERROR_CONFIG	= -1,	//!< Invalid configuration or command order
	LPC_ERROR_SYSTEM	= -2,	//!< A UNIX system call reported an error
	LPC_ERROR_CHIP		= -3,	//!< Unknown chip type
	LPC_ERROR_COMMS		= -4,	//!< Communication with the target failed
	LPC_ERROR_PARAM		= -5,	//!< Invalid command parameter
	LPC_ERROR_PROTECT	= -6,	//!< Target is read-protected
	LPC_ERROR_SECTOR	= -7,	//!< Target reported a sector number error
	LPC_ERROR_BUSY		= -8,	//!< Target reported a FLASH busy state
	LPC_ERROR_FAIL		= -9,	//!< Target test (blank or compare) failed
	LPC_ERROR_COMMAND	= -10,	//!< Target command or parameter invalid
	LPC_ERROR_LOCKED	= -11,	//!< Target sector is locked
	LPC_ERROR_FLASH		= -12,	//!< Target FLASH write verify failed
	LPC_ERROR_ADDRESS	= -13,	//!< Target reported an address error
	LPC_ERROR_UNKNOWN	= -14,	//!< Target response is not a known error code
	LPC_ERROR_FILE		= -15,	//!< File format error
	LPC_ERROR_FILETYPE	= -16,	//!< Duplicate file type identifier
	LPC_ERROR_CBACK		= -17	//!< Target control callback failure

} LPC_ERROR;

/** @} */

LPC			LPC_Open( void );
void		LPC_Close( LPC lpc );

LPC_ERROR	LPC_LogOpen( LPC lpc, const char *file, int append );
void		LPC_LogClose( LPC lpc );
void		LPC_LogEnable( LPC lpc, LPC_LOG_TYPE type );
void		LPC_LogDisable( LPC lpc, LPC_LOG_TYPE type );
void		LPC_LogCallback( LPC lpc, void (*func)(void*,const char*),
					  		 void *user );
char		*LPC_LogLastError( LPC lpc );

LPC_ERROR	LPC_SerialOpen( LPC lpc, const char *name, const char *lock );
void		LPC_SerialClose( LPC lpc );
int			LPC_SerialPort( LPC lpc );
LPC_ERROR	LPC_SerialBaud( LPC lpc, int baud );
LPC_ERROR	LPC_SerialRead( LPC lpc, void *ptr, int len, int tim );
LPC_ERROR	LPC_SerialWrite( LPC lpc, const void *ptr, int len );
LPC_ERROR	LPC_SerialSignal( LPC lpc, int rts, int val );

void		LPC_TargetPower( LPC lpc, void (*func)(int,void*), void *user );
int			LPC_TargetCrystal( LPC lpc, int freq );
LPC_ERROR	LPC_TargetBaud( LPC lpc, int baud, int fast );
LPC_ERROR	LPC_TargetControlModem( LPC lpc, LPC_CONTROL_MODE reset,
								 	LPC_CONTROL_MODE isp );
LPC_ERROR	LPC_TargetControlManual( LPC lpc,
								     int (*func)( LPC_CONTROL, void *),
								  	 void *param );
LPC_ERROR	LPC_TargetReset( LPC lpc, int val );
LPC_ERROR	LPC_TargetIsp( LPC lpc, int val );
LPC_ERROR	LPC_TargetConnect( LPC lpc );
LPC_ERROR	LPC_TargetMemWrite( LPC lpc, int addr, const void *data, int dlen );
LPC_ERROR	LPC_TargetMemRead( LPC lpc, int addr, void *data, int dlen );
LPC_ERROR	LPC_TargetExecute( LPC lpc, int addr, int thumb );
LPC_ERROR	LPC_TargetSector( LPC lpc, unsigned addr );
LPC_ERROR	LPC_TargetCompare( LPC lpc, int adr1, int adr2, int dlen );
LPC_ERROR	LPC_TargetFlash( LPC lpc, int addr, const void *data, int dlen );
LPC_ERROR	LPC_TargetErase( LPC lpc, int first, int last );
LPC_ERROR	LPC_TargetBlank( LPC lpc, int first, int last );
void		LPC_TargetVectab( LPC lpc, void *data );

const LPC_CHIP	*LPC_TargetChip( LPC lpc );

LPC_ERROR	LPC_FileType( LPC lpc, const LPC_IO_FUNC *ftab );

LPC_ERROR	LPC_FileOpen( LPC lpc, LPC_IO *io,  const char *name,
					   	  const char *type, int wr );
LPC_ERROR	LPC_FileRead( LPC_IO *io );
LPC_ERROR	LPC_FileWrite( LPC_IO *io );
LPC_ERROR	LPC_FileClose( LPC_IO *io );

#endif

