noexpand
;file dynlib.src

;file project_template.src
;
;*****************************************************************************************
; Test/template program for sxvplib.inc
;                   
; Filename:	project_template.src
;
; Author:	Peter Verkaik
;		peterverkaik@boselectro.nl
;
; Revision:	1.0 beta/development
;
; Last Revised: July 25,2005
;
; Program Description:
;
; Revision History:
;	1.0 initial release
;*****************************************************************************************
; TARGET SX
; Uncomment one of the following lines to choose the SX18/SX20, SX28, SX48/52
;*****************************************************************************************
;DEV_18
DEV_28
;DEV_48

;*****************************************************************************************
; PROGRAM DEFINES
;*****************************************************************************************
ifdef DEV_18
device		SX18,oschs1,turbo,stackx,optionx	;sx device options
irc_cal		IRC_SLOW
endif

ifdef DEV_28
device		SX28,oschs1,turbo,stackx,optionx	;sx device options
irc_cal		IRC_SLOW
endif

ifdef DEV_48
device		SX48,oschs1				;sx device options
irc_cal		IRC_SLOW
endif

id		'sxvptest'				;sxvplib test program
reset		reset_entry				;set reset vector
freq		50_000_000				;cpu frequency

cpufreq		equ	50_000_000			;set to freq (for use in calculations)
maxvp		equ	6				;set max number of virtual peripherals (1-16)
maxbaud		equ	57600				;max baudrate for uarts
							;1200,2400,3600,4800,7200,9600,14400,19200,28800,33600
							;38400,57600,76800,115200,153600,230400,307200,460800
THREADS		equ	4				;define number of threads (1-16) in interrupt routine

;*****************************************************************************************
; Threads (1-16 threads supported)
;*****************************************************************************************
;
; Threads   VP ratios (1/n = once per n isr cycles)   Recommended
;     1     1/1                                           yes
;     2     1/1, 1/2                                      yes
;     3     1/1, 1/3                                      yes
;     4     1/1, 1,2, 1/4                                 yes
;     5     1/1, 1/5                                      no
;     6     1/1, 1/2, 1/3, 1/6                            yes
;     7     1/1, 1/7                                      no
;     8     1/1, 1/2, 1/4, 1/8                            yes
;     9     1/1, 1/3, 1/9                                 no
;    10     1/1, 1/2, 1/5, 1/10                           no
;    11     1/1, 1/11                                     no
;    12     1/1, 1/2, 1/3, 1/4, 1/6, 1/12                 yes
;    13     1/1, 1/13                                     no
;    14     1/1, 1/2, 1/7, 1/14                           no
;    15     1/1, 1/3, 1/5, 1/15                           no
;    16     1/1, 1/2, 1/4, 1/8, 1/16                      yes
;
; For example, if THREADS = 6 and ratio = 3
; the following thread values can be used in VP declarations
; %0000000000100100
; %0000000000010010
; %0000000000001001
; For ratio = 1 use %0000000000000000

;*****************************************************************************************
; Macros
;*****************************************************************************************

;file lib_constants.inc

;*****************************************************************************************
; Data Locations
;*****************************************************************************************
ifdef DEV_48
global_org	=	$0A
bank0_org	=	$00
bank1_org	=	$10
bank2_org	=	$20
bank3_org	=	$30
bank4_org	=	$40
bank5_org	=	$50
bank6_org	=	$60
bank7_org	=	$70
bank8_org	=	$80
bank9_org	=	$90
bank10_org	=	$A0
bank11_org	=	$B0
bank12_org	=	$C0
bank13_org	=	$D0
bank14_org	=	$E0
bank15_org	=	$F0
else
global_org	=	$08
bank0_org	=	$10
bank1_org	=	$30
bank2_org	=	$50
bank3_org	=	$70
bank4_org	=	$90
bank5_org	=	$B0
bank6_org	=	$D0
bank7_org	=	$F0
endif

;*****************************************************************************************
; Code Locations
;*****************************************************************************************
page0_org	equ	$0
page1_org	equ	$200
page2_org	equ	$400
page3_org	equ	$600
ifdef DEV_48
page4_org	equ	$800
page5_org	equ	$A00
page6_org	equ	$C00
page7_org	equ	$E00
endif

code_page0_low	=	$0
code_page0_high	=	$200
code_page1_low	=	$200
code_page1_high	=	$400
code_page2_low	=	$400
code_page2_high	=	$600
code_page3_low	=	$600
ifdef DEV_48
code_page3_high	=	$800
else
code_page3_high	=	$7FF
endif
ifdef DEV_48
code_page4_low	=	$800
code_page4_high	=	$A00
code_page5_low	=	$A00
code_page5_high	=	$C00
code_page6_low	=	$C00
code_page6_high	=	$E00
code_page7_low	=	$E00
code_page7_high	=	$FFF
endif

;*****************************************************************************************
; Port pins
;*****************************************************************************************
NO_PIN		equ	0x00

PORTPIN_RA0	equ	0xA0
PORTPIN_RA1	equ	0xA1
PORTPIN_RA2	equ	0xA2
PORTPIN_RA3	equ	0xA3
PORTPIN_RA4	equ	0xA4
PORTPIN_RA5	equ	0xA5
PORTPIN_RA6	equ	0xA6
PORTPIN_RA7	equ	0xA7

PORTPIN_RB0	equ	0xB0
PORTPIN_RB1	equ	0xB1
PORTPIN_RB2	equ	0xB2
PORTPIN_RB3	equ	0xB3
PORTPIN_RB4	equ	0xB4
PORTPIN_RB5	equ	0xB5
PORTPIN_RB6	equ	0xB6
PORTPIN_RB7	equ	0xB7

ifndef DEV_18
PORTPIN_RC0	equ	0xC0
PORTPIN_RC1	equ	0xC1
PORTPIN_RC2	equ	0xC2
PORTPIN_RC3	equ	0xC3
PORTPIN_RC4	equ	0xC4
PORTPIN_RC5	equ	0xC5
PORTPIN_RC6	equ	0xC6
PORTPIN_RC7	equ	0xC7
endif

ifdef DEV_48
PORTPIN_RD0	equ	0xD0
PORTPIN_RD1	equ	0xD1
PORTPIN_RD2	equ	0xD2
PORTPIN_RD3	equ	0xD3
PORTPIN_RD4	equ	0xD4
PORTPIN_RD5	equ	0xD5
PORTPIN_RD6	equ	0xD6
PORTPIN_RD7	equ	0xD7

PORTPIN_RE0	equ	0xE0
PORTPIN_RE1	equ	0xE1
PORTPIN_RE2	equ	0xE2
PORTPIN_RE3	equ	0xE3
PORTPIN_RE4	equ	0xE4
PORTPIN_RE5	equ	0xE5
PORTPIN_RE6	equ	0xE6
PORTPIN_RE7	equ	0xE7
endif

;*****************************************************************************************
; Power up register values
;*****************************************************************************************

RA_tris_PU	equ	%11111111	;port A direction register 1=input 0=output
RA_plp_PU	equ	%11111111	;port A pull up register 1=off 0=on
RA_lvl_PU	equ	%11111111	;port A level register 1=ttl 0=cmos

RB_tris_PU	equ	%11111111	;port B direction register 1=input 0=output
RB_plp_PU	equ	%11111111	;port B pull up register 1=off 0=on
RB_lvl_PU	equ	%11111111	;port B level register 1=ttl 0=cmos
RB_st_PU	equ	%11111111	;port B schmitt trigger register 1=off 0=on
RB_wken_PU	equ	%11111111	;port B wake up enable register 1=off 0=on
RB_wked_PU	equ	%11111111	;port B wake up edge register 1=neg 0=pos
RB_wkpnd_PU	equ	%11111111	;port B MIWI pending register 1=detected 0=not detected
RB_cmp_PU	equ	%11111111	;port B comparator enable register 1=disabled 0=enabled

RC_tris_PU	equ	%11111111	;port C direction register 1=input 0=output
RC_plp_PU	equ	%11111111	;port C pull up register 1=off 0=on
RC_lvl_PU	equ	%11111111	;port C level register 1=ttl 0=cmos
RC_st_PU	equ	%11111111	;port C schmitt trigger register 1=off 0=on

RD_tris_PU	equ	%11111111	;port D direction register 1=input 0=output
RD_plp_PU	equ	%11111111	;port D pull up register 1=off 0=on
RD_lvl_PU	equ	%11111111	;port D level register 1=ttl 0=cmos
RD_st_PU	equ	%11111111	;port D schmitt trigger register 1=off 0=on

RE_tris_PU	equ	%11111111	;port E direction register 1=input 0=output
RE_plp_PU	equ	%11111111	;port E pull up register 1=off 0=on
RE_lvl_PU	equ	%11111111	;port E level register 1=ttl 0=cmos
RE_st_PU	equ	%11111111	;port E schmitt trigger register 1=off 0=on

lib_threadcount	equ	$F0		;thread counter
lib_rbint	equ	$F1		;rb interrupt flags
lib_systimerL	equ	$F2		;16bit free running timer
lib_systimerH	equ	$F3

portA_dirbuf	equ	$FA		;copy of port A direction register
portB_dirbuf	equ	$FB		;copy of port B direction register
portC_dirbuf	equ	$FC		;copy of port C direction register
portD_dirbuf	equ	$FD		;copy of port D direction register
portE_dirbuf	equ	$FE		;copy of port E direction register

;*****************************************************************************************
; Mode register values
;*****************************************************************************************
M_CMP			equ	$08
M_WKPND			equ	$09
M_WKED			equ	$0A
M_WKEN			equ	$0B
M_ST			equ	$0C
M_LVL			equ	$0D
M_PLP			equ	$0E
M_TRIS			equ	$0F

