
#ifndef ATISP_H_
#define ATISP_H_

#ifdef WIN32
#include <windows.h>
#include <process.h>
#else
#include "compiler.h"
#endif  // LINUX



#include <string>
#include <map>
#include <algorithm>
#include <vector>


using namespace std;

#ifdef WIN32
// Implement the DLL export/import mechanism and allow a C-written program
// to use our DLL.
#ifdef ATISP_EXPORTS
#define ATISP_API extern "C" __declspec(dllexport)
#else
#define ATISP_API extern "C" __declspec(dllimport)
#endif

// This macro function calls the C runtime's _beginthreadex function. 
// The C runtime library doesn't want to have any reliance on Windows' data 
// types such as HANDLE. This means that a Windows programmer needs to cast
// values when using _beginthreadex. Since this is terribly inconvenient, 
// this macro has been created to perform the casting.
typedef unsigned (__stdcall *PTHREAD_START) (void *);

#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr, \
   pvParam, fdwCreate, pdwThreadId)                 \
      ((HANDLE)_beginthreadex(                      \
         (void *)        (psa),                     \
         (unsigned)      (cbStack),                 \
         (PTHREAD_START) (pfnStartAddr),            \
         (void *)        (pvParam),                 \
         (unsigned)      (fdwCreate),               \
         (unsigned *)    (pdwThreadId)))

// Allow applications not built with Microsoft Visual C++ to link with our DLL.

#define STDCALL __stdcall
#else

// Linux specific
#define ATISP_API extern "C"
#define STDCALL
#endif// ifndef LINUX

typedef vector<string> ERROR_VEC;


#define READ_ERROR "error"
#define TIMEOUT_ERROR ""

// The AT89C5131's pID. The USB_LPC dongle embeds a AT89C5131 uc.
#define USB_LPC_PID 0x2FFD

// ISP application status report.

enum  STATUS {
  STATUS_PASS,
  STATUS_MEMORY_ALLOC_ERROR,
  STATUS_ADDRESS_OUT_OF_RANGE_ERROR,
  STATUS_FUNCTION_NOT_IMPLEMENTED_ERROR,
  STATUS_TIMEOUT_ERROR,
  STATUS_READING_ERROR,
  STATUS_CHECKSUM_ERROR,
  STATUS_DEVICE_DOES_NOT_EXIST, 
  STATUS_PROTOCOL_DOES_NOT_EXIST,
  STATUS_CANNOT_EXECUTE_COMMAND,
  STATUS_INVALID_DEVICE_HARDWARE_ASSOCIATION,
  STATUS_CANNOT_CREATE_DEVICE_OBJECT,
  STATUS_CANNOT_CREATE_PROTOCOL_OBJECT,
  STATUS_HARDWARE_DOES_NOT_EXIST,
  STATUS_COMMAND_DOES_NOT_EXIST,
  STATUS_OPEN_PORT_ERROR,
  STATUS_CLOSE_PORT_ERROR,
  STATUS_CANNOT_WRITE_TO_PORT,
  STATUS_POSSIBLE_FRAMING_ERROR,
  STATUS_WRITE_PROTECTION_ERROR,
  STATUS_READ_WRITE_PROTECTION_ERROR,
  STATUS_SOFTWARE_SECURITY_ERROR,
  STATUS_CANNOT_OPEN_FILE,
  STATUS_INVALID_HEX_FILE_SYNTAX,
  STATUS_INVALID_HEX_FILE_CHECKSUM,
  STATUS_INVALID_HEXFILE_PATHNAME,
  STATUS_VERIFY_DEVICE_ERROR,
  STATUS_TARGET_REPLY_ERROR,
  STATUS_BLANK_CHECK_ERROR,
  STATUS_INVALID_CAN_MESSAGE_LENGTH_ERROR,
  STATUS_INVALID_CAN_MESSAGE_ID_ERROR,
  STATUS_CAN_NODE_IS_CLOSED_ERROR,
  STATUS_COMMAND_EXECUTION_ERROR,
  STATUS_INVALID_MEMORY_CONFIG_ERROR,
  STATUS_INVALID_BOOTLOADER_REPLY_ERROR,
  STATUS_INVALID_CRIS_VALUE_ERROR,
  STATUS_NO_ARGUMENT_ERROR,
  STATUS_MISSING_PARAMETER,
  STATUS_MISSING_DEVICE_SWITCH,
  STATUS_MISSING_OPERATION_SWITCH,
  STATUS_INVALID_NUMBER_OF_DEVICE_ARGUMENT,
  STATUS_INVALID_PORT_SELECTION,
  STATUS_INVALID_BAUDRATE,
  STATUS_INVALID_CANBITRATE,
  STATUS_NO_OPERATION_SPECIFIED,
  STATUS_INVALID_OPERATION,
  STATUS_INVALID_ARGUMENT,
  STATUS_TOO_MANY_OPERATIONS,
  STATUS_INVALID_CMDFILE_ARGUMENT,
  STATUS_NO_WINDRIVER_LICENSE_ERROR,
  STATUS_NO_USB_DEVICE_FOUND_ERROR,
  STATUS_COULD_NOT_OPEN_USB_DEVICE_ERROR,
  STATUS_COULD_NOT_WRITE_USB_DEVICE_ERROR,
  STATUS_COULD_NOT_READ_USB_DEVICE_ERROR,
  STATUS_CANNOT_LOAD_DLL,
  STATUS_SN_OUT_OF_RANGE_ERROR,
  STATUS_INVALID_SERIALIZE_ARGUMENT,
  STATUS_SN_IS_64_BITS_ERROR,
  STATUS_USB_DRIVER_NOT_INSTALLED
  // FLIP developer:
  // DON'T FORGET TO UPDATE THE COMMAND MANAGER initErrorVect FUNCTION
  // IF YOU MODIFY THIS ENUM.
};

