/*
 *
 *                   Copyright 2007, 2008 Elba Corporation
 *                         All rights reserved
 *
 *    This source code is provided to the purchaser of the product
 *    for the purpose of allowing the purchaser to compile their
 *    application code.  The source code remains the property of
 *    Elba Corporation with all rights reserved.  Any modifications to
 *    this source code are considered derivative works and all rights
 *    thereto are reserved to Elba Corporation except that the purchaser
 *    may use the modified source code in the same permitted manner as
 *    the unmodified source code. It is expressly prohibited to distribute
 *    in any manner any part of the original source code, whether in
 *    source or object form, without the express written permission
 *    from Elba Corporation.
 *
 *    Owner:
 *        Elba Corp.
 *        10915 SW Avocet Ct.
 *        Beaverton, OR  97007
 *
 */

#ifndef	__ZXLIB_H__
#define __ZXLIB_H__

#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <setjmp.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

//**********************************************************************
//
//                         ZX Library v2.5.6
//
// This file is generated automatically.  Do not modify it directly.
//
//**********************************************************************


//---------------------------------------------------------------------------
// Id: avrdef.h rev 170
//---------------------------------------------------------------------------
// port indices
#define __PORT_A						0
#define __PORT_B						1
#define __PORT_C						2
#define __PORT_D						3
#define __PORT_E						4
#define __PORT_F						5
#define __PORT_G						6
#define __PORT_H						7
#define __PORT_I						8			// not used
#define __PORT_J						9
#define __PORT_K						10
#define __PORT_L						11

#define PORT_BIT_FLAG					0x80
#define PORT_PORT_MASK					0x78
#define PORT_PORT_SHIFT					3
#define PORT_BIT_MASK					0x07

// preprocessor macro to encode a port/bit number as a port designator
#define PORT_PORT(p)					(((p) << PORT_PORT_SHIFT) & PORT_PORT_MASK)
#define PORT_BIT(p, b)					(PORT_BIT_FLAG + ((p) << PORT_PORT_SHIFT) + ((b) & PORT_BIT_MASK))
#define __PORT(p, b)					PORT_BIT(__PORT_##p, b)

#if !defined(__ASSEMBLER__)
#if defined(RAMPZ) && !defined(ZVM)
typedef uint32_t ProgMemAddr;
#else
typedef uint16_t ProgMemAddr;
#endif

#define NORETURN				__attribute__((noreturn))
#define INLINE					__attribute__((always_inline))
#define NO_INLINE				__attribute__((noinline))
#define PURE					__attribute__((pure))
#define UNUSED					__attribute__((unused))
#define USED					__attribute__((used))
#define NO_INIT					__attribute__((section(".noinit")))
#if !defined(EEMEM)
#define EEMEM					__attribute__((section(".eeprom")))
#endif
#define ZX_EEMEM				__attribute__((section(".zx_eeprom")))
#if !defined(PROGMEM)
#define PROGMEM					__attribute__((__progmem__))
#endif

#define NAKED 					__attribute__((naked))

#if !defined(NAKED_ISR)
#define NAKED_ISR(v) \
void v(void) NAKED; \
void v(void)
#endif
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: zxstring.h rev 160
//---------------------------------------------------------------------------
// string type identifiers
#define BX_STR				0x00		// BasicX variable length string
#define BX_FSTR				0xff		// BasicX fixed length string
#define AN_STR				0xe0		// an allocated string
#define TMP_STR				0xe1		// a temporary string
#define PRG_STR				0xe2		// string characters in PROG memory
#define EEP_STR				0xe3		// string characters in EEPROM memory
#define RAM_STR				0xe4		// string characters in RAM (non-allocated)
#define LOC_STR				0xe5		// string characters in the descriptor (length <= 2)
#define IND_STR				0xe6		// indirect: sp points to actual string
                                        //    (used only for passing BX and fixed-length strings by value)
#define ZX_STR_MAX			255			// maximum string length

#if !defined(__ASSEMBLER__)
// test for an allocated string
#define IS_ALLOC_STR(s)		(s.type & 0xfe) == AN_STR)
#define STR_BY_VAL(s)		({String s1 = s; if (IS_ALLOC_STR(s)) s1.type = RAM_STR; s1;})
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
typedef struct _string
{
	uint8_t len;			// the length of the string (not valid for indirect type)
	uint8_t type;			// the string type
	union
	{
		char chars[1];		// used for BX-style strings (variable and fixed length)
		char *mem;			// used for temporary, program memory, persistent and allocated strings
		struct _string *sp;	// used for indirect string type, points to actual string descriptor
	};
} String;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)

// String helper macros
#define STR_INIT			{ 0, TMP_STR }
#define PSTRING(p,n)		({String s; s.len = n; s.type = PRG_STR; s.mem = p; s;})
#define STRING(p,n)			makeString(PSTR(p), n, PRG_STR)
#define STRTBL(n)			strConst((ProgMemAddr)(uint16_t)(stringTbl + n))
#define STR_LEN(s)			(((s).type == IND_STR) ? (s).sp->len : (s).len)
#define STR_FREE(s)			strFreeType(s.mem, s.type)
#define STR_FREE_TEMP(s)	if ((s).type == TMP_STR) memFree((s).mem)

#define STR_TEMP(_s)							\
({												\
	String s = _s;								\
	__asm__ __volatile__						\
	(											\
		"cpi %B0, %1"		   	"\n\t"			\
		"brne 1f"			   	"\n\t"			\
		"ldi %B0, %2"		   	"\n\t"			\
		"1:"				   	"\n\t"			\
		: "=&d" (s)								\
		: "M" (AN_STR), "M" (TMP_STR), "0" (s)	\
	);											\
	s;											\
})

void strCopyChars(char *dstp, String s, uint8_t len);
void strCopyCharsEx(char *dstp, String s, uint8_t ofst, uint8_t len);

void strInit(String *dst, uint8_t type);
void strInitStr(String *dst, uint8_t type, String s);
void strInitN(String *sp, uint8_t type, uint8_t len, uint16_t cnt);
void strInitFixed(String *dst, uint8_t len);
void strInitFixedN(String *dst, uint8_t len, uint16_t cnt);