;*****************************************************************************************
; Option register values
;*****************************************************************************************
RTCC_ON			equ	%10000000	;Enables RTCC at address $01 (RTW hi)
						;*WREG at address $01 (RTW lo) by default
RTCC_ID			equ	%01000000	;Disables RTCC edge interrupt (RTE_IE hi)
						;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT		equ	%00100000	;Sets RTCC increment on RTCC pin transition (RTS hi)
						;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE			equ	%00010000	;Sets RTCC to increment on falling edge (RTE_ES hi)
						;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON		equ	%00000000	;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF		equ	%00001000	;Assigns prescaler to WDT (PSA hi)
RTCC_PS_000		equ	%00000000	;RTCC = 1:2, WDT = 1:1
RTCC_PS_001		equ	%00000001	;RTCC = 1:4, WDT = 1:2
RTCC_PS_010		equ	%00000010	;RTCC = 1:8, WDT = 1:4
RTCC_PS_011		equ	%00000011	;RTCC = 1:16, WDT = 1:8
RTCC_PS_100		equ	%00000100	;RTCC = 1:32, WDT = 1:16
RTCC_PS_101		equ	%00000101	;RTCC = 1:64, WDT = 1:32
RTCC_PS_110		equ	%00000110	;RTCC = 1:128, WDT = 1:64
RTCC_PS_111		equ	%00000111	;RTCC = 1:256, WDT = 1:128

;-----------------------------------------------------------------------------------------

			; secret instruction fifo
fifo			macro
			dw	$47
endm

			; secret instruction pushW
pushW			macro
			dw	$48
endm

			; secret instruction pushST
pushST			macro
			dw	$49
endm

			; secret instruction pushFSR
pushFSR			macro
			dw	$4A
endm

			; secret instruction pushPC
pushPC			macro
			dw	$4B
endm

			; secret instruction popW
popW			macro
			dw	$4C
endm

			; secret instruction popST
popST			macro
			dw	$4D
endm

			; secret instruction popFSR
popFSR			macro
			dw	$4E
endm

			; secret instruction popPC
popPC			macro
			dw	$4F
endm


	;*********************************************************************************
	; Macro: _bank
	; Sets the bank appropriately for all revisions of SX.
	;
	; This is required since the bank instruction has only a 3-bit operand, it cannot
	; be used to access all 16 banks of the SX48/52. For this reason FSR.4 (for SX48/52BD/ES)
	; or FSR.7 (SX48/52bd production release) needs to be set appropriately, depending
	; on the bank address being accessed. This macro fixes this.
	;
	; So, instead of using the bank instruction to switch between banks, use _bank instead.
	; 
	;*********************************************************************************
_bank	macro	1
	bank	\1
	ifdef DEV48
		if \1 & %10000000		;SX48BD and SX52BD (production release) bank instruction 
			setb	fsr.7		;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by software.
		else
			clrb	fsr.7
		endif
	endif
	endm

;-----------------------------------------------------------------------------------------

;end of file lib_constants.inc
;file lib_uartCalculations.inc

;-----------------------------------------------------------------------------------------
; uart calculations (also sets int_period)
;-----------------------------------------------------------------------------------------

if maxbaud < 1200
  maxbaud = 1200
endif
;calculate uartfs
uartfs = maxbaud * 2		;2x oversampling at maxbaud
if uartfs < cpufreq / 240	;limit int_period to 240
  uartfs = cpufreq / 240
endif
expand
;Calculations are for no RTCC prescaler
noexpand
if uartfs <= 3600
expand
uartfs = 3600
noexpand
else
  if uartfs <= 7200
expand
uartfs = 7200
noexpand
  else
    if uartfs <= 14400
expand
uartfs = 14400
noexpand
    else
      if uartfs <= 28800
expand
uartfs = 28800
noexpand
      else
        if uartfs <= 57600
expand
uartfs = 57600
noexpand
        else
          if uartfs <= 115200
expand
uartfs = 115200
noexpand
          else
            if uartfs <= 230400
expand
uartfs = 230400
noexpand
            else
              if uartfs <= 460800
expand
uartfs = 460800
noexpand
              else
expand
uartfs = 921600
noexpand
              endif
            endif
          endif
        endif
      endif
    endif
  endif
endif
expand
int_period = ((2 * cpufreq / uartfs) + 1) / 2		;int_period = int(cpufreq/uartfs + 0.5)
noexpand

mscount		equ	((2*1000*cpufreq/1_000_000/int_period)+1)/2	;isr cycles for 1 msec
			;50MHz -> 230, 20MHz -> 115, 10MHz -> 57, 4MHz -> 29
uscount		equ	((2*250*cpufreq/1_000_000/int_period)+1)/2	;isr cycles for 250 usec
			;50MHz -> 58, 20MHz -> 29, 10MHz -> 14, 4MHz -> 7

;The following baudrates are available

_lib_uart_calc3	macro	baud, ratio, divide
if ratio == 1
expand
BAUD_??baud??_1 = divide
noexpand
endif
if ratio == 2
expand
BAUD_??baud??_2 = divide
noexpand
endif
if ratio == 3
expand
BAUD_??baud??_3 = divide
noexpand
endif
if ratio == 4
expand
BAUD_??baud??_4 = divide
noexpand
endif
if ratio == 5
expand
BAUD_??baud??_5 = divide
noexpand
endif
if ratio == 6
expand
BAUD_??baud??_6 = divide
noexpand
endif
if ratio == 7
expand
BAUD_??baud??_7 = divide
noexpand
endif
if ratio == 8
expand
BAUD_??baud??_8 = divide
noexpand
endif
if ratio == 9
expand
BAUD_??baud??_9 = divide
noexpand
endif
if ratio == 10
expand
BAUD_??baud??_10 = divide
noexpand
endif
if ratio == 11
expand
BAUD_??baud??_11 = divide
noexpand
endif
if ratio == 12
expand
BAUD_??baud??_12 = divide
noexpand
endif
if ratio == 13
expand
BAUD_??baud??_13 = divide
noexpand
endif
if ratio == 14
expand
BAUD_??baud??_14 = divide
noexpand
endif
if ratio == 15
expand
BAUD_??baud??_15 = divide
noexpand
endif
if ratio == 16
expand
BAUD_??baud??_16 = divide
noexpand
endif
endm

_lib_uart_calc2	macro	baud
if ratio < THREADS
  ratio = ratio + 1
  divide = ((2 * uartfs / baud / ratio) + 1) / 2	;defines bittime, roundoff value
  if (THREADS / ratio) * ratio == THREADS		;ratio must be integer multiple of THREADS
    ;minimum divide must be 2
    ;to sample at middle of databits, startdelay must be 1.5 * bittime
    if divide < 2		;min startdelay = 1.5 * 2 = 3
      divide = 0
    endif
    if divide > 170		;max startdelay = 1.5 * 170 = 255
      divide = 0
    endif
    if divide != 0
      _lib_uart_calc3 baud,ratio,divide
    endif
  endif
endif
endm

lib_uart_calc	macro	baud
ratio = 0
if baud <= maxbaud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
  _lib_uart_calc2 baud
endif
endm

;serial data formats
E71		equ	%00001110	; even parity, 7 databits, 1 stopbit , 1 startbit, 10 bits total
E72		equ	%00001111	; even parity, 7 databits, 2 stopbit , 1 startbit, 11 bits total
E81		equ	%00001011	; even parity, 8 databits, 1 stopbit , 1 startbit, 11 bits total
O71		equ	%00010110	; odd  parity, 7 databits, 1 stopbit , 1 startbit, 10 bits total
O72		equ	%00010111	; odd  parity, 7 databits, 2 stopbit , 1 startbit, 11 bits total
O81		equ	%00010011	; odd  parity, 8 databits, 1 stopbit , 1 startbit, 11 bits total
N71		equ	%00000101	; no   parity, 7 databits, 1 stopbit , 1 startbit,  9 bits total 
N72		equ	%00000110	; no   parity, 7 databits, 2 stopbit , 1 startbit, 10 bits total 
N81		equ	%00000010	; no   parity, 8 databits, 1 stopbit , 1 startbit, 10 bits total
N82		equ	%00000011	; no   parity, 8 databits, 2 stopbit , 1 startbit, 11 bits total
UART_ENABLE	equ	%01000000	; load [UART_ENABLE] + dataformat value into rx_format or tx_format

;end of file lib_uartCalculations.inc
;file lib_threads.inc

vp0_thread = -1
vp1_thread = -1
vp2_thread = -1
vp3_thread = -1
vp4_thread = -1
vp5_thread = -1
vp6_thread = -1
vp7_thread = -1
vp8_thread = -1
vp9_thread = -1
vp10_thread = -1
vp11_thread = -1
vp12_thread = -1
vp13_thread = -1
vp14_thread = -1
vp15_thread = -1

lib_thread_jumptable	macro
		org	code
if THREADS > 1
expand
do_thread
noexpand
if THREADS > 8
expand
		and	w,#$0F
noexpand
else
  if THREADS > 4
expand
		and	w,#$07
noexpand
  else
    if THREADS > 2
expand
		and	w,#$03
noexpand
    else
      if THREADS > 1
expand
		and	w,#$01
noexpand
      endif
    endif
  endif
endif
expand
		add	pc,w
		jmp	isr0_thread
noexpand
if THREADS > 1
expand
		jmp	isr1_thread
noexpand
endif
if THREADS > 2
expand
		jmp	isr2_thread
		jmp	isr3_thread
noexpand
endif
if THREADS > 4
expand
		jmp	isr4_thread
		jmp	isr5_thread
		jmp	isr6_thread
		jmp	isr7_thread