enum {
    NOT_SELECTED,
    SELECTED
};

// Fuse bits.

enum {
	OSC_FUSE,
	BLJB_FUSE,
	X2_FUSE,
  SELBOOT_FUSE
};

// Before running any command, a device and a communication
// hardware must have been selected.

enum {
    DEVICE_SELECTED = 1,
    COMM_HARDWARE_SELECTED,
    DEVICE_AND_COMM_HW_SELECTED
};


// Supported microcontrollers list.

enum 
{
  AT89C5114 = 1,
    AT89C5115,
    AT89C5131,
    AT89C5132,
    AT89C51ED2,
    AT89C51IC2,
    AT89C51ID2,
    AT89C51RB2,
    AT89C51RC2,
    AT89C51RD2,
    AT89C51SND1,
    AT89C51SND2,
    AT8XC5122,
    AT8XC5122_DPW,
   	T89C51AC2,
    T89C51CC01,
    T89C51CC02,
   	T89C51IC2,
    T89C51RB2,
    T89C51RC2,
    T89C51RD2,
    T8XC5121,
    AT89C51CC03,
    AT89C51AC3,
    SA4LU2000,

    // Here begins the list of devices not supported by Flip (batchisp only).
    AT90CAN128
    // FLIP developer:
    // If you modify this list, you must update the isplists.tcl file
    // and the Cdevice.cpp one.
};


// ISP protocols list.

enum PTCL {
    NO_PROTOCOL_SELECTED,
    RS232_STANDARD,
    CAN_STANDARD,
    USB_DFU_STANDARD
};

// ISP communication media list.

enum 
{
    NO_HW_SELECTED,
    RS232_PORT,
    USB_PORT,
    ATMEL_RS232_CAN,
    RM_CANVIEW_RS232_CAN,
    VECTOR,
    IXXAT,
    PEAK,
    SYSTEC_USB_CAN,
    USB_LPC,
    USB_UART,
    USB_SPI
};

enum
{
    RS232_HW = 1,
    USB_HW,
    CAN_HW
};

// XAF and others special bytes.

enum  {
    BOOTLOADER_VERSION,
    SOFTWARE_BOOT_VECTOR,
    SOFTWARE_SECURITY_BYTE,
    BOOT_STATUS_BYTE,
    HARDWARE_BYTE,
    EXTRA_BYTE,
    DEVICE_BOOT_ID1,
    DEVICE_BOOT_ID2,
    DEVICE_MANUF_ID,
    DEVICE_ID1,
    DEVICE_ID2,
    DEVICE_ID3,
    BTC_1,
    BTC_2,
    BTC_3,
    NNB,
    CRIS,
	P1_CONF,
	P3_CONF,
	P4_CONF
};

enum SPECIAL_CMD {
	BYPASS_NONE,
	BYPASS_I2C,
	BYPASS_UART,
	BYPASS_BOTH
};

enum MEMORY_TYPE {
	FLASH,
	EEPROM,
	CUSTOM,
	BOOT,
	XAF,
	HSB,
	SIGNATURE,
	LPC_BOOT,
	MULTICAST
};

enum HEX_FORMAT {
    HEX386, // Extended Linear Address Records
    HEX86   // Extended Segment Address Records
};


// *************************************************************************
// ********************* ISP API functions pointers ************************
// *************************************************************************

// These function pointers may be used by applications which load our atisp
// DLL dynamically.

typedef bool (STDCALL *PF_ispSetTimeout)(DWORD tsec, bool permanent);
typedef int	(STDCALL *PF_ispGetLastError)(void);
typedef char* (STDCALL *PF_ispGetLastResult)(void);
typedef bool (STDCALL *PF_ispInit)(void);
typedef void (STDCALL *PF_ispCancel)(void);
typedef bool (STDCALL *PF_ispSelectDevice)(int device);
typedef bool (STDCALL *PF_ispSelectDevice2)(const char* device);   // for JNI purpose.
typedef bool (STDCALL *PF_ispCreateBuffer)(DWORD size);   // for JNI purpose.
typedef bool (STDCALL *PF_ispSelectCommHardware)(int hardware);
typedef bool (STDCALL *PF_ispOpenCanPort)(ULONG bitrate,
                            BYTE pType,
                            WORD port,
                            BYTE channel,
							BYTE cris,
							DWORD baudrate);
typedef bool (STDCALL *PF_ispOpenRs232Port)(char* portName,
										 ULONG baudrate);
typedef bool (STDCALL *PF_ispOpenUsbPort)(void);
typedef bool (STDCALL *PF_ispSelectCanNode)(BYTE nodeNumber);
typedef bool (STDCALL *PF_ispUpdateCmdsIds)(BYTE cris);
typedef bool (STDCALL *PF_ispClosePort)(void);
typedef bool (STDCALL *PF_ispSyncTarget)(void);
typedef bool (STDCALL *PF_ispWriteSpecialByte)(int sbyte, BYTE value);
typedef bool (STDCALL *PF_ispReadSpecialByte)(int sbyte);
typedef bool (STDCALL *PF_ispExecSpecialCmd)(int cmd);
typedef bool (STDCALL *PF_ispReadSignatureBytes)(void);
typedef bool (STDCALL *PF_ispParseHexFile)(char* hexFile);
typedef bool (STDCALL *PF_ispWriteHexFile)(ULONG addrLo, ULONG addrHi,
                                           char* hexFile, int format);