void strFreeType(void *ptr, uint8_t type);
void strFree(String *str);
void strFreeN(String *str, uint16_t cnt);
void strDelete(String s);

char *strPtr(String *s);
char *strAddr(String s);
uint16_t strLen(String s);
uint8_t strType(String s);

void strCopy(String *dst, String src);
String strCat(String s1, String s2);
int16_t strCmp(String s1, String s2, uint8_t ignCase);
String strFromChar(uint8_t c);
uint8_t strChar(String s, uint8_t idx);
String strCase(String s, uint8_t upper);
String strMid(String orig, int16_t idx, int16_t cnt);
String strLeft(String orig, int16_t cnt);
String strRight(String orig, int16_t cnt);
String strDup(String orig);
String strNew(String orig);
String strTrim(String orig);
String strAppend(String s, uint8_t c);
void strSet(String *dst, int16_t idx, int16_t cnt, String src);
String strSelect(uint8_t flag, String s1, String s2);
uint8_t strFind(String haystack, String needle, uint8_t idx, uint8_t ignCase);
String strReplace(String origStr, String findStr, String replStr, int16_t idx, uint16_t cnt, uint8_t ignCase);
uint8_t strIdx(String s, uint16_t cnt, uint8_t c);

String boolToString(uint8_t val);
String byteToString(uint8_t val);
String intToString(int16_t val);
String uintToString(uint16_t val);
String longToString(int32_t val);
String ulongToString(uint32_t val);
String floatToString(float val, int16_t precision);

// for floatToString
#define DEF_PRECISION		-1

uint16_t strToWord(String s, uint8_t *flagp);
uint32_t strToDword(String s, uint8_t *flagp);
float strToFloat(String s, uint8_t *flagp);

String makeString(const char *str, uint8_t len, uint8_t type);
String strConst(ProgMemAddr str);
String strDesc(const String *s);

String cstrHex(uint32_t val, uint16_t dlen);
void outStr(String s);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: task.h rev 163
//---------------------------------------------------------------------------
// hardware interrupt designators
#define EXT_INT_0					0
#define EXT_INT_1					1
#define EXT_INT_2					2
#define EXT_INT_3					3
#define EXT_INT_4					4
#define EXT_INT_5					5
#define EXT_INT_6					6
#define EXT_INT_7					7
#ifdef HW_INT_3_7
#define EXT_INT_HI					EXT_INT_7
#else
#define EXT_INT_HI					EXT_INT_2
#endif

#if !defined(__ASSEMBLER__)
// reverse the order of the bytes in a word
#define taskParmWord(parmVal)					\
({												\
	uint16_t val = parmVal;						\
	__asm__ __volatile__						\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (val)							\
		: "0" (val)								\
		: "r0"									\
	);											\
	val;										\
})

// reverse the order of the bytes in a double word
#define taskParmDword(parmVal)					\
({												\
	uint32_t val = parmVal;						\
	__asm__ __volatile__						\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %D0"		   	"\n\t"			\
		"mov %D0, r0"		   	"\n\t"			\
		"mov r0, %C0"		   	"\n\t"			\
		"mov %C0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (val)							\
		: "0" (val)								\
		: "r0"									\
	);											\
	val;										\
})

// reverse the order of the bytes in a double word
#define taskParmFloat(parmVal)					\
({												\
	float val = parmVal;						\
	__asm__ __volatile__						\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %D0"		   	"\n\t"			\
		"mov %D0, r0"		   	"\n\t"			\
		"mov r0, %C0"		   	"\n\t"			\
		"mov %C0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (val)							\
		: "0" (val)								\
		: "r0"									\
	);											\
	val;										\
})

// reverse the order of the bytes in a double word
#define taskParmString(parmVal)					\
({												\
	String val = parmVal;						\
	__asm__ __volatile__						\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %D0"		   	"\n\t"			\
		"mov %D0, r0"		   	"\n\t"			\
		"mov r0, %C0"		   	"\n\t"			\
		"mov %C0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (val)							\
		: "0" (val)								\
		: "r0"									\
	);											\
	val;										\
})

// reverse the order of the bytes in a pointer
#define taskParmPointer(parmVal)				\
({												\
	void *val = parmVal;						\
	__asm__ __volatile__						\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (val)							\
		: "0" (val)								\
		: "r0"									\
	);											\
	val;										\
})