noexpand
endif
if THREADS > 8
expand
		jmp	isr8_thread
		jmp	isr9_thread
		jmp	isr10_thread
		jmp	isr11_thread
		jmp	isr12_thread
		jmp	isr13_thread
		jmp	isr14_thread
		jmp	isr15_thread
noexpand
endif
endif
code		=	$
endm

_lib_make_isr_thread	macro	nr
expand
isr??nr??_thread
noexpand
ifdef vp0_bank
  if vp0_thread & (1<<nr) != 0
expand
		call	vp0_isr
noexpand
  endif
endif
ifdef vp1_bank
  if vp1_thread & (1<<nr) != 0
expand
		call	vp1_isr
noexpand
  endif
endif
ifdef vp2_bank
  if vp2_thread & (1<<nr) != 0
expand
		call	vp2_isr
noexpand
  endif
endif
ifdef vp3_bank
  if vp3_thread & (1<<nr) != 0
expand
		call	vp3_isr
noexpand
  endif
endif
ifdef vp4_bank
  if vp4_thread & (1<<nr) != 0
expand
		call	vp4_isr
noexpand
  endif
endif
ifdef vp5_bank
  if vp5_thread & (1<<nr) != 0
expand
		call	vp5_isr
noexpand
  endif
endif
ifdef vp6_bank
  if vp6_thread & (1<<nr) != 0
expand
		call	vp6_isr
noexpand
  endif
endif
ifdef vp7_bank
  if vp7_thread & (1<<nr) != 0
expand
		call	vp7_isr
noexpand
  endif
endif
ifdef vp8_bank
  if vp8_thread & (1<<nr) != 0
expand
		call	vp8_isr
noexpand
  endif
endif
ifdef vp9_bank
  if vp9_thread & (1<<nr) != 0
expand
		call	vp9_isr
noexpand
  endif
endif
ifdef vp10_bank
  if vp10_thread & (1<<nr) != 0
expand
		call	vp10_isr
noexpand
  endif
endif
ifdef vp11_bank
  if vp11_thread & (1<<nr) != 0
expand
		call	vp11_isr
noexpand
  endif
endif
ifdef vp12_bank
  if vp12_thread & (1<<nr) != 0
expand
		call	vp12_isr
noexpand
  endif
endif
ifdef vp13_bank
  if vp13_thread & (1<<nr) != 0
expand
		call	vp13_isr
noexpand
  endif
endif
ifdef vp14_bank
  if vp14_thread & (1<<nr) != 0
expand
		call	vp14_isr
noexpand
  endif
endif
ifdef vp15_bank
  if vp15_thread & (1<<nr) != 0
expand
		call	vp15_isr
noexpand
  endif
endif
expand
		jmp	isr_thread_end
noexpand
endm

lib_isr_thread	macro
if THREADS <= 1
  vp0_thread = 0
  vp1_thread = 0
  vp2_thread = 0
  vp3_thread = 0
  vp4_thread = 0
  vp5_thread = 0
  vp6_thread = 0
  vp7_thread = 0
  vp8_thread = 0
  vp9_thread = 0
  vp10_thread = 0
  vp11_thread = 0
  vp12_thread = 0
  vp13_thread = 0
  vp14_thread = 0
  vp15_thread = 0
endif
ifdef vp0_bank
  if vp0_thread == 0
expand
		call	vp0_isr
noexpand
  endif
endif
ifdef vp1_bank
  if vp1_thread == 0
expand
		call	vp1_isr
noexpand
  endif
endif
ifdef vp2_bank
  if vp2_thread == 0
expand
		call	vp2_isr
noexpand
  endif
endif
ifdef vp3_bank
  if vp3_thread == 0
expand
		call	vp3_isr
noexpand
  endif
endif
ifdef vp4_bank
  if vp4_thread == 0
expand
		call	vp4_isr
noexpand
  endif
endif
ifdef vp5_bank
  if vp5_thread == 0
expand
		call	vp5_isr
noexpand
  endif
endif
ifdef vp6_bank
  if vp6_thread == 0
expand
		call	vp6_isr
noexpand
  endif
endif
ifdef vp7_bank
  if vp7_thread == 0
expand
		call	vp7_isr
noexpand
  endif
endif
if THREADS > 1
expand
		mov	fsr,#$F0
		mov	w,lib_threadcount
		jmp	do_thread	;execute threaded code
noexpand
_lib_make_isr_thread	0
_lib_make_isr_thread	1
endif
if THREADS > 2
_lib_make_isr_thread	2
_lib_make_isr_thread	3
endif
if THREADS > 4
_lib_make_isr_thread	4
_lib_make_isr_thread	5
_lib_make_isr_thread	6
_lib_make_isr_thread	7
endif
if THREADS > 8
_lib_make_isr_thread	8
_lib_make_isr_thread	9
_lib_make_isr_thread	10
_lib_make_isr_thread	11
_lib_make_isr_thread	12
_lib_make_isr_thread	13
_lib_make_isr_thread	14
_lib_make_isr_thread	15
endif
expand
isr_thread_end
noexpand
ifdef vp8_bank
  if vp8_thread == 0
expand
		call	vp8_isr
noexpand
  endif
endif
ifdef vp9_bank
  if vp9_thread == 0
expand
		call	vp9_isr
noexpand
  endif
endif
ifdef vp10_bank
  if vp10_thread == 0
expand
		call	vp10_isr
noexpand
  endif
endif
ifdef vp11_bank
  if vp11_thread == 0
expand
		call	vp11_isr
noexpand
  endif
endif
ifdef vp12_bank
  if vp12_thread == 0
expand
		call	vp12_isr
noexpand
  endif
endif
ifdef vp13_bank
  if vp13_thread == 0
expand
		call	vp13_isr
noexpand
  endif
endif
ifdef vp14_bank
  if vp14_thread == 0
expand
		call	vp14_isr
noexpand
  endif
endif
ifdef vp15_bank
  if vp15_thread == 0
expand
		call	vp15_isr
noexpand
  endif
endif
code		=	$
endm

;end of file lib_threads.inc
;file lib_initPorts.inc

lib_initPorts	macro
if RB_wked != RB_wked_PU
expand
			mov	m,#M_WKED	; point mode to WKED
			mov	!rb,#RB_wked
noexpand
endif
if RB_wken != RB_wken_PU
expand
			mov	m,#M_WKEN	; point mode to WKEN
			mov	!rb,#RB_wken
noexpand
endif
if RB_wkpnd != RB_wkpnd_PU
expand
			mov	m,#M_WKPND	 ;point mode to WKPND
			mov	w,#RB_WKPND
			mov	!rb,w
noexpand
endif
if RB_cmp != RB_cmp_PU
expand
			mov	m,#M_CMP	; point mode to CMP
			mov	w,#RB_cmp
			mov	!rb,w
noexpand
endif
if (RB_st != RB_st_PU) or (RC_st != RC_st_PU) or (RD_st != RD_st_PU) or (RE_st != RE_st_PU)
expand
			mov	m,#M_ST		; point mode to ST
noexpand
endif
if RE_st != RE_st_PU
  ifdef DEV_48
expand
			mov	!re,#RE_st
noexpand
  endif
endif
if RD_st != RD_st_PU
  ifdef DEV_48
expand
			mov	!rd,#RD_st
noexpand
  endif
endif
if RC_st != RC_st_PU
  ifndef DEV_18
expand
			mov	!rc,#RC_st
noexpand
  endif
endif
if RB_st != RB_st_PU
expand
			mov	!rb,#RB_st
noexpand
endif
if (RA_lvl != RA_lvl_PU) or (RB_lvl != RB_lvl_PU) or (RC_lvl != RC_lvl_PU) or (RD_lvl != RD_lvl_PU) or (RE_lvl != RE_lvl_PU)
expand
			mov	m,#M_LVL	; point mode to LVL
noexpand
endif
if RE_lvl != RE_lvl_PU
  ifdef DEV_48
expand
			mov	!re,#RE_lvl
noexpand
  endif
endif
if RD_lvl != RD_lvl_PU
  ifdef DEV_48
expand
			mov	!rd,#RD_lvl
noexpand
  endif
endif
if RC_lvl != RC_lvl_PU
  ifndef DEV_18
expand
			mov	!rc,#RC_lvl
noexpand
  endif
endif
if RB_lvl != RB_lvl_PU
expand
			mov	!rb,#RB_lvl
noexpand
endif
if RA_lvl != RA_lvl_PU
expand
			mov	!ra,#RA_lvl
noexpand
endif
if (RA_plp != RA_plp_PU) or (RB_plp != RB_plp_PU) or (RC_plp != RC_plp_PU) or (RD_plp != RD_plp_PU) or (RE_plp != RE_plp_PU)
expand
			mov	m,#M_PLP	; point mode to PLP
noexpand
endif
if RE_plp != RE_plp_PU
  ifdef DEV_48
expand
			mov	!re,#RC_plp
noexpand
  endif
endif
if RD_plp != RD_plp_PU
  ifdef DEV_48
expand
			mov	!rd,#RD_plp
noexpand
  endif
endif
if RC_plp != RC_plp_PU
  ifndef DEV_18
expand
			mov	!rc,#RC_plp
noexpand
  endif
endif
if RB_plp != RB_plp_PU
expand
			mov	!rb,#RB_plp
noexpand
endif
if RA_plp != RA_plp_PU
expand
			mov	!ra,#RA_plp
noexpand
endif
			;init latches
ifdef DEV_48
expand
			mov	re,#RE_latch
			mov	rd,#RD_latch
noexpand
endif
ifndef DEV_18
expand
			mov	rc,#RC_latch
