#ifndef	_PIC18_H
#define	_PIC18_H

#ifndef _HTC_H_
#include <htc.h>
#endif

/* If __TCP_H or __TCPIP_H are defined, probably using Microchip TCP/IP Stack,
 * which has their own bitfields, so don't include our Microchip compatible 
 * headers or some symbols will be redefined. */
#if defined (__TCP_H) || defined (__TCPIP_H)
// These devices are newly added and have no old-style headers, so include regardless of whether using TCP or not
#warning __TCP_H || __TCPIP_H detected, not including Microchip-compatible headers.
#if defined(_18F24J11) || defined(_18LF24J11)
	#warning not auto-including 18f24j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F25J11) || defined(_18LF25J11)
	#warning not auto-including 18f25j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F26J11) || defined(_18LF26J11)
	#warning not auto-including 18f26j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F44J11) || defined(_18LF44J11)
	#warning not auto-including 18f44j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F45J11) || defined(_18LF45J11)
	#warning not auto-including 18f45j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F46J11) || defined(_18LF46J11)
	#warning not auto-including 18f46j11.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F24J50) || defined(_18LF24J50)
	#warning not auto-including 18f24j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F25J50) || defined(_18LF25J50)
	#warning not auto-including 18f25j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F26J50) || defined(_18LF26J50)
	#warning not auto-including 18f26j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F44J50) || defined(_18LF44J50)
	#warning not auto-including 18f44j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F45J50) || defined(_18LF45J50)
	#warning not auto-including 18f45j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F46J50) || defined(_18LF46J50)
	#warning not auto-including 18f46j50.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F66J90)
	#warning not auto-including 18f66j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F67J90)
	#warning not auto-including 18f67j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F86J90)
	#warning not auto-including 18f86j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F87J90)
	#warning not auto-including 18f87j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F66J93)
	#warning not auto-including 18f66j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F67J93)
	#warning not auto-including 18f67j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F86J93)
	#warning not auto-including 18f86j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#if defined(_18F87J93)
	#warning not auto-including 18f87j90.h to avoid conflicting declarations with Microchip's TCP/IP Stack. 
#endif
#else
#include <chipselect.h>
#endif

/* if _PLIB is defined (which driver will do when --runtime=+plib is used), include plib.h */
#if defined _PLIB
#include <plib.h>
#endif

/* Get definitions for errata codes that may be
 * defined in preprocessor symbol _ERRATA_TYPES */
#if _HTC_VER_MAJOR_ >= 9
	#include <errata.h>
#endif

#ifdef __MPLAB_REALICE__
	#include <trace18.h>
#endif


/* Define J_PART for J parts with only new header files */

#if defined(_18F44J11) || defined(_18LF44J11) || defined(_18F24J11) || defined(_18LF24J11) || \
	defined(_18F45J11) || defined(_18LF45J11) || defined(_18F25J11) || defined(_18LF25J11) || \
	defined(_18F46J11) || defined(_18LF46J11) || defined(_18F26J11) || defined(_18LF26J11) || \
	defined(_18F44J50) || defined(_18LF44J50) || defined(_18F24J50) || defined(_18LF24J50) || \
	defined(_18F45J50) || defined(_18LF45J50) || defined(_18F25J50) || defined(_18LF25J50) || \
	defined(_18F46J50) || defined(_18LF46J50) || defined(_18F26J50) || defined(_18LF26J50) || \
	defined(_18F66J90) || defined(_18F67J90) || defined(_18F86J90) || defined(_18F87J90) || \
	defined(_18F66J93) || defined(_18F67J93) || defined(_18F86J93) || defined(_18F87J93)
#define	__J_PART
#endif

//ENDHDR
#if	defined(_18C242) || defined(_18C252) || defined(_18C442) || defined(_18C452) 
#include	<pic18xx2.h>
#endif

#if	defined(_18C658) || defined(_18C858) || defined(_18C958)
#include	<pic18xx8.h>
#endif

#if	defined(_18C601) || defined(_18C801)
#include	<pic18xx1.h>
#endif

#if	defined(_18F242) || defined(_18F252) || defined(_18F442) || defined(_18F452)
#include	<pic18fxx2.h>
#endif

#if	defined(_18F248) || defined(_18F258) || defined(_18F448) || defined(_18F458)
#include	<pic18fxx8.h>
#endif

#if	defined(_18F6520) || defined(_18F6620) || defined(_18F6720) || \
	defined(_18F8520) || defined(_18F8620) || defined(_18F8720)
#include	<pic18fxx20.h>
#endif

#if	defined(_18F2525) || defined(_18F2620) || defined(_18F4525) || \
	defined(_18F4620)
