/*
 *
 *                 Copyright 2007-2011 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
 *
 */

//***************************************************************************
//
//                         ZBasic Library v4.0.1
//
//     This file is generated automatically.  Do not modify it directly.
//
//***************************************************************************

#ifndef __ZBASIC_H__
#define __ZBASIC_H__

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

#if defined(__cplusplus)

#include <stdlib.h>

void * operator new(size_t zb_size);
void operator delete(void * zb_ptr);
__extension__ typedef int __guard __attribute__((mode (__DI__)));

#define ZB_SET_NAME(zb_n)				asm(#zb_n)
#if !defined(ZB_MOD_NAME)
#define ZB_MOD_NAME __cpp
#endif

#undef PROGMEM
#define ZB_PROGMEM_C(zb_sect)			__attribute__((section(#zb_sect)))
#define ZB_PROGMEM_B(zb_n1, zb_n2)		ZB_PROGMEM_C(.progmem. ##zb_n1 ##zb_n2)
#define ZB_PROGMEM_A(zb_n1, zb_n2)		ZB_PROGMEM_B(zb_n1, zb_n2)
#define PROGMEM							ZB_PROGMEM_A(__LINE__, ZB_MOD_NAME)

extern "C"
{

int  __cxa_guard_acquire(__guard *);
void __cxa_guard_release(__guard *);
void __cxa_guard_abort(__guard *);
void __cxa_pure_virtual(void);

#endif	// defined(__cplusplus)

#if !defined(ZB_MOD_NAME)
	#define ZB_MOD_NAME __c
#endif

#if !defined(ZB_SET_NAME)
	#define ZB_SET_NAME(zb_n)
#endif
#define ZB_PUB_NAME(zb_pub, zb_priv)		void zb_pub(void) ZB_SET_NAME(zb_pub) __attribute__((alias(#zb_priv)))
#define ZB_PUB_VAR_NAME(zb_pub, zb_priv)	void zb_pub(void) __attribute__((alias(#zb_priv)))
#define ZB_ALIAS_NAME(zb_name)			__attribute__((alias(#zb_name)))


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

#if !defined(_BV)
#define _BV(zb_v)						(1 << (zb_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(ZB_NUMVAL)
	#if defined(__ASSEMBLER__)
		#define ZB_NUMVAL(zb_x)			zb_x
	#else
		#define ZB_NUMVAL(zb_x)			zb_x##L
	#endif
#endif

#if !defined(__ASSEMBLER__)
#define ZB_WEAK							__attribute__((weak))
#define ZB_OS_MAIN						__attribute__((OS_main))
#define ZB_NORETURN						__attribute__((noreturn))
#define ZB_INLINE						__attribute__((always_inline))
#define ZB_NO_INLINE					__attribute__((noinline))
#define ZB_PURE							__attribute__((pure))
#define ZB_UNUSED						__attribute__((unused))
#define ZB_USED							__attribute__((used))
#define ZB_NAKED 						__attribute__((naked))
#define ZB_NO_INIT						__attribute__((section(".noinit")))
#define ZB_INIT0						__attribute__((section(".init0")))
#define ZB_INIT1						__attribute__((section(".init1")))
#define ZB_INIT2						__attribute__((section(".init2")))
#define ZB_INIT3						__attribute__((section(".init3")))
#define ZB_INIT4						__attribute__((section(".init4")))
#define ZB_INIT5						__attribute__((section(".init5")))
#define ZB_INIT6						__attribute__((section(".init6")))
#define ZB_INIT7						__attribute__((section(".init7")))
#define ZB_INIT8						__attribute__((section(".init8")))
#define ZB_INIT9						__attribute__((section(".init9")))

// This set of macros is employed to generate names for initialized PROGMEM
// strings.  Each use of PSTR generates a name of the form "__PSTR_mod_155_2".
#undef PSTR
#define ZB_PSTR_C(zb_s, zb_name)			(__extension__({ static const char zb_name[] asm(#zb_name) PROGMEM = (zb_s); zb_name; }))
#define ZB_PSTR_B(zb_s, zb_n1, zb_n2, zb_n3) ZB_PSTR_C(zb_s, __PSTR_ ##zb_n1 ##_ ##zb_n2 ##_ ##zb_n3)
#define ZB_PSTR_A(zb_s, zb_n1, zb_n2, zb_n3) ZB_PSTR_B(zb_s, zb_n1, zb_n2, zb_n3)
#define PSTR(zb_s)							ZB_PSTR_A(zb_s, ZB_MOD_NAME, __LINE__, __COUNTER__)

#if !defined(ZB_NAKED_ISR)
#define ZB_NAKED_ISR(zb_v) \
void zb_v(void) ZB_NAKED; \
void zb_v(void)
#endif
#endif	// !defined(__ASSEMBLER__)

#if defined(__ASSEMBLER__)
	#define ZB_PROVIDE_SYM(zb_name)		ZB_GLOBAL_SYM zb_name
	#define ZB_REQUEST_SYM(zb_name)		.global zb_name
	#if defined(__AVR__)
		.macro	ZB_GLOBAL_SYM zb_name
			.global \zb_name
		\zb_name:
		.endm

		.macro	ZB_WEAK_GLOBAL_SYM zb_name
			.weak \zb_name
			.global \zb_name
		\zb_name:
		.endm

		.macro ZB_SET_VALUE zb_name, zb_value=0
			.global \zb_name
			.set \zb_name, \zb_value
		.endm

		.macro ZB_SET_WEAK_VALUE zb_name, zb_value=0
			.weak \zb_name
			.global \zb_name
			.set \zb_name, \zb_value
		.endm

		.macro ZB_MARK_DATA zb_name
			.type \zb_name, @object
			.size \zb_name, . - \zb_name
		.endm
	#endif
#else
	#define ZB_ALIAS_SYM(zb_alias, zb_name)	__asm__ __volatile__(".global " #zb_alias "\n.set " #zb_alias ", " #zb_name "\n"::)
	#define ZB_PROVIDE_SYM(zb_name)			__asm__ __volatile__(".global " #zb_name "\n" #zb_name ":\n"::)
	#define ZB_REQUEST_SYM(zb_name)			__asm__ __volatile__(".global " #zb_name "\n"::)
	#define ZB_SET_VALUE_(zb_n, zb_v)		__asm__ __volatile__(".global " #zb_n "\n.set " #zb_n ", " #zb_v "\n"::)
	#define ZB_SET_WEAK_VALUE_(zb_n, zb_v)	__asm__ __volatile__(".weak " #zb_n "\n.global " #zb_n "\n.set " #zb_n ", " #zb_v "\n"::)
	#define ZB_SET_VALUE(zb_n, zb_v)		ZB_SET_VALUE_(zb_n, zb_v)
	#define ZB_SET_WEAK_VALUE(zb_n, zb_v)	ZB_SET_WEAK_VALUE_(zb_n, zb_v)
#endif
#define ZB_PROVIDE_ENTRY(zb_name)			ZB_PROVIDE_SYM(_zb_tag_##zb_name)
#define ZB_REQUEST_ENTRY(zb_name)			ZB_REQUEST_SYM(_zb_tag_##zb_name)

	#define ZB_START(zb_d)
	#define ZB_OFST(zb_n, zb_s)
	#define ZB_SIZEOF(zb_n)
	#define ZB_PTR(zb_n)
	#define ZB_PORT_ADDR(zb_n)
	#define ZB_EQUIV(zb_s, zb_v)
	#define ZB_EMIT(zb_s)


//---------------------------------------------------------------------------
// Id: avrdef.h rev 582
//---------------------------------------------------------------------------
#if defined(__AVR__)
// definitions for RAM start address and size
#if defined(__AVR_XMEGA__)
	#define ZB_INTERNAL_RAM_START		INTERNAL_SRAM_START
	#define ZB_AVR_XMEGA				1
#elif defined(__AVR_ATtiny4__) || defined(__AVR_ATtiny5__) || defined(__AVR_ATtiny9__) || \
		defined(__AVR_ATtiny10__) || defined(__AVR_ATtiny20__)
	#define ZB_INTERNAL_RAM_START		0x0040
	#define ZB_AVR_TINY					1
#elif defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny13A__) || \
		defined(__AVR_ATtiny22__) || \
		defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__) || \
		defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny24A__) || \
		defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny26__) || \
		defined(__AVR_ATtiny261__) || defined(__AVR_ATtiny261A__) || \
		defined(__AVR_ATtiny4313__) || defined(__AVR_ATtiny4313A__) || \
		defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny44A__) || \
		defined(__AVR_ATtiny45__) || \
		defined(__AVR_ATtiny461__) || defined(__AVR_ATtiny461A__) || \
		defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny84A__) || \
		defined(__AVR_ATtiny85__) || \
		defined(__AVR_ATtiny861__) || defined(__AVR_ATtiny861A__)
	#define ZB_INTERNAL_RAM_START		0x0060
	#define ZB_AVR_TINY					1
#elif defined(__AVR_ATtiny48__) || defined(__AVR_ATtiny48A__) || \
		defined(__AVR_ATtiny88__) || defined(__AVR_ATtiny88A__) || \
		defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
	#define ZB_INTERNAL_RAM_START		0x0100
	#define ZB_AVR_TINY					1
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || \
		defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \
		defined(__AVR_ATmega16__) || defined(__AVR_ATmega16A__) || \
		defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) || \
		defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) || \
		defined(__AVR_ATmega323__)
	#define ZB_INTERNAL_RAM_START		0x0060
	#define ZB_AVR_MEGA					1
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || \
		defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PA__) || \
		defined(__AVR_ATmega88__) || defined(__AVR_ATmega88A__) || \
		defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PA__) || \
		defined(__AVR_ATmega162__) || \
		defined(__AVR_ATmega164__) || defined(__AVR_ATmega164A__) || \
		defined(__AVR_ATmega164P__) || defined(__AVR_ATmega164PA__) || \
		defined(__AVR_ATmega165__) || defined(__AVR_ATmega165A__) || \
		defined(__AVR_ATmega165P__) || defined(__AVR_ATmega165PA__) || \
		defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \
		defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || \
		defined(__AVR_ATmega169__) || defined(__AVR_ATmega169A__) || \
		defined(__AVR_ATmega169P__) || defined(__AVR_ATmega169PA__) || \
		defined(__AVR_ATmega324__) || defined(__AVR_ATmega324A__) || \
		defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324PA__) || \
		defined(__AVR_ATmega325__) || defined(__AVR_ATmega325A__) || \
		defined(__AVR_ATmega325P__) || defined(__AVR_ATmega325PA__) || \
		defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3250A__) || \
		defined(__AVR_ATmega3250P__) || defined(__AVR_ATmega3250PA__) || \
		defined(__AVR_ATmega328__) || defined(__AVR_ATmega328A__) || \
		defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PA__) || \
		defined(__AVR_ATmega329__) || defined(__AVR_ATmega329A__) || \
		defined(__AVR_ATmega329P__) || defined(__AVR_ATmega329PA__) || \
		defined(__AVR_ATmega3290__) || defined(__AVR_ATmega3290A__) || \
		defined(__AVR_ATmega3290P__) || defined(__AVR_ATmega3290PA__) || \
		defined(__AVR_ATmega64__) || defined(__AVR_ATmega64A__) || \
		defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || \
		defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || \
		defined(__AVR_ATmega645__) || defined(__AVR_ATmega645A__) || \
		defined(__AVR_ATmega645P__) || defined(__AVR_ATmega645PA__) || \
		defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6450A__) || \
		defined(__AVR_ATmega6450P__) || defined(__AVR_ATmega6450PA__) || \
		defined(__AVR_ATmega649__) || defined(__AVR_ATmega649A__) || \
		defined(__AVR_ATmega649P__) || defined(__AVR_ATmega649PA__) || \
		defined(__AVR_ATmega6490__) || defined(__AVR_ATmega6490A__) || \
		defined(__AVR_ATmega6490P__) || defined(__AVR_ATmega6490PA__) || \
		defined(__AVR_ATmega128__) || defined(__AVR_ATmega128A__) || \
		defined(__AVR_AT90CAN32__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN128__) || \
		defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
		defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || \
		defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__) || \
		defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || \
		defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \
		defined(__AVR_ATmega1284P__)
	#define ZB_INTERNAL_RAM_START		0x0100
	#define ZB_AVR_MEGA					1