noexpand
endif
expand
			mov	rb,#RB_latch
			mov	ra,#RA_latch
noexpand
if (RA_tris != RA_tris_PU) or (RB_tris != RB_tris_PU) or (RC_tris != RC_tris_PU) or (RD_tris != RD_tris_PU) or (RE_tris != RE_tris_PU)
expand
			mov	m,#M_TRIS	; point mode to TRIS
noexpand
endif
expand
			mov	fsr,#$F0	;access direction register copies
			mov	w,#RE_tris
noexpand
if RE_tris != RE_tris_PU
  ifdef DEV_48
expand
			mov	!re,w
noexpand
  endif
endif
expand
			mov	portE_dirbuf,w
noexpand
if RD_tris != RE_tris
expand
			mov	w,#RD_tris
noexpand
endif
if RD_tris != RD_tris_PU
  ifdef DEV_48
expand
			mov	!rd,w
noexpand
  endif
endif
expand
			mov	portD_dirbuf,w
noexpand
if RC_tris != RD_tris
expand
			mov	w,#RC_tris
noexpand
endif
if RC_tris != RC_tris_PU
  ifndef DEV_18
expand
			mov	!rc,w
noexpand
  endif
endif
expand
			mov	portC_dirbuf,w
noexpand
if RB_tris != RC_tris
expand
			mov	w,#RB_tris
noexpand
endif
if RB_tris != RB_tris_PU
expand
			mov	!rb,w
noexpand
endif
expand
			mov	portB_dirbuf,w
noexpand
if RA_tris != RB_tris
expand
			mov	w,#RA_tris
noexpand
if RA_tris != RA_tris_PU
expand
			mov	!ra,w
noexpand
endif
expand
			mov	portA_dirbuf,w
noexpand
code		=	$
endm

;end of file lib_initPorts.inc
;file lib_dirbuf.inc

_lib_dirbuf_lowsize	equ	$013
_lib_dirbuf_lowhalf		macro
		org	code
	begin	=	$
expand
	;access dirbuf
	;entry: w = port pin (highnib = port, lownib = pin)
access_dirbuf
		mov	vp_portpin,w		;save pin id
		mov	w,<>vp_portpin		;port (ra to re) in lownib
		or	w,#$F0
		mov	fsr,w			;portA_dirbuf to portE_dirbuf
		mov	w,vp_portpin		;pin number 0 to 7 in lownib
	;get pin mask
	;entry: w lownib = pin number 0-7
	;exit:  w = pin mask
pin_mask
		and	w,#$07
		add	pc,w
		retw	1		;pin0
		retw	2		;pin1
		retw	4		;pin2
		retw	8		;pin3
		retw	16		;pin4
		retw	32		;pin5
		retw	64		;pin6
		retw	128		;pin7
		retp
get_pin		jmp	_get_pin
clrb_dirbuf	jmp	_clrb_dirbuf
setb_dirbuf	jmp	_setb_dirbuf
noexpand
code		=	$
if _lib_dirbuf_lowsize > code - begin
  error P2W "_dirbuf_lowsize too large"
endif
if _lib_dirbuf_lowsize < code - begin
  error "_dirbuf_lowsize too small"
endif
endm

_lib_dirbuf_highsize	equ	$013
_lib_dirbuf_highhalf	macro
		org	code
	begin	=	$
expand
	;get pin state
	;entry: w = port pin (highnib = port, lownib = pin)
	;exit: Z if pin low, NZ if pin high
_get_pin
		call	access_dirbuf
		sub	fsr,#portA_dirbuf-5	;ra to re
		mov	w,indf			;read all pins
		xor	vp_portpin,w		;swap vp_portpin and w
		xor	w,vp_portpin
		xor	vp_portpin,w
		call	pin_mask		;get mask for pin
		and	vp_portpin,w		;Z if pin low, NZ if pin high
		jmp	vp_access
	;make dirbuf bit high
	;entry: w = port pin (highnib = port, lownib = pin)
_setb_dirbuf
		call	access_dirbuf
		or	indf,w			;set dirbuf bit
		jmp	vp_access
	;make dirbuf bit low
	;entry: w = port pin (highnib = port, lownib = pin)
_clrb_dirbuf
		call	access_dirbuf
		not	w			;invert mask
		and	indf,w			;clear dirbuf bit
vp_access
		mov	fsr,vp_bank
		retp
noexpand
code		=	$
if _lib_dirbuf_highsize > code - begin
  error P2W "_dirbuf_highsize too large"
endif
if _lib_dirbuf_highsize < code - begin
  error "_dirbuf_highsize too small"
endif
endm

;end of file lib_dirbuf.inc
;file lib_timer8.inc

_lib_timer8_var		macro	nr, prefix
			org	data
expand
vp??nr??_bank		equ	($ & $F8)|nr
timer8_set		=	$+0		;set value
timer8_count		=	$+1		;counter
prefix??_??bank		equ	($ & $F0) | nr
prefix??_??set		ds	1		;set value
prefix??_??count	ds	1		;counter
noexpand
data			=	$
endm

lib_timer8		macro	nr, prefix, timeout, thread
if nr >= maxvp
  error "vp number too high"
endif
ifndef vp_timer8
vp_timer8
endif
vp??nr??_thread	= thread
_lib_timer8_var nr,prefix
			org	code
expand
vp??nr??_init
		mov	timer8_set,#timeout
noexpand
code			=	$
expand
		org	vp??nr??_isr
		jmp	@timer8_isr
noexpand
endm

_lib_timer8_lowsize	equ	$001
_lib_timer8_lowhalf		macro
			org	code
	begin	=	$
expand
timer8_isr		jmp	_timer8_isr
noexpand
code		=	$
if _lib_timer8_lowsize > code - begin
  error P2W "_timer8_lowsize too large"
endif
if _lib_timer8_lowsize < code - begin
  error "_timer8_lowsize too small"
endif
endm

_lib_timer8_highsize	equ	$009
_lib_timer8_highhalf	macro
			org	code
	begin	=	$
expand
_timer8_isr
			dec	timer8_count
			jnz	:timer8_isr_end
			mov	w,timer8_set
			mov	timer8_count,w
			mov	w,fsr			;isr_flag to use in lownib
			call	pin_mask
			or	vp_flags,w
:timer8_isr_end
			retp
noexpand
code			=	$
if _lib_timer8_highsize > code - begin
  error P2W "_timer8_highsize too large"
endif
if _lib_timer8_highsize < code - begin
  error "_timer8_highsize too small"
endif
endm

;end of file lib_timer8.inc
;file lib_timer16.inc

_lib_timer16_var	macro	nr, prefix
			org	data
expand
vp??nr??_bank		equ	($ & $F8)|nr
lib_timer16_setL	=	$+0		;set value
lib_timer16_setH	=	$+1
lib_timer16_countL	=	$+2		;counter
lib_timer16_countH	=	$+3
prefix??_??bank		equ	($ & $F0) | nr
prefix??_??setL		ds	1		;set value
prefix??_??setH		ds	1
prefix??_??countL	ds	1		;counter
prefix??_??countH	ds	1
noexpand
data			=	$
endm

lib_timer16		macro	nr, prefix, timeout, thread
if nr >= maxvp
  error "vp number too high"
endif
ifndef vp_timer16
vp_timer16
endif
vp??nr??_thread	= thread
_lib_timer16_var nr,prefix
			org	code
expand
vp??nr??_init
		mov	lib_timer16_setL,#(timeout&255)
		mov	lib_timer16_setH,#(timeout>>8)
noexpand
code			=	$
expand
		org	vp??nr??_isr
		jmp	@timer16_isr
noexpand
endm

_lib_timer16_lowsize	equ	$001
_lib_timer16_lowhalf	macro
			org	code
	begin	=	$
expand
timer16_isr		jmp	_timer16_isr
noexpand
code		=	$
if _lib_timer16_lowsize > code - begin
  error P2W "_timer16_lowsize too large"
endif
if _lib_timer16_lowsize < code - begin
  error "_timer16_lowsize too small"
endif
endm

_lib_timer16_highsize	equ	$009
_lib_timer16_highhalf	macro
			org	code
	begin		=	$
expand
_timer16_isr
			dec	lib_timer16_countL
			jnz	:timer16_isr_end
			mov	w,lib_timer16_setL
			mov	lib_timer16_countL,w
			mov	w,fsr			;isr_flag to use in lownib
			call	pin_mask
			or	vp_flags,w
:timer16_isr_end
			retp
noexpand
code			=	$
if _lib_timer16_highsize > code - begin
  error P2W "_timer16_highsize too large"
endif
if _lib_timer16_highsize < code - begin
  error "_timer16_highsize too small"
endif
endm

;end of file lib_timer16.inc
;file lib_queue.inc

;queue buffer layout
;
; +----+----+
; |size| num|  size = number of databytes in queue buffer, num = number of values in queue 
; +----+----+
; |head|tail|  head = position last stored value, tail = position before value to retrieve
; +----+----+
; | d a t a |
; | d a t a |

_lib_queue_var		macro	name, size
  tempsize = size+2
if ((data + tempsize - 1) & $F0) != (data & $F0)
error "queue buffer too large, crossing rambank boundary"
endif
ifndef vp_queue
vp_queue
endif
			org	data
expand
??name??		equ	$
queue_??name??_sizenum	ds	1
queue_??name??_headtail	ds	1
queue_??name??_buffer	ds	size
noexpand
data		=	$
endm

lib_queue	macro	name, size
_lib_queue_var name,size
endm

_lib_queue_lowsize	equ	$002
_lib_queue_lowhalf	macro
		org	code
	begin	=	$
