/*
 *
 *                Copyright 2007, 2008, 2009 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
 *
 *        http://www.zbasic.net
 *
 */

//***************************************************************************
//
//                           ZX Library v3.1.0
//
//     This file is generated automatically.  Do not modify it directly.
//
//***************************************************************************


#ifndef __ZXLIB_H__
#define __ZXLIB_H__

#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <setjmp.h>
#if defined(__AVR)
	#include <avr/io.h>
	#if !defined(__ASSEMBLER__)
		#include <avr/interrupt.h>
		#include <avr/pgmspace.h>
	#endif
#endif
#if defined(__arm__)
	#include <arch/philips/lpc/LPC210x.h>
#endif

#if !defined(SET_NAME)
#define SET_NAME(n)
#endif
#define PUB_NAME(pub, priv)		void pub(void) SET_NAME(pub) __attribute__((alias(#priv)))
#define PUB_VAR_NAME(pub, priv)	void pub(void) __attribute__((alias(#priv)))
#define ALIAS_NAME(name)		__attribute__((alias(#name)))

//---------------------------------------------------------------------------
// Id: zx_port.h rev 346
//---------------------------------------------------------------------------

#if !defined(_BV)
#define _BV(v)					(1 << (v))
#endif

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

#if !defined(TRUE)
#define TRUE					1
#endif

#if !defined(FALSE)
#define FALSE					0
#endif

#if !defined(NUMVAL)
	#if defined(__ASSEMBLER__)
		#define NUMVAL(x)		x
	#else
		#define NUMVAL(x)		x##L
	#endif
#endif

#if !defined(__ASSEMBLER__)
#define WEAK					__attribute__((weak))
#define OS_MAIN					__attribute__((OS_main))
#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 NAKED 					__attribute__((naked))
#define INIT2					__attribute__((section(".init2")))
#define INIT3					__attribute__((section(".init3")))
#define INIT4					__attribute__((section(".init4")))
#define INIT5					__attribute__((section(".init5")))
#define INIT6					__attribute__((section(".init6")))
#define INIT7					__attribute__((section(".init7")))
#define INIT8					__attribute__((section(".init8")))
#define INIT9					__attribute__((section(".init9")))
#define __UNUSED

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

#if defined(__ASSEMBLER__)
	#define PROVIDE_SYM(name)		GLOBAL_SYM name
	#define REQUEST_SYM(name)		.global name
#else
	#define PROVIDE_SYM(name)		__asm__ __volatile__(".global " #name "\n" #name ":\n"::)
	#define REQUEST_SYM(name)		__asm__ __volatile__(".global " #name "\n"::)
#endif
#define PROVIDE_ENTRY(name)			PROVIDE_SYM(_gbl_##name)
#define REQUEST_ENTRY(name)			REQUEST_SYM(_gbl_##name)


//---------------------------------------------------------------------------
// Id: avrdef.h rev 360
//---------------------------------------------------------------------------
#if defined(__AVR__)
#if !defined(__ASSEMBLER__)
#define ENABLE_INTERRUPTS()				sei()

#define FORCE_ALIGN

#define FORCE_INDIRECT(ptr) 			__asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr))

#define NO_INIT							__attribute__((section(".noinit")))

#if !defined(INT_MAX)
#define INT_MAX							__INT_MAX__
#endif

#if defined(__AVR_XMEGA__)
typedef uint16_t RTC_OCR_t;
#else
typedef uint8_t RTC_OCR_t;
#endif
typedef uint8_t CPU_stat_t;
typedef uint16_t Address_t;
extern uint8_t *_end;

// for defining a heap initialization
#define INIT_HEAP(heapLimit, heapSize) \
static void heapInit(void) SET_NAME(heapInit) NAKED USED INIT2; \
static void heapInit(void) { SP = initMemory(heapLimit, heapSize); }

// for defining a ZX initialization function
#define ZX_INIT_FUNC(func) \
static void func(void) SET_NAME(func) NAKED USED INIT8; \
static void func(void)

// for defining the main ZX initialization function
#define ZX_INIT_MAIN(func, heapLimit, heapSize) \
INIT_HEAP(heapLimit, heapSize) \
ZX_INIT_FUNC(func)

#define SET_VALUE(n, v)			__asm__ __volatile__(".global " #n "\n.set " #n ", " #v "\n"::)
#define SET_WEAK_VALUE(n, v)	__asm__ __volatile__(".weak " #n "\n.global " #n "\n.set " #n ", " #v "\n"::)