#elif defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || \
		defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega128RFA1__)
	#define ZB_INTERNAL_RAM_START		0x0200
	#define ZB_AVR_MEGA					1
#elif !defined(ZB_ARCH_TARG)
	#error need RAM start information
#endif

#define ZB_INTERNAL_RAM_SIZE			(RAMEND - ZB_INTERNAL_RAM_START + 1)
#if !defined(ZB_FLASH_SIZE)
	#define ZB_FLASH_SIZE				(FLASHEND + 1)
#endif
#define ZB_EEP_SIZE						(E2END + 1)


#if !defined(__ASSEMBLER__)
#define ZB_ENBL_INT()						sei()

#define ZB_FORCE_ALIGN

#define ZB_FORCE_INDIRECT(zb_ptr) 			__asm__ __volatile__ ("" : "=e" (zb_ptr) : "0" (zb_ptr))

#if defined(ZB_AVR_XMEGA)
typedef uint16_t zb_RTC_OCR_t;
typedef uint16_t zb_SW_UART_OCR_t;
#else
typedef uint8_t zb_RTC_OCR_t;
typedef uint8_t zb_SW_UART_OCR_t;
#endif
typedef uint8_t zb_CPU_stat_t;
typedef uint16_t zbAddress_t;
typedef uint16_t zbVirtPtr_t;

extern uint8_t *_end;

// for defining a heap initialization
#define ZB_INIT_HEAP(zb_limit, zb_size) \
	static void zbHeapInit(void) ZB_SET_NAME(zbHeapInit) ZB_NAKED ZB_USED ZB_INIT4; \
	static void zbHeapInit(void) { SP = zbInitMemory(zb_limit, zb_size); }

// for defining a ZBasic initialization function
#define ZB_INIT_FUNC(zb_func) \
	static void zb_func(void) ZB_SET_NAME(zb_func) ZB_NAKED ZB_USED ZB_INIT7; \
	static void zb_func(void)

// for defining the main ZBasic initialization function
#define ZB_INIT_MAIN(zb_func, zb_limit, zb_size) 	\
	ZB_INIT_HEAP(zb_limit, zb_size)					\
	ZB_INIT_FUNC(zb_func)

#define ZB_BYTE_VAL(zb_v)							\
({													\
	uint8_t zb_val;									\
	__asm__											\
	(												\
		"ldi %0, lo8(" #zb_v ")"	"\n\t"			\
		: "=d" (zb_val)								\
		:											\
	);												\
	zb_val;											\
})

#define ZB_WORD_VAL(zb_v)							\
({													\
	uint16_t zb_val;								\
	__asm__											\
	(												\
		"ldi %A0, lo8(" #zb_v ")"	"\n\t"			\
		"ldi %B0, hi8(" #zb_v ")"	"\n\t"			\
		: "=d" (zb_val)								\
		:											\
	);												\
	zb_val;											\
})

#define ZB_DWORD_VAL(zb_v)							\
({													\
	uint32_t zb_val;								\
	__asm__											\
	(												\
		"ldi %A0, lo8(" #zb_v ")"	"\n\t"			\
		"ldi %B0, hi8(" #zb_v ")"	"\n\t"			\
		"ldi %C0, hlo8(" #zb_v ")"	"\n\t"			\
		"ldi %D0, hhi8(" #zb_v ")"	"\n\t"			\
		: "=d" (zb_val)								\
		:											\
	);												\
	zb_val;											\
})

#define ZB_FLOAT_VAL(zb_v)							\
({													\
	float zb_val;									\
	__asm__											\
	(												\
		"ldi %A0, lo8(" #zb_v ")"	"\n\t"			\
		"ldi %B0, hi8(" #zb_v ")"	"\n\t"			\
		"ldi %C0, hlo8(" #zb_v ")"	"\n\t"			\
		"ldi %D0, hhi8(" #zb_v ")"	"\n\t"			\
		: "=d" (zb_val)								\
		:											\
	);												\
	zb_val;											\
})
// unconditionally disable interrupts and return the prior status register content
#define zbDsblInt()									\
({													\
	zb_CPU_stat_t zb_flag;							\
	__asm__ __volatile__							\
	(												\
		"in %0, 0x3f"		   	"\n\t"				\
		"cli"			   		"\n\t"				\
		: "=r" (zb_flag)							\
		: 											\
	);												\
	zb_flag;										\
})

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

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


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

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

#if !defined(__cplusplus)
#define ZB_CRIT_SECT		inline void zb_intRestore(uint8_t *zb_statp) { SREG = *zb_statp; } \
	uint8_t zb_intSave __attribute__((__cleanup__(zb_intRestore))) = zbDsblInt()
#endif

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

// complement a byte value (avoiding integer promotion)
#define zbNot8(zb_v)								\
({													\
	uint8_t zb_val = zb_v;							\
	__asm__											\
	(												\
		"com %0"			   	"\n\t"				\
		: "=r" (zb_val)								\
		: "0" (zb_val)								\
	);												\
	zb_val;											\
})

// macro to return the bytes of a float value as a double word
#define zbFloatBytes(zb_f)							\
({													\
	float zb_fval = zb_f;							\
	uint32_t zb_uval;								\
	__asm__											\
	(												\
		".if %A0 != %A1"		"\n\t"				\
		"movw %A0, %A1"			"\n\t"				\
		"movw %C0, %C1"			"\n\t"				\
		".endif"				"\n\t"				\
		: "=r" (zb_uval)							\
		: "r" (zb_fval)								\
	);												\
	zb_uval;										\
})

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

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

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

// macro to return the address of the first unused Flash location
#define zbEndCode()									\
({													\
	uint32_t zb_val;								\
	__asm__											\
	(												\
		"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" (zb_val)							\
		: 											\
	);												\
	zb_val;											\
})

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

// macro to return the address of the first unused EEPROM location
#define zbEndEEPROM()								\
({													\
	uint16_t zb_val;								\
	__asm__											\
	(												\
		"ldi %A0, lo8(__zb_eeprom_end)"	"\n\t"		\
		"ldi %B0, hi8(__zb_eeprom_end)"	"\n\t"		\
		: "=d" (zb_val)								\
		: 											\
	);												\
	zb_val;											\
})

// union for composing/decomposing word and byte values
typedef union
{
	uint16_t word;
	struct
	{
		uint8_t loByte;
		uint8_t hiByte;
	};
} zbWordByte_t;

// macro to configure the console pin as an output in the idle state
#define ZB_SET_CONSOLE_PIN(zb_addr, zb_mask, zb_state)\
	uint16_t zb_a = zb_addr;						\
	uint8_t zb_m = zb_mask;							\
	uint8_t zb_s = zb_state;						\
	__asm__ __volatile__							\
	(												\
		"ldd r0, %a0 + 2"	"\n\t"					\
		"or r0, %1"			"\n\t"					\
		"sbrs %2, 0"		"\n\t"					\
		"eor r0, %1"		"\n\t"					\
		"std %a0 + 2, r0"	"\n\t"					\
		"ldd r0, %a0 + 1"	"\n\t"					\
		"or r0, %1"			"\n\t"					\
		"std %a0 + 1, r0"	"\n\t"					\
		:											\
		: "b" (zb_a), "r" (zb_m), "r" (zb_s)		\
		: "r0"										\
	)

#endif	// !defined(__ASSEMBLER__)

// port indices
#define ZB_PORT_A							0
#define ZB_PORT_B							1
#define ZB_PORT_C							2
#define ZB_PORT_D							3
#define ZB_PORT_E							4
#define ZB_PORT_F							5
#define ZB_PORT_G							6
#define ZB_PORT_H							7
#define ZB_PORT_I							8			// not used
#define ZB_PORT_J							9
#define ZB_PORT_K							10
#define ZB_PORT_L							11

#define ZB_PORT_Q							15			// N.B.: ordinal deviation

#define ZB_PORT_BIT_FLAG					0x80
#define ZB_PORT_PORT_MASK					0x78
#define ZB_PORT_PORT_SHIFT					3
#define ZB_PORT_BIT_MASK					0x07

// preprocessor macro to encode a port/bit number as a port designator
#define ZB_PORT_PORT(zb_p)					(((zb_p) << ZB_PORT_PORT_SHIFT) & ZB_PORT_PORT_MASK)
#define ZB_PORT_BIT(zb_p, zb_b)				(ZB_PORT_BIT_FLAG + ((zb_p) << ZB_PORT_PORT_SHIFT) + ((zb_b) & ZB_PORT_BIT_MASK))
#define ZB_PORT(zb_p, zb_b)					ZB_PORT_BIT(ZB_PORT_##zb_p, zb_b)

// macro to extract the port index and port bit index from an encoded pin number
#define ZB_PORT_IDX(zb_p)					(((zb_p) & ZB_PORT_PORT_MASK) >> ZB_PORT_PORT_SHIFT)
#define ZB_PORT_BIT_IDX(zb_p)				((zb_p) & ZB_PORT_BIT_MASK)


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

#if defined(__AVR_ATxmega256A1__) || defined(__AVR_ATxmega192A1__) || \
		defined(__AVR_ATxmega128A1__) || defined(__AVR_ATxmega64A1__)
	#define ZB_AVR_XMEGA_A1					1
	#define ZB_HAS_DAC
	#define ZB_HAS_ADCB
#elif defined(__AVR_ATxmega256A3__) || defined(__AVR_ATxmega192A3__) || \
		defined(__AVR_ATxmega128A3__) || defined(__AVR_ATxmega64A3__)
	#define ZB_AVR_XMEGA_A3					1
	#define ZB_HAS_DAC
	#define ZB_HAS_ADCB
#elif defined(__AVR_ATxmega256A3B__)
	#define ZB_AVR_XMEGA_A3B				1
	#define ZB_HAS_ADCB
#elif defined(__AVR_ATxmega128A4__) || defined(__AVR_ATxmega64A4__) || \
		defined(__AVR_ATxmega32A4__) || defined(__AVR_ATxmega16A4__)
	#define ZB_AVR_XMEGA_A4					1
	#define ZB_HAS_DAC
#elif defined(__AVR_ATxmega256D3__) || defined(__AVR_ATxmega192D3__) || \
		defined(__AVR_ATxmega128D3__) || defined(__AVR_ATxmega64D3__)
	#define ZB_AVR_XMEGA_D3				1
#elif defined(__AVR_ATxmega128D4__) || defined(__AVR_ATxmega64D4__) || \
		defined(__AVR_ATxmega32D4__) || defined(__AVR_ATxmega16D4__)
	#define ZB_AVR_XMEGA_D4					1