expand
enqueue		jmp	_enqueue
dequeue		jmp	_dequeue
noexpand
code		=	$
if _lib_queue_lowsize > code - begin
  error P2W "_queue_lowsize too large"
endif
if _lib_queue_lowsize < code - begin
  error "_queue_lowsize too small"
endif
endm

_lib_queue_highsize	equ	$02B
_lib_queue_highhalf	macro
		org	code
	begin	=	$
expand
	;enqueue value
	;entry: value in main_temp
	;       fsr set to queue_var address
	;return: Z if queue full (and value not stored)
	;	 fsr destroyed
_enqueue
		mov	w,<>indf	;load size+num
		xor	w,indf		;xor size with num
		snz
		retp			;queue full
		inc	indf		;inc num
		inc	fsr
		add	indf,#$10	;inc head
		dec	fsr
		mov	w,indf		;get size
		inc	fsr
		xor	w,indf		;xor size with head
		and	w,#$F0
		mov	w,#$0F
		snz			;head == size?
		and	indf,w		;yes, clear head
		mov	w,<>indf	;get head in lownib
		and	w,#$0F
		inc	fsr		;point to queue begin
		add	fsr,w		;head position
		mov	w,main_temp
		mov	indf,w		;store value
		retp
	;dequeue value
	;entry: fsr set to queue address
	;return: Z if queue empty (and no value returned)
	;        value in w
_dequeue
		mov	w,indf		;load size+num
		and	w,#$0F		;test num
		snz
		retp			;queue empty
		dec	indf		;dec num
		mov	w,<>indf	;get size in lownib
		inc	fsr
		inc	indf		;inc tail
		xor	w,indf		;xor size with tail
		and	w,#$0F
		mov	w,#$F0
		snz			;tail == size?
		and	indf,w		;yes, clear tail
		mov	w,indf		;get tail in lownib
		and	w,#$0F
		inc	fsr		;point to queue begin
		add	fsr,w		;tail position
		mov	w,indf		;get value
		mov	main_temp,w
		retp
noexpand
code		=	$
if _lib_queue_highsize > code - begin
  error P2W "_queue_highsize too large"
endif
if _lib_queue_highsize < code - begin
  error "_queue_highsize too small"
endif
endm

;end of file lib_queue.inc
;file lib_stack.inc

;stack buffer layout
;
; +----+----+
; |size| num|  size = number of databytes in stack buffer, num = number of values on stack 
; +----+----+
; | d a t a |
; | d a t a |

_lib_stack_var		macro	name, size
  tempsize = size+1
if ((data + tempsize - 1) & $F0) != (data & $F0)
error "stack buffer too large, crossing rambank boundary"
endif
ifndef vp_stack
vp_stack
endif
			org	data
expand
??name??		equ	$
stack_??name??_sizenum	ds	1
stack_??name??_buffer	ds	size
noexpand
data		=	$
endm

lib_stack	macro	name, size
_lib_stack_var name,size
endm

_lib_stack_lowsize	equ	$002
_lib_stack_lowhalf	macro
		org	code
	begin	=	$
expand
push		jmp	_push
pop		jmp	_pop
noexpand
code		=	$
if _lib_stack_lowsize > code - begin
  error P2W "_stack_lowsize too large"
endif
if _lib_stack_lowsize < code - begin
  error "_stack_lowsize too small"
endif
endm

_lib_stack_highsize	equ	$018
_lib_stack_highhalf	macro
		org	code
	begin	=	$
expand
	;push value
	;entry: value in main_temp
	;       fsr set to stack_var address
	;return: Z if stack full (and value not stored)
	;	 fsr destroyed
_push
		mov	w,<>indf	;load size+num
		xor	w,indf		;xor size with num
		snz
		retp			;stack full
		inc	indf		;inc num
		mov	w,indf		;get num in lownib
		and	w,#$0F
		inc	fsr		;point to stack begin
		add	fsr,w		;top of stack position
		mov	w,main_temp
		mov	indf,w		;store value
		retp
	;pop value
	;entry: fsr set to stack address
	;return: Z if stack empty (and no value returned)
	;        value in w
_pop
		mov	w,indf		;load size+num
		and	w,#$0F		;test num
		snz
		retp			;stack empty
		dec	indf		;dec num
		mov	w,indf		;get num in lownib
		and	w,#$0F
		inc	fsr		;point to stack begin
		add	fsr,w		;top of stack position
		mov	w,indf		;get value
		mov	main_temp,w
		retp
noexpand
code		=	$
if _lib_stack_highsize > code - begin
  error P2W "_stack_highsize too large"
endif
if _lib_stack_highsize < code - begin
  error "_stack_highsize too small"
endif
endm

;end of file lib_stack.inc
;file lib_parity.inc

_lib_parity_lowsize		equ	$001
_lib_parity_lowhalf		macro
			org	code
	begin	=	$
expand
even_parity		jmp	_even_parity
noexpand
code		=	$
if _lib_parity_lowsize > code - begin
  error P2W "_parity_lowsize too large"
endif
if _lib_parity_lowsize < code - begin
  error "_parity_lowsize too small"
endif
endm

_lib_parity_highsize	equ	$08
_lib_parity_highhalf	macro
			org	code
	begin	=	$
expand
	; calculate even parity for w
	; result in vp_portpin.0
	;---------------------------------------------------------------------------------
_even_parity
			mov	vp_portpin,w

	;calculation code by John Payson, as found on sxlist.com
	;This routine will leave the parity of vp_portpin in vp_portpin.0
	;while blenderizing most of the rest of vp_portpin

			mov	w,<>vp_portpin	; vp_portpin = abcdefgh
			xor	vp_portpin,w
			mov	w,>>vp_portpin
			xor	vp_portpin,w

	; at this point, the parity for half the bits
	; (a, b, e, and f) is in bit 2 of vp_portpin, and the
	; parity for the other half (bits c, d, g, and h)
	; is in bit 0 of vp_portpin.

			snb	vp_portpin.2	; if the parity of (a,b,e,f) is 0,
                        			; then the parity of (a,b,c,d,e,f,g,h)
                        			; is equal to the parity of (c,d,g,h)...
                        			; which is already in bit 0, so skip ahead.

			inc	vp_portpin	; otherwise, the parity of (a,b,e,f) is 1,
						; so the parity of (a,b,c,d,e,f,g,h) is
						; NOT equal to the parity of (c,d,g,h).
						; invert bit 0.

	; at this point, bit 0 contains the parity of
	; (a,b,c,d,e,f,g,h).

			retp
noexpand
code			=	$
if _lib_parity_highsize > code - begin
  error P2W "_parity_highsize too large"
endif
if _lib_parity_highsize < code - begin
  error "_parity_highsize too small"
endif
endm

;end of file lib_parity.inc
;file lib_uartTransmit.inc

_lib_uart_tx_var	macro	nr, prefix
			org	data
expand
vp??nr??_bank		equ	($ & $F8) | nr
lib_tx_count		=	$+0		;number of bits
lib_tx_divide		=	$+1		;timing counter
lib_tx_low		=	$+2		;shift register
lib_tx_high		=	$+3		;value
lib_tx_format		=	$+4
  lib_tx_bits_0		=	lib_tx_format.0	;bits 1 and 0 specify number of total bits
  lib_tx_bits_1		=	lib_tx_format.1	;01 -> 9bits, 10 -> 10bits, 11 -> 11bits (start+data+parity+stop)
  lib_tx_7bits		=	lib_tx_format.2	;set for 7 databits (0 = 8 databits)
  lib_tx_even		=	lib_tx_format.3	;set for even parity
  lib_tx_odd		=	lib_tx_format.4	;set for odd parity
  lib_tx_data		=	lib_tx_format.5	;set if valid value, cleared after value grabbed
  lib_tx_enable		=	lib_tx_format.6	;set to enable uart
  lib_tx_parity		=	lib_tx_format.7	;parity bit placeholder
lib_tx_baud		=	$+5		;baudrate
lib_tx_datapin		=	$+6		;high nib = port (5 to 9), low nib = pin (0 to 7)
  lib_tx_error		=	lib_tx_datapin.3	;set if parity error
lib_tx_hspin		=	$+7		;high nib = port (5 to 9), low nib = pin (0 to 7)
lib_tx_headtail		=	$+8
prefix??_??bank		equ	($ & $F0) | nr
prefix??_??count	ds	1		;number of bits
prefix??_??divide	ds	1		;timing counter
prefix??_??low		ds	1		;shift register
prefix??_??high		ds	1		;value
prefix??_??format	ds	1
  prefix??_??bits_0	equ	prefix??_??format.0	;bits 1 and 0 specify number of total bits
  prefix??_??bits_1	equ	prefix??_??format.1	;01 -> 9bits, 10 -> 10bits, 11 -> 11bits (start+data+parity+stop)
  prefix??_??7bits	equ	prefix??_??format.2	;set for 7 databits (0 = 8 databits)
  prefix??_??even	equ	prefix??_??format.3	;set for even parity
  prefix??_??odd	equ	prefix??_??format.4	;set for odd parity
  prefix??_??data	equ	prefix??_??format.5	;set if valid value, cleared after value grabbed
  prefix??_??enable	equ	prefix??_??format.6	;set to enable uart
  prefix??_??parity	equ	prefix??_??format.7	;parity bit placeholder
prefix??_??baud		ds	1		;baudrate
prefix??_??datapin	ds	1		;high nib = port (5 to 9), low nib = pin (0 to 7)
  prefix??_??error	equ	prefix??_??datapin.3	;set if parity error
prefix??_??hspin	ds	1		;high nib = port (5 to 9), low nib = pin (0 to 7)
prefix??_??headtail	ds	8
noexpand
data			=	$
endm