void initHeap(void);
uint16_t taskHeadRoom(void *taskStack);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void taskRun(void *task);
void taskExit(void *task);
void taskResume(void *task);
void taskLock(void *task);
void taskUnlock(void *task);
void taskPause(uint16_t tickCnt);
void taskSleep(uint16_t tickCount);
void taskDelay(float delay);
void taskDelayUntilTick(void);
uint8_t taskIsLocked(void *task);
uint8_t taskIsValid(void *task);
uint8_t taskStatus(void *task);
void taskStartMain(void (*task)(void), void *heapLimit, uint16_t heapSize) NORETURN;
void taskStart(void (*task)(void), void *taskStack, uint16_t stackSize, uint16_t parmBytes, ...);
uint16_t taskByteParm(uint8_t parm);
uint16_t taskWordParm(uint16_t parm);
uint16_t taskRefParm(void *parm);
uint32_t taskDwordParm(uint32_t parm);
uint32_t taskFloatParm(float parm);
uint32_t taskStringParm(String parm);
void setInterval(uint16_t ticks);
uint8_t waitInterval(uint8_t mode);
uint8_t waitForInterrupt(uint8_t mode, uint8_t intNum);
void yield(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: queue.h rev 136
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
struct _Queue
{
	uint16_t cap;				// capacity of the queue
	uint16_t cnt;				// bytes available in the queue
	uint16_t head;				// the index to which to add bytes
	uint16_t tail;				// the index from which to remove bytes
	uint8_t flags;
	char queue[1];
};
typedef struct _Queue Queue;

#define getQueueMember(qp,mbr,mbrType)			\
({												\
	uint8_t flag = dsblInt();					\
	mbrType val = ((Queue *)(qp))->mbr;			\
	restInt(flag);								\
	val;										\
})
#endif	// !defined(__ASSEMBLER__)

// flag bits for getQueueData() and putQueueData()
#define QUEUE_ALL_OR_NONE_BIT	1			// do operation only if all can be transferred
#define QUEUE_PEEK_BIT			2			// copy data only, do not remove
#define QUEUE_SRC_STR_BIT		3			// source is a StringOp (ZVM putQueueData() only)

#define QUEUE_NO_FLAGS			0x00

#define QUEUE_ALL_OR_NONE		_BV(QUEUE_ALL_OR_NONE_BIT)
#define QUEUE_PEEK				_BV(QUEUE_PEEK_BIT)
#define QUEUE_SRC_STR			_BV(QUEUE_SRC_STR_BIT)

#if !defined(__ASSEMBLER__)
uint16_t getQueueCnt(volatile Queue *qp);
uint16_t getQueueSpace(volatile Queue *qp);
void initQueue(volatile Queue *qp, int len);
void clearQueue(volatile Queue *qp);
uint16_t getQueueData(volatile Queue *qp, void *datap, uint16_t cnt, uint8_t flags);
uint16_t putQueueData(volatile Queue *qp, void *datap, uint16_t cnt, uint8_t flags);
uint16_t getQueueByte(volatile Queue *qp);
uint16_t putQueueByte(volatile Queue *qp, uint8_t data);
char *getQueueStr(volatile Queue *qp, uint16_t maxLen);
String getQueueString(volatile Queue *qp, uint16_t maxLen);
void putQueueStr(volatile Queue *qp, String s);
uint16_t putQueue(volatile Queue *qp, void *datap, uint16_t cnt);
uint16_t getQueue(volatile Queue *qp, void *datap, uint16_t cnt);
uint16_t getQueueEx(volatile Queue *qp, void *datap, uint16_t cnt, uint16_t timeout, uint8_t *flagp);
uint16_t peekQueue(volatile Queue *qp, void *datap, uint16_t cnt);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: zx.h rev 166
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)

// for defining prototypes for ZX initialization functions
#define ZX_INIT_FUNC(f) \
static void f(void) NAKED USED __attribute__((section(".init6"))); \
static void f(void)

#define ASM_EOL					"\n\t"

extern uint8_t *_end;