#define BYTE_VAL(v)									\
({													\
	uint8_t __val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %0, lo8(" #v ")"	   	"\n\t"			\
		: "=&d" (__val)								\
		:											\
	);												\
	__val;											\
})

#define WORD_VAL(v)									\
({													\
	uint16_t __val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %A0, lo8(" #v ")"	   	"\n\t"			\
		"ldi %B0, hi8(" #v ")"	   	"\n\t"			\
		: "=&d" (__val)								\
		:											\
	);												\
	__val;											\
})

#define DWORD_VAL(v)								\
({													\
	uint32_t __val;									\
	__asm__ __volatile__							\
	(												\
		"ldi %A0, lo8(" #v ")"	   	"\n\t"			\
		"ldi %B0, hi8(" #v ")"	   	"\n\t"			\
		"ldi %C0, hlo8(" #v ")"	   	"\n\t"			\
		"ldi %D0, hhi8(" #v ")"	   	"\n\t"			\
		: "=&d" (__val)								\
		:											\
	);												\
	__val;											\
})

// unconditionally disable interrupts and return the prior status register content
#define dsblInt()								\
({												\
	CPU_stat_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()								\
({												\
	CPU_stat_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)							\
	);											\
})

#define CRIT_SECT		inline void intRestore(uint8_t *statp) { SREG = *statp; } \
	uint8_t intSave __attribute__((__cleanup__(intRestore))) = dsblInt()

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

// complement a byte value (avoiding integer promotion)
#define NOT8(val)								\
({												\
	uint8_t __val = val;						\
	__asm__ __volatile__						\
	(											\
		"com %0"			   	"\n\t"			\
		: "=&r" (__val)							\
		: "0" (__val)							\
	);											\
	__val;										\
})

#if !defined(__LPM_float)
#define __LPM_float(addr)					\
({											\
	uint16_t __addr16 = (uint16_t)(addr);   \
	float __result;						 	\
	__asm__ __volatile__				 	\
	(										\
		"lpm %A0, Z+"	"\n\t"				\
		"lpm %B0, Z+"	"\n\t"				\
		"lpm %C0, Z+"	"\n\t"				\
		"lpm %D0, Z"	"\n\t"				\
		: "=r" (__result), "=z" (__addr16)	\
		: "1" (__addr16)					\
	);										\
	__result;								\
})
#endif

// 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;									\
})

// macro to get the high word of a 16-bit value
#define hiByte16(val)						\
({											\
	uint8_t res;							\
	__asm__ __volatile__					\
	(										\
		"mov %0, %B1"		   	"\n\t"		\
		: "=r" (res)						\
		: "r" (val)							\
	);										\
	res;									\
})

// macro to get the high byte of a 32-bit value
#define hiByte32(val)						\
({											\
	uint8_t res;							\
	__asm__ __volatile__					\
	(										\
		"mov %0, %D1"		   	"\n\t"		\
		: "=r" (res)						\
		: "r" (val)							\
	);										\
	res;									\
})

// macro to get the high word of a 32-bit value
#define hiWord32(val)						\
({											\
	uint16_t res;							\
	__asm__ __volatile__					\
	(										\
		"movw %0, %C1"		   	"\n\t"		\
		: "=r" (res)						\
		: "r" (val)							\
	);										\
	res;									\
})

// macro to return the address of the first unused Flash location
#define myEndCode()									\
({													\
	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 myEndRAM()									\
({													\
	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 myEndEEPROM()								\
({													\
	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__)

// 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_Q						15			// N.B.: ordinal deviation

#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)

// macro to extract the port index and port bit index from an encoded pin number
#define PORT_IDX(p)						(((p) & PORT_PORT_MASK) >> PORT_PORT_SHIFT)
#define PORT_BIT_IDX(p)					((p) & PORT_BIT_MASK)


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

#if defined(__AVR_XMEGA__) && !defined(__AVR_ATxmega32A4__)
	#define BIG_FLASH
#elif !defined(__AVR_XMEGA__) && defined(RAMPZ)
	#define BIG_FLASH
#endif

#if defined(__AVR_MEGA__)
#if defined(SPCR) && !defined(SPCR0)
#undef SPDR0
#undef SPSR0
#define SPDR0					SPDR
#define SPCR0					SPCR
	#define SPIE0				SPIE
	#define SPE0				SPE
	#define DORD0				DORD
	#define MSTR0				MSTR
	#define CPOL0				CPOL
	#define CPHA0				CPHA
	#define SPR00				SPR0
	#define SPR01				SPR1
#define SPSR0					SPSR
	#define SPIF0				SPIF
	#define SPI2X0				SPI2X
#endif	// defined(SPCR) && !defined(SPCR0)
#endif	// defined(__AVR_MEGA__)

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

#if !defined(EEMEM)
#define EEMEM					__attribute__((section(".eeprom")))
#endif
#define ZX_EEMEM				__attribute__((section(".zx_eeprom")))
#if !defined(PROGMEM)
#define PROGMEM					__attribute__((__progmem__))
#endif

#endif	// !defined(__ASSEMBLER__)

#endif	// defined(__AVR__)

//---------------------------------------------------------------------------
// Id: zxstring.h rev 281
//---------------------------------------------------------------------------
// 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;})
#define FIX_PARM_STR(t,s)	do {								\
								if ((t = (s).type) == TMP_STR)	\
									(s).type = AN_STR;			\
							} while(0)
#define FREE_PARM_STR(t,p)	if ((t) == TMP_STR) memFree((p).mem)
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
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
	};
};
typedef struct _string 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_FREE(s)			strFreeType(s.mem, s.type)
#define STR_FREE_TEMP(s)	if ((s).type == TMP_STR) memFree((s).mem)

#if defined(__AVR__)

#define STR_LEN(s)								\
({												\
	String ss = s;								\
	uint8_t len;								\
	uint8_t *p;									\
	__asm__ __volatile__						\
	(											\
		"mov %0, %A2"			"\n\t"			\
		"cpi %B2, %3"			"\n\t"			\
		"brne 1f"				"\n\t"			\
		"movw %A1, %C2"			"\n\t"			\
		"ld %0, %a1"			"\n\t"			\
		"1:"					"\n\t"			\
		: "=&r" (len), "=&e" (p)				\
		: "d" (ss), "M" (IND_STR)				\
	);											\
	len;										\
})

#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;											\
})

#else

#define STR_LEN(s)			(((s).type == IND_STR) ? (s).sp->len : (s).len)

#define STR_TEMP(_s)							\
({												\
	String s = _s;								\
	if (s.type == AN_STR)						\
		s.type = TMP_STR;						\
	s;											\
})

#endif


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);
void strCopyN(String *dst, const String *src, uint16_t cnt);
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 345
//---------------------------------------------------------------------------
#define CTX_SP_OFST					0
#define CTX_STACK_OFST				2

#define TASK_STATE_OFST	 					0
#define TASK_TIMEOUT_OFST					1
#define TASK_NEXT_OFST						3
#define TASK_CTX_OFST						5

	#define TASK_SP_OFST					TASK_CTX_OFST + CTX_SP_OFST
	#define TASK_STACK_OFST					TASK_CTX_OFST + CTX_STACK_OFST

#define TASK_FLAGS_OFST						11

#if !defined(__ASSEMBLER__)
#if defined(__AVR__)
// 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 float value
#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 string descriptor
#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;										\
})
#endif

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