lib_uartTransmit	macro	nr, prefix, datapin, hspin, format, baud, thread
if nr >= maxvp
  error "vp number too high"
endif
ifndef vp_uartTransmit
vp_uartTransmit
endif
ifndef vp_dirbuf
vp_dirbuf
endif
ifndef vp_parity
vp_parity
endif
vp??nr??_thread	= thread
_lib_uart_tx_var nr,prefix
			org	code
expand
vp??nr??_init
			mov	fsr,#vp??nr??_bank
			mov	lib_tx_format,#format
			mov	lib_tx_baud,#baud
			mov	lib_tx_datapin,#datapin
			mov	lib_tx_hspin,#hspin
noexpand
code			=	$
expand
			org	vp??nr??_isr
			jmp	@uart_tx_isr
noexpand
endm

_lib_uartTransmit_lowsize	equ	$002
_lib_uartTransmit_lowhalf	macro
			org	code
	begin	=	$
expand
uart_tx_isr		jmp	_uart_tx_isr
uart_tx_task		jmp	_uart_tx_task
noexpand
code		=	$
if _lib_uartTransmit_lowsize > code - begin
  error P2W "_uartTransmit_lowsize too large"
endif
if _lib_uartTransmit_lowsize < code - begin
  error "_uartTransmit_lowsize too small"
endif
endm

_lib_uartTransmit_highsize	equ	$04E
_lib_uartTransmit_highhalf	macro
			org	code
	begin	=	$
expand
_uart_tx_isr
			mov	fsr,vp_bank		;select target uart bank
			jnb	lib_tx_enable,:txdone
			decsz	lib_tx_divide		;time for next bit?
			jmp	:txdone			;no
			mov	w,lib_tx_baud		;renew delay time
			mov	lib_tx_divide,w
			test    lib_tx_count		;bits to send?
			snz
			jmp	:txdone			;no
			clc				;ready stop bit
			rr	lib_tx_high		;and shift to next bit
			rr	lib_tx_low
			mov	w,lib_tx_datapin	;pin number 0 to 7 in lownib
			call	pin_mask		;get ORmask for pin
			stc
			snb	lib_tx_low.5		;clear carry and keep ORmask to make pin high
			not	w			;set carry and make ANDmask to make pin low
			sb	lib_tx_low.5
			clc
			mov	vp_portpin,w		;save bitmask
			mov	w,<>lib_tx_datapin	;port (ra to re) in lownib
			or	w,#$F0
			mov	fsr,w			;portA_dirbuf to portE_dirbuf
			mov	w,vp_portpin		;get bitmask
			snc
			and	indf,w
			sc
			or	indf,w
			mov	w,vp_bank		;select target uart bank
			mov	fsr,w
			dec	lib_tx_count		;decrement bit counter
			jnz	:txdone
			call	pin_mask		;set vp flag
			or	vp_flags,w
:txdone
			retp
_uart_tx_task
			sb	lib_tx_data
			retp
			snb	lib_tx_7bits		;8 databits?
			clrb	lib_tx_high.7		;no, clear b7 for parity calculation
			mov	w,lib_tx_high
			call	@even_parity
			snb	lib_tx_7bits		;8 databits?
			setb	lib_tx_high.7		;no, ready stop bit
			jnb	lib_tx_odd,:uot1
			movb	C,/vp_portpin.0
			jmp	:uot2
:uot1
			jnb	lib_tx_even,:uot3
			movb	C,vp_portpin.0
:uot2
			jnb	lib_tx_7bits,:uot4	;7 databits?
			movb	lib_tx_high.7,C		;yes, move parity into b7
:uot3
			stc				;ready stop bit
:uot4
			clrb	lib_tx_low.7		;setup start bit
			rr	lib_tx_high		;rotate in parity bit or stop bit
			rr	lib_tx_low
			not	lib_tx_high		;inverted mode
			not	lib_tx_low
			mov	w,lib_tx_format		;get total number of bits
			and	w,#$03			;1, 2 or 3
			or	w,#$08			;9, 10, or 11
			mov	lib_tx_count,w		;now uart vp starts to transmit
			clrb	lib_tx_data		;mark byte grabbed
			retp
noexpand
code			=	$
if _lib_uartTransmit_highsize > code - begin
  error P2W "_uartTransmit_highsize too large"
endif
if _lib_uartTransmit_highsize < code - begin
  error "_uartTransmit_highsize too small"
endif
endm

;end of file lib_uartTransmit.inc
;file lib_uartReceive.inc

_lib_uart_rx_var	macro	nr, prefix
			org	data
expand
vp??nr??_bank		equ	($ & $F8) | nr
lib_rx_count		=	$+0		;number of bits
lib_rx_divide		=	$+1		;timing counter
lib_rx_low		=	$+2		;shift register
lib_rx_high		=	$+3		;value
lib_rx_format		=	$+4
  lib_rx_bits_0		=	lib_rx_format.0	;bits 1 and 0 specify number of total bits
  lib_rx_bits_1		=	lib_rx_format.1	;01 -> 9bits, 10 -> 10bits, 11 -> 11bits (start+data+parity+stop)
  lib_rx_7bits		=	lib_rx_format.2	;set for 7 databits (0 = 8 databits)
  lib_rx_even		=	lib_rx_format.3	;set for even parity
  lib_rx_odd		=	lib_rx_format.4	;set for odd parity
  lib_rx_data		=	lib_rx_format.5	;set if valid value, cleared after value grabbed
  lib_rx_enable		=	lib_rx_format.6	;set to enable uart
  lib_rx_parity		=	lib_rx_format.7	;parity bit placeholder
lib_rx_baud		=	$+5		;baudrate
lib_rx_datapin		=	$+6		;high nib = port (5 to 9), low nib = pin (0 to 7)
  lib_rx_error		=	lib_rx_datapin.3	;set if parity error
lib_rx_hspin		=	$+7		;high nib = port (5 to 9), low nib = pin (0 to 7)
  lib_rx_full		=	lib_rx_hspin.3	;set if buffer full
lib_rx_headtail		=	$+8
prefix??_??bank		equ	($ & $F0) | nr
prefix??_??count	ds	1		;number of bits
prefix??_??divide	ds	1		;timing counter
prefix??_??low		ds	1		;shift register
prefix??_??high		ds	1		;value
prefix??_??format	ds	1
  prefix??_??bits_0	equ	prefix??_??format.0	;bits 1 and 0 specify number of total bits
  prefix??_??bits_1	equ	prefix??_??format.1	;01 -> 9bits, 10 -> 10bits, 11 -> 11bits (start+data+parity+stop)
  prefix??_??7bits	equ	prefix??_??format.2	;set for 7 databits (0 = 8 databits)
  prefix??_??even	equ	prefix??_??format.3	;set for even parity
  prefix??_??odd	equ	prefix??_??format.4	;set for odd parity
  prefix??_??data	equ	prefix??_??format.5	;set if valid value, cleared after value grabbed
  prefix??_??enable	equ	prefix??_??format.6	;set to enable uart
  prefix??_??parity	equ	prefix??_??format.7	;parity bit placeholder
prefix??_??baud		ds	1		;baudrate
prefix??_??datapin	ds	1		;high nib = port (5 to 9), low nib = pin (0 to 7)
  prefix??_??error	equ	prefix??_??datapin.3	;set if parity error
prefix??_??hspin	ds	1		;high nib = port (5 to 9), low nib = pin (0 to 7)
prefix??_??headtail	ds	8
noexpand
data			=	$
endm

lib_uartReceive		macro	nr, prefix, datapin, hspin, format, baud, thread
if nr >= maxvp
  error "vp number too high"
endif
ifndef vp_uartReceive
vp_uartReceive
endif
ifndef vp_dirbuf
vp_dirbuf
endif
ifndef vp_parity
vp_parity
endif
vp??nr??_thread	= thread
_lib_uart_rx_var nr,prefix
			org	code
expand
vp??nr??_init
			mov	fsr,#vp??nr??_bank
			mov	lib_rx_format,#format
			mov	lib_rx_baud,#baud
			mov	lib_rx_datapin,#datapin
			mov	lib_rx_hspin,#hspin
noexpand
code			=	$
expand
			org	vp??nr??_isr
			jmp	@uart_rx_isr
noexpand
endm

_lib_uartReceive_lowsize	equ	$002
_lib_uartReceive_lowhalf	macro
			org	code
	begin	=	$
expand
uart_rx_isr		jmp	_uart_rx_isr
uart_rx_task		jmp	_uart_rx_task
noexpand
code		=	$
if _lib_uartReceive_lowsize > code - begin
  error P2W "_uartReceive_lowsize too large"
endif
if _lib_uartReceive_lowsize < code - begin
  error "_uartReceive_lowsize too small"
endif
endm

_lib_uartReceive_highsize	equ	$05D
_lib_uartReceive_highhalf	macro
			org	code
	begin	=	$
expand
_uart_rx_isr
			mov	fsr,vp_bank		;select target uart rambank
			jnb	lib_rx_enable,:rxdone
			mov	w,<>lib_rx_datapin		;port (ra to re) in lownib
			or	w,#$F0
			mov	fsr,w			;portA_dirbuf to portE_dirbuf
			sub	fsr,#portA_dirbuf-5	;ra to re
			mov	w,indf			;read all pins
			mov	vp_portpin,w		;save pin states
			mov	fsr,vp_bank
			mov	w,lib_rx_datapin	;pin number 0 to 7 in lownib
			call	pin_mask			;get mask for pin
			and	vp_portpin,w		;extract bit for pin
			test	lib_rx_count		;currently receiving byte?
			sz				;no
			jmp	:rx1			;yes, jump ahead
			mov	w,--lib_rx_format		;ready bits for start
			and	w,#$03			;number of bits 1, 2 or 3
			or	w,#$08			;9, 10 or 11
			test	vp_portpin		;start bit?
			snz				;no
			mov	lib_rx_count,w		;yes, renew bit count
			mov	w,>>lib_rx_baud		;half bittime delay
			add	w,lib_rx_baud		;plus bittime delay -> start delay
			mov	lib_rx_divide,w