// macro to return the address of the first unused Flash location
#define codeEnd()									\
({													\
	uint32_t val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %A0, lo8(__data_load_end)"		"\n\t"	\
		"ldi %B0, hi8(__data_load_end)"		"\n\t"	\
		"ldi %C0, hlo8(__data_load_end)"	"\n\t"	\
		"ldi %D0, hhi8(__data_load_end)"	"\n\t"	\
		: "=&d" (val)								\
		: 											\
	);												\
	val;											\
})

// macro to return the address of the first unused RAM location
#define ramEnd()									\
({													\
	uint16_t val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %A0, lo8(_end)"	"\n\t"				\
		"ldi %B0, hi8(_end)"	"\n\t"				\
		: "=&d" (val)								\
		: 											\
	);												\
	val;											\
})

// macro to return the address of the first unused EEPROM location
#define eepromEnd()									\
({													\
	uint16_t val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %A0, lo8(__zx_eeprom_end)"	"\n\t"		\
		"ldi %B0, hi8(__zx_eeprom_end)"	"\n\t"		\
		: "=&d" (val)								\
		: 											\
	);												\
	val;											\
})
#endif	// !defined(__ASSEMBLER__)

#ifdef __ASSEMBLER__
#define NUMVAL(x)		x
#else
#define NUMVAL(x)		x##L
#endif

#if !defined(__ASSEMBLER__)
// main clock and RTC data for various models
#define CLOCK_FREQ_MEGA644_HI			NUMVAL(18432000)
#define TICK_FREQ_MEGA644_HI			500
#define RTC_TIMER_FREQ_MEGA644_HI		(CLOCK_FREQ_MEGA644_HI / 256)

#define CLOCK_FREQ_MEGA644_LO			NUMVAL(14745600)
#define TICK_FREQ_MEGA644_LO			512
#define RTC_TIMER_FREQ_MEGA644_LO		(CLOCK_FREQ_MEGA644_LO / 64)

#define CLOCK_FREQ_MEGA644P_LO			NUMVAL(14745600)
#define TICK_FREQ_MEGA644P_LO			512
#define RTC_TIMER_FREQ_MEGA644P_LO		(CLOCK_FREQ_MEGA644P_LO / 64)

#define CLOCK_FREQ_MEGA32				NUMVAL(14745600)
#define TICK_FREQ_MEGA32				512
#define RTC_TIMER_FREQ_MEGA32			(CLOCK_FREQ_MEGA32 / 64)

#define CLOCK_FREQ_MEGA324P				NUMVAL(14745600)
#define TICK_FREQ_MEGA324P				512
#define RTC_TIMER_FREQ_MEGA324P			(CLOCK_FREQ_MEGA324P / 64)

#define CLOCK_FREQ_MEGA644P				NUMVAL(14745600)
#define TICK_FREQ_MEGA644P				512
#define RTC_TIMER_FREQ_MEGA644P			(CLOCK_FREQ_MEGA644P / 64)

#define CLOCK_FREQ_MEGA1284P			NUMVAL(14745600)
#define TICK_FREQ_MEGA1284P				512
#define RTC_TIMER_FREQ_MEGA1284P		(CLOCK_FREQ_MEGA1284P / 64)

#define CLOCK_FREQ_MEGA128				NUMVAL(14745600)
#define TICK_FREQ_MEGA128				512
#define RTC_TIMER_FREQ_MEGA128			(CLOCK_FREQ_MEGA128 / 64)

#define CLOCK_FREQ_MEGA1281				NUMVAL(14745600)
#define TICK_FREQ_MEGA1281				512
#define RTC_TIMER_FREQ_MEGA1281			(CLOCK_FREQ_MEGA1281 / 64)

#define CLOCK_FREQ_MEGA1280				NUMVAL(14745600)
#define TICK_FREQ_MEGA1280				512
#define RTC_TIMER_FREQ_MEGA1280			(CLOCK_FREQ_MEGA1280 / 64)

#define CLOCK_FREQ_MEGA168P_LO			NUMVAL(14745600)
#define TICK_FREQ_MEGA168P_LO			512
#define RTC_TIMER_FREQ_MEGA168P_LO		(CLOCK_FREQ_MEGA168P_LO / 64)

#define CLOCK_FREQ_MEGA328P_LO			NUMVAL(14745600)
#define TICK_FREQ_MEGA328P_LO			512
#define RTC_TIMER_FREQ_MEGA328P_LO		(CLOCK_FREQ_MEGA328P_LO / 64)
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#if defined(zx24b) || defined(zx40b) || defined(zx44b)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA644_HI
	#define RTC_FREQ					TICK_FREQ_MEGA644_HI
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA644_HI
#elif defined(zx24l) || defined(zx40l) || defined(zx44l)
	#define XTAL_FREQ					7372800
	#define RTC_FREQ					TICK_FREQ_MEGA644_LO
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA644_LO
#elif defined(__AVR_ATmega644__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA644_LO
	#define RTC_FREQ					TICK_FREQ_MEGA644_LO
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA644_LO
#elif defined(__AVR_ATmega644P__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA644P_LO
	#define RTC_FREQ					TICK_FREQ_MEGA644P_LO
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA644P_LO
#elif defined(__AVR_ATmega1284P__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA1284P
	#define RTC_FREQ					TICK_FREQ_MEGA1284P
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA1284P
#elif defined(__AVR_ATmega128__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA128
	#define RTC_FREQ					TICK_FREQ_MEGA128
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA128
#elif defined(__AVR_ATmega1281__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA1281
	#define RTC_FREQ					TICK_FREQ_MEGA1281
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA1281
#elif defined(__AVR_ATmega1280__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA1280
	#define RTC_FREQ					TICK_FREQ_MEGA1280
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA1280
#elif defined(__AVR_ATmega32__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA32
	#define RTC_FREQ					TICK_FREQ_MEGA32
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA32
#elif defined(__AVR_ATmega324P__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA324P
	#define RTC_FREQ					TICK_FREQ_MEGA324P
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA324P
#elif defined(__AVR_ATmega328P__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA328P_LO
	#define RTC_FREQ					TICK_FREQ_MEGA328P_LO
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA328P_LO
#elif defined(__AVR_ATmega168P__)
	#define XTAL_FREQ					CLOCK_FREQ_MEGA168P_LO
	#define RTC_FREQ					TICK_FREQ_MEGA168P_LO
	#define RTC_TIMER_FREQ				RTC_TIMER_FREQ_MEGA168P_LO
#endif

// RTC specifications
#define FAST_TICKS_PER_SEC				(RTC_FREQ * 2)
#define TICKS_PER_SEC					RTC_FREQ
#define TICKS_PER_MIN					(TICKS_PER_SEC * NUMVAL(60))
#define TICKS_PER_HR					(TICKS_PER_MIN * NUMVAL(60))
#define TICKS_PER_DAY					RTC_FREQ * NUMVAL(60) * NUMVAL(60) * NUMVAL(24)
#define FTICKS_PER_SEC					(float)TICKS_PER_SEC
#endif	// !defined(__ASSEMBLER__)

#define ZX_TRUE					0xff
#define ZX_FALSE				0

#if !defined(__ASSEMBLER__)
#define ZX_BOOL(b)				((b) ? ZX_TRUE : ZX_FALSE)

#define BIT_VAL(b)				((b) & 0x01)
#define NIB_VAL(b)				((b) & 0x0f)

// memory types
#define MEM_RAM					0
#define MEM_PERSIST				1
#define MEM_PROGRAM				2
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#if !defined(NULL)
#define NULL					0
#endif

#define MIN(x,y)				(((x)<(y))?(x):(y))
#define MAX(x,y)				(((x)>(y))?(x):(y))

// t is a data type, f is the boolean selector, x and y are the alternative values
// e.g. i = IIF(int16_t, flag, foo(), bar());
#define IIF(t,f,x,y)			({ \
									t valT = (x); \
									t valF = (y); \
									((f) ? valT : valF); \
								})

#define LO_BYTE(x)				((uint8_t)(x) & 0xff)
#define HI_BYTE_W(x)			((uint8_t)((x) >> 8) & 0xff)
#define HI_BYTE_D(x)			((uint8_t)((x) >> 24) & 0xff)
#define LO_WORD(x)				((uint16_t)(x) & 0xffff)
#define MID_WORD(d)				((uint16_t)((d) >> 8) & 0xffff)
#define HI_WORD(x)				((uint16_t)((x) >> 16) & 0xffff)
#define MAKE_WORD(l,h)			(((uint16_t)(l) & 0xff) | ((uint16_t)(h) << 8))
#define MAKE_DWORD(l,h)			(((uint32_t)(l) & 0xffff) | ((uint32_t)(h) << 16))

#define TYPECAST(t,v)			(t)(v)
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#define EEP_PAD_SIZE			12		// to make the structure exactly 32 bytes

typedef struct
{
	uint8_t unused1;
	uint8_t firstTime;			// indicates first execution after download
	uint8_t faultCode;
	uint16_t faultData;
	uint8_t signOn;				// enable initial sign-on
	uint8_t progMemPgSize;		// page size in terms of 16-byte blocks - value 4 implies 64 bytes
	uint8_t progMemPgMode;		// non-zero if full pages must be written
	uint16_t progMemLen;		// length of downloaded program
	uint16_t progMemCRC;		// CRC of downloaded program
	uint16_t faultData2;
	uint16_t xmemFlags;			// external memory configuration flags
	uint8_t bootPinCS;			// chip select pin for boot load device
	uint16_t bootCnt;			// program length
	uint8_t atnChar;			// ATN escape character
	uint8_t unused2[EEP_PAD_SIZE];
} PersistData;

#endif	// !defined(__ASSEMBLER__)

// fault types
#define FAULT_NONE					0
#define FAULT_STACK					1
#define FAULT_INTERRUPT				2

#define SYS_EEPROM_ADDR				0

// offsets into the PersistData structure
#define EEP_UNUSED1_OFST			0
#define EEP_FIRST_TIME_OFST			1
#define EEP_FAULT_CODE_OFST			2
#define EEP_FAULT_DATA_OFST			3
#define EEP_SIGN_ON_OFST			5
#define EEP_PM_PAGE_SIZE_OFST		6
#define EEP_PM_PAGE_MODE_OFST		7
#define EEP_PROG_LEN_LO_OFST		8
#define EEP_PROG_LEN_HI_OFST		9
#define EEP_PROG_CRC_LO_OFST		10
#define EEP_PROG_CRC_HI_OFST		11
#define EEP_FAULT_DATA2_OFST		12
#define EEP_XMEM_FLAGS_OFST			14
#define EEP_BOOT_PIN_OFST			16
#define EEP_BOOT_CNT_OFST			17
#define EEP_ATN_CHAR_OFST			19
#define EEP_UNUSED2_OFST			20

#define SER_NUM_SIZE				6
#define DEV_ID_MAX_LEN				10

// values for floating point numbers classification returned by sngClass()
#define ZFP_NORMAL					0x01		// +/- normalized, non-zero
#define ZFP_ZERO					0x02		// +/- zero
#define ZFP_INFINITY				0x03		// +/- infinity
#define ZFP_DENORMAL				0x04		// +/- denormalized
#define ZFP_NAN						0x05		// NaN
#define ZFP_NEGATIVE				0x80		// combine with others (except NaN)
#define ZFP_MASK					0x07		// mask to remove sign bit

#if !defined(__ASSEMBLER__)
// the A/D resolution
#define ADC_RES						(1.0 / 1024.0)
#endif	// !defined(__ASSEMBLER__)

#define FAST_TICK_OFST				0
#define ALT_TICK_OFST				1
#define STOPWATCH_OFST				2
#define TICK_OFST					4
#define DAY_OFST					8

#define SIZEOF_RTC					10

#define ZX_RTC_OFST					0
#define ZX_FAST_TICK_OFST			ZX_RTC_OFST + FAST_TICK_OFST
#define ZX_ALT_TICK_OFST			ZX_RTC_OFST + ALT_TICK_OFST
#define ZX_STOPWATCH_OFST			ZX_RTC_OFST + STOPWATCH_OFST
#define ZX_TICK_OFST				ZX_RTC_OFST + TICK_OFST
#define ZX_DAY_OFST					ZX_RTC_OFST + DAY_OFST
#define ZX_MAIN_TASK_OFST			ZX_RTC_OFST + SIZEOF_RTC + 0
#define ZX_CUR_TASK_OFST			ZX_RTC_OFST + SIZEOF_RTC + 2
#define ZX_FLAGS_OFST				ZX_RTC_OFST + SIZEOF_RTC + 4
#define ZX_FLAGS2_OFST				ZX_RTC_OFST + SIZEOF_RTC + 5
#define ZX_FLAGS3_OFST				ZX_RTC_OFST + SIZEOF_RTC + 6
#define ZX_FLAGS4_OFST				ZX_RTC_OFST + SIZEOF_RTC + 7
#define ZX_IO_FLAGS_OFST			ZX_RTC_OFST + SIZEOF_RTC + 8
#define ZX_IO_FLAGS2_OFST			ZX_RTC_OFST + SIZEOF_RTC + 9
#define ZX_IO_FLAGS3_OFST			ZX_RTC_OFST + SIZEOF_RTC + 10
#define ZX_TIMER0_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 11
#define ZX_TIMER1_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 12
#define ZX_TIMER2_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 13
#define ZX_TIMER3_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 14
#define ZX_TIMER4_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 15
#define ZX_TIMER5_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 16
#define ZX_TSPEED1_OFST				ZX_RTC_OFST + SIZEOF_RTC + 17
#define ZX_TSPEED2_OFST				ZX_RTC_OFST + SIZEOF_RTC + 18
#define ZX_INTERVAL_CUR_OFST		ZX_RTC_OFST + SIZEOF_RTC + 19
#define ZX_INTERVAL_VAL_OFST		ZX_RTC_OFST + SIZEOF_RTC + 21
#define ZX_SEED_OFST				ZX_RTC_OFST + SIZEOF_RTC + 23
#define ZX_RX_QPTR_OFST				ZX_RTC_OFST + SIZEOF_RTC + 27
#define ZX_TX_QPTR_OFST				ZX_RTC_OFST + SIZEOF_RTC + 29
#define ZX_COM1_SPEED_OFST			ZX_RTC_OFST + SIZEOF_RTC + 31
#define ZX_EOL_CHAR_OFST			ZX_RTC_OFST + SIZEOF_RTC + 33
#define ZX_RST_FLAGS_OFST			ZX_RTC_OFST + SIZEOF_RTC + 34
#define ZX_X10_HDLR_OFST			ZX_RTC_OFST + SIZEOF_RTC + 35

// bit definitions for ioFlags
#define IOF_ADC_COM1_BIT			0		// ADCToCom1 in progress
#define IOF_ADC_COM1_DONE_BIT		1		// ADCToCom1 completed
#define IOF_COM1_DAC_BIT			2		// Com1ToDAC in progress
#define IOF_COM1_DAC_DONE_BIT		3		// Com1ToDAC completed
#define IOF_SW_UART_ENBL_BIT		4		// SW UART is enabled
#define IOF_COM1_TX_BUSY_BIT		5		// Com1 is busy transmitting
#define IOF_COM1_OPEN_BIT			6		// Com1 has been opened
#define IOF_CONSOLE_ECHO_BIT		7		// enable console echo

#define IOF_ADC_COM1				_BV(IOF_ADC_COM1_BIT)
#define IOF_ADC_COM1_DONE			_BV(IOF_ADC_COM1_DONE_BIT)
#define IOF_COM1_DAC				_BV(IOF_COM1_DAC_BIT)
#define IOF_COM1_DAC_DONE			_BV(IOF_COM1_DAC_DONE_BIT)
#define IOF_SW_UART_ENBL			_BV(IOF_SW_UART_ENBL_BIT)
#define IOF_COM1_TX_BUSY			_BV(IOF_COM1_TX_BUSY_BIT)
#define IOF_COM1_OPEN				_BV(IOF_COM1_OPEN_BIT)
#define IOF_CONSOLE_ECHO			_BV(IOF_CONSOLE_ECHO_BIT)

// bit definitions for ioFlags2
#define IOF_COM2_OPEN_BIT			0		// Com1 has been opened
#define IOF_COM2_TX_BUSY_BIT		1		// Com1 is busy transmitting
#define IOF_COM7_OPEN_BIT			2		// Com7 has been opened
#define IOF_COM7_TX_BUSY_BIT		3		// Com7 is busy transmitting
#define IOF_COM8_OPEN_BIT			4		// Com8 has been opened
#define IOF_COM8_TX_BUSY_BIT		5		// Com8 is busy transmitting

#define IOF_COM2_OPEN				_BV(IOF_COM2_OPEN_BIT)
#define IOF_COM2_TX_BUSY			_BV(IOF_COM2_TX_BUSY_BIT)
#define IOF_COM7_OPEN				_BV(IOF_COM7_OPEN_BIT)
#define IOF_COM7_TX_BUSY			_BV(IOF_COM7_TX_BUSY_BIT)
#define IOF_COM8_OPEN				_BV(IOF_COM8_OPEN_BIT)
#define IOF_COM8_TX_BUSY			_BV(IOF_COM8_TX_BUSY_BIT)

// bit definitions for ioFlags3
#define IOF_IO_SCALING_BIT			0		// if some I/O function timing s/b scaled
#define IOF_COM1_CLOSED_BIT			1		// com1 has been closed

#define IOF_IO_SCALING				_BV(IOF_IO_SCALING_BIT)
#define IOF_COM1_CLOSED				_BV(IOF_COM1_CLOSED_BIT)

#if !defined(__ASSEMBLER__)

// unconditionally disable interrupts and return the prior status register content
#define dsblInt()								\
({												\
	uint8_t __flag;								\
	__asm__ __volatile__						\
	(											\
		"in %0, 0x3f"		   	"\n\t"			\
		"cli"			   		"\n\t"			\
		: "=&r" (__flag)						\
		: 										\
	);											\
	__flag;										\
})

// conditionally reenable interrupts (typically using the return value from dsblInt())
#define enblInt(__flag)							\
({												\
	__asm__ __volatile__						\
	(											\
		"sbrc %0, 7"	   		"\n\t"			\
		"sei"			   		"\n\t"			\
		:										\
		: "d" (__flag)							\
	);											\
})

// restore the status register (typically using the return value from dsblInt())
#define restInt(__flag)							\
({												\
	__asm__ __volatile__						\
	(											\
		"out 0x3f, %0"	   		"\n\t"			\
		:										\
		: "d" (__flag)							\
	);											\
})


// unconditionally enable interrupts and return the prior state
#define setInt()								\
({												\
	uint8_t __flag;								\
	__asm__ __volatile__						\
	(											\
		"in %0, 0x3f"		   	"\n\t"			\
		"sei"			   		"\n\t"			\
		: "=&r" (__flag)						\
		: 										\
	);											\
	__flag;										\
})

// conditionally disable interrupts (typically using the return value from setInt())
#define clrInt(__flag)							\
({												\
	__asm__ __volatile__						\
	(											\
		"sbrs %0, 7"	   		"\n\t"			\
		"cli"			   		"\n\t"			\
		:										\
		: "d" (__flag)							\
	);											\
})

// arrange for a block of code to be executed with interrupts disabled
//
// Usage:
//   {
//      atomic_block
//      <your code>
//   }
#define atomic_block \
   inline void intRestore(uint8_t *statp) { SREG = *statp; } \
   uint8_t intSave __attribute__((__cleanup__(intRestore))) = dsblInt();

#define begin_atomic	{ atomic_block
#define end_atomic		}

// produce a Flash memory byte address given a word address
#if defined(RAMPZ)
#define flashAddr(a)                            \
({												\
	uint32_t addr = (uint32_t)(uint16_t)a;		\
												\
	__asm__ __volatile__						\
	(											\
		"lsl %A0"				"\n\t"			\
		"rol %B0"				"\n\t"			\
		"rol %C0"				"\n\t"			\
		: "=r" (addr)							\
		: "0" (addr)							\
	);											\
	addr;										\
})
#else
#define flashAddr(a)	((uint16_t)(a) << 1)
#endif

#define RD_WORD(a)		({ uint8_t flag = dsblInt(); uint16_t v = *(uint16_t *)(a); restInt(flag); v; })
#define WR_WORD(a,v)	{ uint8_t flag = dsblInt(); *(uint16_t *)(a) = v; restInt(flag); }

#define NOP()					__asm__ __volatile__ ("nop"::)

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)

void zxInit(unsigned ubrr2x);

uint8_t zxGetByte(uint8_t idx);
uint16_t zxGetWord(uint8_t idx);
uint32_t zxGetDword(uint8_t idx);
void zxPutByte(uint8_t data, uint8_t idx);
void zxPutWord(uint16_t data, uint8_t idx);
void zxPutDword(uint32_t data, uint8_t idx);
uint16_t sysDataWord(uint16_t id);
uint32_t sysDataDword(uint16_t id);

void toggleBits(uint8_t *addr, uint8_t mask);
void setBits(uint8_t *addr, uint8_t mask, uint8_t val);

uint8_t firstTime(void);
uint16_t versionInfo(void *buf, uint16_t len);
uint8_t deviceID(void *buf, uint8_t len);

void memRep(void *dst, const void *src, uint8_t len, uint16_t cnt);
void memCopy(void *dst, const void *src, uint16_t cnt);
void memMove(void *dst, const void *src, uint16_t cnt);
int16_t memCmp(void *p1, const void *p2, uint16_t cnt);
void memSet(void *dst, uint8_t val, uint16_t cnt);

void setBit(void *addr, uint16_t bitOfst, uint8_t val);
void setNib(void *addr, uint16_t nibOfst, uint8_t val);
uint8_t getBit(void *addr, uint16_t bitOfst);
uint8_t getNib(void *addr, uint16_t nibOfst);

uint8_t sngClass(float fval);
float intf(float f);
float fracf(float f);
int32_t floatToLong(float fval);
uint8_t floatToByte(float fval);

uint32_t powui(uint32_t val, int32_t exp);
int32_t powi(int32_t val, int32_t exp);

float rnd(void);
void randomize(void);
float minf(float f1, float f2);
float maxf(float f1, float f2);
uint8_t minb(uint8_t d1, uint8_t d2);
uint8_t maxb(uint8_t d1, uint8_t d2);
int16_t mini(int16_t d1, int16_t d2);
int16_t maxi(int16_t d1, int16_t d2);
uint16_t minu(uint16_t d1, uint16_t d2);
uint16_t maxu(uint16_t d1, uint16_t d2);
uint32_t mind(uint32_t d1, uint32_t d2);
uint32_t maxd(uint32_t d1, uint32_t d2);
int32_t minl(int32_t d1, int32_t d2);
int32_t maxl(int32_t d1, int32_t d2);
int32_t sigl(int32_t lval);
uint32_t sigd(uint32_t dval);
float sigf(float fval);
float floatResult(uint8_t fclass);
float pow10I(int expVal);
float fsqrt(float fval);
float flog(float fval);
float flog10(float fval);
float fexp(float fval);
float fexp10(float fval);

// conversions for BasicX compatibility
uint8_t intToByte(uint16_t val);
uint8_t longToByte(uint32_t val);

void bitCopy(void *dst, uint16_t dstBitIdx, void *src, uint16_t srcBitIdx, uint16_t bitCnt);
void blockCopy(void *dst, uint8_t dtype, void *src, uint8_t stype, uint16_t len);
int blockCompare(void *dst, uint8_t dtype, void *src, uint8_t stype, uint16_t len);

uint16_t CRC16(void *data, uint16_t dataLen, uint16_t crcPoly, uint16_t crcInit, uint8_t flags);
uint32_t CRC32(void *data, uint16_t dataLen, uint32_t crcPoly, uint32_t crcInit, uint8_t flags);

uint8_t parityCheck(uint8_t data, uint8_t oddParity);

void openWatchDog(uint8_t timeout);
void watchDog(void);
void closeWatchDog(void);
void resetProc(void) NORETURN;
void cpuSleep(uint8_t mode);

uint8_t semaphore(uint8_t *sem);

uint16_t revWord(uint16_t val);
uint8_t revByte(uint8_t val);

void portConfig(uint8_t portIdx, uint8_t ddrBits, uint8_t portBits);

// macro get get the bytes of a float value as a double word
#define floatBytes(floatVal)				\
({											\
	float fval = floatVal;					\
	uint32_t uval;							\
	__asm__ __volatile__					\
	(										\
		".if %A0 != %A1"	"\n\t"			\
		"movw %A0, %A1"		"\n\t"			\
		"movw %C0, %C1"		"\n\t"			\
		".endif"			"\n\t"			\
		: "=r" (uval)						\
		: "r" (fval)						\
	);										\
	uval;									\
})
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void rtcUpdate(uint16_t ticks);
void runMonitor(uint8_t fast) NORETURN;
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: heap.h rev 142
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
extern  uint16_t heapLimit;

void *memAlloc(int16_t len);
void memFree(void *ptr);
void *memHeapInit(void *heapEnd);
uint16_t heapHeadRoom(void);
uint16_t heapSize(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: bootldr.h rev 163
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Id: iofunc.h rev 163
//---------------------------------------------------------------------------
#define I2C_SLAVE_FLAG				0x80

// general I/O functions
uint8_t getPin(uint8_t pin);
void putPin(uint8_t pin, uint8_t val);
void shiftOut(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t val);
uint8_t shiftIn(uint8_t dpin, uint8_t cpin, uint8_t cnt);
void shiftOutEx(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime, uint16_t val);
uint16_t shiftInEx(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime);
void inputCapture(uint8_t pin, uint16_t *array, uint16_t len, uint8_t flags, uint16_t timeoutCount);
void outputCapture(uint8_t pin, uint16_t *array, uint16_t len, uint8_t flags, uint16_t rptCnt);
void freqOut(uint8_t pin, uint16_t freqA, uint16_t freqB, uint16_t duration);
uint8_t dacPin(uint8_t acc, uint8_t dacVal, uint8_t pin, uint8_t repCnt);
void putDAC(uint8_t pin, uint8_t dacVal, uint8_t *acc, uint8_t cycles);
uint16_t rcTime(uint8_t pin, uint8_t startLevel);
uint16_t pulseIn(uint8_t pin, uint8_t highPulse);
void pulseOut(uint8_t pin, uint8_t highPulse, uint16_t duration);
int32_t countTrans(uint8_t pin, int32_t ticks);
void playSound(uint8_t pin, void *dataAddr, uint16_t len, uint16_t rate, uint16_t repeat);
void x10Cmd(uint8_t pinData, uint8_t pin60Hz, uint8_t houseCode, uint8_t keyCode, uint8_t rptCnt, uint8_t flags);
uint16_t getADC(uint8_t pin, uint8_t wait);
void adcToCom1(uint8_t pin, int16_t rate);
void com1ToDAC(uint8_t pin);

// Bus Op functions
void defineBus(uint8_t port, uint8_t alePin, uint8_t rdPin, uint8_t wrPin);
void readBus(uint16_t addr, void *data, uint16_t count, uint8_t delta);
void writeBus(uint16_t addr, void *data, uint8_t count, uint8_t delta);

// 1-Wire function
uint8_t reset1Wire(uint8_t pin);
uint8_t get1WireByte(uint8_t pin);
uint8_t get1WireBit(uint8_t pin);
void get1WireData(uint8_t pin, void *data, uint8_t cnt);
void put1WireBit(uint8_t pin, uint8_t data);
void put1WireByte(uint8_t pin, uint8_t data);
void put1WireData(uint8_t pin, void *data, uint8_t cnt);

// SPI functions
void openSPI(uint8_t chan, uint8_t setup, uint8_t pin);
void openSPIEx(uint8_t chan, uint8_t setup, uint8_t pin, uint8_t rxDelay);
void openSPISlave(uint8_t setup);
void cmdSPI(uint8_t chan, uint16_t outCnt, void *outBuf, uint16_t inCnt, void *inBuf);
void closeSPI(uint8_t chan);

// I2C functions
void openI2C(uint8_t chan, uint8_t sdaPin, uint8_t sclPin, uint16_t bitTime);
void openI2CSlave(uint8_t slaveAddr);
void startI2C(uint8_t chan);
uint8_t sendI2C(uint8_t channel, uint8_t value);
uint8_t recvI2C(uint8_t chan, uint8_t ack);
int cmdI2C(uint8_t chan, uint8_t slaveID, uint16_t outCnt, void *outBuf, uint16_t inCnt, void *inBuf);
void stopI2C(uint8_t chan);
void closeI2C(uint8_t chan);

// PWM functions
uint8_t pwmOpen(uint8_t chan, float frequency, uint8_t mode);
uint8_t pwmStart(uint8_t chan, uint16_t duty);
uint8_t pwmClose(uint8_t chan);
uint8_t pwm8Open(uint8_t chan, float frequency, uint8_t mode);
uint8_t pwm8Start(uint8_t chan, uint16_t duty);
uint8_t pwm8Close(uint8_t chan);

// pin I/O helpers
uint8_t getPortBit(uint8_t pin);
uint16_t getPortBitInfo(uint8_t pin);
uint16_t getPortPinInfo(uint8_t pin);
uint16_t getPortPinData(uint8_t pin);
uint8_t adcChan(uint8_t pin);


//---------------------------------------------------------------------------
// Id: serial.h rev 141
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
// formulae for determining the UART UBRR value
#define BAUD_FACTOR(s)				((((XTAL_FREQ / (s)) + 8) / 16) - 1)
#define BAUD_FACTOR_2X(s)			((((XTAL_FREQ / (s)) + 4) / 8) - 1)
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void defineCom(uint8_t chan, uint8_t rxPin, uint8_t txPin, uint8_t flags, uint8_t stopBits);
void openCom(uint8_t chan, uint32_t speed, Queue *iq, Queue *oq);
uint8_t statusCom(uint8_t chan);
void setComParm(uint8_t cnt, uint16_t maxSpeed);
void closeCom(uint8_t chan, Queue *iq, Queue *oq);

void sendCRLF(void);
void sendByte(uint8_t c);
void sendPStr(const char *str);

uint8_t getChar(void);
String getLine(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: persist.h rev 160
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
uint8_t persistReadByte(const void *addr);
uint16_t persistReadWord(const void *addr);
uint32_t persistReadDword(const void *addr);
double persistReadFloat(const void *addr);
String persistReadString(const void *addr);
void persistRead(const void *addr, void *buf, uint16_t cnt);

void persistWriteByte(void *addr, uint8_t val);
void persistWriteWord(void *addr, uint16_t val);
void persistWriteDword(void *addr, uint32_t val);
void persistWriteFloat(void *addr, double val);
void persistWriteString(void *addr, String s);
void persistWrite(void *addr, void *buf, uint16_t cnt);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: progmem.h rev 160
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
#define PROG_MEM(a)			(ProgMemAddr)(uint16_t)(a)
#define PROG_MEM_ADDR(a)	(ProgMemAddr)flashAddr(a)
uint8_t progMemReadByte(ProgMemAddr addr);
uint16_t progMemReadWord(ProgMemAddr addr);
uint32_t progMemReadDword(ProgMemAddr addr);
double progMemReadFloat(ProgMemAddr addr);
String progMemReadString(ProgMemAddr addr);
String progMemReadStringTbl(ProgMemAddr addr);
void progMemRead(ProgMemAddr addr, void *buf, uint16_t cnt);
void progMemReadFew(ProgMemAddr addr, void *buf, uint8_t cnt);

void progMemWriteByte(ProgMemAddr addr, uint8_t val);
void progMemWriteWord(ProgMemAddr addr, uint16_t val);
void progMemWriteDword(ProgMemAddr addr, uint32_t val);
void progMemWriteFloat(ProgMemAddr addr, double val);
void progMemWriteString(ProgMemAddr addr, String s);
uint16_t progMemWrite(ProgMemAddr addr, void *buf, uint16_t cnt);

#if defined(RAMPZ) || (defined(ZVM) && defined(EXTERNAL_PROGMEM))
#define getProgMemByte(a)		progMemReadByte((ProgMemAddr)(uint16_t)(a))
#else
#define getProgMemByte(a)						\
({												\
	uint16_t addr = (uint16_t)(a);				\
	uint8_t res;								\
	__asm__ __volatile__						\
	(											\
		"lpm %0, %a1"			"\n\t"			\
		: "=&r" (res)							\
		: "z" (addr)							\
	);											\
	res;										\
})
#endif
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: datefunc.h rev 3
//---------------------------------------------------------------------------
// return value from dateEncode to indicate invalid parameters
#define INVALID_DAYNUM		0xffff0000

#if !defined(__ASSEMBLER__)

// determine the day of the week (Sun=1, Sat=7) for a date
uint8_t getDayOfWeek(uint16_t dayNum);

uint16_t getDayOfYear(uint16_t dayNum, uint16_t *yearp);

uint16_t getDayNumber(uint16_t day, uint16_t year);

// decompose a day number into year, month and day components
void getDate(uint16_t *yearp, uint8_t *monthp, uint8_t *dayp, uint16_t dayNum);

// decompose an RTC tick value into hour, minute and second components
void getTime(uint8_t *hourp, uint8_t *minp, float *secp, uint32_t tick);

void setDate(uint16_t year, uint8_t month, uint8_t day);

void setTime(uint8_t hourp, uint8_t minp, float secp);

void setTimestamp(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, float second);

void getTimestamp(uint16_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, float *second);

float getTimer(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: uart.h rev 109
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
void enableSerialSW(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: x10.h rev 151
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
void defineX10(uint8_t chan, uint8_t rxPin, uint8_t txPin, uint8_t flags);
void openX10(uint8_t chan, Queue *iq, Queue *oq);
uint8_t statusX10(uint8_t chan);
void closeX10(uint8_t chan, Queue *iq, Queue *oq);
#endif	// !defined(__ASSEMBLER__)

#endif	// __ZXLIB_H__