#if !defined(__ASSEMBLER__)
unsigned initMemory(uint8_t *heapLimit, unsigned heapSize);
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 startMainTask(void (*task)(void)) 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: waitInt.h rev 288
//---------------------------------------------------------------------------
// 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


//---------------------------------------------------------------------------
// Id: queue.h rev 297
//---------------------------------------------------------------------------
#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];
} FORCE_ALIGN;
typedef struct _Queue Queue;

#define QUEUE_PTR(v)			(Queue *)(void *)(v)

#define getQueueMember(qp,mbr,mbrType)				\
({													\
	CPU_stat_t flag = dsblInt();					\
	mbrType val = ((volatile 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);
uint16_t findInQueue(volatile Queue *qp, uint8_t val);
uint16_t findPatternInQueue(volatile Queue *qp, uint8_t *pattern, uint16_t len);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: zx.h rev 362
//---------------------------------------------------------------------------
#define ZX_OUTPUT_LOW					0
#define ZX_OUTPUT_HIGH					1
#define ZX_INPUT_TRISTATE				2
#define ZX_INPUT_PULLUP					3
#define ZX_TOGGLE_OUTPUT				4
#define ZX_PULSE_OUTPUT					5
#define ZX_INPUT_PULLDOWN				6
#define ZX_INVERT_IO					7
#define ZX_NORMAL_IO					8

#if !defined(__ASSEMBLER__)

#define ASM_EOL							"\n\t"

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)

// standard timing parameters
#define STD_CLOCK_FREQ					NUMVAL(14745600)
#define STD_RTC_TIMER_FREQ				(STD_CLOCK_FREQ / 64)
#define STD_RTC_TICK_FREQ				512

// special low frequency parameters
#define ALT_CLOCK_FREQ_LO				NUMVAL(7372800)
#define ALT_RTC_TIMER_FREQ_LO			(ALT_CLOCK_FREQ_LO / 64)

// special high frequency parameters
#define ALT_CLOCK_FREQ_HI				NUMVAL(18432000)
#define ALT_RTC_TIMER_FREQ_HI			(ALT_CLOCK_FREQ_HI / 256)
#define ALT_RTC_TICK_FREQ				500
#endif	// !defined(__ASSEMBLER__)

// system data elements
#define SYS_DATA_SER_NUM				0		// read the VM serial number
#define SYS_DATA_CPU_FREQ				1		// read the CPU frequency
#define SYS_DATA_RTC_FREQ				2		// read the RTC frequency
#define SYS_DATA_RAM_SIZE				3		// read the user RAM size
#define SYS_DATA_BOOT_VER				4		// read the bootloader version number
#define SYS_DATA_FREE_LIST				5		// get the heap free list pointer
#define SYS_DATA_HEAP_END				6		// get the heap end pointer
#define SYS_DATA_DEVICE_ID				7		// get the device ID string
#define SYS_DATA_VM_HEADROOM			8		// get the VM stack headroom
#define SYS_DATA_HEAP_SIZE				9		// get the heap size (VM: returned on the stack)
#define SYS_DATA_HEAP_LIMIT				10		// get the heap limit (VM: returned on the stack)
#define SYS_DATA_HEAP_HEADROOM			11		// get the unused heap space (returned on the stack)

#if !defined(__ASSEMBLER__)
// set parameters for special cases
#if defined(zx328l) || defined(zx32l) || defined(zx328le)
	#define CPU_FREQ					ALT_CLOCK_FREQ_LO
	#define RTC_SCALE_FACTOR			1
	#define RTC_TIMER_FREQ				ALT_RTC_TIMER_FREQ_LO
#elif defined(zx24b) || defined(zx40b) || defined(zx44b)
	#define CPU_FREQ					ALT_CLOCK_FREQ_HI
	#define RTC_TIMER_FREQ				ALT_RTC_TIMER_FREQ_HI
	#define RTC_FREQ					ALT_RTC_TICK_FREQ
#elif defined(__AVR_XMEGA__)
	#define PLL_MULT					8
	#define XTAL_FREQ					NUMVAL(14745600)
	#define CPU_FREQ					NUMVAL(29491200)
	#define RTC_TIMER_FREQ				(CPU_FREQ / 64)
	#define USART_SCALE					0
#endif

// set standard parameters
#if !defined(CPU_FREQ)
	#define CPU_FREQ					STD_CLOCK_FREQ
#endif
#if !defined(XTAL_FREQ)
	#define XTAL_FREQ					CPU_FREQ
#endif
#if !defined(USART_FREQ)
	#define USART_FREQ					CPU_FREQ
#endif
#if !defined(USART_SCALE)
	#define USART_SCALE					0
#endif
#if !defined(TIMER_FREQ)
	#define TIMER_FREQ					CPU_FREQ
#endif
#if !defined(RTC_TIMER_FREQ)
	#define RTC_TIMER_FREQ				STD_RTC_TIMER_FREQ
#endif
#if !defined(RTC_FREQ)
	#define RTC_FREQ					STD_RTC_TICK_FREQ
#endif
#if !defined(RTC_SCALE_FACTOR)
	#define RTC_SCALE_FACTOR			2
#endif

// RTC specifications
#define FAST_TICKS_PER_SEC				(RTC_FREQ * RTC_SCALE_FACTOR)
#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 ZX_INV_BOOL(b)			((b) ? ZX_FALSE : ZX_TRUE)

#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__)

#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			11		// 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 defBaud;			// default baud rate selector (VM only)
	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_DEF_BAUD_OFST			20
#define EEP_UNUSED2_OFST			21

#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__)
typedef struct
{
	uint8_t timerTicks;			// low-level RTC timer ticks (typically 64/14.7456MHz sec.)
	uint32_t fastTicks;			// fast RTC ticks (typically 1/1024 sec.)
} MicroTime;
#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_FLAGS5_OFST				ZX_RTC_OFST + SIZEOF_RTC + 8
#define ZX_IO_FLAGS_OFST			ZX_RTC_OFST + SIZEOF_RTC + 9
#define ZX_IO_FLAGS2_OFST			ZX_RTC_OFST + SIZEOF_RTC + 10
#define ZX_IO_FLAGS3_OFST			ZX_RTC_OFST + SIZEOF_RTC + 11
#define ZX_TSPEED1_OFST				ZX_RTC_OFST + SIZEOF_RTC + 12
#define ZX_TSPEED2_OFST				ZX_RTC_OFST + SIZEOF_RTC + 13
#define ZX_INTERVAL_CUR_OFST		ZX_RTC_OFST + SIZEOF_RTC + 14
#define ZX_INTERVAL_VAL_OFST		ZX_RTC_OFST + SIZEOF_RTC + 16
#define ZX_SEED_OFST				ZX_RTC_OFST + SIZEOF_RTC + 18
#define ZX_RX_QPTR_OFST				ZX_RTC_OFST + SIZEOF_RTC + 22
#define ZX_TX_QPTR_OFST				ZX_RTC_OFST + SIZEOF_RTC + 24
#define ZX_EOL_CHAR_OFST			ZX_RTC_OFST + SIZEOF_RTC + 26
#define ZX_RST_FLAGS_OFST			ZX_RTC_OFST + SIZEOF_RTC + 27
#define ZX_X10_HDLR_OFST			ZX_RTC_OFST + SIZEOF_RTC + 28
#define ZX_TIMER_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 30
#define ZX_TIMER0_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 30
#define ZX_TIMER1_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 31
#define ZX_TIMER2_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 32
#define ZX_TIMER3_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 33
#define ZX_TIMER4_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 34
#define ZX_TIMER5_BUSY_OFST			ZX_RTC_OFST + SIZEOF_RTC + 35
#define ZX_EVENT_BUSY_OFST			ZX_TIMER_BUSY_OFST + TIMER_BUSY_FLAG_CNT

// bit definitions for ioFlags
#define IOF_ADC_COM1_BIT			0		// ADCToCom1 in progress
#define IOF_COM1_DAC_BIT			1		// Com1ToDAC in progress
#define IOF_COM1_ADC_DAC_DONE_BIT	2		// ADCToCom1 or Com1ToDAC completed
#define IOF_TX_FLOW_INHIBITED_BIT	3		// at least one HW channel is flow inhibited
#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 is open
#define IOF_CONSOLE_ECHO_BIT		7		// enable console echo

#define IOF_ADC_COM1				_BV(IOF_ADC_COM1_BIT)
#define IOF_COM1_DAC				_BV(IOF_COM1_DAC_BIT)
#define IOF_COM1_ADC_DAC_DONE		_BV(IOF_COM1_ADC_DAC_DONE_BIT)
#define IOF_TX_FLOW_INHIBITED		_BV(IOF_TX_FLOW_INHIBITED_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		// Com2 is open
#define IOF_COM2_TX_BUSY_BIT		1		// Com2 is busy transmitting
#define IOF_COM7_OPEN_BIT			2		// Com7 is open
#define IOF_COM7_TX_BUSY_BIT		3		// Com7 is busy transmitting
#define IOF_COM8_OPEN_BIT			4		// Com8 is open
#define IOF_COM8_TX_BUSY_BIT		5		// Com8 is busy transmitting
#define IOF_COM1_CLOSED_BIT			6		// com1 has been closed
#define IOF_IO_SCALING_BIT			7		// if some I/O function timing s/b scaled

#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)
#define IOF_COM1_CLOSED				_BV(IOF_COM1_CLOSED_BIT)
#define IOF_IO_SCALING				_BV(IOF_IO_SCALING_BIT)

// bit definitions for ioFlags3
#define IOF_COM9_OPEN_BIT			0		// Com9 is open
#define IOF_COM9_TX_BUSY_BIT		1		// Com9 is busy transmitting
#define IOF_COM10_OPEN_BIT			2		// Com10 is open
#define IOF_COM10_TX_BUSY_BIT		3		// Com10 is busy transmitting
#define IOF_COM11_OPEN_BIT			4		// Com11 is open
#define IOF_COM11_TX_BUSY_BIT		5		// Com11 is busy transmitting
#define IOF_COM12_OPEN_BIT			6		// Com12 is open
#define IOF_COM12_TX_BUSY_BIT		7		// Com12 is busy transmitting

#define IOF_COM9_OPEN				_BV(IOF_COM9_OPEN_BIT)
#define IOF_COM9_TX_BUSY			_BV(IOF_COM9_TX_BUSY_BIT)
#define IOF_COM10_OPEN				_BV(IOF_COM10_OPEN_BIT)
#define IOF_COM10_TX_BUSY			_BV(IOF_COM10_TX_BUSY_BIT)
#define IOF_COM11_OPEN				_BV(IOF_COM11_OPEN_BIT)
#define IOF_COM11_TX_BUSY			_BV(IOF_COM11_TX_BUSY_BIT)
#define IOF_COM12_OPEN				_BV(IOF_COM12_OPEN_BIT)
#define IOF_COM12_TX_BUSY			_BV(IOF_COM12_TX_BUSY_BIT)

#if !defined(__ASSEMBLER__)

// arrange for a block of code to be executed with interrupts disabled
#ifdef __cplusplus

class CritSect
{
public:
	CritSect() { m_sreg = dsblInt(); }
	~CritSect() { restInt(m_sreg); }
private:
	CPU_stat_t m_sreg;
};

#define CRIT_SECT		CritSect cs

#endif	//  __cplusplus

#define begin_atomic	{ CRIT_SECT;
#define end_atomic		}

// convert a Program Memory word address to an integral value
#define flashAddr(a)			(uint16_t)(a)

// non-atomic read/write
#define RD_WORD(a)				({ uint16_t val = *(uint16_t *)(a); val; })
#define WR_WORD(a,v)			*(uint16_t *)(a) = (v)

// atomic read/write
#define RD_WORD_ATOMIC(a)		({ CRIT_SECT; uint16_t val; { val = *(uint16_t *)(a); } val; })
#define WR_WORD_ATOMIC(a,v)		{ CRIT_SECT; *(uint16_t *)(a) = (v); }

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#define SIGN_ON()					\
{									\
	ENABLE_INTERRUPTS();			\
	sendPStr(PSTR("ZBasic"));		\
	sendPStr(verStr);				\
}

extern const char verStr[] PROGMEM;
extern const char serNum[] PROGMEM;
extern PersistData sysData EEMEM;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void zxInit(void);
void zxInit2(uint8_t signOn);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
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 memSwap(void *blk1, void *blk2, uint16_t len);
void memMove(void *dst, const void *src, uint16_t cnt);
int16_t memCmp(const void *p1, const void *p2, uint16_t cnt);
void memSet(void *dst, uint8_t val, uint16_t cnt);
uint16_t memFind(uint16_t addr, uint16_t len, uint8_t val, uint8_t ignCase);

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 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);

// object iteration functions
typedef void (*ObjIteratorFunc)(void *);
void objIterator(void *obj, ObjIteratorFunc func, unsigned cnt, unsigned size);
void revObjIterator(void *obj, ObjIteratorFunc func, unsigned cnt, unsigned size);

typedef uint16_t VirtPtr;
void vtblInit(void *obj, VirtPtr *vtblPtr, unsigned cnt, unsigned size);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void rtcUpdate(uint16_t ticks);
void runMonitor(uint8_t baudIdx) NORETURN;
void getMicroTime(MicroTime *t0);
uint32_t getElapsedMicroTime(MicroTime *t0);
uint32_t getElapsedMicroTimeEx(MicroTime *t0, MicroTime *t1);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
void rtcUpdate(uint16_t ticks);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: bootldr.h rev 333
//---------------------------------------------------------------------------
// baud rate selector values for ZXCmdMode() et al
#define BAUD_IDX_NO_CHG			0
#define BAUD_IDX_1200			1
#define BAUD_IDX_2400			2
#define BAUD_IDX_4800			3
#define BAUD_IDX_9600			4
#define BAUD_IDX_19200			5
#define BAUD_IDX_38400			6
#define BAUD_IDX_57600			7
#define BAUD_IDX_115200			8
#define BAUD_IDX_230400			9


//---------------------------------------------------------------------------
// Id: heap.h rev 262
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
extern volatile void *heapEnd;
extern volatile void *heapLimit;
extern volatile uint16_t freeList;
//extern volatile HeapFreeNode *freeList;

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: iofunc.h rev 336
//---------------------------------------------------------------------------
typedef struct
{
	uint8_t dirBits;		// data direction bits
	uint8_t portBits;		// port value bits
	uint8_t puBits;			// pullup bits
	uint8_t pdBits;			// pulldown bits
	uint8_t invBits;		// inverted I/O bits
} PortConfigData;

#define I2C_SLAVE_FLAG				0x80

// general I/O functions
uint8_t getPin(uint8_t pin);
void putPin(uint8_t pin, uint8_t val);
uint8_t shiftIn(uint8_t dpin, uint8_t cpin, uint8_t cnt);
uint16_t shiftInEx(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime);
uint8_t shiftInI2C(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime);
void shiftOut(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t val);
void shiftOutEx(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime, uint16_t val);
uint8_t shiftOutI2C(uint8_t dpin, uint8_t cpin, uint8_t cnt, uint8_t flags, uint16_t bitTime, uint8_t val);
void freqOut(uint8_t pin, uint16_t freqA, uint16_t freqB, uint16_t duration);
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);
void calibrateADC(void);
uint16_t getADC(uint8_t pin, uint8_t wait);
void adcToCom1(uint8_t pin, int16_t rate);
void com1ToDAC(uint8_t pin);