:rx1
			clc
			test	vp_portpin
			sz
			stc
			decsz	lib_rx_divide		;middle of next bit?
          		jmp	:rxdone			;no
			dec	lib_rx_count		;last bit?
			jz	:rx2			;yes
			rr	lib_rx_low			;no, rotate in new bit
			movb	lib_rx_parity,C		;save b0
			jmp	:rx3			;renew delay time
:rx2
			mov	w,lib_rx_low		;save byte to allow receive another byte
			mov	lib_rx_high,w
			setb	lib_rx_data			;mark byte received
:rx3
			mov	w,lib_rx_baud		;renew delay time
			mov	lib_rx_divide,w
:rxdone
			retp
_uart_rx_task
			sb	lib_rx_data
			retp
			movb	C,lib_rx_parity		;get last saved b0
			jb	lib_rx_format.1,:uit1
			clc				;adjust for 7 databits + no parity (total bits is 9)
			rr	lib_rx_high
			rr	lib_rx_high
:uit1
			snb	lib_rx_format.0
			rl	lib_rx_high			;adjust for 8 databits + parity (total bits is 11)
			jnb	lib_rx_7bits,:uit2
			movb	C,lib_rx_high.7		;save possible parity in case 7 databits
			clrb	lib_rx_high.7		;clear b7 in case 7 databits
:uit2
			movb	lib_rx_parity,C		;save possible parity bit
			clrb	lib_rx_error		;assume no error
			jb	lib_rx_odd,:uit3
			jb	lib_rx_even,:uit3
			jmp	:uit4
:uit3
			mov	w,lib_rx_high
			call	@even_parity
			snb	lib_rx_odd
			not	vp_portpin			;invert calculated even parity bit for odd parity
			addb	vp_portpin,lib_rx_parity		;if parity matches, b0 will be cleared
			snb	vp_portpin.0
			setb	lib_rx_error		;parity error
:uit4
			clrb	lib_rx_data			;mark byte grabbed
			mov	w,fsr			;isr_flag to use in lownib
			call	pin_mask
			or	vp_flags,w		;C isr() gets called
			retp
noexpand
code			=	$
if _lib_uartReceive_highsize > code - begin
  error P2W "_uartReceive_highsize too large"
endif
if _lib_uartReceive_highsize < code - begin
  error "_uartReceive_highsize too small"
endif
endm

;end of file lib_uartReceive.inc

;*****************************************************************************************
; Autoplacement macros
;*****************************************************************************************	

lowcodeloc = 0
highcodeloc = 0

_lib_install_test	macro	loworg, highorg, lowhalfsize, highhalfsize
lowcodeloc = loworg
  if lowcodeloc + lowhalfsize > (lowcodeloc & $E00) + $100
    lowcodeloc = 0
    highcodeloc = 0
  else
highcodeloc = highorg
    if highcodeloc - highhalfsize < lowcodeloc + lowhalfsize
      lowcodeloc = 0
      highcodeloc = 0
    endif
  endif
endm

_lib_install_vpcode	macro	lowhalfname, lowhalfsize, highhalfname, highhalfsize
_lib_install_test code_page1_low, code_page1_high, lowhalfsize, highhalfsize
if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page1_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page1_high	=	code
highhalfname
else
  _lib_install_test code_page2_low, code_page2_high, lowhalfsize, highhalfsize
  if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page2_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page2_high	=	code
highhalfname
  else
    _lib_install_test code_page3_low, code_page3_high, lowhalfsize, highhalfsize
    if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page3_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page3_high	=	code
highhalfname
    else
ifdef DEV_48
      _lib_install_test code_page4_low, code_page4_high, lowhalfsize, highhalfsize
      if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page4_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page4_high	=	code
highhalfname
      else
        _lib_install_test code_page5_low, code_page5_high, lowhalfsize, highhalfsize
        if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page5_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page5_high	=	code
highhalfname
        else
          _lib_install_test code_page6_low, code_page6_high, lowhalfsize, highhalfsize
          if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page6_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page6_high	=	code
highhalfname
          else
            _lib_install_test code_page7_low, code_page7_high, lowhalfsize, highhalfsize
            if ((lowcodeloc | highcodeloc) != 0)
expand
		org	lowcodeloc
noexpand
code		=	$
lowhalfname
code_page7_low	=	code
expand
		org	highcodeloc-highhalfsize
noexpand
code		=	$
code_page7_high	=	code
highhalfname
            else
              error "Not enough space to install code"
            endif
          endif
        endif
      endif
else
  error "Not enough space to install code"
endif
    endif
  endif
endif
endm

lib_install	macro
ifdef vp_i2cSlave
  _lib_install_vpcode _lib_i2cSlave_lowhalf, _lib_i2cSlave_lowsize, _lib_i2cSlave_highhalf, _lib_i2cSlave_highsize
endif
ifdef vp_i2cMaster
  _lib_install_vpcode _lib_i2cMaster_lowhalf, _lib_i2cMaster_lowsize, _lib_i2cMaster_highhalf, _lib_i2cMaster_highsize
endif
ifdef vp_uartReceive
  _lib_install_vpcode _lib_uartReceive_lowhalf, _lib_uartReceive_lowsize, _lib_uartReceive_highhalf, _lib_uartReceive_highsize
endif
ifdef vp_uartTransmit
  _lib_install_vpcode _lib_uartTransmit_lowhalf, _lib_uartTransmit_lowsize, _lib_uartTransmit_highhalf, _lib_uartTransmit_highsize
endif
ifdef vp_dirbuf
  _lib_install_vpcode _lib_dirbuf_lowhalf, _lib_dirbuf_lowsize, _lib_dirbuf_highhalf, _lib_dirbuf_highsize
endif
ifdef vp_parity
  _lib_install_vpcode _lib_parity_lowhalf, _lib_parity_lowsize, _lib_parity_highhalf, _lib_parity_highsize
endif
ifdef vp_queue
  _lib_install_vpcode _lib_queue_lowhalf, _lib_queue_lowsize, _lib_queue_highhalf, _lib_queue_highsize
endif
ifdef vp_stack
  _lib_install_vpcode _lib_stack_lowhalf, _lib_stack_lowsize, _lib_stack_highhalf, _lib_stack_highsize
endif
ifdef vp_timer16
  _lib_install_vpcode _lib_timer16_lowhalf, _lib_timer16_lowsize, _lib_timer16_highhalf, _lib_timer16_highsize
endif
ifdef vp_timer8
  _lib_install_vpcode _lib_timer8_lowhalf, _lib_timer8_lowsize, _lib_timer8_highhalf, _lib_timer8_highsize
endif
endm

		;interrupt dispatcher
lib_intdispatch	macro
expand
			test	vp_flags
			jz	:end			;no interrupts
:m0			jnb	vp_flags.0,:m1
noexpand
ifdef vp0_bank
expand
			mov	fsr,#vp0_bank
			;code here
noexpand
endif
ifdef vp8_bank
expand
			mov	fsr,#vp8_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.0
:m1			jnb	vp_flags.1,:m2
noexpand
ifdef vp1_bank
expand
			mov	fsr,#vp1_bank
			;code here
noexpand
endif
ifdef vp9_bank
expand
			mov	fsr,#vp9_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.1
:m2			jnb	vp_flags.2,:m3
noexpand
ifdef vp2_bank
expand
			mov	fsr,#vp2_bank
			;code here
noexpand
endif
ifdef vp10_bank
expand
			mov	fsr,#vp10_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.2
:m3			jnb	vp_flags.3,:m4
noexpand
ifdef vp3_bank
expand
			mov	fsr,#vp3_bank
			;code here
noexpand
endif
ifdef vp11_bank
expand
			mov	fsr,#vp11_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.3
:m4			jnb	vp_flags.4,:m5
noexpand
ifdef vp4_bank
expand
			mov	fsr,#vp4_bank
			;code here
noexpand
endif
ifdef vp12_bank
expand
			mov	fsr,#vp12_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.4
:m5			jnb	vp_flags.5,:m6
noexpand
ifdef vp5_bank
expand
			mov	fsr,#vp5_bank
			;code here
noexpand
endif
ifdef vp13_bank
expand
			mov	fsr,#vp13_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.5
:m6			jnb	vp_flags.6,:m7
noexpand
ifdef vp6_bank
expand
			mov	fsr,#vp6_bank
			;code here
noexpand
endif
ifdef vp14_bank
expand
			mov	fsr,#vp14_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.6
:m7			jnb	vp_flags.7,main2
noexpand
ifdef vp7_bank
expand
			mov	fsr,#vp7_bank
			;code here
noexpand
endif
ifdef vp15_bank
expand
			mov	fsr,#vp15_bank
			;code here
noexpand
endif
expand
			clrb	vp_flags.7
:end
noexpand
endm

;end of file dynlib.src
;lib_uart_calc 300
;lib_uart_calc 600
lib_uart_calc 1200
lib_uart_calc 2400
;lib_uart_calc 3600
lib_uart_calc 4800
;lib_uart_calc 7200
lib_uart_calc 9600
;lib_uart_calc 14400
lib_uart_calc 19200
lib_uart_calc 28800
;lib_uart_calc 33600
lib_uart_calc 38400
lib_uart_calc 57600
;lib_uart_calc 76800
lib_uart_calc 115200
;lib_uart_calc 153600
lib_uart_calc 230400
;lib_uart_calc 307200
;lib_uart_calc 460800