typedef bool (STDCALL *PF_ispEraseDevice)(void);
typedef bool (STDCALL *PF_ispEraseBlock)(int blockN);
typedef bool (STDCALL *PF_ispEraseSbvBsb)(void);
typedef bool (STDCALL *PF_ispSetSecurityLev1)(void);
typedef bool (STDCALL *PF_ispSetSecurityLev2)(void);
typedef bool (STDCALL *PF_ispGetExpectedSsbValue)(int level);
typedef bool (STDCALL *PF_ispGetDefaultByteValue)(int sbyte);
typedef bool (STDCALL *PF_ispProgramAddrRange)(ULONG addrLo, ULONG addrHi);
typedef bool (STDCALL *PF_ispProgramDevice)(void);
typedef bool (STDCALL *PF_ispReadAddrRange)(ULONG addrLo, ULONG addrHi,
										    char* hexF);
typedef bool (STDCALL *PF_ispReadDevice)(char* hexF);
typedef bool (STDCALL *PF_ispVerifyAddrRange)(ULONG addrLo, ULONG addrHi);
typedef bool (STDCALL *PF_ispVerifyDevice)(void);
typedef bool (STDCALL *PF_ispBlankCheckAddrRange)(ULONG addrLo, ULONG addrHi);
typedef bool (STDCALL *PF_ispBlankCheckDevice)(void);
typedef void (STDCALL *PF_ispRandomizeBuffer)(void);
typedef bool (STDCALL *PF_ispFillBufferAddrRange)(ULONG addrLo, ULONG addrHi,
											   char* data);
typedef bool (STDCALL *PF_ispFillBuffer)(char* data);
typedef void (STDCALL *PF_ispResetBuffer)(void);
typedef void (STDCALL *PF_ispGetBufferAddrHi)(void);
typedef void (STDCALL *PF_ispGetBufferAddrLo)(void);
typedef bool (STDCALL *PF_ispWriteSingleByteToBuffer)(ULONG addr, char* value);
typedef void (STDCALL *PF_ispReadSingleByteFromBuffer)(ULONG addr);
typedef void (STDCALL *PF_ispComputeBufferChecksum)(ULONG addrLo, ULONG addrHi);
typedef bool (STDCALL *PF_ispSelectMemory)(int selectMem);
typedef bool (STDCALL *PF_ispEnterIspMode)(BYTE nodeNumber, ULONG addr);
typedef bool (STDCALL *PF_ispEnterAppliMode)(bool rstPulse, ULONG addr);
typedef ERROR_VEC* (STDCALL *PF_ispGetErrorVecPtr)(void);
typedef void (STDCALL *PF_ispSetDemoMode)(void);
typedef void (STDCALL *PF_ispCancelDemoMode)(void);

#ifdef WIN32
typedef void (STDCALL *PF_ispSetDebugMode)(HANDLE hCon);
#else
typedef void (STDCALL *PF_ispSetDebugMode)(void);
#endif
typedef void (STDCALL *PF_ispCancelDebugMode)(void);
typedef void (STDCALL *PF_ispOpenLogFile)(char* logFile = "log.txt");
typedef void (STDCALL *PF_ispDataLog)(const char* data);

typedef bool (STDCALL *PF_ispSetAutoIsp)(bool rstHi, bool psenLo);
typedef void (STDCALL *PF_ispGetMemorySize)(void);
typedef bool (STDCALL *PF_ispSerialize)(int memory, ULONG addr, LONG64 sn,
                                     UCHAR snBase, string format);
typedef bool (STDCALL *PF_ispEnableFuseBit)(int fuse);
typedef bool (STDCALL *PF_ispDisableFuseBit)(int fuse);
typedef bool (STDCALL *PF_ispComputeCrc)(void);
typedef int (STDCALL *PF_ispGetDeviceIndex)(char* name);
typedef int (STDCALL *PF_ispGetTaskCompletionPercent)(void);
typedef void (STDCALL *PF_ispResetTaskCompletionPercent)(void);
#ifdef LINUX
typedef pthread_cond_t* (STDCALL *PF_ispGetTaskPeriodicEventHandle)(void);
#else
typedef HANDLE (STDCALL *PF_ispGetTaskPeriodicEventHandle)(void);
#endif

typedef bool (STDCALL *PF_ispSetDtrLow)(void);
typedef bool (STDCALL *PF_ispSetDtrHigh)(void);
typedef bool (STDCALL *PF_ispSetRtsLow)(void);
typedef bool (STDCALL *PF_ispSetRtsHigh)(void);

typedef void (STDCALL *PF_ispCheckUsbDriver)(bool check);

typedef bool (STDCALL *PF_ispInitOcd)(void);

// *************************************************************************
// ******************** ISP API functions prototypes ***********************
// *************************************************************************



/*!
******************************************************************************
\fn         ispGetLastError
\brief	    Reads the last error code.
\return     The last error code as an index in the enumeration of error codes.
\par        Example of use:
\c          error = ispGetLastError();
\note
The purpose of this function is to get the error status of
previously executed commands.
******************************************************************************
*/
ATISP_API int STDCALL ispGetLastError(void);