#endif
#if defined(__AVR_ATxmega256A1__) || defined(__AVR_ATxmega256A3__) || defined(__AVR_ATxmega256D3__)
	#define ZB_AVR_XMEGA_256				1
#elif defined(__AVR_ATxmega192A1__) || defined(__AVR_ATxmega192A3__) || defined(__AVR_ATxmega192D3__)
	#define ZB_AVR_XMEGA_192				1
#elif defined(__AVR_ATxmega128A1__) || defined(__AVR_ATxmega128A3__) || defined(__AVR_ATxmega128A4__) || \
		 defined(__AVR_ATxmega128D3__) || defined(__AVR_ATxmega128D4__)
	#define ZB_AVR_XMEGA_128				1
#elif defined(__AVR_ATxmega64A1__) || defined(__AVR_ATxmega64A3__) || defined(__AVR_ATxmega64A4__) || \
		 defined(__AVR_ATxmega64D3__) || defined(__AVR_ATxmega64D4__)
	#define ZB_AVR_XMEGA_64					1
#elif defined(__AVR_ATxmega32A4__) || defined(__AVR_ATxmega32D4__)
	#define ZB_AVR_XMEGA_32					1
#elif defined(__AVR_ATxmega16A4__) || defined(__AVR_ATxmega16D4__)
	#define ZB_AVR_XMEGA_16					1
#endif

#if !defined(__ASSEMBLER__) && !defined(ZB_WORD_REG)
	#define ZB_WORD_REG(zb_reg)				\
		union								\
		{									\
			zbReg16_t zb_reg;				\
			struct							\
			{								\
				zbReg8_t zb_reg ## L;		\
				zbReg8_t zb_reg ## H;		\
			};								\
		}
#endif

// determine if the device has more than 64K of Flash
#if (defined(ZB_AVR_XMEGA) || defined(ZB_AVR_MEGA)) && defined(__AVR_HAVE_ELPM__)
	#define ZB_BIG_FLASH
#endif

#if defined(ZB_AVR_MEGA) || defined(ZB_AVR_TINY)
#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(ZB_AVR_MEGA)

#if !defined(__ASSEMBLER__)
#if defined(ZB_BIG_FLASH)
typedef uint32_t zbProgMemAddr_t;
#else
typedef uint16_t zbProgMemAddr_t;
#endif
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#define ZB_SYS_EEMEM						__attribute__((section(".zb_sys_eeprom")))
#define ZB_USR_EEMEM						__attribute__((section(".zb_usr_eeprom")))
#if !defined(EEMEM)
	#define EEMEM							__attribute__((section(".eeprom")))
#endif
#if !defined(PROGMEM)
	#define PROGMEM							__attribute__((__progmem__))
#endif

// macros to provide quoted call/rcall and jmp/rjmp for use in inline assembly code
#if defined(__AVR_HAVE_JMP_CALL__)
	#define ZB_QCALL						"call "
	#define ZB_QJMP							"jmp "
#else
	#define ZB_QCALL						"rcall "
	#define ZB_QJMP							"rjmp "
#endif

#endif	// !defined(__ASSEMBLER__)

#endif	// defined(__AVR__)

//---------------------------------------------------------------------------
// Id: zxstring.h rev 582
//---------------------------------------------------------------------------
// string type identifiers
#define ZB_BX_STR						0x00	// BasicX variable length string
#define ZB_BX_FSTR						0xff	// BasicX fixed length string
#define ZB_AN_STR						0xe0	// an allocated string
#define ZB_TMP_STR						0xe1	// a temporary string
#define ZB_PRG_STR						0xe2	// string characters in PROG memory
#define ZB_EEP_STR						0xe3	// string characters in EEPROM memory
#define ZB_RAM_STR						0xe4	// string characters in RAM (non-allocated)
#define ZB_LOC_STR						0xe5	// string characters in the descriptor (length <= 2)
#define ZB_IND_STR						0xe6	// indirect: sp points to actual string
                                        		//    (used only for passing BX and fixed-length strings by value)
#define ZB_STR_MAX						255		// maximum string length

#if !defined(__ASSEMBLER__)
// test for an allocated string
#define ZB_IS_ALLOC_STR(zb_s)			((zb_s.zb_type & 0xfe) == ZB_AN_STR)
#define ZB_STR_BY_VAL(zb_s)				({zbString_t zb_s1 = zb_s; if (ZB_IS_ALLOC_STR(zb_s)) zb_s1.zb_type = ZB_RAM_STR; zb_s1;})
#define ZB_FIX_PARM_STR(zb_t, zb_s)		do { if ((zb_t = (zb_s).zb_type) == ZB_TMP_STR) (zb_s).zb_type = ZB_AN_STR; } while(0)
#define ZB_FREE_PARM_STR(zb_t, zb_p)	do { if ((zb_t) == ZB_TMP_STR) zbMemFree((zb_p).zb_mem); } while(0)
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
struct _zb_string
{
	uint8_t zb_len;					// the length of the string (not valid for indirect type)
	uint8_t zb_type;				// the string type
	union
	{
		char zb_chars[1];			// used for BX-style strings (variable and fixed length)
		char *zb_mem;				// used for temporary, program memory, persistent and allocated strings
		struct _zb_string *zb_sp;	// used for indirect string type, points to actual string descriptor
	};
};
typedef struct _zb_string zbString_t;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)

// zbString_t helper macros
#define ZB_STR_INIT						{ 0, ZB_TMP_STR }
#define ZB_PSTRING(zb_p, zb_n)			({ zbString_t zb_s; zb_s.zb_len = zb_n; zb_s.zb_type = ZB_PRG_STR; zb_s.zb_mem = p; zb_s; })
#define ZB_STRING(zb_p, zb_n)			zbMakeString(PSTR(zb_p), zb_n, ZB_PRG_STR)
#define ZB_STRTBL(zb_n)					zbStrConst((zbProgMemAddr_t)(uint16_t)(zbStringTbl + zb_n))
#define ZB_STRTBL_ADDR(zb_n)			(zbProgMemAddr_t)(uint16_t)(zbStringTbl + zb_n)
#define ZB_STR_FREE(zb_s)				zbStrFreeType(zb_s.zb_mem, zb_s.type)
#define ZB_STR_FREE_TEMP(zb_s)			if ((zb_s).zb_type == ZB_TMP_STR) zbMemFree((zb_s).zb_mem)

#if defined(__AVR__)

#define ZB_STR_LEN(zb_s)							\
({													\
	zbString_t zb_ss = zb_s;						\
	uint8_t zb_len;									\
	uint8_t *zb_p;									\
	__asm__											\
	(												\
		"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" (zb_len), "=&e" (zb_p)				\
		: "d" (zb_ss), "M" (ZB_IND_STR)				\
	);												\
	zb_len;											\
})

#define ZB_STR_TEMP(_zb_s)							\
({													\
	zbString_t zb_s = _zb_s;						\
	__asm__											\
	(												\
		"cpi %B0, %1"		   	"\n\t"				\
		"brne 1f"			   	"\n\t"				\
		"ldi %B0, %2"		   	"\n\t"				\
		"1:"				   	"\n\t"				\
		: "=&d" (zb_s)								\
		: "M" (ZB_AN_STR), "M" (ZB_TMP_STR), "0" (zb_s)\
	);												\
	zb_s;											\
})

#else

#define ZB_STR_LEN(zb_s)			(((zb_s).zb_type == ZB_IND_STR) ? (zb_s).sp->zb_len : (zb_s).zb_len)

#define ZB_STR_TEMP(_zb_s)							\
({													\
	zbString_t zb_s = _zb_s;						\
	if (zb_s.zb_type == ZB_AN_STR)					\
		zb_s.zb_type = ZB_TMP_STR;					\
	zb_s;											\
})

#endif


void zbStrCopyChars(char *zb_dstp, zbString_t zb_s, uint8_t zb_len);
void zbStrCopyCharsEx(char *zb_dstp, zbString_t zb_s, uint8_t zb_ofst, uint8_t zb_len);

void zbStrInit(zbString_t *zb_dst, uint8_t zb_type);
void zbStrInitStr(zbString_t *zb_dst, uint8_t zb_type, zbString_t zb_s);
void zbStrInitN(zbString_t *zb_sp, uint8_t zb_type, uint8_t zb_len, uint16_t zb_cnt);
void zbStrInitFixed(zbString_t *zb_dst, uint8_t zb_len);
void zbStrInitFixedN(zbString_t *zb_dst, uint8_t zb_len, uint16_t zb_cnt);

void zbStrFreeType(void *zb_ptr, uint8_t zb_type);
void zbStrFree(zbString_t *zb_str);
void zbStrFreeN(zbString_t *zb_str, uint16_t zb_cnt);
void zbStrDelete(zbString_t zb_s);

char *zbStrPtr(zbString_t *zb_s);
char *zbStrAddr(zbString_t zb_s);
uint16_t zbStrLen(zbString_t zb_s);
uint8_t zbStrType(zbString_t zb_s);

void zbStrCopy(zbString_t *zb_dst, zbString_t zb_src);
void zbStrCopyN(zbString_t *zb_dst, const zbString_t *zb_src, uint16_t zb_cnt);
zbString_t zbStrCat(zbString_t zb_s1, zbString_t zb_s2);
int16_t zbStrCmp(zbString_t zb_s1, zbString_t zb_s2, uint8_t zb_ignCase);
zbString_t zbStrFromChar(uint8_t zb_c);
uint8_t zbStrChar(zbString_t zb_s, uint8_t zb_idx);
zbString_t zbStrCase(zbString_t zb_s, uint8_t zb_upper);
zbString_t zbStrMid(zbString_t zb_orig, int16_t zb_idx, int16_t zb_cnt);
zbString_t zbStrLeft(zbString_t zb_orig, int16_t zb_cnt);
zbString_t zbStrRight(zbString_t zb_orig, int16_t zb_cnt);
zbString_t zbStrDup(zbString_t zb_orig);
zbString_t zbStrNew(zbString_t zb_orig);
zbString_t zbStrTrim(zbString_t zb_orig);
zbString_t zbStrAppend(zbString_t zb_s, uint8_t zb_c);
void zbStrSet(zbString_t *zb_dst, int16_t zb_idx, int16_t zb_cnt, zbString_t zb_src);
zbString_t zbStrSelect(uint8_t zb_flag, zbString_t zb_s1, zbString_t szb_2);
uint8_t zbStrFind(zbString_t zb_haystack, zbString_t zb_needle, uint8_t zb_idx, uint8_t zb_ignCase);
zbString_t zbStrReplace(zbString_t zb_origStr, zbString_t zb_findStr, zbString_t zb_replStr, int16_t zb_idx, uint16_t zb_cnt, uint8_t zb_ignCase);
uint8_t zbStrIdx(zbString_t zb_s, uint16_t zb_cnt, uint8_t zb_c);

extern const char zbTrue[] PROGMEM;
extern const char zbFalse[] PROGMEM;

zbString_t zbBoolToString(uint8_t zb_val);
zbString_t zbByteToString(uint8_t zb_val);
zbString_t zbIntToString(int16_t zb_val);
zbString_t zbUintToString(uint16_t zb_val);
zbString_t zbLongToString(int32_t zb_val);
zbString_t zbUlongToString(uint32_t zb_val);
zbString_t zbFloatToString(float zb_val, uint8_t zb_precision);

uint16_t zbStrToWord(zbString_t zb_s, uint8_t *zb_flagp);
uint32_t zbStrToDword(zbString_t zb_s, uint8_t *zb_flagp);
float zbStrToFloat(zbString_t zb_s, uint8_t *zb_flagp);