#include	<pic18f4620.h>
#endif

#if	defined(_18F1220) || defined(_18F1320)
#include	<pic18f1220.h>
#endif

#if	defined(_18F13K50) || defined(_18F14K50) || defined(_18LF13K50) || defined(_18LF14K50)
#include	<pic18f1xk50.h>
#endif

#if	defined(_18F1230) || defined(_18F1330)
#include	<pic18f1330.h>
#endif

#if	defined(_18F2220) || defined(_18F2320) || defined(_18F4220) || defined(_18F4320)
#include	<pic18f2320.h>
#endif

#if	defined(_18F2331) || defined(_18F2431) || defined(_18F4331) || defined(_18F4431)
#include	<pic18fxx31.h>
#endif

#if	defined(_18F2410) || defined(_18F2510) || defined(_18F2515) || defined(_18F2610) ||\
	defined(_18F4410) || defined(_18F4510) || defined(_18F4515) || defined(_18F4610)
#include	<pic18f2x1x.h>
#endif

#if	defined(_18F2439) || defined(_18F2539) || defined(_18F4439) || defined(_18F4539)
#include	<pic18fxx39.h>
#endif

#if	defined(_18F6585) || defined(_18F6680) || defined(_18F8585) || defined(_18F8680)
#include	<pic18fxx8x.h>
#endif

#if	defined(_18F2585) || defined(_18F2680) || defined(_18F4585) || defined(_18F4680)
#include	<pic18f2x8x.h>
#endif

#if	defined(_18F6310) || defined(_18F6410) || defined(_18F8310) || defined(_18F8410)
#include	<pic18f6x10.h>
#endif

#if	defined(_18F6525) || defined(_18F6621) || defined(_18F8525) || defined(_18F8621)
#include	<pic18f6x2x.h>
#endif

#if	defined(_18F6390) || defined(_18F6490) || defined(_18F8390) || defined(_18F8490)
#include	<pic18fx490.h>
#endif

#if	defined(_18F6393) || defined(_18F6493) || defined(_18F8393) || defined(_18F8493)
#include	<pic18fx493.h>
#endif

#if	defined(_18F2221) || defined(_18F2321) || defined(_18F4221) || defined(_18F4321)
#include	<pic18f4321.h>
#endif

#if	defined(_18F2420) || defined(_18F2520) || defined(_18F4420) || defined(_18F4520)
#include	<pic18f4520.h>
#endif

#if	defined(_18F23K20) || defined(_18F24K20) || defined(_18F25K20) || defined(_18F26K20) || \
       	defined(_18F43K20) || defined(_18F44K20) || defined(_18F45K20) || defined(_18F46K20)
#include	<pic18f45k20.h>
#endif

#if	defined(_18F2423) || defined(_18F2523) || defined(_18F4423) || defined(_18F4523)
#include	<pic18f4523.h>
#endif

#if	defined(_18F2480) || defined(_18F2580) || defined(_18F4480) || defined(_18F4580)
#include	<pic18f4580.h>
#endif

#if	defined(_18F2455) || defined(_18F2550) || defined(_18F4455) || defined(_18F4550) || \
	defined(_18F2458) || defined(_18F2553) || defined(_18F4458) || defined(_18F4553)
#include	<pic18f4550.h>
#endif

#if	defined(_18F2450) || defined(_18F4450)
#include	<pic18f4450.h>
#endif

#if	defined(_18F24J10) || defined(_18LF24J10) || defined(_18F25J10) || defined(_18LF25J10) || \
	defined(_18F44J10) || defined(_18LF44J10) || defined(_18F45J10) || defined(_18LF45J10)
#include	<pic18f45j10.h>
#define	__J_PART
#endif

#if	defined(_18F2682) || defined(_18F2685) || defined(_18F4682) || defined(_18F4685)
#include	<pic18f4685.h>
#endif

#if	defined(_18F6627) || defined(_18F6722) || defined(_18F8627) || defined(_18F8722) || \
	defined(_18F6527) || defined(_18F6622) || defined(_18F8527) || defined(_18F8622) || \
	defined(_18F6628) || defined(_18F6723) || defined(_18F8628) || defined(_18F8723)
#include	<pic18fxx22.h>
#endif

#if	defined(_18F65J10) || defined(_18F65J15) || defined(_18F66J10) || defined(_18F66J15) || \
       	defined(_18F67J10) || defined(_18F85J10) || defined(_18F85J15) || defined(_18F86J10) || \
	defined(_18F86J15) || defined(_18F87J10)
#include	<pic18f87j10.h>
#define	__J_PART
#endif