/*!
******************************************************************************
\fn         ispGetLastResult
\brief	    Reads the last result.
\return     The requested value as a string of chars
\par        Example of use:
\c          s = ispGetLastResult();
\note
The purpose of this function is to get the results of previously executed
commands like reading a XAF byte, verifying or blank checking the device;
in these last two cases, we will get the first failing address.
******************************************************************************
*/
ATISP_API char* STDCALL ispGetLastResult(void);


/*!
******************************************************************************
\fn         ispInit
\brief	    Performs some ISP initialization tasks; must be called before any
			ISP session.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispInit() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispInit(void);



/*!
******************************************************************************
\fn         ispSetTimeout
\brief	    Sets the timeout of the next ISP operation.
\param      tsec        Timeout duration in seconds (min = 1, max = 3600)
\param      permanent   If true, the new timeout is set for ever.
\return     true if the timeout value is valid; else false.
\par        Example of use:
\c          if ( ispSetTimeout(50, true) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSetTimeout(DWORD tsec, bool permanent = false);



/*!
******************************************************************************
\fn         ispCancel
\brief	    Frees memory from any dynamic allocation; closes any open port.
            Must always be called before leaving an ISP session.
\par        Example of use:
\c          ispCancel();
******************************************************************************
*/
ATISP_API void STDCALL ispCancel(void);


/*!
******************************************************************************
\fn         ispSelectDevice
\brief	    Selects a microcontroller.
\param	    device      Device index in the enumeration of devices
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSelectDevice( T89C51RD2 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSelectDevice(int device);


/*!
******************************************************************************
\fn         ispSelectDevice2
\brief	    Selects a microcontroller. Used by the JNI.
\param	    device      Name of the device.
\return     True if successful; else false.
******************************************************************************
*/
ATISP_API bool STDCALL ispSelectDevice2(const char* device);


/*!
******************************************************************************
\fn         ispCreateBuffer
\brief	    Creates a memory buffer. Used by the JNI.
\param	    size      Size of the buffer in bytes.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSelectDevice( T89C51RD2 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispCreateBuffer(const DWORD size);


/*!
******************************************************************************
\fn         ispSelectCommHardware
\brief	    Selects a hardware interface for communication with the target.
\param	    hardware    Hardware index in the enumeration of communication
						media 
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSelectCommHardware( SYSTEC_USB_CAN ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSelectCommHardware(int hardware);


/*!
******************************************************************************
\fn         ispOpenCanPort
\brief	    This is the open port function for the CAN interface.
\param      bitrate     Bitrate value of the CAN bus; default = 500Kbit
\param      pType       Protocol type; 0 = Standard (default)/ 1 = Extended.
\param      port		Port number; 0 = any / 1 = LPT1 (default) / 2 = LPT2 / 
						3 = PCMCIA-slot0 / 4 = PCMCIA-slot1 /
						5 = COM1 / 6 = COM2 / 7 = COM3 / ...
\param      channel     For VECTOR CANcardx dongle; 1 (default) or 2.
\param		cris
\param		baudrate	RS232 baudrate for RS232-to-CAN dongles
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispOpenCanPort( 500, 0, 1, 1, 0, 115200 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispOpenCanPort(ULONG bitrate = 500,
                            BYTE pType = 0,
                            WORD port = 1,
                            BYTE channel = 1,
							BYTE cris = 0,
							DWORD baudrate = 115200);



/*!
******************************************************************************
\fn         ispOpenRs232Port
\brief	    This is the open port function for the RS232 port.
\param	    portName    Name of the RS232 port (default = COM1)
\param      baudrate    Baudrate value of the RS232 port (default = 115200)
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispOpenRs232Port( "COM1", 115200 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispOpenRs232Port(char* portName = "COM1",
										 ULONG baudrate = 115200);


/*!
******************************************************************************
\fn         ispOpenUsbPort
\brief	    This is the open port function for the USB port.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispOpenUsbPort() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispOpenUsbPort(void);


/*!
******************************************************************************
\fn         ispSelectCanNode
\brief	    Opens a CAN node for ISP; the node number 0xFF always open a node
			for ISP, whatever its actual node number is.
\param      nodeNumber (default = 0xFF)
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSelectCanNode(0xFF) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSelectCanNode(BYTE nodeNumber = 0xFF);


/*!
********************************************************************************
\fn        ispUpdateCmdsIds
\brief     Updates the CAN protocol commands IDs from the specified CRIS value.
\param     BYTE cris	The maximum value for CRIS is 0x7F
\return    bool			False if CRIS > 0x7F
\par       Example of use:
\c         if ( ispUpdateCmdsIds(0x02) ) ...
********************************************************************************
*/
ATISP_API bool STDCALL ispUpdateCmdsIds(BYTE cris);