zbString_t zbMakeString(const char *zb_str, uint8_t zb_len, uint8_t zb_type);
zbString_t zbStrConst(zbProgMemAddr_t zb_str);
zbString_t zbStrDesc(const zbString_t *zb_s);

zbString_t zbCstrHex(uint32_t zb_val, uint16_t zb_dlen);
void zbOutStr(zbString_t zb_s);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: task.h rev 583
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
typedef struct
{
	uint16_t zb_sp;				// stack pointer
	uint16_t zb_taskStack;		// beginning of task stack
	uint16_t zb_unused;
} zbContext_t;
#endif	// !defined(__ASSEMBLER__)

#define ZB_CTX_SP_OFST						0
#define ZB_CTX_STACK_OFST					2

#if !defined(__ASSEMBLER__)
struct _zbTaskData;
typedef struct _zbTaskData zbTaskData_t;
struct _zbTaskData
{
	uint8_t zb_state;		// task state
	uint16_t zb_timeout;	// ticks remaining in a timeout period (sleep or otherwise)
	zbTaskData_t *zb_next;	// tasks are kept in a circular linked list, curTask points to the current
	zbContext_t zb_ctx;		// the task's context (when not current)
	uint8_t zb_flags;		// task-specific status flags
};
#endif	// !defined(__ASSEMBLER__)

#define ZB_TASK_STATE_OFST	 				0
#define ZB_TASK_TIMEOUT_OFST				1
#define ZB_TASK_NEXT_OFST					3
#define ZB_TASK_CTX_OFST					5

	#define TASK_SP_OFST					ZB_TASK_CTX_OFST + ZB_CTX_SP_OFST
	#define TASK_STACK_OFST					ZB_TASK_CTX_OFST + ZB_CTX_STACK_OFST

#define ZB_TASK_FLAGS_OFST					11

#if !defined(__ASSEMBLER__)
#if defined(__AVR__)

// reverse the order of the bytes in a word
#define zbTaskParmWord(zb_parmVal)				\
({												\
	uint16_t zb_val = zb_parmVal;				\
	__asm__										\
	(											\
		"mov r0, %A0"		   	"\n\t"			\
		"mov %A0, %B0"		   	"\n\t"			\
		"mov %B0, r0"		   	"\n\t"			\
		: "=&r" (zb_val)						\
		: "0" (zb_val)							\
		: "r0"									\
	);											\
	zb_val;										\
})

// reverse the order of the bytes in a double word
#define zbTaskParmDword(zb_parmVal)				\
({												\
	uint32_t zb_val = zb_parmVal;				\
	__asm__										\
	(											\
		"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" (zb_val)						\
		: "0" (zb_val)							\
		: "r0"									\
	);											\
	zb_val;										\
})

// reverse the order of the bytes in a float value
#define zbTaskParmFloat(zb_parmVal)				\
({												\
	float zb_val = zb_parmVal;					\
	__asm__										\
	(											\
		"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" (zb_val)						\
		: "0" (zb_val)							\
		: "r0"									\
	);											\
	zb_val;										\
})

// reverse the order of the bytes in a string descriptor
#define zbTaskParmString(zb_parmVal)			\
({												\
	zbString_t zb_val = zb_parmVal;				\
	__asm__										\
	(											\
		"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" (zb_val)						\
		: "0" (zb_val)							\
		: "r0"									\
	);											\
	zb_val;										\
})

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

void zbInitHeap(void);
uint16_t zbTaskHeadRoom(void *zb_taskStack);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
unsigned zbInitMemory(uint8_t *zb_HeapLimit, unsigned zb_HeapSize);
void zbTaskRun(void *zb_task);
void zbTaskExit(void *zb_task);
void zbTaskResume(void *zb_task);
void zbTaskLock(void *zb_task);
void zbTaskUnlock(void *zb_task);
void zbTaskPause(uint16_t zb_tickCnt);
void zbTaskSleep(uint16_t zb_tickCount);
void zbTaskDelay(float zb_delay);
void zbTaskDelayUntilTick(void);
void zbTaskDelayTicks(uint32_t zb_count);
uint8_t zbTaskIsLocked(void *zb_task);
uint8_t zbTaskIsValid(void *zb_task);
uint8_t zbTaskStatus(void *zb_task);
void zbStartMainTask(void) ZB_NORETURN;
void zbStartOnlyTask(void) ZB_NORETURN;
void zbTaskStart(void (*zb_task)(void), void *zb_taskStack, uint16_t zb_stackSize, uint16_t zb_parmBytes, ...);
uint16_t zbTaskByteParm(uint8_t zb_parm);
uint16_t zbTaskWordParm(uint16_t zb_parm);
uint16_t zbTaskRefParm(void *zb_parm);
uint32_t zbTaskDwordParm(uint32_t zb_parm);
uint32_t zbTaskFloatParm(float zb_parm);
uint32_t zbTaskStringParm(zbString_t pzb_arm);
void zbSetInterval(uint16_t zb_ticks);
uint8_t zbWaitInterval(uint8_t zb_mode);
uint8_t zbWaitForInterrupt(uint8_t zb_mode, uint8_t zb_intNum);
uint8_t zbWaitForInterruptEx(uint16_t zb_mode, uint8_t zb_intNum);
void zbYield(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: zx.h rev 584
//---------------------------------------------------------------------------
#define ZB_OUTPUT_LOW					0
#define ZB_OUTPUT_HIGH					1
#define ZB_INPUT_TRISTATE				2
#define ZB_INPUT_PULLUP					3
#define ZB_TOGGLE_OUTPUT				4
#define ZB_PULSE_OUTPUT					5
#define ZB_INPUT_PULLDOWN				6
#define ZB_INVERT_IO					7
#define ZB_NORMAL_IO					8

#if !defined(__ASSEMBLER__)

#define ZB_ASM_EOL						"\n\t"

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
	typedef struct
	{
		float zb_maxFreq;
		uint16_t zb_divisor;
	} zb_PWM16_timerData_t;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
		const extern uint8_t zb_pinTable[] PROGMEM;
		const extern uint16_t zb_oneWireDelays[] PROGMEM;
		const extern zb_PWM16_timerData_t zb_pwm16_timerTable[] PROGMEM;

		#define ZB_CPU_FREQ					ZB_DWORD_VAL(zb_cpuFreq)
		#define ZB_HAVE_RTC					ZB_BYTE_VAL(zb_haveRTC)
		#define ZB_RTC_FREQ					ZB_DWORD_VAL(zb_rtcFreq)
		#define ZB_RTC_SCALE_FACTOR			ZB_BYTE_VAL(zb_rtcScale)
		#define ZB_RTC_TIMER_FREQ			ZB_DWORD_VAL(zb_rtcTimerFreq)
#if defined(ZB_AVR_XMEGA)
		#define ZB_RTC_MODULUS				ZB_DWORD_VAL(zb_rtcModulus)
#else
		#define ZB_RTC_MODULUS				ZB_WORD_VAL(zb_rtcModulus)
#endif
		#define ZB_TICKS_PER_MIN			ZB_DWORD_VAL(zb_ticksPerMin)
		#define ZB_TICKS_PER_HOUR			ZB_DWORD_VAL(zb_ticksPerHour)
		#define ZB_TICKS_PER_DAY			ZB_DWORD_VAL(zb_ticksPerDay)
		#define ZB_FTICKS_PER_SEC			ZB_FLOAT_VAL(zb_rtcFreqFloat)
		#define ZB_FAST_TICKS_PER_SEC		ZB_DWORD_VAL(zb_fastTicksPerSec)
		#define ZB_FAST_TICKS_PER_DAY		ZB_DWORD_VAL(zb_fastTicksPerDay)
#endif	// !defined(__ASSEMBLER__)

#define ZB_TRUE							0xff
#define ZB_FALSE						0

#if !defined(__ASSEMBLER__)
#define ZB_BOOL(zb_b)					((zb_b) ? ZB_TRUE : ZB_FALSE)
#define ZB_INV_BOOL(zb_b)				((zb_b) ? ZB_FALSE : ZB_TRUE)

#define ZB_BIT_VAL(zb_b)				((zb_b) & 0x01)
#define ZB_NIB_VAL(zb_b)				((zb_b) & 0x0f)

// memory types for zbBlockCopy() and zbBlockCompare()
#define ZB_MEM_RAM						0
#define ZB_MEM_PERSIST					1
#define ZB_MEM_PROG						2
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)

#define ZB_MIN(zb_x,zb_y)				(((zb_x)<(zb_y))?(zb_x):(zb_y))
#define ZB_MAX(zb_x,zb_y)				(((zb_x)>(zb_y))?(zb_x):(zb_y))

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

#define ZB_LO_BYTE(zb_x)				((uint8_t)(zb_x) & 0xff)
#define ZB_HI_BYTE_W(zb_x)				((uint8_t)((zb_x) >> 8) & 0xff)
#define ZB_HI_BYTE_D(zb_x)				((uint8_t)((zb_x) >> 24) & 0xff)
#define ZB_LO_WORD(zb_x)				((uint16_t)(zb_x) & 0xffff)
#define ZB_MID_WORD(zb_d)				((uint16_t)((zb_d) >> 8) & 0xffff)
#define ZB_HI_WORD(zb_x)				((uint16_t)((zb_x) >> 16) & 0xffff)
#define ZB_MAKE_WORD(zb_l,zb_h)			(((uint16_t)(zb_l) & 0xff) | ((uint16_t)(zb_h) << 8))
#define ZB_MAKE_DWORD(zb_l,zb_h)		(((uint32_t)(zb_l) & 0xffff) | ((uint32_t)(zb_h) << 16))

#define ZB_TYPECAST(zb_t,zb_v)			(zb_t)(zb_v)
#endif	// !defined(__ASSEMBLER__)

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

// Members marked with an asterisk in the comment apply to VM devices only.
typedef struct
{
	uint8_t zb_unused1;
	uint8_t zb_firstTime;				//  indicates first execution after download
	uint8_t zb_faultCode;
	uint16_t zb_faultData;
	uint8_t zb_signOn;					//  enable initial sign-on
	uint8_t zb_progMemPgSize;			//* page size in terms of 16-byte blocks - value 4 implies 64 bytes
	uint8_t zb_progMemPgMode;			//* non-zero if full pages must be written
	uint16_t zb_progMemLen;				//  length of downloaded program
	uint16_t zb_progMemCRC;				//  CRC of downloaded program
	uint16_t zb_faultData2;
	uint16_t zb_xmemFlags;				//  external memory configuration flags
	uint8_t zb_bootPinCS;				//* chip select pin for boot load device
	uint16_t zb_bootCnt;				//  program length
	uint8_t zb_atnChar;					//  ATN escape character
	uint8_t zb_defBaud;					//* default baud rate selector
	uint8_t zb_unused2[ZB_EEP_PAD_SIZE];
} zbPersistData_t;

#endif	// !defined(__ASSEMBLER__)

// fault types
#define ZB_FAULT_NONE					0
#define ZB_FAULT_STACK					1
#define ZB_FAULT_INTERRUPT				2

#define ZB_SYS_EEPROM_ADDR				0