#if	defined(_18F63J11) || defined(_18F64J11) || defined(_18F65J11) || defined(_18F83J11) || \
       	defined(_18F84J11) || defined(_18F85J11)
#include	<pic18f85j11.h>
#define	__J_PART
#endif

#if	defined(_18F66J11) || defined(_18F66J16) || defined(_18F67J11) || defined(_18F86J11) || \
       	defined(_18F86J16) || defined(_18F87J11)
#include	<pic18f87j11.h>
#define	__J_PART
#endif

#if	defined(_18F65J50) || defined(_18F66J50) || defined(_18F66J55) || defined(_18F67J50) || \
       	defined(_18F85J50) || defined(_18F86J50) || defined(_18F86J55) || defined(_18F87J50)
#include	<pic18f87j50.h>
#define	__J_PART
#endif

#if	defined(_18F63J90) || defined(_18F64J90) || defined(_18F65J90) || defined(_18F83J90) || \
       	defined(_18F84J90) || defined(_18F85J90)
#include	<pic18f85j90.h>
#define	__J_PART
#endif

#if	defined(_18F66J60) || defined(_18F66J65) || defined(_18F67J60) || defined(_18F86J60) || \
       	defined(_18F86J65) || defined(_18F87J60) || defined(_18F96J60) || defined(_18F96J65) || \
	defined(_18F97J60)
#include	<pic18f97j60.h>
#define	__J_PART
#endif

#if defined(_18F13K20) || defined(_18F13K22) || defined(_18LF13K22)
	    #include <pic18f13k22.h>
#endif

#if defined(_18F14K20) || defined(_18F14K22) || defined(_18LF14K22)
	    #include <pic18f14k22.h>
#endif

#if defined(_18F24J11) || defined(_18LF24J11)
    #include <pic18f24j11.h>
#define	__J_PART
#endif

#if defined(_18F25J11) || defined(_18LF25J11)
    #include <pic18f25j11.h>
#define	__J_PART
#endif

#if defined(_18F26J11) || defined(_18LF26J11)
    #include <pic18f26j11.h>
#define	__J_PART
#endif

#if defined(_18F44J11) || defined(_18LF44J11)
    #include <pic18f44j11.h>
#define	__J_PART
#endif

#if defined(_18F45J11) || defined(_18LF45J11)
    #include <pic18f45j11.h>
#define	__J_PART
#endif

#if defined(_18F46J11) || defined(_18LF46J11)
    #include <pic18f46j11.h>
#define	__J_PART
#endif

#if defined(_18F24J50) || defined(_18LF24J50)
    #include <pic18f24j50.h>
#define	__J_PART
#endif

#if defined(_18F25J50) || defined(_18LF25J50)
    #include <pic18f25j50.h>
#define	__J_PART
#endif

#if defined(_18F26J50) || defined(_18LF26J50)
    #include <pic18f26j50.h>
#define	__J_PART
#endif

#if defined(_18F44J50) || defined(_18LF44J50)
    #include <pic18f44j50.h>
#define	__J_PART
#endif

#if defined(_18F45J50) || defined(_18LF45J50)
    #include <pic18f45j50.h>
#define	__J_PART
#endif

#if defined(_18F46J50) || defined(_18LF46J50)
    #include <pic18f46j50.h>
#define	__J_PART
#endif

#if defined(_18F66J90)
#include <pic18f66j90.h>
#define	__J_PART
#endif

#if defined(_18F67J90)
#include <pic18f67j90.h>
#define	__J_PART
#endif

#if defined(_18F86J90)
#include <pic18f86j90.h>
#define	__J_PART
#endif

#if defined(_18F87J90)
#include <pic18f87j90.h>
#define	__J_PART
#endif

#if defined(_18F66J93)
#include <pic18f66j93.h>
#define	__J_PART
#endif

#if defined(_18F67J93)
#include <pic18f67j93.h>
#define	__J_PART
#endif

#if defined(_18F86J93)
#include <pic18f86j93.h>
#define	__J_PART
#endif

#if defined(_18F87J93)
#include <pic18f87j93.h>
#define	__J_PART
#endif

#if defined(_18F87K90)
#include <pic18f87k90.h>
#endif

#if defined(_18F87K22)
#include <pic18f87k22.h>
#endif

/* Macros to access bytes within words and words within longs */
#define LOW_BYTE(x)     ((unsigned char)((x)&0xFF))
#define HIGH_BYTE(x)    ((unsigned char)(((x)>>8)&0xFF))
#define LOW_WORD(x)     ((unsigned short)((x)&0xFFFF))
#define HIGH_WORD(x)    ((unsigned short)(((x)>>16)&0xFFFF))