/*!
******************************************************************************
\fn         ispClosePort
\brief	    Closes the currently open port.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispClosePort() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispClosePort(void);


/*!
******************************************************************************
\fn         ispSyncTarget
\brief	    Sets the target RS232 baudrate equal to the PC one.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSyncTarget() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSyncTarget(void);


/*!
******************************************************************************
\fn         ispWriteSpecialByte
\brief	    Writes a special byte of the target microcontroller.
\param	    sbyte       Special byte index in the enumeration of XAF bytes
\param	    value       Hexadecimal value to be written (string of chars)
\return     True if successful; else false.
\par        Example of use:
\c          if ( writeSpecialByte( SOFTWARE_BOOT_VECTOR, 0xFC ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispWriteSpecialByte(int sbyte, BYTE value);


/*!
******************************************************************************
\fn         ispReadSpecialByte
\brief	    Reads a special byte of the target microcontroller.
\param	    sbyte       Special byte index in the enumeration of XAF bytes 
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispReadSpecialByte( SOFTWARE_BOOT_VECTOR ) ) ...
\note
After successful completion of this function, the required information
may be got by calling the ispGetLastResult function.
******************************************************************************
*/
ATISP_API bool STDCALL ispReadSpecialByte(int sbyte);


/*!
******************************************************************************
\fn         ispExecSpecialCmd
\brief	    Executes a special command on the target microcontroller.
\param	    cmd       Special command index in the enumeration of commands.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispExecSpecialCmd( BYPASS_NONE ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispExecSpecialCmd(int cmd);


/*!
******************************************************************************
\fn         ispReadSignatureBytes
\brief	    Reads the signature bytes of the microcontroller: manuf id,...
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispReadSignatureBytes() ...
\note
After successful completion of this function, the required information
may be got by calling the ispGetLastResult function.
******************************************************************************
*/
ATISP_API bool STDCALL ispReadSignatureBytes(void);


/*!
******************************************************************************
\fn         ispParseHexFile
\brief	    Parses an Intel Hex format file.
\param      hexFile     HEX file pathname
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispParseHexFile( "C:\dev\isp.hex" ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispParseHexFile(char* hexFile);


/*!
******************************************************************************
\fn         ispWriteHexFile
\brief	    Creates an HEX file from a defined address range of buffer.
\param		addrLo		Low boundary address
\param		addrHi		High boundary address
\param      hexFile     Pathname of the HEX file to be generated
\param      format      HEX386 (default) or HEX86
\return     True if successful; else false.
\par		Example of use:
\c			if ( ispWriteHexFile( 0, 0x3FF, "C:\dev\isp.hex" ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispWriteHexFile(ULONG addrLo, ULONG addrHi,
                                       char* hexFile, int format=HEX386);


/*!
******************************************************************************
\fn         ispEraseDevice
\brief	    Erases the whole device memory.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispEraseDevice() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispEraseDevice(void);


/*!
******************************************************************************
\fn         ispEraseBlock
\brief	    Erases one block of the device memory.
\param      blockN      Index of the block to ne erased
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispEraseBlock( 2 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispEraseBlock(int blockN);


/*!
******************************************************************************
\fn         ispEraseSbvBsb
\brief	    Erases the Software Boot Vector and the Boot Status Byte.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispEraseSbvBsb() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispEraseSbvBsb(void);


/*!
******************************************************************************
\fn         ispSetSecurityLev1
\brief	    Sets the device in ISP write protected mode.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSetSecurityLev1() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSetSecurityLev1(void);


/*!
******************************************************************************
\fn         ispSetSecurityLev2
\brief	    Sets the device in ISP read/write protected mode.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSetSecurityLev2() ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSetSecurityLev2(void);


/*!
******************************************************************************
\fn         ispGetExpectedSsbValue
\brief	    Reads the expected Software Security Byte associated to a 
			security level value.
\param	    level       Software security level value (0, 1 or 2)
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispGetExpectedSsbValue( 1 ) ) ...
\note
This function is useful in non regression tests, when we modify the security
level and want to check the actual SSB value. The ispGetLastResult function
must be called afterwards.
******************************************************************************
*/
ATISP_API bool STDCALL ispGetExpectedSsbValue(int level);


/*!
******************************************************************************
\fn         ispGetDefaultByteValue
\brief	    Reads the expected value of a special byte after reset.
\param	    sbyte       Special byte index in the enumeration of XAF bytes 
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispGetDefaultByteValue( SOFTWARE_BOOT_VECTOR ) ) ...
\note
The purpose of this function is to get the values of XAF bytes
after reset; this is useful during the execution of non regression tests.
After successful completion of this function, the required information
may be got by calling the ispGetLastResult function.
******************************************************************************
*/
ATISP_API bool STDCALL ispGetDefaultByteValue(int sbyte);


/*!
******************************************************************************
\fn         ispProgramAddrRange
\brief	    Programs the device memory between (included) specified
			addresses boundaries.
\param	    addrLo      Low boundary programming address
\param	    addrHi      High boundary programming address
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispProgramAddrRange( 0x2C, 0xFBFA ) ) ...
\note
The programming data source is the buffer associated with the target memory.
This function is useful in non regression tests, when we have to program a
single address or a small address range. If a HEX file has been parsed before
programming, the ispProgramDevice function may be used.
******************************************************************************
*/
ATISP_API bool STDCALL ispProgramAddrRange(ULONG addrLo, ULONG addrHi);


/*!
******************************************************************************
\fn         ispProgramDevice
\brief	    Programs the device memory between (included) addresses boundaries
			got from the last parsed HEX file.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispProgramDevice() ) ...
\note
The programming data source is the buffer associated to the target memory.
Use this function when a HEX file has been previously parsed; in that case, 
the programming boundary addresses are those read from the HEX file.
******************************************************************************
*/
ATISP_API bool STDCALL ispProgramDevice(void);