;*****************************************************************************************
; Constants
;*****************************************************************************************

;uncomment following to override int_period set by Uart calculations in sxvplib
;int_period	=	163		; This sets the interrupt rate

;*****************************************************************************************
; Port initialization values
;*****************************************************************************************

RA_latch	equ	%00000101	;port A output latch init 1=high 0=low
RA_tris		equ	%11111010	;port A direction register 1=input 0=output
RA_plp		equ	%00000000	;port A pull up register 1=off 0=on
RA_lvl		equ	%11111111	;port A level register 1=ttl 0=cmos

RB_latch	equ	%00000000	;port B output latch 1=high 0=low
RB_tris		equ	%11111111	;port B direction register 1=input 0=output
RB_plp		equ	%00000000	;port B pull up register 1=off 0=on
RB_lvl		equ	%00000000	;port B level register 1=ttl 0=cmos
RB_st		equ	%11111111	;port B schmitt trigger register 1=off 0=on
RB_wken		equ	%11111111	;port B wake up enable register 1=off 0=on
RB_wked		equ	%11111111	;port B wake up edge register 1=neg 0=pos
RB_wkpnd	equ	%00000000	;port B MIWI pending register 1=detected 0=not detected
RB_cmp		equ	%11111111	;port B comparator enable register 1=disabled 0=enabled

RC_latch	equ	%00000000	;port C output latch 1=high 0=low
RC_tris		equ	%11111111	;port C direction register 1=input 0=output
RC_plp		equ	%00000000	;port C pull up register 1=off 0=on
RC_lvl		equ	%11111111	;port C level register 1=ttl 0=cmos
RC_st		equ	%11111111	;port C schmitt trigger register 1=off 0=on

RD_latch	equ	%00000000	;port D output latch 1=high 0=low
RD_tris		equ	%11111111	;port D direction register 1=input 0=output
RD_plp		equ	%11111111	;port D pull up register 1=off 0=on
RD_lvl		equ	%11111111	;port D level register 1=ttl 0=cmos
RD_st		equ	%11111111	;port D schmitt trigger register 1=off 0=on

RE_latch	equ	%00000000	;port E output latch 1=high 0=low
RE_tris		equ	%11111111	;port E direction register 1=input 0=output
RE_plp		equ	%11111111	;port E pull up register 1=off 0=on
RE_lvl		equ	%11111111	;port E level register 1=ttl 0=cmos
RE_st		equ	%11111111	;port E schmitt trigger register 1=off 0=on

;*****************************************************************************************
; Port Assignment
;*****************************************************************************************

;*****************************************************************************************
; Pin Definitions 
;*****************************************************************************************
	
;*****************************************************************************************
; Global Register definitions
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on SX18/20/28.
;*****************************************************************************************
		org     global_org

;required for sxvplib macros
main_temp	equ	global_org+4
vp_bank		equ	global_org+5
vp_portpin	equ	global_org+6
vp_flags	equ	global_org+7

;*****************************************************************************************
; code page #0
;*****************************************************************************************
		org	page0_org

		mov	w,m
		fifo
		mov	w,main_temp
		fifo
		mov	w,vp_bank
		fifo
		mov	w,vp_portpin
		fifo
		mov	w,vp_flags
		fifo
		;placeholder to save a register
		fifo
		;placeholder to save a register
		fifo
		;placeholder to save a register
		fifo				;next fifo will move saved m into w (see isr_end)
		jmp	@interrupt
vp_isr_table	equ	$
vp0_isr		equ	vp_isr_table+0		;jmp @name_isr
vp1_isr		equ	vp_isr_table+2
vp2_isr		equ	vp_isr_table+4
vp3_isr		equ	vp_isr_table+6
vp4_isr		equ	vp_isr_table+8
vp5_isr		equ	vp_isr_table+10
vp6_isr		equ	vp_isr_table+12
vp7_isr		equ	vp_isr_table+14
vp8_isr		equ	vp_isr_table+16
vp9_isr		equ	vp_isr_table+18
vp10_isr	equ	vp_isr_table+20
vp11_isr	equ	vp_isr_table+22
vp12_isr	equ	vp_isr_table+24
vp13_isr	equ	vp_isr_table+26
vp14_isr	equ	vp_isr_table+28
vp15_isr	equ	vp_isr_table+30
code		=	vp_isr_table+(maxvp*2)
lib_thread_jumptable
	;*********************************************************************************
	; Program execution begins here on power-up or after a reset
	;*********************************************************************************
reset_entry
	;clear all ram
			mov	fsr,#global_org
:zero_global
			clr	indf
			inc	fsr
			cjne	fsr,#$10,:zero_global
:zero_ram
			clr	indf
			inc	fsr
			jz	:init_regs
ifndef DEV_48
			setb	fsr.4
endif
			jmp	:zero_ram
:init_regs
lib_initPorts
	;initialize vp data
code			=	$

;*****************************************************************************************
; RAM Bank Register definitions
; REMEMBER: All identical VP must be located at the same bank offset !!!
;*****************************************************************************************

;vp0 to vp7 flags are mapped onto vp_flags.0 to vp_flags.7
;vp8 to vp15 flags are also mapped onto vp_flags.0 to vp_flags.7

;i2cMaster   : 8 databytes, best located at offsets 0 or 8
;i2cSlave    : 8 databytes, best located at offsets 0 or 8
;uartReceive : 8 databytes, best located at offsets 0 or 8
;uartTransmit: 8 databytes, best located at offsets 0 or 8

	;*********************************************************************************
	; Bank 0 -
	;*********************************************************************************
			org	bank0_org
data			=	$

	;*********************************************************************************
	; Bank 1 -
	;*********************************************************************************
			org	bank1_org
data			=	$
lib_uartTransmit	0, tx0, PORTPIN_RA0, NO_PIN, UART_ENABLE+N81, 128, %0000000000000100

	;*********************************************************************************
	; Bank 2 -
	;*********************************************************************************
			org	bank2_org
data			=	$
lib_uartReceive		1, rx0, PORTPIN_RA1, NO_PIN, UART_ENABLE+N81, 128, %0000000000000010

	;*********************************************************************************
	; Bank 3 -
	;*********************************************************************************
			org	bank3_org
data			=	$
lib_timer16		2, timer16, 3099, %0000000000000000

	;*********************************************************************************
	; Bank 4 -
	;*********************************************************************************
			org	bank4_org
data			=	$
lib_queue		tx1, 6

	;*********************************************************************************
	; Bank 5 -
	;*********************************************************************************
			org	bank5_org
data			=	$
lib_timer8		3, timer8, 53, %0000000000000000

	;*********************************************************************************
	; Bank 6 -
	;*********************************************************************************
			org	bank6_org
data			=	$
lib_stack		st1, 15

	;*********************************************************************************
	; Bank 7 -
	;*********************************************************************************
			org	bank7_org
data			=	$

;*****************************************************************************************
; Finalize initialization
;*****************************************************************************************
		org	code
	; Initialise all port configuration
	;*********************************************************************************

ifdef DEV_48
		mov	w,#$1f			; point MODE to write DDIR (SX48/52)
else
		mov	w,#$0f			; point MODE to DDIR (SX18/20/28)
endif
		mov	m,w

	;*********************************************************************************
	; Setup option register. 
	;*********************************************************************************
		mov	w,#RTCC_PS_OFF	;setup option register
		mov	!option,w
		jmp	main

;*****************************************************************************************
; Interrupt Service Routine
;*****************************************************************************************
; Interrupt Frequency = (Cycle Frequency / -(retiw value))  For example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this
; code runs every 4.34us.
;*****************************************************************************************

interrupt					;3
		mov	fsr,#$F0
if THREADS > 1
:threadcount
		inc	lib_threadcount
		csne	lib_threadcount,#THREADS
		clr	lib_threadcount
endif
:systimer
		inc	lib_systimerL
		snz
		inc	lib_systimerH
:rbint
		mov	m,#M_WKPND
		clr	w
		mov	!rb,w
		or	lib_rbint,w

lib_isr_thread

	;*********************************************************************************
	; Update ports with buffered port data
	;*********************************************************************************
		mov	m,#M_TRIS
		mov	fsr,#$F0
		mov	w,portA_dirbuf
		mov	!ra,w
		mov	w,portB_dirbuf
		mov	!rb,w
ifndef DEV_18
		mov	w,portC_dirbuf
		mov	!rc,w
endif
ifdef DEV_48
		mov	w,portD_dirbuf
		mov	!rd,w
		mov	w,portE_dirbuf
		mov	!re,w
endif

isr_end
	;*********************************************************************************
	; Restore mode register and variables
	;*********************************************************************************
		fifo
		mov	m,w
		fifo
		mov	main_temp,w
		fifo
		mov	vp_bank,w
		fifo
		mov	vp_portpin,w
		fifo
		mov	vp_flags,w
		fifo
		;placeholder to restore a register
		fifo
		;placeholder to restore a register
		fifo
		;placeholder to restore a register
	;*********************************************************************************
	; Set Interrupt Rate
	;*********************************************************************************
		mov	w,#-int_period & 255		;1 ; refresh RTCC on return
		retiw				;3 ; return from the interrupt

;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************

;*****************************************************************************************
; MAIN PROGRAM CODE
;*****************************************************************************************

main

lib_intdispatch

main2
		;other tasks here
			jmp	main

code		=	$

;*****************************************************************************************
; Include the library modules.
;*****************************************************************************************

lib_install

;*****************************************************************************************
;		End of program code
;*****************************************************************************************
end

;end of file project_template.src