// offsets into the zbPersistData_t structure
#define ZB_EEP_UNUSED1_OFST				0
#define ZB_EEP_FIRST_TIME_OFST			1
#define ZB_EEP_FAULT_CODE_OFST			2
#define ZB_EEP_FAULT_DATA_OFST			3
#define ZB_EEP_SIGN_ON_OFST				5
#define ZB_EEP_PM_PAGE_SIZE_OFST		6
#define ZB_EEP_PM_PAGE_MODE_OFST		7
#define ZB_EEP_PROG_LEN_LO_OFST			8
#define ZB_EEP_PROG_LEN_HI_OFST			9
#define ZB_EEP_PROG_CRC_LO_OFST			10
#define ZB_EEP_PROG_CRC_HI_OFST			11
#define ZB_EEP_FAULT_DATA2_OFST			12
#define ZB_EEP_XMEM_FLAGS_OFST			14
#define ZB_EEP_BOOT_PIN_OFST			16
#define ZB_EEP_BOOT_CNT_OFST			17
#define ZB_EEP_ATN_CHAR_OFST			19
#define ZB_EEP_DEF_BAUD_OFST			20
#define ZB_EEP_UNUSED2_OFST				21

#define ZB_SER_NUM_SIZE						6
#define ZB_DEV_ID_MAX_LEN					10

// values for floating point numbers classification returned by zbSngClass()
#define ZB_FP_NORMAL						0x01	// +/- normalized, non-zero
#define ZB_FP_ZERO							0x02	// +/- zero
#define ZB_FP_INFINITY						0x03	// +/- infinity
#define ZB_FP_DENORMAL						0x04	// +/- denormalized
#define ZB_FP_NAN							0x05	// NaN
#define ZB_FP_NEGATIVE						0x80	// combine with others (except NaN)
#define ZB_FP_MASK							0x07	// mask to remove sign bit

#if !defined(__ASSEMBLER__)
typedef struct
{
	// N.B.: these are accessed in assembly code, see the offset definitions below
	uint8_t zb_fastTick;	//* divide-by-2 counter for producing 'tick'
	uint8_t zb_altTick;		//  same as above but resettable
	uint16_t zb_stopWatch;	//* user-resettable tick counter
	uint32_t zb_tick;		//* current tick (typically 1/512 of a second)
	uint16_t zb_day;		//* current day (01 Jan 1999 = 0)
} zbRTC_t;

typedef struct
{
	zb_RTC_OCR_t zb_timerTicks;	// low-level RTC timer ticks (typically 64/14.7456MHz sec.)
	uint32_t zb_fastTicks;		// fast RTC ticks (typically 1/1024 sec.)
} zbMicroTime_t;

#endif	// !defined(__ASSEMBLER__)

#define ZB_FAST_TICK_OFST				0
#define ZB_ALT_TICK_OFST				1
#define ZB_STOPWATCH_OFST				2
#define ZB_TICK_OFST					4
#define ZB_DAY_OFST						8
#define ZB_SIZEOF_RTC					10

#if !defined(__ASSEMBLER__)
	#define ZB_RTC_TICK					zb_rtc.zb_tick
	#define ZB_RTC_FAST_TICK			zb_rtc.zb_fastTick
#endif	// !defined(__ASSEMBLER__)

// bit definitions for zbIOFlags1
#define ZB_IOF_COM1_OPEN_BIT			0		// Com1 is open
#define ZB_IOF_COM1_TX_BUSY_BIT			1		// Com1 is busy transmitting
#define ZB_IOF_COM1_CAN_CLOSE_BIT		2		// allow Com1 to be closed
#define ZB_IOF_COM1_CLOSED_BIT			3		// Com1 has been closed
#define ZB_IOF_CONSOLE_ECHO_BIT			4		// enable console echo
#define ZB_IOF_ADC_COM1_BIT				5		// ADCToCom1 in progress
#define ZB_IOF_COM1_DAC_BIT				6		// Com1ToDAC in progress
#define ZB_IOF_COM1_ADC_DAC_DONE_BIT	7		// ADCToCom1 or Com1ToDAC completed

#define ZB_IOF_COM1_OPEN				_BV(ZB_IOF_COM1_OPEN_BIT)
#define ZB_IOF_COM1_TX_BUSY				_BV(ZB_IOF_COM1_TX_BUSY_BIT)
#define ZB_IOF_COM1_CAN_CLOSE			_BV(ZB_IOF_COM1_CAN_CLOSE_BIT)
#define ZB_IOF_COM1_CLOSED				_BV(ZB_IOF_COM1_CLOSED_BIT)
#define ZB_IOF_CONSOLE_ECHO				_BV(ZB_IOF_CONSOLE_ECHO_BIT)
#define ZB_IOF_ADC_COM1					_BV(ZB_IOF_ADC_COM1_BIT)
#define ZB_IOF_COM1_DAC					_BV(ZB_IOF_COM1_DAC_BIT)
#define ZB_IOF_COM1_ADC_DAC_DONE		_BV(ZB_IOF_COM1_ADC_DAC_DONE_BIT)

// bit definitions for zbIOFlags2
#define ZB_IOF_IO_SCALING_BIT			0		// if some I/O function timing s/b scaled
#define ZB_IOF_TX_FLOW_INHIBITED_BIT	1		// at least one HW channel is flow inhibited
#define ZB_IOF_COM2_OPEN_BIT			2		// Com2 is open
#define ZB_IOF_COM2_TX_BUSY_BIT			3		// Com2 is busy transmitting
#define ZB_IOF_COM7_OPEN_BIT			4		// Com7 is open
#define ZB_IOF_COM7_TX_BUSY_BIT			5		// Com7 is busy transmitting
#define ZB_IOF_COM8_OPEN_BIT			6		// Com8 is open
#define ZB_IOF_COM8_TX_BUSY_BIT			7		// Com8 is busy transmitting

#define ZB_IOF_IO_SCALING				_BV(ZB_IOF_IO_SCALING_BIT)
#define ZB_IOF_TX_FLOW_INHIBITED		_BV(ZB_IOF_TX_FLOW_INHIBITED_BIT)
#define ZB_IOF_COM2_OPEN				_BV(ZB_IOF_COM2_OPEN_BIT)
#define ZB_IOF_COM2_TX_BUSY				_BV(ZB_IOF_COM2_TX_BUSY_BIT)
#define ZB_IOF_COM7_OPEN				_BV(ZB_IOF_COM7_OPEN_BIT)
#define ZB_IOF_COM7_TX_BUSY				_BV(ZB_IOF_COM7_TX_BUSY_BIT)
#define ZB_IOF_COM8_OPEN				_BV(ZB_IOF_COM8_OPEN_BIT)
#define ZB_IOF_COM8_TX_BUSY				_BV(ZB_IOF_COM8_TX_BUSY_BIT)

// bit definitions for zbIOFlags3
#define ZB_IOF_COM9_OPEN_BIT			0		// Com9 is open
#define ZB_IOF_COM9_TX_BUSY_BIT			1		// Com9 is busy transmitting
#define ZB_IOF_COM10_OPEN_BIT			2		// Com10 is open
#define ZB_IOF_COM10_TX_BUSY_BIT		3		// Com10 is busy transmitting
#define ZB_IOF_COM11_OPEN_BIT			4		// Com11 is open
#define ZB_IOF_COM11_TX_BUSY_BIT		5		// Com11 is busy transmitting
#define ZB_IOF_COM12_OPEN_BIT			6		// Com12 is open
#define ZB_IOF_COM12_TX_BUSY_BIT		7		// Com12 is busy transmitting

#define ZB_IOF_COM9_OPEN				_BV(ZB_IOF_COM9_OPEN_BIT)
#define ZB_IOF_COM9_TX_BUSY				_BV(ZB_IOF_COM9_TX_BUSY_BIT)
#define ZB_IOF_COM10_OPEN				_BV(ZB_IOF_COM10_OPEN_BIT)
#define ZB_IOF_COM10_TX_BUSY			_BV(ZB_IOF_COM10_TX_BUSY_BIT)
#define ZB_IOF_COM11_OPEN				_BV(ZB_IOF_COM11_OPEN_BIT)
#define ZB_IOF_COM11_TX_BUSY			_BV(ZB_IOF_COM11_TX_BUSY_BIT)
#define ZB_IOF_COM12_OPEN				_BV(ZB_IOF_COM12_OPEN_BIT)
#define ZB_IOF_COM12_TX_BUSY			_BV(ZB_IOF_COM12_TX_BUSY_BIT)

#if !defined(__ASSEMBLER__)

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

class zbCritSect
{
public:
	zbCritSect() { m_zb_sreg = zbDsblInt(); }
	~zbCritSect() { zbRestInt(m_zb_sreg); }
private:
	zb_CPU_stat_t m_zb_sreg;
};

#define ZB_CRIT_SECT					zbCritSect cs

#endif	//  __cplusplus

#define zbBeginAtomic					{ ZB_CRIT_SECT;
#define zbEndAtomic						}

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

// non-atomic read/write
#define ZB_RD_WORD(zb_a)				({ uint16_t zb_val = *(uint16_t *)(zb_a); zb_val; })
#define ZB_WR_WORD(zb_a,zb_v)			*(uint16_t *)(zb_a) = (zb_v)

// atomic read/write
#define ZB_RD_WORD_ATOMIC(zb_a)			({ ZB_CRIT_SECT; uint16_t zb_val; { zb_val = *(uint16_t *)(zb_a); } zb_val; })
#define ZB_WR_WORD_ATOMIC(zb_a,zb_v)	{ ZB_CRIT_SECT; *(uint16_t *)(zb_a) = (zb_v); }

#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
extern volatile zbRTC_t zb_rtc;
extern zbTaskData_t *zbMainTask;
extern zbTaskData_t *zbCurTask;
extern uint8_t zbTimer0BusyFlag;
extern uint8_t zbTimer1BusyFlag;
extern uint8_t zbTimer2BusyFlag;
extern uint8_t zbTimer3BusyFlag;
extern uint8_t zbTimer4BusyFlag;
extern uint8_t zbTimer5BusyFlag;
extern uint8_t zbTimer6BusyFlag;
extern uint8_t zbTimer7BusyFlag;
extern uint8_t zbTimer8BusyFlag;
  #if defined(__AVR_XMEGA__)
extern uint8_t zbTimerBusyFlags[];
extern uint8_t zbEventBusyFlags[];
  #endif
extern uint8_t zbSysFlags1;
extern uint8_t zbSysFlags2;
extern uint8_t zbSysFlags3;
extern uint8_t zbSysFlags4;
extern uint8_t zbSysFlags5;
extern uint8_t zbIOFlags1;
extern uint8_t zbIOFlags2 ZB_NO_INIT;
extern uint8_t zbIOFlags3;
extern uint8_t zbTimerSpeed1 ZB_NO_INIT;
extern uint8_t zbTimerSpeed2 ZB_NO_INIT;
extern uint8_t zbEolChar;
extern uint32_t zbSeedPRNG ZB_NO_INIT;
extern uint8_t zbResetFlags ZB_NO_INIT;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
extern const char zbVerStr[];			// in Flash
extern const char zbSerNum[];			// in Flash
extern zbPersistData_t zbSysData;		// in EEPROM
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#define ZB_GET_MICRO_TIME(zb_p)							\
{														\
	zbMicroTime_t *zb_mtp = (zbMicroTime_t *)zb_p;		\
	uint8_t zb_tAdjust;									\
	uint32_t zb_fastTicks;								\
	zb_mtp->zb_timerTicks = ZB_RTC_TCNT;				\
	zb_tAdjust = (ZB_RTC_TIFR & _BV(ZB_RTC_OCF_BIT));	\
	if (zb_tAdjust) zb_tAdjust = 1;						\
	zb_fastTicks = ZB_RTC_TICK;							\
	if (ZB_RTC_SCALE_FACTOR == 2)						\
	{													\
		zb_fastTicks <<= 1;								\
		if (ZB_RTC_FAST_TICK & 1) zb_tAdjust++;			\
	}													\
	zb_mtp->zb_fastTicks = zb_fastTicks + zb_tAdjust;	\
}