/*!
******************************************************************************
\fn         ispReadAddrRange
\brief	    Reads the device memory between (included) specified addresses
			boundaries and optionally creates a Hex file from the read data.
\param	    addrLo      Low boundary reading address
\param	    addrHi      High boundary reading address
\param		hexF		Optional path to the Intel HEX file to create
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispReadAddrRange( 0xBEEF, 0xDEAD ) ) ...
\note
Reading the device memory updates the associated buffer contents.
This function is useful in non regression tests when we need to read
only a part of the target memory. If we have to read the whole memory
the ispReadDevice function, without arguments, may be used.
******************************************************************************
*/
ATISP_API bool STDCALL ispReadAddrRange(ULONG addrLo, ULONG addrHi,
										 char* hexF = "");


/*!
******************************************************************************
\fn         ispReadDevice
\brief	    Reads the whole device memory and optionally creates a
			Hex file from the read data.
\param		hexF		Optional path to the Intel HEX file to create
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispReadDevice() ) ...
\note
Reading the device memory updates the associated buffer contents.
******************************************************************************
*/
ATISP_API bool STDCALL ispReadDevice(char* hexF = "");


/*!
******************************************************************************
\fn         ispVerifyAddrRange
\brief	    Reads the target device memory from addrLo to addrHi and compares
			its	contents with the associated buffer one.
\param	    addrLo      Low boundary verifying address
\param	    addrHi      High boundary verifying address
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispVerifyAddrRange( 0xBEEF, 0xDEAD ) ) ...
\note
This function is useful in non regression tests when we need to verify
only a part of the target memory. If a HEX file has been parsed and the
device programmed between the HEX file boundary addresses, the
ispVerifyDevice function can be used.
If this function returns false, call the ispGetLastError() function.
If the error is STATUS_VERIFY_DEVICE_ERROR, call the ispGetLastResult()
function in order to retrieve the failing address.
******************************************************************************
*/
ATISP_API bool STDCALL ispVerifyAddrRange(ULONG addrLo, ULONG addrHi);


/*!
******************************************************************************
\fn         ispVerifyDevice
\brief	    Reads the target device memory between boundary addresses taken
			from the last parsed HEX file and compares its contents with the
			associated buffer one.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispVerifyDevice() ) ...
\note
If this function returns false, call the ispGetLastError() function.
If the error is STATUS_VERIFY_DEVICE_ERROR, call the ispGetLastResult()
function in order to retrieve the failing address.
******************************************************************************
*/
ATISP_API bool STDCALL ispVerifyDevice(void);


/*!
******************************************************************************
\fn         ispBlankCheckAddrRange
\brief	    Checks that the target device memory is blank from address
			addrLo to addrHi included.
\param	    addrLo      Low boundary blank checking address
\param	    addrHi      High boundary blank checking address
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispBlankCheckAddrRange( 0xBEEF, 0xDEAD ) ) ...
\note
This function is useful in non regression tests when we need to blank check
only a part of the target memory. Use ispBlankCheckDevice to check the whole
memory.
If this function returns false, call the ispGetLastError() function.
If the error is STATUS_BLANK_CHECK_ERROR, call the ispGetLastResult()
function in order to retrieve the failing address.
******************************************************************************
*/
ATISP_API bool STDCALL ispBlankCheckAddrRange(ULONG addrLo, ULONG addrHi);


/*!
******************************************************************************
\fn         ispBlankCheckDevice
\brief	    Checks that the whole target device memory is blank.
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispBlankCheckDevice() ) ...
\note
If this function returns false, call the ispGetLastError() function.
If the error is STATUS_BLANK_CHECK_ERROR, call the ispGetLastResult()
function in order to retrieve the failing address.
******************************************************************************
*/
ATISP_API bool STDCALL ispBlankCheckDevice(void);


/*!
******************************************************************************
\fn         ispRandomizeBuffer
\brief	    Writes random data into the memory associated buffer.
\par        Example of use:
\c          ispRandomizeBuffer();
******************************************************************************
*/
ATISP_API void STDCALL ispRandomizeBuffer(void);


/*!
******************************************************************************
\fn         ispFillBufferAddrRange
\brief	    Fills the application internal buffer with the specified byte
			within the specified address range.
\param	    addrLo      Low boundary filling address
\param	    addrHi      High boundary filling address
\param      data        Filling data
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispFillBuffer( 0xBEEF, 0xDEAD, "A7" ) ) ...
\note
An argument-less form exists for this function; it fills the whole buffer.
******************************************************************************
*/
ATISP_API bool STDCALL ispFillBufferAddrRange(ULONG addrLo, ULONG addrHi,
											   char* data);


/*!
******************************************************************************
\fn         ispFillBuffer
\brief	    Fills the whole application internal buffer with the specified
			byte.
\param	    addrLo      Low boundary filling address
\param	    addrHi      High boundary filling address
\param      data        Filling data
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispFillBuffer( "A7" ) ) ...
\note
Use the second form of this function if you wish to fill only a part of the
buffer.
******************************************************************************
*/
ATISP_API bool STDCALL ispFillBuffer(char* data);


/*!
******************************************************************************
\fn         ispResetBuffer
\brief	    Resets the ISP internal buffer to the default value.
\par        Example of use:
\c          ispResetBuffer();
******************************************************************************
*/
ATISP_API void STDCALL ispResetBuffer(void);