// Input/output capture
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);

// 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);

// DAC functions
void calibrateDAC(void);
uint8_t dacOpen(uint8_t chan, uint16_t mode);
uint8_t dacValue(uint8_t chan, uint16_t val);
uint8_t dacClose(uint8_t chan);
uint8_t dacPin(uint8_t acc, uint8_t dacVal, uint8_t pin, uint8_t repCnt);
uint8_t dacPinEx(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);

// pin I/O helpers
uint8_t getPortBit(uint8_t pin);
uint8_t getPortMask(uint8_t pin);
uint16_t getPortBitInfo(uint8_t pin);
uint16_t getPortPinInfo(uint8_t pin);
uint32_t getPortPinInfoEx(uint8_t pin);
uint32_t getPortPinData(uint8_t pin);
uint8_t *getPortAddress(uint8_t pin, uint8_t idx);
uint8_t adcChan(uint8_t pin);

void portConfig(uint8_t portIdx, uint8_t ddrBits, uint8_t portBits);
void portConfigEx(uint8_t portIdx, PortConfigData pcd);



//---------------------------------------------------------------------------
// Id: serial.h rev 351
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
// formulae for determining the UART UBRR value
#define AVR_BAUD_FACTOR(s)			((((USART_FREQ / (1 << USART_SCALE) / (s)) + 8) / 16) - 1)
#define AVR_BAUD_FACTOR_2X(s)		((((USART_FREQ / (1 << USART_SCALE) / (s)) + 4) / 8) - 1)