#define ZB_SIGN_ON()									\
{														\
	ZB_ENBL_INT();										\
	zbSendPStr(PSTR("ZBasic"));							\
	zbSendPStr(zbVerStr);								\
}
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
// the number of 5-cycle loops to execute for a given number of microseconds
#define ZB_MICROSEC_TO_LOOPCNT(zb_us)			(uint16_t)((((uint32_t)(zb_us) * (F_CPU / 5000)) + 500) / 1000)

// the number of 10-cycle loops to execute for a given number of milliseconds
#define ZB_MILLISEC_TO_LOOPCNT(zb_ms)			((((uint32_t)(zb_ms) * (F_CPU / 1000)) + 5) / 10)

void zbDelayLoop1(uint16_t zb_cnt);
void zbDelayLoop2(uint32_t zb_cnt);

uint8_t zbGetByteRTC(uint8_t zb_idx);
uint16_t zbGetWordRTC(uint8_t zb_idx);
uint32_t zbGetDwordRTC(uint8_t zb_idx);
void zbPutByteRTC(uint8_t zb_data, uint8_t zb_idx);
void zbPutWordRTC(uint16_t zb_data, uint8_t zb_idx);
void zbPutDwordRTC(uint32_t zb_data, uint8_t zb_idx);
uint16_t zbSysDataWord(uint16_t zb_id);
uint32_t zbSysDataDword(uint16_t zb_id);

void zbToggleBits(uint8_t *zb_addr, uint8_t zb_mask);
void zbSetBits(uint8_t *zb_addr, uint8_t zb_mask, uint8_t zb_val);

uint8_t zbFirstTime(void);
uint16_t zbVersionInfo(void *zb_buf, uint16_t zb_len);
uint8_t zbDeviceId(void *zb_buf, uint8_t zb_len);
uint8_t zbDeviceSig(void *zb_buf, uint8_t zb_len);

void zbMemRep(void *zb_dst, const void *zb_src, uint8_t zb_len, uint16_t zb_cnt);
void zbMemCopy(void *zb_dst, const void *zb_src, uint16_t zb_cnt);
void zbMemSwap(void *zb_blk1, void *zb_blk2, uint16_t zb_len);
void zbMemMove(void *zb_dst, const void *zb_src, uint16_t zb_cnt);
int16_t zbMemCmp(const void *zb_p1, const void *zb_p2, uint16_t zb_cnt);
void zbMemSet(void *dst, uint8_t val, uint16_t cnt);
uint16_t zbMemFind(uint16_t addr, uint16_t len, uint8_t val, uint8_t ignCase);

void zbSetBit(void *zb_addr, uint16_t zb_bitOfst, uint8_t zb_val);
void zbSetNib(void *zb_addr, uint16_t zb_nibOfst, uint8_t zb_val);
uint8_t zbGetBit(void *zb_addr, uint16_t zb_bitOfst);
uint8_t zbGetNib(void *zb_addr, uint16_t zb_nibOfst);

uint8_t zbSngClass(float zb_fval);
float zbIntf(float zb_f);
float zbFracf(float zb_f);
int32_t zbFloatToLong(float zb_fval);
uint8_t zbFloatToByte(float zb_fval);

uint32_t zbPowUI(uint32_t zb_val, int32_t zb_exp);
int32_t zbPowI(int32_t zb_val, int32_t zb_exp);

void zbRndSeed(uint32_t zb_rndSeed);
int32_t zbRndI(int32_t zb_rndMax);
float zbRnd(void);
void zbRandomize(void);
float zbMinF(float zb_f1, float zb_f2);
float zbMaxF(float zb_f1, float zb_f2);
uint8_t zbMinB(uint8_t zb_d1, uint8_t zb_d2);
uint8_t zbMaxB(uint8_t zb_d1, uint8_t zb_d2);
int16_t zbMinI(int16_t zb_d1, int16_t zb_d2);
int16_t zbMaxI(int16_t zb_d1, int16_t zb_d2);
uint16_t zbMinU(uint16_t zb_d1, uint16_t zb_d2);
uint16_t zbMaxU(uint16_t zb_d1, uint16_t zb_d2);
uint32_t zbMinD(uint32_t zb_d1, uint32_t zb_d2);
uint32_t zbMaxD(uint32_t zb_d1, uint32_t zb_d2);
int32_t zbMinL(int32_t zb_d1, int32_t zb_d2);
int32_t zbMaxL(int32_t zb_d1, int32_t zb_d2);
int32_t zbSigL(int32_t zb_lval);
uint32_t zbSigD(uint32_t zb_dval);
float zbSigF(float zb_fval);
float zbFloatResult(uint8_t zb_fclass);
float zbfsqrt(float zb_fval);
float zbflog(float zb_fval);
float zbflog10(float zb_fval);
float zbfexp(float zb_fval);
float zbfexp10(float zb_fval);

// conversions for BasicX compatibility
uint8_t zbIntToByte(uint16_t zb_val);
uint8_t zbLongToByte(uint32_t zb_val);

void zbBitCopy(void *zb_dst, uint16_t zb_dstBitIdx, void *zb_src, uint16_t zb_srcBitIdx, uint16_t zb_bitCnt);
void zbBlockCopy(void *zb_dst, uint8_t zb_dtype, void *zb_src, uint8_t zb_stype, uint16_t zb_len);
int zbBlockCompare(void *zb_dst, uint8_t zb_dtype, void *zb_src, uint8_t zb_stype, uint16_t zb_len);

uint16_t zbCRC16(void *zb_data, uint16_t zb_dataLen, uint16_t zb_crcPoly, uint16_t zb_crcInit, uint8_t zb_flags);
uint32_t zbCRC32(void *zb_data, uint16_t zb_dataLen, uint32_t zb_crcPoly, uint32_t zb_crcInit, uint8_t zb_flags);

uint8_t zbParityCheck(uint8_t zb_data, uint8_t zb_oddParity);

void zbOpenWatchDog(uint8_t zb_timeout);
void zbWatchDog(void);
void zbCloseWatchDog(void);
void zbResetProc(void) ZB_NORETURN;
void zbCPUSleep(uint8_t zb_mode);

uint8_t zbSemaphore(uint8_t *zb_sem);

uint16_t zbRevWord(uint16_t zb_val);
uint8_t zbRevByte(uint8_t zb_val);

// object iteration functions
typedef void (*zbObjIteratorFunc_t)(void *);
void zbObjIterator(void *zb_obj, zbObjIteratorFunc_t zb_func, unsigned zb_cnt, unsigned zb_size);
void zbRevObjIterator(void *zb_obj, zbObjIteratorFunc_t zb_func, unsigned czb_nt, unsigned zb_size);

void zbVtblInit(void *zb_obj, const zbVirtPtr_t *zb_vtblPtr, unsigned zb_cnt, unsigned zb_size);
#endif	// !defined(__ASSEMBLER__)

// constants for zbFloatToString, et al
#define ZB_MAX_DECIMALS						6
#define ZB_DEF_PRECISION					0xff