/*!
******************************************************************************
\fn         ispGetBufferAddrHi
\brief	    Get buffer high address for programming.
\c          ispGetBufferAddrHi();
\c			s = ispGetLastResult();
\note
This function may be used by the GUI to update buffer information.
The buffer high address may be the target memory highest address or the
last loaded HEX file one, depending on the ISP application setup.

******************************************************************************
*/
ATISP_API void STDCALL ispGetBufferAddrHi(void);


/*!
******************************************************************************
\fn         ispGetBufferAddrLo
\brief	    Get buffer low address for programming.
\c          ispGetBufferAddrLo();
\c			s = ispGetLastResult();
\note
This function may be used by the GUI to update buffer information.
The buffer low address may be the target memory lowest address or the
last loaded HEX file one, depending on the ISP application setup.
******************************************************************************
*/
ATISP_API void STDCALL ispGetBufferAddrLo(void);


/*!
******************************************************************************
\fn         ispWriteSingleByteToBuffer
\brief	    Writes a single buffer location.
\param	    addr        Buffer location to be written
\param	    value       Hexadecimal string of chars
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispWriteSingleByteToBuffer( 0xBEEF, "A9" ) ) ...
\note
This function is useful in non regression tests when we need to write
a single target memory location.
******************************************************************************
*/
ATISP_API bool STDCALL ispWriteSingleByteToBuffer(ULONG addr, char* value);


/*!
******************************************************************************
\fn         ispReadSingleByteFromBuffer
\brief	    Reads a single buffer location.
\param	    addr        Buffer location to be written
\return     Read byte value
\par        Example of use:
\c          ispReadSingleByteFromBuffer( 0xBEEF );
\c			s = ispGetLastResult();
\note
Call ispGetLastResult after calling ispReadSingleByteFromBuffer in order
to get the buffer byte value.
This function may be used to update a GUI ISP buffer window.
******************************************************************************
*/
ATISP_API void STDCALL ispReadSingleByteFromBuffer(ULONG addr);


/*!
******************************************************************************
\fn         ispComputeBufferChecksum
\brief	    Computes the checksum of the ISP buffer between (and including)
			two addresses.
\param	    addrLo		Buffer low boundary address
\param	    addrHi		Buffer high boundary address
\par        Example of use:
\c          ispComputeBufferChecksum( 0x000A, 0x0FFC );
\c			s = ispGetLastResult();
\note
Call ispGetLastResult after calling ispComputeBufferChecksum in order
to get the buffer checksum value.
******************************************************************************
*/
ATISP_API void STDCALL ispComputeBufferChecksum(ULONG addrLo, ULONG addrHi);


/*!
******************************************************************************
\fn         ispSelectMemory
\brief	    Modifies the memory context (FLASH or EEPROM).
\param	    selectMem   1 = FLASH; 2 = EEPROM
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispSelectMemory( 1 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispSelectMemory(int selectMem);


/*!
******************************************************************************
\fn         ispEnterIspMode
\brief	    Forces the target to enter back the ISP mode.
\param      nodeNumber  The CAN node number we send the message to
\param	    addr        ATMEL's bootloader address; defaults to 0xFF00
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispEnterIspMode( 0xFF, 0xFC00 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispEnterIspMode(BYTE nodeNumber, ULONG addr = 0xFF00);


/*!
******************************************************************************
\fn         ispEnterAppliMode
\brief	    Forces the target to enter the application mode.
\param      rstPulse    If true, the bootloader will generate a Reset pulse
                        on the target hardware; defaults to false (no pulse).
\param	    addr        User's application start address; defaults to 0x0000
\return     True if successful; else false.
\par        Example of use:
\c          if ( ispEnterAppliMode( true, 0x01F0 ) ) ...
******************************************************************************
*/
ATISP_API bool STDCALL ispEnterAppliMode(bool rstPulse = false,
										  ULONG addr = 0x0000);


/*!
******************************************************************************
\fn         ispGetErrorVecPtr
\brief	    Gets a pointer to the error vector container.
			The error vector contains the error text to be displayed.
\return     A pointer to the error vector container.
\par        Example of use:
\c          errvect = ispGetErrorVecPtr();
******************************************************************************
*/
ATISP_API ERROR_VEC* STDCALL ispGetErrorVecPtr(void);


/*!
******************************************************************************
\fn         ispSetDemoMode
\brief	    Forces the application to enter the demo mode.
\par        Example of use:
\c          ispSetDemoMode();
\note		In demo mode, functions are called but ISP operations are not
			performed, allowing the user to play a full ISP sequence without
			needing any target hardware.
******************************************************************************
*/
ATISP_API void STDCALL ispSetDemoMode(void);


/*!
******************************************************************************
\fn         ispCancelDemoMode
\brief	    Forces the application to quit demo mode.
\par        Example of use:
\c          ispCancelDemoMode();
******************************************************************************
*/
ATISP_API void STDCALL ispCancelDemoMode(void);


/*!
******************************************************************************
\fn         ispSetDebugMode
\brief	    Forces the application to enter the debug mode.
\param      hCon      Debug console handle (Windows only)
\note		In debug mode, the names of top level functions are displayed
			as well as the traffic on the selected medium.
******************************************************************************
*/
#ifdef WIN32
ATISP_API void STDCALL ispSetDebugMode(HANDLE hCon);
#else
ATISP_API void STDCALL ispSetDebugMode(void);
#endif

/*!
******************************************************************************
\fn         ispCancelDebugMode
\brief	    Forces the application to quit the debug mode.
\par        Example of use:
\c          ispCancelDebugMode();
******************************************************************************
*/
ATISP_API void STDCALL ispCancelDebugMode(void);