#define ARM_BAUD_DIVISOR(s)			(((USART_FREQ / (s)) + 8) / 16)

#if defined(__AVR__)
#define BAUD_DIV					AVR_BAUD_FACTOR_2X
#define BAUD_FACTOR_2X				AVR_BAUD_FACTOR_2X
#elif defined(__arm__)
#define BAUD_DIV					ARM_BAUD_DIVISOR
#endif

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
int getComChanIdx(uint8_t chan);
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 ctrlCom(uint8_t chan, uint8_t rxCtrlPin, uint8_t txCtrlPin, uint8_t ctrlFlags);
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 281
//---------------------------------------------------------------------------
#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 318
//---------------------------------------------------------------------------
#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);
void progMemRead(ProgMemAddr addr, void *buf, uint16_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);

String progMemReadStringTbl(ProgMemAddr addr);
uint16_t progMemFind(ProgMemAddr addr, uint16_t len, uint8_t val, uint8_t ignCase);

#if defined(BIG_FLASH) || (defined(ZVM) && defined(EXTERNAL_PROGMEM))
#define getProgMemByte(a)		progMemReadByte((ProgMemAddr)(uint16_t)(a))
#elif defined(__AVR__)
#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 289
//---------------------------------------------------------------------------
// 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);

// convert a date to day number
uint32_t dateEncode(uint16_t year, uint8_t month, uint8_t day);

#endif	// !defined(__ASSEMBLER__)


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


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

#endif	// __ZXLIB_H__