/* C access to assembler insructions */	
#define	CLRWDT()	asm(" clrwdt")
#define	NOP()		asm(" nop")
#define	RESET()		asm(" reset")
#define SLEEP()		asm(" sleep")

/* Store a word value to a particular configuration word register eg.
 * __CONFIG(4, DEBUGEN & LVPDIS); // write to config word 4
 * config mask attributes (such as DEBUGEN) defined in chip-specific
 * header file. */
#define __CONFIG(w,s)	asm("\tglobal __config" ___mkstr(w));	\
						asm("\t__config" ___mkstr(w) " equ " 	\
								___mkstr(s))

/* J series devices don't have user ID memory */
#ifndef __J_PART
/* read/write to user ID regs */
extern unsigned char idloc_read(unsigned char reg_no);
extern void idloc_write(unsigned char reg_no,unsigned char data);

#define __IDLOC(w)      asm("\tpsect idloc,class=IDLOC");\
			asm("\tglobal\tidloc_word"); \
			asm("idloc_word:"); \
			asm("\tirpc\t__arg," ___mkstr(w)); \
			asm("\tdb 0f&__arg&h"); \
			asm("\tendm")
#endif


/* Address definitions for config word registers
 * (NOT TO BE USED WITH __CONFIG MACRO!) */
#define CONFIG1L	0x300000
#define CONFIG1H	0x300001
#define CONFIG2L	0x300002
#define CONFIG2H	0x300003
#define CONFIG3L	0x300004
#define CONFIG3H	0x300005
#define CONFIG4L	0x300006
#define CONFIG4H	0x300007
#define CONFIG5L	0x300008
#define CONFIG5H	0x300009
#define CONFIG6L	0x30000A
#define CONFIG6H	0x30000B
#define CONFIG7L	0x30000C
#define CONFIG7H	0x30000D


/* Initialise device EEPROM (if available) with 8 bytes of data at a time eg.
 * // store initial values to first 16-bytes of EEPROM address range.
 * __EEPROM_DATA(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07);
 * __EEPROM_DATA(0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F);*/
#if _EEPROMSIZE > 0
 #define __EEPROM_DATA(a, b, c, d, e, f, g, h) \
			 asm("\tpsect eeprom_data,class=EEDATA"); \
			 asm("\tdb\t" ___mkstr(a) "," ___mkstr(b) "," ___mkstr(c) "," ___mkstr(d) "," \
				      ___mkstr(e) "," ___mkstr(f) "," ___mkstr(g) "," ___mkstr(h))
#else
 #define __EEPROM_DATA(a, b, c, d, e, f, g, h)	// Added only for code portability
#endif

// Various helper macros used in EEPROM/flash routines
#if	_EEPROMSIZE > 256
 #define _LOAD_EEADR(addr)	(EEADRH=(((addr)>>8)&0xFF),EEADR=((addr)&0xFF))
#else
 #define _LOAD_EEADR(addr)	(EEADR=((addr)&0xFF))
#endif

#if	_EEPROMSIZE > 0
 #define _CLEAR_EEIF()	EEIF=0
#else
 #define _CLEAR_EEIF()
#endif

#if defined(SMALL_DATA)
 #define _LOAD_TBLPTR(addr)	TBLPTRU=0;TBLPTR=(far unsigned char*)(addr)
#else
 #define _LOAD_TBLPTR(addr)	TBLPTR=(far unsigned char*)(addr)
#endif

/* REALICE functions */
#define __builtin_enum_label(x,y)		\
	do {					\
		asm("global " x ___mkstr(y) );	\
		asm(x ___mkstr(y)":");		\
	} while(0)

// MACROS for EEPROM Access
/* macro versions of EEPROM read and write */

/* NOTE WELL:

   The macro EEPROM_READ() is NOT safe to use immediately after any
   write to EEPROM, as it does NOT wait for WR to clear.  This is by
   design, to allow minimal code size if a sequence of reads is
   desired.  To guarantee uncorrupted writes, use the function
   eeprom_read() or insert
	while(WR)continue;
   before calling EEPROM_READ().
*/
#if(_EEPROMSIZE == 0)
 #define EEPROM_READ(addr)	0	// Added only for code portability
#elif	(_ERRATA_TYPES & ERRATA_EEDATARD)
	/* For chips which must read EEDATA immediately after RD is
	 * set, EEDATA is read into temp variable EEADR because, if
	 * the result of EEPROM_READ is returned to an indirect
	 * object, it may take several instructions to set up access
	 * to that object. */
 #define EEPROM_READ(addr)   \
	 (_LOAD_EEADR(addr),\
	 CARRY=GIE,GIE=0,   \
	 EECON1&=0x3F,RD=1, \
	 EEADR=EEDATA,	    \
	 GIE=CARRY,	    \
	 (EEADR))