/*!
******************************************************************************
\fn         ispOpenLogFile
\brief	    Opens a file for data logging.
\param      logFile: the log file pathname.
\par        Example of use:
\c          ispOpenLogFile("C:\temp\my_logfile.txt");
******************************************************************************
*/
ATISP_API void STDCALL ispOpenLogFile(char* logFile = "log.txt");


/*!
******************************************************************************
\fn         ispDataLog
\brief	    Logs data to the console and to the log file if one is open.
\par        Example of use:
\c          ispDataLog("erasing memory");
******************************************************************************
*/
ATISP_API void STDCALL ispDataLog(const char* data);

/*!
******************************************************************************
\fn         ispSetAutoIsp
\brief	    Sets the hardware conditions on the target to enter ISP mode
			automatically. For RS232 only.
\param		bool rstHi		Reset signal polarity (default = active high)
\param		bool psenLo		Psen signal polarity (default = active low)
\par        Example of use:
\c          ispSetAutoIsp();
******************************************************************************
*/
ATISP_API bool STDCALL ispSetAutoIsp(bool rstHi = true, bool psenLo = true);


/*!
******************************************************************************
\fn         ispGetMemorySize
\brief	    Gets the currently selected memory size in bytes.
\par        Example of use:
\c          ispGetMemorySize();
\c			s = ispGetLastResult();
\note		This function may be used by the GUI.
******************************************************************************
*/
ATISP_API void ispGetMemorySize(void);


/*!
******************************************************************************
\fn        ispSerialize
\brief	  Stores an ISP serial number in memory.
\param		memory	Memory in which we store the serial number.
\param		addr	  Serial number most significant byte address in memory.
\param		sn  	  Serial number value.
\param    snBase  Serial number base (10 or 16)
\param		format	We can write the SN as number | ascii | unicode
\par      Example of use:
\c        ispSerialize( EEPROM, 0x7FF, 0x1245, 16, "number" );
******************************************************************************
*/
ATISP_API bool STDCALL ispSerialize(int memory, ULONG addr, LONG64 sn,
                                    UCHAR snBase, string format);


/*!
******************************************************************************
\fn         ispEnableFuseBit
\brief	    Enables the fuse bit which number is passed as argument.
\param		fuse	Fuse bit index in the fuse bits list. 
\par        Example of use:
\c          if ( ! ispEnableFuseBit( 0 ) )
\c				s = ispGetLastError();
******************************************************************************
*/
ATISP_API bool STDCALL ispEnableFuseBit(int fuse);


/*!
******************************************************************************
\fn         ispDisableFuseBit
\brief	    Disables the fuse bit which number is passed as argument.
\param		fuse	Fuse bit index in the fuse bits list. 
\par        Example of use:
\c          if ( ! ispDisableFuseBit( 0 ) )
\c				s = ispGetLastError();
******************************************************************************
*/
ATISP_API bool STDCALL ispDisableFuseBit(int fuse);


/*!
******************************************************************************
\fn         ispComputeCrc
\brief	    Computes a complex CRC on the memory buffer from address zero
			to memory address max - 2.
\par        Example of use:
\c          if ( ispComputeCrc() )
\c				s = ispGetLastResult();
******************************************************************************
*/
ATISP_API bool STDCALL ispComputeCrc(void);


/*!
********************************************************************************
\fn        ispGetDeviceIndex
\brief     Returns the index of the specified device; used by batchisp only.
\param     char* name			Name of the device (uppercase letters)
\return    ATISP_API int		Index of the device
********************************************************************************
*/
ATISP_API int STDCALL ispGetDeviceIndex(char* name);


/*!
******************************************************************************
\fn         ispGetTaskCompletionPercent
\brief	    Returns the percentage of completion of the current task.
******************************************************************************
*/
ATISP_API int STDCALL ispGetTaskCompletionPercent(void);


/*!
******************************************************************************
\fn         ispResetTaskCompletionPercent
\brief	    Resets the percentage of completion of the current task.
******************************************************************************
*/
ATISP_API void STDCALL ispResetTaskCompletionPercent(void);


/*!
******************************************************************************
\fn         ispGetTaskPeriodicEventHandle
\brief	    Returns the handle of the event used to control the progress bar.
			The event is periodically set to the signaled state.
******************************************************************************
*/
#ifdef LINUX
ATISP_API pthread_cond_t* STDCALL ispGetTaskPeriodicEventHandle(void);
#else
ATISP_API HANDLE STDCALL ispGetTaskPeriodicEventHandle(void);
#endif

/*
   The following functions may be called to set and clear the ISP hardware
   conditions when the DTR and RTS signals are properly connected to the 
   microcontroller RESET and PSEN pins.
*/

ATISP_API bool STDCALL ispSetDtrLow(void);

ATISP_API bool STDCALL ispSetDtrHigh(void);

ATISP_API bool STDCALL ispSetRtsLow(void);

ATISP_API bool STDCALL ispSetRtsHigh(void);

ATISP_API void STDCALL ispCheckUsbDriver(bool check);


/*!
******************************************************************************
\fn         ispInitOcd
\brief	    When running batchisp to perform Flash programming through
            the OCD dongle, we have to init the dongle in ISP mode.
******************************************************************************
*/
ATISP_API void STDCALL ispInitOcd(void);


#endif // ATISP_H_