#if !defined(__ASSEMBLER__)
void zbUpdateRTC(uint16_t zb_ticks);
void zbRunMonitor(uint8_t zb_baudIdx) ZB_NORETURN;
void zbRunMonitorEx(uint16_t zb_baudSel, uint8_t zb_usart2X) ZB_NORETURN;
void zbGetMicroTime(zbMicroTime_t *zb_t0);
uint32_t zbGetElapsedMicroTime(zbMicroTime_t *zb_t0);
uint32_t zbGetElapsedMicroTimeEx(zbMicroTime_t *zb_t0, zbMicroTime_t *zb_t1);
uint16_t zb_getBootVersion(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: waitInt.h rev 551
//---------------------------------------------------------------------------
// hardware interrupt designators
#define ZB_EXT_INT_0					0
#define ZB_EXT_INT_1					1
#define ZB_EXT_INT_2					2
#define ZB_EXT_INT_3					3
#define ZB_EXT_INT_4					4
#define ZB_EXT_INT_5					5
#define ZB_EXT_INT_6					6
#define ZB_EXT_INT_7					7


//---------------------------------------------------------------------------
// Id: queue.h rev 583
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
typedef struct
{
	uint16_t zb_cap;				// capacity of the queue
	uint16_t zb_cnt;				// bytes available in the queue
	uint16_t zb_head;				// the index to which to add bytes
	uint16_t zb_tail;				// the index from which to remove bytes
	uint8_t zb_flags;				// status flags
	char zb_queue[1];
} zbQueue_t ZB_FORCE_ALIGN;

#define ZB_QUEUE_PTR(zb_v)				(zbQueue_t *)(void *)(zb_v)

#define zbGetQueueMember(zb_qp, zb_mbr, zb_mbrType)		\
({														\
	zb_CPU_stat_t zb_flag = zbDsblInt();				\
	zb_mbrType zb_val = ((zbQueue_t *)(zb_qp))->zb_mbr;	\
	zbRestInt(zb_flag);									\
	zb_val;												\
})
#endif	// !defined(__ASSEMBLER__)

// flag bits for zbGetQueueData() and zbPutQueueData()
#define ZB_QUEUE_ALL_OR_NONE_BIT		1  // do operation only if all can be transferred
#define ZB_QUEUE_PEEK_BIT				2  // copy data only, do not remove
#define ZB_QUEUE_SRC_STR_BIT			3  // source is a zbStringOp_t (ZVM zbPutQueueData() only)

#define ZB_QUEUE_NO_FLAGS				0x00

#define ZB_QUEUE_ALL_OR_NONE			_BV(ZB_QUEUE_ALL_OR_NONE_BIT)
#define ZB_QUEUE_PEEK					_BV(ZB_QUEUE_PEEK_BIT)
#define ZB_QUEUE_SRC_STR				_BV(ZB_QUEUE_SRC_STR_BIT)

#if !defined(__ASSEMBLER__)
uint16_t zbGetQueueCnt(volatile zbQueue_t *zb_qp);
uint16_t zbGetQueueSpace(volatile zbQueue_t *zb_qp);
void zbInitQueue(volatile zbQueue_t *zb_qp, int zb_len);
void zbClearQueue(volatile zbQueue_t *zb_qp);
uint16_t zbGetQueueData(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt, uint8_t zb_flags);
uint16_t zbPutQueueData(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt, uint8_t zb_flags);
uint16_t zbGetQueueByte(volatile zbQueue_t *zb_qp);
uint16_t zbPutQueueByte(volatile zbQueue_t *zb_qp, uint8_t zb_data);
char *zbGetQueueStr(volatile zbQueue_t *zb_qp, uint16_t zb_maxLen);
zbString_t zbGetQueueString(volatile zbQueue_t *zb_qp, uint16_t zb_maxLen);
void zbPutQueueStr(volatile zbQueue_t *zb_qp, zbString_t zb_s);
uint16_t zbPutQueue(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt);
uint16_t zbGetQueue(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt);
uint16_t zbGetQueueEx(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt, uint16_t zb_timeout, uint8_t *zb_flagp);
uint16_t zbPeekQueue(volatile zbQueue_t *zb_qp, void *zb_datap, uint16_t zb_cnt);
uint16_t zbFindInQueue(volatile zbQueue_t *zb_qp, uint8_t zb_val);
uint16_t zbFindPatternInQueue(volatile zbQueue_t *zb_qp, uint8_t *zb_pattern, uint16_t zb_len);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: bootldr.h rev 574
//---------------------------------------------------------------------------
// baud rate selector values for ZXCmdMode() et al
#define ZB_BAUD_IDX_NO_CHG			0
#define ZB_BAUD_IDX_1200			1
#define ZB_BAUD_IDX_2400			2
#define ZB_BAUD_IDX_4800			3
#define ZB_BAUD_IDX_9600			4
#define ZB_BAUD_IDX_19200			5
#define ZB_BAUD_IDX_38400			6
#define ZB_BAUD_IDX_57600			7
#define ZB_BAUD_IDX_115200			8
#define ZB_BAUD_IDX_230400			9


//---------------------------------------------------------------------------
// Id: x10.h rev 581
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
void zbDefineX10(uint8_t zb_chan, uint8_t zb_rxPin, uint8_t zb_txPin, uint8_t zb_flags);
void zbDefineX10Ex(uint8_t zb_chan, uint8_t zb_rxPin, uint8_t zb_txPin, uint8_t zb_flags, uint8_t zb_agcResetPin, uint8_t zb_agcWindowPin);
void zbOpenX10(uint8_t zb_chan, zbQueue_t *zb_iq, zbQueue_t *zb_oq);
uint8_t zbStatusX10(uint8_t zb_chan);
void zbCloseX10(uint8_t zb_chan, zbQueue_t *zb_iq, zbQueue_t *zb_oq);
void zbResetX10(uint8_t zb_chan, uint8_t zb_mask);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: iofunc.h rev 582
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
typedef struct
{
	uint8_t zb_dirBits;		// data direction bits
	uint8_t zb_portBits;	// port value bits
	uint8_t zb_puBits;		// pullup bits
	uint8_t zb_pdBits;		// pulldown bits
	uint8_t zb_invBits;		// inverted I/O bits
} zbPortConfigData_t;
#endif	// !defined(__ASSEMBLER__)

#define ZB_I2C_SLAVE_FLAG					0x80

#if !defined(__ASSEMBLER__)
// general I/O functions
uint8_t zbGetPin(uint8_t zb_pin);
void zbPutPin(uint8_t zb_pin, uint8_t zb_val);
uint8_t zbShiftIn(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt);
uint16_t zbShiftInEx(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt, uint8_t zb_flags, uint16_t zb_bitTime);
uint8_t zbShiftInI2C(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt, uint8_t zb_flags, uint16_t zb_bitTime);
void zbShiftOut(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt, uint8_t zb_val);
void zbShiftOutEx(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt, uint8_t zb_flags, uint16_t zb_bitTime, uint16_t zb_val);
uint8_t zbShiftOutI2C(uint8_t zb_dpin, uint8_t zb_cpin, uint8_t zb_cnt, uint8_t zb_flags, uint16_t zb_bitTime, uint8_t zb_val);
void zbDefineSPI(uint8_t zb_sck, uint8_t zb_mosi, uint8_t zb_miso);
uint8_t zbSendRecvSPI(uint8_t zb_val, uint8_t zb_spiFlags);
void zbFreqOut(uint8_t zb_pin, uint16_t zb_freqA, uint16_t zb_freqB, uint16_t zb_duration);
uint16_t zbRCTime(uint8_t zb_pin, uint8_t zb_startLevel);
uint16_t zbPulseIn(uint8_t zb_pin, uint8_t zb_highPulse);
void zbPulseOut(uint8_t zb_pin, uint8_t zb_highPulse, uint16_t zb_duration);
int32_t zbCountTrans(uint8_t zb_pin, int32_t zb_ticks);
void zbPlaySound(uint8_t zb_pin, void *zb_dataAddr, uint16_t zb_len, uint16_t zb_rate, uint16_t zb_repeat);
void zbX10Cmd(uint8_t zb_pinData, uint8_t zb_pin60Hz, uint8_t zb_houseCode, uint8_t zb_keyCode, uint8_t zb_rptCnt, uint8_t zb_flags);
void zbCalibrateADC(void);
uint16_t zbGetADC(uint8_t zb_pin, uint8_t zb_wait);
uint16_t zbGetADC_byIdx(uint8_t zb_pin, uint8_t zb_wait, uint8_t zb_refSel);
void zbADCtoCom1(uint8_t zb_pin, int16_t zb_rate);
void zbCom1ToDAC(uint8_t zb_pin);

// Input/output capture
void zbInputCapture(uint8_t zb_pin, uint16_t *zb_array, uint16_t zb_len, uint8_t zb_flags, uint16_t zb_timeoutCount);
void zbOutputCapture(uint8_t zb_pin, uint16_t *zb_array, uint16_t zb_len, uint8_t zb_flags, uint16_t zb_rptCnt);

// Bus Op functions
void zbDefineBus(uint8_t zb_port, uint8_t zb_alePin, uint8_t zb_rdPin, uint8_t zb_wrPin);
void zbReadBus(uint16_t zb_addr, void *zb_data, uint16_t zb_count, uint8_t zb_delta);
void zbWriteBus(uint16_t azb_ddr, void *zb_data, uint8_t zb_count, uint8_t zb_delta);

// 1-Wire function
uint8_t zbReset1Wire(uint8_t zb_pin);
uint8_t zbGet1WireByte(uint8_t zb_pin);
uint8_t zbGet1WireBit(uint8_t zb_pin);
void zbGet1WireData(uint8_t zb_pin, void *zb_data, uint8_t zb_cnt);
void zbPut1WireBit(uint8_t zb_pin, uint8_t zb_data);
void zbPut1WireByte(uint8_t zb_pin, uint8_t zb_data);
void zbPut1WireData(uint8_t zb_pin, void *zb_data, uint8_t zb_cnt);

// SPI functions
#if defined(ZB_AVR_XMEGA)
	typedef uint16_t zbSPI_flags_t;
#else
	typedef uint8_t zbSPI_flags_t;
#endif
void zbOpenSPI(uint8_t zb_chan, zbSPI_flags_t zb_flags, uint8_t zb_pin);
void zbOpenSPIEx(uint8_t zb_chan, zbSPI_flags_t zb_flags, uint8_t zb_pin, uint8_t zb_rxDelay);
void zbOpenSPISlave(zbSPI_flags_t zb_flags);
void zbCmdSPI(uint8_t zb_chan, uint16_t zb_outCnt, void *zb_outBuf, uint16_t zb_inCnt, void *zb_inBuf);
void zbStartSPI(uint8_t zb_chan, uint8_t zb_opFlags);
void zbStopSPI(uint8_t zb_chan, uint8_t zb_opFlags);
uint8_t zbPutByteSPI(uint8_t zb_chan, uint8_t zb_data);
uint16_t zbPutDataSPI(uint8_t zb_chan, uint16_t zb_cnt, void *zb_buf);
uint8_t zbGetByteSPI(uint8_t zb_chan, uint8_t zb_data);
uint16_t zbGetDataSPI(uint8_t zb_chan, uint16_t zb_cnt, void *zb_buf, uint8_t zb_data);
void zbCloseSPI(uint8_t zb_chan);

// I2C functions
void zbOpenI2C(uint8_t zb_chan, uint8_t szb_daPin, uint8_t zb_sclPin, uint16_t zb_bitTime);
void zbStartI2C(uint8_t zb_chan);
uint8_t zbSendI2C(uint8_t zb_chan, uint8_t zb_value);
uint8_t zbRecvI2C(uint8_t zb_chan, uint8_t zb_ack);
int zbCmdI2C(uint8_t zb_chan, uint8_t zb_slaveID, uint16_t zb_outCnt, void *zb_outBuf, uint16_t zb_inCnt, void *zb_inBuf);
void zbStopI2C(uint8_t zb_chan);
void zbCloseI2C(uint8_t zb_chan);
void zbOpenI2CSlave(uint8_t zb_slaveAddr);
void zbOpenI2CSlaveEx(uint8_t zb_slaveAddr, uint8_t zb_chan);

// PWM functions
uint8_t zbOpenPWM(uint8_t zb_chan, float zb_freq, uint8_t zb_mode);
uint8_t zbStartPWM(uint8_t zb_chan, uint16_t duty);
uint8_t zbClosePWM(uint8_t zb_chan);
uint8_t zbOpenPWM8(uint8_t zb_chan, float zb_freq, uint8_t zb_mode);
uint8_t zbStartPWM8(uint8_t zb_chan, uint16_t zb_duty);
uint8_t zbClosePWM8(uint8_t zb_chan);

// DAC functions
void zbCalibrateDAC(void);
uint8_t zbOpenDAC(uint8_t zb_chan, uint16_t zb_mode);
uint8_t zbSetDAC(uint8_t zb_chan, uint16_t zb_val);
uint8_t zbCloseDAC(uint8_t zb_chan);
uint8_t zbPinDAC(uint8_t zb_acc, uint8_t zb_dacVal, uint8_t zb_pin, uint8_t zb_repCnt);
uint8_t zbPinDACEx(uint8_t *zb_acc, uint8_t dacVal, uint8_t zb_pin, uint8_t zb_repCnt);
void zbPutDAC(uint8_t zb_pin, uint8_t zb_dacVal, uint8_t *zb_acc, uint8_t zb_cycles);

// pin I/O helpers
uint8_t zbGetPortBit(uint8_t zb_pin);
uint8_t zbGetPortMask(uint8_t zb_pin);
uint16_t zbGetPortBitInfo(uint8_t zb_pin);
uint16_t zbGetPortPinInfo(uint8_t zb_pin);
uint32_t zbGetPortPinInfoEx(uint8_t zb_pin);
uint32_t zbGetPortPinData(uint8_t zb_pin);
uint8_t *zbGetPortAddress(uint8_t zb_pin, uint8_t zb_idx);
uint8_t zbChanADC(uint8_t zb_pin);

void zbPortConfig(uint8_t zb_portIdx, uint8_t zb_ddrBits, uint8_t zb_portBits);
void zbPortConfigEx(uint8_t zb_portIdx, zbPortConfigData_t zb_pcd);

#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: serial.h rev 582
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)

// flag indicating direct specification of baud divisor
#define ZB_BAUD_DIV_DIRECT						0x80000000UL

// formulae for determining the UART UBRR value
#if defined(__AVR__)
	#define ZB_AVR_BAUD_FACTOR_SIMPLE(zb_f, zb_s)	((((zb_f) / (zb_s)) / 16) - 1)
	#define ZB_AVR_BAUD_FACTOR_2X_SIMPLE(zb_f, zb_s)((((zb_f) / (zb_s)) / 8) - 1)
	#define ZB_AVR_BAUD_FACTOR(zb_f, zb_s)			(((((zb_f) / (zb_s)) + 8) / 16) - 1)
	#define ZB_AVR_BAUD_FACTOR_2X(zb_f, zb_s)		(((((zb_f) / (zb_s)) + 4) / 8) - 1)
	#if defined(ZB_AVR_XMEGA)
		#define ZB_AVR_UBRR_2X_TO_1X(zb_u)			(((zb_u)&0xf000)?0:((((zb_u) + 1) / 2) - 1))
	#else
		#define ZB_AVR_UBRR_2X_TO_1X(zb_u)			((((zb_u) + 1) / 2) - 1)
	#endif
#elif defined(__arm__)
	#define ZB_ARM_BAUD_DIVISOR(zb_f, zb_s)			((((zb_f) / (zb_s)) + 8) / 16)