#else 	/* Plain and simple version */
 #define EEPROM_READ(addr)    \
	 (_LOAD_EEADR(addr),  \
	 EECON1&=0x3F,RD=1,   \
	 (EEDATA))
#endif

#if(_EEPROMSIZE == 0)
 #define EEPROM_WRITE(addr, value)	// Added only for code portability
#else
 #define EEPROM_WRITE(addr, value)			\
	do{						\
		while(WR)continue;			\
		_LOAD_EEADR(addr);			\
		EEDATA=(value);				\
		EECON1&=0x3F;				\
		CARRY=0;if(GIE)CARRY=1;GIE=0;		\
		WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;	\
		_CLEAR_EEIF();WREN=0;			\
		if(CARRY)GIE=1;				\
	}while(0)
#endif

/* read/write EEPROM data memory */
extern unsigned char eeprom_read(unsigned int address);
extern void eeprom_write(unsigned int address,unsigned char data);


/* read/write/erase sections of program memory */
extern unsigned char flash_read(unsigned long addr);
#define FLASH_READ(addr) flash_read(addr)

#if	_FLASH_ERASE_SIZE
extern void flash_write(const unsigned char *,unsigned int,far unsigned char *);
#define FLASH_WRITE(source,length,dest) flash_write(source,length,dest)

extern void flash_erase(unsigned long addr);
/* erasing a flash program memory row */
#define FLASH_ERASE(addr)				\
	do{						\
		_LOAD_TBLPTR(addr);			\
		while(WR)continue;			\
		CARRY=0;if(GIE)CARRY=1;GIE=0;		\
		EECON1|=0x94;EECON1&=0xBF;		\
		WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;	\
		asm("\tNOP");				\
		_CLEAR_EEIF();WREN=0;			\
		if(CARRY)GIE=1;				\
	}while(0)

#endif /* _FLASH_ERASE_SIZE */


/* read/write device configuration registers */
extern unsigned int config_read(unsigned char reg_no);
extern void config_write(unsigned char reg_no, unsigned int dataword);

/* read factory-programmed device ID code */
extern unsigned int device_id_read(void);

/* general purpose EE/flash init sequence used by above functions */
extern void initiate_write(void);


/* Accurate read/write macros for 16-Bit timers */
/*** please note, the timer needs to be enabled ***
 *** to handle 16-Bit read/write operations for ***
 *** these routines to be of benefit ***/
#define T1RD16ON  T1CON|=0x80
#define T3RD16ON  T3CON|=0x80
#define WRITETIMER0(x) ((void)(TMR0H=((x)>>8),TMR0L=((x)&0xFF)))
#define WRITETIMER1(x) ((void)(TMR1H=((x)>>8),TMR1L=((x)&0xFF)))
#define WRITETIMER3(x) ((void)(TMR3H=((x)>>8),TMR3L=((x)&0xFF)))
#define READTIMER0() (TMR0)
#define READTIMER1() (TMR1)
#define READTIMER3() (TMR3)

/* General purpose 8-bit summative checksum routines
 * parameter 1: start address
 * parameter 2: length of address to calculate (end - start) */
extern unsigned char checksum8(unsigned long startAddr, unsigned long length);
extern unsigned int checksum16(unsigned long startAddr, unsigned long length);
extern unsigned long checksum32(unsigned long startAddr, unsigned long length);

/* Macro expansions to the above routines.
 * In the macro version the second parameter is the end address - not length */
#define CHECKSUM8(START, END)	checksum8((START),((END)-(START)))
#define CHECKSUM16(START, END)	checksum16((START),((END)-(START)))
#define CHECKSUM32(START, END)	checksum32((START),((END)-(START)))

#ifdef _OMNI_CODE_
/****************************************************************/
/* Built-in delay routine					*/
/****************************************************************/
#pragma inline(_delay)
extern void _delay(unsigned long);
#pragma inline(_delay3)
extern void _delay3(unsigned char);
// NOTE: To use the macros below, YOU must have previously defined _XTAL_FREQ
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#endif

/* Global Interrupt Enable */
#ifndef	ei
#define	ei()	(GIE = 1) 	// Interrupts of Hi/Lo Priority or Peripheral interrupts 
#endif

/* Global Interrupt Disable */
#ifndef	di
#define	di()	(GIE = 0)	// Interrupts of Hi/Lo Priority or Peripheral interrupts 
#endif


#endif	/* _PIC18_H */