#endif
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
	typedef struct
	{
		uint16_t zb_baud;				// the baud rate
		zb_SW_UART_OCR_t zb_ocrVal;		// the corresponding timer OCR value
	} zbSW_UART_BaudTable_t;
	const extern zbSW_UART_BaudTable_t zb_swUartBaudTable[] PROGMEM;

	typedef struct
	{
		uint32_t zb_baud;				// the baud rate
		uint16_t zb_ubrr;				// the corresponding UBRR value
	} zbBaudRateSelect_t;
	const extern zbBaudRateSelect_t zb_uartBaudTable[] PROGMEM;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
uint16_t zbBaudDivisor(uint32_t zb_speed);
int zbGetComChanIdx(uint8_t zb_chan);
void zbSetComParm(uint8_t zb_cnt, uint16_t zb_maxSpeed);
void zbInitComN(uint8_t zb_chan, uint16_t zb_baudDiv, zbQueue_t *zb_iq, zbQueue_t *zb_oq);

void zbDefineCom(uint8_t zb_chan, uint8_t zb_rxPin, uint8_t zb_txPin, uint8_t zb_flags, uint8_t zb_stopBits);
void zbOpenCom(uint8_t zb_chan, uint32_t zb_speed, zbQueue_t *zb_iq, zbQueue_t *zb_oq);
uint8_t zbStatusCom(uint8_t zb_chan);
void zbCtrlCom(uint8_t zb_chan, uint8_t zb_rxCtrlPin, uint8_t zb_txCtrlPin, uint8_t zb_ctrlFlags);
void zbCloseCom(uint8_t zb_chan, zbQueue_t *zb_iq, zbQueue_t *zb_oq);

void zbDefineComHW(uint8_t zb_chan, uint8_t zb_flags, uint8_t zb_stopBits);
void zbOpenComHW(uint8_t zb_chan, uint32_t zb_speed, zbQueue_t *zb_iq, zbQueue_t *ozb_q);
uint8_t zbStatusComHW(uint8_t zb_chan);
void zbCtrlComHW(uint8_t zb_chan, uint8_t zb_rxCtrlPin, uint8_t zb_txCtrlPin, uint8_t zb_ctrlFlags);
void zbCloseComHW(uint8_t zb_chan, zbQueue_t *zb_iq, zbQueue_t *zb_oq);

void zbDefineComSW(uint8_t zb_chan, uint8_t zb_rxPin, uint8_t zb_txPin, uint8_t zb_flags, uint8_t zb_stopBits);
void zbOpenComSW(uint8_t zb_chan, uint32_t zb_speed, zbQueue_t *zb_iq, zbQueue_t *zb_oq);
uint8_t zbStatusComSW(uint8_t zb_chan);
void zbCtrlComSW(uint8_t zb_chan, uint8_t zb_rxCtrlPin, uint8_t zb_txCtrlPin, uint8_t zb_ctrlFlags);
void zbCloseComSW(uint8_t zb_chan, zbQueue_t *zb_iq, zbQueue_t *zb_oq);

void zbSendCRLF(void);
void zbSendStr(const char *zb_s);
void zbSendString(zbString_t zb_s);
void zbSendStrN(const char *zb_str, uint16_t zb_len);
void zbSendPStr(const char *zb_str);
void zbSendPStrN(const char *zb_str, uint16_t zb_len);
void zbSendBoolVal(uint8_t zb_val);
void zbSendByteVal(uint8_t zb_val);
void zbSendWordVal(int16_t zb_val, uint8_t zb_isSigned);
void zbSendDwordVal(int32_t zb_val, uint8_t zb_isSigned);
void zbSendFloatVal(float zb_val, uint8_t zb_fracDigits);
void zbSendFloatValDef(float zb_val);
void zbSerOut(uint8_t zb_c, uint8_t zb_pin, uint16_t zb_baud);
void zbSerOutStr(zbString_t zb_s, uint8_t zb_pin, uint16_t zb_baud);
uint8_t zbSerIn(uint8_t zb_pin, uint16_t zb_baud);

int16_t zbGetChar(void);
zbString_t zbGetLine(void);
void zbSendByte(uint8_t zb_c) ZB_NAKED;

void zbSendNibbleHex(uint8_t zb_n);
void zbSendByteHex(uint8_t zb_b);
void zbSendWordHex(uint16_t zb_w);
void zbSendDwordHex(uint32_t zb_d);
void zbSendFloatHex(float zb_f);

zbQueue_t *zbRxQPtr(void);
zbQueue_t *zbTxQPtr(void);
zbQueue_t *zbGetQPtr(uint8_t zb_chan, uint8_t zb_txQ);
void zbSetComSpeed(uint8_t zb_chan, uint32_t zb_baud);

// zbSendByte is ultimately mapped to one of these
void zbSendByteHW(uint8_t zb_c);
void zbSendByteSW(uint8_t zb_c);
void zbSendBytePin(uint8_t zb_c);

// zbGetChar is ultimately mapped to one of these
int16_t zbGetCharSW(void);
int16_t zbGetCharHW(void);

// zbBaudDivisor is ultimately mapped to one of these
uint16_t zbBaudDivSimple(uint32_t zb_speed);
uint16_t zbBaudDivComplex(uint32_t zb_speed);
uint16_t zbBaudDivTable(uint32_t zb_speed);
uint16_t zbBaudDivDirect(uint32_t zb_speed);
uint16_t zbBaudDivNull(uint32_t zb_speed);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: uart.h rev 582
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
typedef struct								ZB_START(zb_UART_Data_t)
{
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
} zb_UART_Data_t;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
	extern volatile zb_UART_Data_t zbUartData;
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
// ultimately zb_UartData maps to one of these
extern volatile zb_UART_Data_t zbUartData1;
extern volatile zb_UART_Data_t zbUartData2;
extern volatile zb_UART_Data_t zbUartData3;
extern volatile zb_UART_Data_t zbUartData4;
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: heap.h rev 581
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
extern volatile void *zbHeapEnd;
extern volatile void *zbHeapLimit;
extern volatile uint16_t zbFreeList;

void *zbMemAlloc(uint16_t zb_len);
void zbMemFree(void *zb_ptr);
void *zbMemRealloc(void *zb_ptr, uint16_t zb_len);
void *zbMemCalloc(uint16_t zb_elemSize, uint16_t zb_elemCnt);
void *zbMemHeapInit(void *zb_heapEnd);
uint16_t zbHeapHeadRoom(void);
uint16_t zbHeapSize(void);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: persist.h rev 581
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
uint8_t zbPersistReadByte(const void *zb_addr);
uint16_t zbPersistReadWord(const void *zb_addr);
uint32_t zbPersistReadDword(const void *zb_addr);
double zbPersistReadFloat(const void *zb_addr);
zbString_t zbPersistReadString(const void *zb_addr);
void zbPersistRead(const void *zb_addr, void *zb_buf, uint16_t zb_cnt);

void zbPersistWriteByte(void *zb_addr, uint8_t zb_val);
void zbPersistWriteWord(void *zb_addr, uint16_t zb_val);
void zbPersistWriteDword(void *zb_addr, uint32_t zb_val);
void zbPersistWriteFloat(void *zb_addr, double zb_val);
void zbPersistWriteString(void *zb_addr, zbString_t zb_s);
void zbPersistWrite(void *zb_addr, void *zb_buf, uint16_t zb_cnt);
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: progmem.h rev 581
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
#define ZB_PROG_MEM(zb_a)				(zbProgMemAddr_t)(uint16_t)(zb_a)
#define ZB_PROG_MEM_ADDR(zb_a)			(zbProgMemAddr_t)zbFlashAddr(zb_a)

uint8_t zbProgMemReadByte(zbProgMemAddr_t zb_addr);
uint16_t zbProgMemReadWord(zbProgMemAddr_t zb_addr);
uint32_t zbProgMemReadDword(zbProgMemAddr_t zb_addr);
double zbProgMemReadFloat(zbProgMemAddr_t zb_addr);
zbString_t zbProgMemReadString(zbProgMemAddr_t zb_addr);
void zbProgMemRead(zbProgMemAddr_t zb_addr, void *zb_buf, uint16_t zb_cnt);

void zbProgMemWriteByte(zbProgMemAddr_t zb_addr, uint8_t zb_val);
void zbProgMemWriteWord(zbProgMemAddr_t zb_addr, uint16_t zb_val);
void zbProgMemWriteDword(zbProgMemAddr_t zb_addr, uint32_t zb_val);
void zbProgMemWriteFloat(zbProgMemAddr_t zb_addr, double zb_val);
void zbProgMemWriteString(zbProgMemAddr_t zb_addr, zbString_t zb_s);
uint16_t zbProgMemWrite(zbProgMemAddr_t zb_addr, void *buf, uint16_t zb_cnt);

zbString_t zbProgMemReadStringTbl(zbProgMemAddr_t zb_addr);
uint16_t zbProgMemFind(zbProgMemAddr_t zb_addr, uint16_t zb_len, uint8_t zb_val, uint8_t zb_ignCase);
#endif	// !defined(__ASSEMBLER__)

#if !defined(__ASSEMBLER__)
#if defined(ZB_BIG_FLASH)
#define zbGetProgMemByte(a)				zbProgMemReadByte((zbProgMemAddr_t)(uint16_t)(a))
#elif defined(__AVR__)
#define zbGetProgMemByte(zb_addr)				\
({												\
	uint8_t zb_res;								\
	__asm__										\
	(											\
		"lpm %0, %a1"			"\n\t"			\
		: "=r" (zb_res)							\
		: "z" ((uint16_t)(zb_addr))				\
	);											\
	zb_res;										\
})
#endif
#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------
// Id: datefunc.h rev 581
//---------------------------------------------------------------------------
#if !defined(__ASSEMBLER__)
// determine the day of the week (Sun=1, Sat=7) for a date
uint8_t zbGetDayOfWeek(uint16_t zb_dayNum);

uint16_t zbGetDayOfYear(uint16_t zb_dayNum, uint16_t *zb_yearp);

uint16_t zbGetDayNumber(uint16_t zb_day, uint16_t zb_year);

// decompose a day number into year, month and day components
void zbGetDate(uint16_t *zb_yearp, uint8_t *zb_monthp, uint8_t *zb_dayp, uint16_t zb_dayNum);
uint16_t zbGetDateVal(uint16_t zb_dayNum);

// decompose an RTC tick value into hour, minute and second components
void zbGetTime(uint8_t *zb_hourp, uint8_t *zb_minp, float *zb_secp, uint32_t zb_tick);
uint32_t zbGetTimeVal(uint32_t zb_tick);

void zbSetDate(uint16_t zb_year, uint8_t zb_month, uint8_t zb_day);

void zbSetTime(uint8_t zb_hourp, uint8_t zb_minp, float zb_secp);

void zbSetTimestamp(uint16_t zb_year, uint8_t zb_month, uint8_t zb_day, uint8_t zb_hour, uint8_t zb_minute, float zb_second);

void zbGetTimestamp(uint16_t *zb_year, uint8_t *zb_month, uint8_t *zb_day, uint8_t *zb_hour, uint8_t *zb_minute, float *zb_second);

float zbGetTimer(void);

// convert a date to day number
uint32_t zbDateEncode(uint16_t zb_year, uint8_t zb_month, uint8_t zb_day);

#endif	// !defined(__ASSEMBLER__)


//---------------------------------------------------------------------------

#if defined(__cplusplus)
}
#endif

#endif	// __ZBASIC_H__
