;SUMMARY This is a modified MINI SPOT (ET 44262)

;created primarily to replace the Addmaster printers in Spit Test.
;Also provides a means to reduce firing voltage for some portion of 
;the firing pulse for heat soaking the fluid & environment prior to 
;applying ejection energy.
;Also provides a switch to select up to 16 pre-programmed combinations
;of essential firing and receipt simulation parameters.
;Runs until manually stopped or clocks out (reaches max firings).
;LED indicator is on when Ready, off when complete & flashes while running.


;MINI SPOT (ET 44262)

;5/2/02 Edited to make 7500 firing cycles (~5 seconds) then hang up until the next switch cycle. Also provide an
;external signal to drive an "operating" indicator LED. Fred Ornellas
;4/3/01 Edited to make 1,000,000 equivalent characters (1.333.333. firing cycles) then hang up until the next switch cycle. Fred Ornellas
;12/17/01 change to 1500hz 5m characters. eric ames
;AUTHOR: FRED ORNELLAS, TN396-5749,	12/4/00

;THIS SOFTWARE IS INTENDED TO DRIVE A SCENIX SX28 CHIP & TWO DARLINGTON TRANSISTOR ARRAY CHIP'S SO AS TO 


;EMULATE THE ESSENTIAL PEN FIRING SERVICES PROVIDED BY THE BODINE 'PREFIRE' SYSTEM. 

;THE COMPLETED CIRCUIT OPERATES FROM AN EXTERNAL POWER SUPPLY OF VOLTAGE Vp. 30>Vp>Vf+1.25 (FIRING VOLTAGE).
;
;THE FIRING VOLTAGE IS ADJUSTED BY VR1 & REGULATED ON BOARD BY IC5. THE FIRING VOLTAGE IS FURTHER REGULATED TO
;+5V FOR THE SX28. CASCADING IN THIS MANNER DISTRIBUTES DISIPATED POWER OVER BOTH CHIPS & PROVIDES MORE THAN SUFFICIENT LOAD
;TO EXCEED IC5 MINIMUMS. THE TWO DARLINGTON TRANSISTOR ARRAY IC2 & IC3 PROVIDE THE NECESSARY CURRENT GAIN TO DIRECTLY
;DRIVE A ST. HELENS OR TABLEROCK PEN. THIS LATTER IS COPIED DIRECTLY FROM A HP THINKJET PRINTER.
;THE SX IS OPERATED AT 50MHz TIMED BY AN EXTERNAL RESONATOR.

;THE CODE INITIALIZES PINS 14-25 (RB4-RC7) AS OUTPUTS DIRECTLY CORRESPONDING TO FIRING SIGNALS 1-12 OF THE TABLEROCK PEN.

;ALL OPERATING PARAMETERS ARE COMPILE TIME 

;THE ESSENCE OF THIS CODE IS TO:
;	1 PREPARE 6 FIRING PHASES BY 'AND'ing THE 'PRINTED' PATTERN WITH THE DEFINED 'FIRING' PATTERN (THIS IS NOT IMPLEMENTED
;		 AT THIS TIME. WHAT DOES HAPPEN IS EQUIVALENT TO A BLACK RECTANGULAR OR 'BOX' PRINTED PATTERN).
;	2 PRESENT THE SIX RESULTING PHASES TO THE OUTPUT PINS CAREFULLY DEFINING THE LENGTH OF TIME THE PULSE IS PRESENT,
;		THE TIME BETWEEN SUCCESSIVE PULSE PHASES & THE TIME BETWEEN SUCCESSIVE GROUPS OF PULSES.
;	3 RESPOND TO AN EXTERNAL GO/NOGO SIGNAL AT PIN 11 (RB1). 
;	4 PROVIDE A TOGGLING SIGNAL ON PIN 13 (RB3) TO DRIVE AN LED 'ACTIVITY' LIGHT


	DEVICE	SX28L
;testing			;----1 for test------

IFDEF __SASM ;use SASM
	DEVICE STACKX
	DEVICE OPTIONX
	DEVICE CARRYX
	DEVICE TURBO
	IRC_CAL IRC_SLOW

ifdef testing
	DEVICE	OSCRC ;Use this to RUN with 50MHz resonator
	FREQ 50_000_000	;500_000
else
	DEVICE OSCHS3
;	FREQ 4_000_000	;500_000
endif
;	DEVICE OSCHS3
;	FREQ 4_000_000	;500_000

else ;use Parallax ASM
	DEVICE TURBO,STACKX_OPTIONX, CARRYX	

ifdef testing
	FREQ 50_000_000	;500_000
else
	DEVICE	OSCXT5	;Use this to RUN with 50MHz resonator
endif

ENDIF

	RESET  Init

	SystemClock EQU 50_000_000







;***************************************************************************************
	DEVICE	SX28L,TURBO		;Use this for internal clock & TROUBLESHOOTING. DELAY loops will be incorrect.
;	testing = 0 	 		;Use 1 for internal clock & TROUBLESHOOTING. DELAY loops will be incorrect.
					;Use 0 to RUN with 50MHz resonator

;Assembly OPTIONS
;Warming_Option

;	DEVICE StackX_OptionX, CarryX		
;	RESET  Init

;IF testing = 1	;---- 1 for test------
;	SystemClock EQU 500_000
;	DEVICE	OSC4MHZ		;Use this for internal clock & TROUBLESHOOTING. DELAY loops will be incorrect.
;	FREQ 50_000_000 ;SystemClock  ;50_000_000	;500_000

;ELSE ;use a fixed resonator
;	SystemClock EQU 50_000_000
;	DEVICE	OSCXT5	;Use this to RUN with 50MHz resonator
;	FREQ 500_000 ;SystemClock  ;50_000_000	;500_000

;ENDIF
	InstructionPeriod EQU 1000000000 / SystemClock ;nS

;		THE BOARD AS WIRED HAS, UNFORTUNATELY, DIFFERENT NOZZLE MAPS OUT EACH CONNECTOR.
;Select one. The assembler will map accordingly.
Socket		EQU 2	;1 = Coiner Connector Socket
			;2 = Ribbon Connector Socket
Pattern 	EQU 2 	;1 = ThinkJet pattern
			;2 = QuietJet Pattern

;***************************************************************************************
;Set up default delay constants. These will be located in EEProm so they can be saved at a power outage.

REAL_DEAD_TIME = 10	;DISCONNECTED IN THIS ITERATION. DEAD TIME  IS 100nS. in tenths of uS. i.e. enter 10 for 1.0 uS 
REAL_PULSE_TIME = 45 	;in tenths of uS. i.e. enter 45 for 4.5 uS 
REAL_PULSE_RATE = 1500	;in Hz
Max_Characters	EQU 1000000	;16 average dots per character

;Pick ONE depending on your definition of "enough"

;Max_dots	= Max_Characters * 16 / 12 - 1	;based on 16 dots/character average, 12 nozzles/firing cycle(Blackout)

;Max_dots	=100000000/12			;100 Million actual DOTS

Max_dots	= 200000				;limit of number of 12 dot firing cycles

;***************************************************************************************************************
StoreParameters MACRO
;StoreParameters :Number_of_Firing_Phases, :pulse_width, :Pulse_Delay, :Firing_Rate, :Number_of_Firings_per_Line, :TurnaroundTime, :Lines_Per_Group, :Group_Rest_Time, :Total_Number_of_Firings
;StoreParameters :Number_of_Firing_Phases, :Warm_width, :Fire_Width, :Firing_Rate, :Number_of_Firings_per_Line, :TurnaroundTime, :Lines_Per_Group, :Group_Rest_Time, :Total_Number_of_Firings
retw \1 ;Number_of_Firing_Phases.

;Pulse_Delay or warming pulse duration
if \2 = 0
	retw 0
else
	retw \2 - 2 
endif

;High power pulse length
if \2 = 0
	retw \3 - 3
else
	retw \3 - 6
endif

retw  ((10000000/ \4) - (\1*(\2+\3+4))) /100 & $FF; Firing_Rate Time minus ~ used warming, firing & dead time
retw ((\5-1) // $100) & $FF, ((\5-1) / $100) & $FF ; Number_of_Firings_per_Line
retw ((\6 * 10) / 25) & $FF ;TurnaroundTime
retw \7-1 ;Number of Lines per Group	
retw \8 ;Group_Rest_Time 
retw (\9-1) & $FF, ((\9-1) / $100) & $FF, ((\9-1) / $10000) & $FF, ((\9-1) / $1000000) & $FF ;Total_Number_of_Firings
ENDM

;ORG $400
;_RunParameters jmp PC+W
;include "Blackout Option Switch Parameters.SRC"



;Select one. The assembler will map accordingly.
Strobed		EQU 	0	;0 = Continuous keyed operation w/pin 11 low
				;1 = Strobe synchronized operation on pin 12 (w/pin 11 held low)
;Set Busy Condition ******************************************************************************

;the busy pin is a simulated tri-state operation to use in a wire-or configuration with other boards.
;it is pulled low (busy) here and set as an output on entry to a data load operation.

;the controller invoking this will look to this as an 'ack' of the interrupt and must hold the load 
;strobe and data until the ack is seen. WARNING... this protocol has the potential for lockup.

;this is also used for the light drive.

SetBusyCondition MACRO ;
	CLRB 	Activity_Light
	MODE	$0F			;open Mode to set i/o ports. 0=output, 1=input.
	mov	!RB, #RB_Control & %11110111 ;%00000111		;set RB3 busy pin as output
ENDM
TurnLightOn macro	;just another reference
	SetBusyCondition
endm


ClearBusyCondition MACRO ;************************************************************************
	MODE	$0F			;open Mode to set i/o ports. 0=output, 1=input.
	mov	!RB, #RB_Control | %00001000 	;set RB3 busy pin as input
ENDM

TurnLightOff macro	;just another reference
	ClearBusyCondition
endm

;-----------------------------------------------------------------------------------------------------------
ORG $10 ;******************************************************************************** Define all symbols
;watch Run, 5, ubin
;watch TotalFirings, 32, udec
;watch GroupFirings, 8, udec
;watch LineFiringsLo, 16, udec

Switch		EQU	RA
HighPower	EQU	RB.0
Button		EQU 	RB.1
Activity_Light	EQU 	RB.3
Busy_Signal	EQU	Activity_Light

		ORG	$08	;REGISTER 8 DEFINITIONS
Flag		DS	1	;Data Movement Flags

;	Fire		EQU Flag.0	;Fire Process Running.
;	RateDelay	EQU Flag.1	;Line-to-Lind Delay Process Running.
;	Turnaround	EQU Flag.2	;End-of-Line turnaround simulation delay running.
;	Rest		EQU Flag.3	;End-of-Receipt simulation delay running.
	Run		EQU Flag.4	;Run. Load the switch selected parameters and start the process running
					;Stop. Assure the pen outputs are OFF and hold for Run.

;				REGISTER 9 DEFINITIONS
Process_Flags	DS 	1	;Functional Control Flags
;	Escape_Immediately EQU Process_Flags.0	;Set on each ESC (1Bh) code that arrives, cleared by everything else
						;two ESC's in a row & we STOP whatever we are doing NOW.

;	Null_Phase	EQU Process_Flags.1	;Indicates a firing phase with no data has been discovered.
						;This is set by make_a_line or receipt of a 2 byte null graphic.
						;It is always cleared (often redundantly) by a firing event.  

;	Skipped_a_Phase	EQU Process_Flags.2	;Skip a firing phase (1)
;	Flush		EQU Process_Flags.3	;a change of procedure has been ordered. Flush (1) all existing print info
;	Inhibit		EQU Process_Flags.4	;Inhibit firing of pen(1) and decrement delay counter
;	Reverse		EQU Process_Flags.5	;Reverse(1) (right-to-left), or  Normal(0) (left-to-right) Printing
;	Graphic		EQU Process_Flags.6	;Graphic(1) or Character(0) Printing
;	Inverted	EQU Process_Flags.7	;Inverted(1) or Normal(0) (upright) Printing

i		DS 	1	;scratch variables
j		DS 	1
k		DS 	1

;return_address	DS	1

Interrupts	DS	1	;a place to retain the interrrupt vectors
Input_Basket	DS	1	;a place to catch the incoming nibbles & make the input byte

M_Stack 	DS	1	;a place to hold M when an interrupt occurs 
;-----------------------------------------------------------------------------------------------------------
;BANKS 7x are the timer delay variables

Timers				ORG	$070

ProcessSelectPage	DS	1	;and for register alignment
Number_of_Firing_Phases DS	1	;number of timing phases to fire pen
WarmingTime		DS	1	;.1uS per count @50MHz
FiringTime		DS	1	;.1uS per count @50MHz
RateTime		DS	1	;10uS per count @50MHz
FiringsPerLine		DS	2	;1 firing/count. 65535 Max firings per line
TurnaroundTime		DS	1	;2.5mS per count @50MHz
LinesPerGroup		DS	1	;1 line/count. 255 Max lines
GroupRestTime		DS	1	;1/2 min per count
TotalFirings		DS	4	;1 firing/count. 4,294,967,295 Max firings
ProcessFlagRegister	DS	1	;working copy of flags
CurrentPeriod		DS	2
Pulse_Delay EQU	WarmingTime		
;-----------------------------------------------------------------------------------------------------------
;BANKS 9x & Bx are the Bit_Pattern banks. These locations contain the masks which
;determine which nozzle(s) fire in any Firing_Phase. These are loaded by ESC F and
;default to the a dual sequential ThinkJet pattern. BANK 9x is the high byte (nozzles 5-12)
;BANK Bx is the low nibble (nozzle 1-4) of the 12 nozzle.

;locations 0 and 13-15 are for other purposes only to make things nice or fast.

Bit_Bank_hi			ORG	$090

Line_definition_hi	DS 	1
Bit_Pattern_hi		DS	12

;-----------------------------------------------------------------------------------------------------------
Bit_Bank_lo			ORG	$0B0

Line_Definition_lo	DS 	1
Bit_Pattern_lo		DS	12

;-----------------------------------------------------------------------------------------------------------
;BANKS Dx & Fx are the Firing_Phase_Pattern banks. These are the locations
;where patterns are assembled to send out. BANK Dx is the high byte (nozzles 5-12)
;BANK Fx is the low nibble (nozzle 1-4) of the 12 nozzle, 12 Phase  pattern.
;Switching banks for each firing phase is easier than stacking the variable pairs.

;locations 0 and 13-15 are for other purposes only to make things nice or fast.

Phase_Bank_hi			ORG	$0D0

GroupFirings		DS	1	;number of contiguous lines in a single group
Phase1Hi		DS	12
_500mS_count		DS	1	;these are the DELAY variables. stored here for expediency.
Long_Count		DS	1	;this space is time shared with the max LineFiringsHi run time counter
LineFiringsLo		EQU	Long_Count ;number of contiguous firings in a single line		
LineFiringsHi		DS	1
;-----------------------------------------------------------------------------------------------------------
Phase_Bank_lo			ORG	$0F0

Number_of_Phases	DS	1
Phase1Lo		DS	12

Delay_variables	EQU	Phase_Bank_lo	;name
_100nS_count		DS	1	;these are the DELAY variables. stored here for expediency.
_10uS_count		DS	1	
_2mS_Count		DS	1

;-----------------------------------------------------------------------------------------------------------
;*************************************************************************************** CATCH THE INTERRUPT
;INTERRUPT SERVICE ROUTINE catches only the Start-Stop button

;
IFDEF testing			;----for test------
	ORG 002					;RE-ORG TO 002 to PROVIDE SPACE FOR DEBUG
ELSE	
	ORG 000
ENDIF			;----for test------

_Interrupt	
	mov	M_Stack, M		;save M. who knows where it is being used.

	MODE	$09			;capture the interrupt(s) by swapping WKPEN_B to w...
	mov	!RB, #$00		;clears WKPEN_B of any pending interrupts 
break
	and w, #%00000010		;is it the button
	jz ReturnFromInterrupt		;no. get out

	mov w, #$0F			;stop any drive to the pen
	and RB, w
	clr RC
	
call DebounceButton			;debounce the depressed button

jnb Run, :SetRun
	clrb Run
	jmp ReturnFromInterrupt
	
:SetRun 				;set run flag

	setb Run


ReturnFromInterrupt
	mov	M, M_Stack 		;restore M.
	MODE	$09			
	mov	!RB, #$00		;clears WKPEN_B of any pending interrupts 
	reti

;******************************************************************************************* END Interrupt
Test_Section ;********************************************************************************************
;if testing 		;----for test------
scope EQU Rc.1

jnb scope, :SetBit
	clrb	scope 
	clrb activity_Light
	jmp :clock
:SetBit
	setb activity_Light
	setb scope 
:clock

setb FSR.4

;_Delay_10uS ;****************************************************************************************************
 ;Delay 10uS/cycle of _10uS_Count Max delay ~2.5mS
;Count variable _10uS_count, Phase_Bank_lo. Range 1-255 (10uS-2.5mS)
		BANK	Phase_Bank_hi;lo	;this BANK + the machine cycles in the
;			;register loads, calls & returns add 300nS
;		mov 	_100nS_Count, #1
;		Page Dispatch_Table
;		Call 	Delay_100nS

:Delay_offset	mov 	_500mS_Count, #3
		;value for a 10.08uS cycle
		Page Dispatch_Table
		Call 	Delay_500mS
;		djnz	_uS_Count, :Delay_offset	;Decrement until all are zero		
;		RETP

jmp Test_Section

;ENDIF			;----for test------
;*********************************************************************************************************
Dispatch_Table ;**************************************************************** Subroutine Dispatch Table
Init			jmp	@_Init
ClearBuffer 		jmp	@_ClearBuffer
DebounceButton		jmp 	@_DebounceButton
ReadSwitch		jmp	@_ReadSwitch
LoadParameters		jmp	@_LoadParameters
RunParameters		jmp 	@_RunParameters
PreparePhases		jmp	@_PreparePhases
FireProcess		jmp	@_FireProcess	
Delay_100nS		jmp	@_Delay_100nS
Delay_10uS		jmp	@_Delay_10uS
Delay_2mS		jmp	@_Delay_2mS
Delay_500mS		jmp	@_Delay_500mS
LongDelay		jmp	@_LongDelay
RateDelay		jmp	@_RateDelay
UpdateRunState		jmp	@_UpdateRunState


;two word inst
;InterruptDispatch	jmp	@FireProcess
;jmp	Pc@RateProcess
;			jmp	WaitProcess
;RunParameters		jmp 	@_RunParameters
;Skip_Phase		jmp 	@_Skip_Phase
;Make_a_Line		jmp	@_Make_a_Line
;Forward			jmp	@_Forward
;Set_Reverse		jmp	@_Set_Reverse
;Upright			jmp	@_Upright
;Invert			jmp	@_Invert
;Ready_Line		jmp	@_Ready_Line
;Cold_start		jmp 	@_Init
;Warm_Start		jmp	@_Warm_Start
;Load_Nibble		jmp	@_Load_Nibble
;Release_a_Byte		jmp	@_Release_a_Byte
;Byte_in_Basket				;this is called from anywhere and sets a return address two? bytes beyond the call
					;allowing a return to main line polling while awaiting a new byte to show up
					;when it does show up, it is delivered to the portion of the routine which
					;is waiting for it.

;	inc	return_address		;move the address to return to 
;	inc	return_address		;up two spots.
;	page	_Byte_in_Basket		;correct page and
;	mov	w, return_address	;address.
;	jmp	w			;now process the next byte.

;***************************************************************************************************************
;in order to preserve the accuracy and resolution of the firing process, _Delay_100nS and _FireProcess
;are located in page 0. This eliminates the need for paging or linking through the jump table.
;This is ignored for longer delay times. _Delay_100nS may be accessed directly or through the jump table.
_Delay_100nS ;***************************************************************************************************
;Delay 100nS/cycle of _100nS_Count + 200nS. Max delay ~25uS
;Count variable _100nS_count, Phase_Bank_lo. Range 1-255 (200nS-25.7uS)

		BANK	Phase_Bank_lo	;this BANK + the machine cycles in the
					;register loads, call & return add 200nS
		nop
:Delay_offset	nop			;this nop causes the routine to cycle at even 100nS intervals

		djnz	_100nS_count, :Delay_Offset	;Decrement until all are zero		
		RETP

;***************************************************************************************************************
_FireProcess ;************************************************************************************* Fire the pen

BANK 	Phase_Bank_lo		;set the bank
setb	FSR.4			;assert banking
mov	FSR, Number_of_Phases	;index into Phase bank

:Loop
setb	FSR.4			;re-assert banking
BANK  Timers			;Load the pre-fire (reduced power) time
mov W, WarmingTime

test w	;determine if warming is requested
jz :StartHighPower
	clrb 	HighPower		;assure Low Power
	BANK Phase_Bank_lo		;store it in the clock variable
	mov _100nS_Count, W

	BANK 	Phase_Bank_lo		;Start the pulse
	or 	RB, IND			;set the low bits noz 1-4
	BANK 	Phase_Bank_Hi		;set the bank
	mov	RC, IND			;turn on noz 5-12
	call 	_Delay_100nS		;wait for the prefire time
	
;nop
;nop
nop

:StartHighPower
	BANK  Timers			;Load the final (high power) firing time
	mov W, FiringTime			
	setb HighPower
	nop
	nop
	nop
	nop
	jmp :StartHighPowerPulse

test WarmingTime	;determine if warming is requested
jz :FinishPulse

:StartHighPowerPulse
;	setb HighPower
	BANK Phase_Bank_lo		;store it in the clock variable
	mov _100nS_Count, W
	BANK 	Phase_Bank_lo		;Start the pulse. (This is redundant when pre-warmed.)
	or 	RB, IND			;set the low bits noz 1-4
	BANK 	Phase_Bank_Hi		;set the bank
	mov	RC, IND			;turn on noz 5-12

:FinishPulse
	call 	_Delay_100nS		;fire time

;	call Delay_100nS
	nop
	nop
	nop
	nop
	and RB, #$0f			;now turn off outputs noz 1-4...
	nop
	nop
	clr RC				;noz 5-12...
	clrb 	HighPower		;and High Power

;	mov _100nS_Count, #15		;wait 1.5uS for common voltage to bleed
;	call Delay_100nS		;to lower value

;	nop
;	nop
;	nop

	dec FSR 			;update the index,
	BANK 	Phase_Bank_lo		;set the bank...
	djnz Number_of_Phases, :Loop 	;and go again until all phases are complete

retp

;***************************************************************************************************************
MAIN ;**** MAIN ******** MAIN ******** MAIN ******** MAIN ******** MAIN ******** MAIN ******** MAIN ******** MAIN ****
;call	Test_Section

jb	Run, StartRunProcess
;Stop process
	mov w, #$0F			;stop any drive to the pen
	and RB, w
	clr RC
	TurnLightOn 			;turn light on. the 'ready' condition

:Loop	jnb Run, :Loop
	jmp main

StartRunProcess
inc $0f

	TurnLightOff 			;turn light off. the 'run' condition

	call @ReadSwitch			;read the switch, return with the value in w
	call @LoadParameters		;load the run parameters into RAM 

ContinueRunProcess

	call @PreparePhases
	call @FireProcess
	call @RateDelay			;

;one complete firing cycle is complete... all firing phases and one firing rate delay.
	call @UpdateRunState

	jnb Run, MAIN			;check run status. if stopped, restart main. otherwise...
	jmp ContinueRunProcess		;otherwise, continue firing the pen


;***************************************************************************************************************
_UpdateRunState ;***********************************************************************************************
	jnb Run, :Exit			;well, somebody musta pushed the button to quit now. this short circuits
					;any pending long delays.
;break
	BANK Timers			;otherwise, reset the line counter and do an end-of-line delay
	stc
	sub TotalFirings, #1
	sub TotalFirings+1, #0 ;W
	sub TotalFirings+2, W
	sub TotalFirings+3, W
	jc :FinishALine			;if firings remain
	
	TurnLightOff 			;otherwise, assure light off. the 'run' condition

:StopNormalRun	jb Run, :StopNormalRun	;wait here 'till someone pushes the button again to stop the process, then carry on.
;	clrb Run			;clear run status
	jmp :Exit			;


:FinishALine				;first, update the activity light
	jnb TotalFirings+1.1, :LightOff
		TurnLightOn
		jmp :FinishedServicingLight
:LightOff
		TurnLightOff 
:FinishedServicingLight

	BANK Phase_Bank_hi
	stc				;have we finished a line
	sub LineFiringsLo, #1
	sub LineFiringsHi, #0
	jc :Exit			;line not done, continue printing.
	
	BANK Timers			;otherwise, reset the line counter and test for group end
	mov i, FiringsPerLine		;copy the line firing times
	mov j, FiringsPerLine+1		

	BANK Phase_Bank_hi		
	mov LineFiringsLo, i		;to the counter variables
	mov LineFiringsHi, j

	stc				;have we finished a group
	sub GroupFirings, #1
	jnc :GroupResetDelay

;line delay

	BANK Timers			;do an end-of-line delay
	mov W, TurnaroundTime 		
	BANK Phase_Bank_Lo		
	mov _2mS_count, W
	jz :GroupResetDelay		;bypass the delay if non is requested

	Page Dispatch_Table
	jmp Delay_2mS			;do the delay and let the delay return bring us back to MAIN


:GroupResetDelay
;break
	BANK Timers			
	mov i, GroupRestTime
	mov W, LinesPerGroup		;copy the group count parameter...
	
	BANK Phase_Bank_hi			
	mov GroupFirings, W		;to the counter & timer variables
	mov Long_Count, i
	jz :NoGroupDelay		;bypass the delay if non is requested

	Page Dispatch_Table
	call @LongDelay			;do the delay

:NoGroupDelay
	BANK Timers			;and reset the line counter damaged by the 500mS loop
	mov i, FiringsPerLine		;copy the line firing times
	mov j, FiringsPerLine+1		

	BANK Phase_Bank_hi		
	mov LineFiringsLo, i		;to the counter variables
	mov LineFiringsHi, j

:Exit retp

;***************************************************************************************************************
_RateDelay ;********************************************************************************** Firing Rate Delay
	BANK  Timers			;Load the pre-fire (reduced power) time
	mov W, RateTime

	BANK Phase_Bank_lo		;store it in the clock variable
	mov _10uS_Count, W
	Page Dispatch_Table
	call Delay_10uS
;2.6uS
	BANK Phase_Bank_lo		;store it in the clock variable
	mov _100nS_Count, #26		;add 5.2uS to correct average at 10KHz
	Page Dispatch_Table
	call Delay_100nS
retp
;***************************************************************************************************************
_PreparePhases ;************************************************************************************************

	setb FSR.4					;point to run parameters
	bank Timers
	mov W, Number_of_Firing_Phases			;locate Number_of_Firing_Phases		

	bank Phase_Bank_lo
	mov Number_of_Phases, W				;use it as loop counter $

	mov FSR, W					;loop index
	mov i, W					;and save it for later
	setb FSR.4

:Loop							;mask the Line_Definition with the phase bits &
							;place the results in the Phase_Bank
	BANK	Bit_Bank_Hi
	mov	W, Line_Definition_Hi
	and 	W, IND
	BANK	Phase_Bank_Hi
	mov	IND, W

	BANK	Bit_Bank_Lo				
	mov	W, Line_Definition_Lo
	and 	W, IND
	BANK	Phase_Bank_Lo
	mov	IND, W

	dec FSR
	djnz Number_of_Phases, :Loop ;through the phases

	mov Number_of_Phases, i				;restore the Number_of_Phases for the fire process
retp

;ORG $200
;***************************************************************************************************************
_Delay_10uS ;****************************************************************************************************
 ;Delay 10uS/cycle of _10uS_Count Max delay ~2.5mS
;Count variable _10uS_count, Phase_Bank_lo. Range 1-255 (10uS-2.5mS)

:Delay_offset	mov 	_100nS_Count, #97	;value for a 10.uS cycle
		Page Dispatch_Table
		Call 	Delay_100nS
		djnz	_10uS_Count, :Delay_offset	;Decrement until all are zero		
		RETP

;***************************************************************************************************************
_Delay_2mS ;*****************************************************************************************************
;Delay 2.mS/cycle of _2mS_Count. Max delay ~620mS
;Count variable _2mS_Count, Phase_Bank_lo. Range 1-255 (20uS-2.mS)
		BANK	Phase_Bank_lo	;forget about the little errors here.

:Delay_offset	mov 	_10uS_Count, #200	;value for a 2.0mS cycle
		jnb run, :ExitDelay		;in case someone requested a stop

		Page Dispatch_Table
		Call 	Delay_10uS

	jnb _2mS_Count.5, :LightOff		;first, update the activity light
		TurnLightOn
		jmp :FinishedServicingLight
:LightOff
		TurnLightOff 
:FinishedServicingLight

		djnz	_2mS_Count, :Delay_offset	;Decrement until all are zero		
:ExitDelay	RETP

;***************************************************************************************************************
_Delay_500mS ;*****************************************************************************************************
;Delay 500mS/cycle of _500mS_Count. Max delay ~2min
;Count variable _500mS_Count, Phase_Bank_hi. Range 1-255 (.5 S-128 S)

		BANK	Phase_Bank_lo	;hi	;forget about the little errors here.

:Delay_offset	mov 	_2mS_Count, #250	;value for a .5 S cycle

		Page Dispatch_Table
		Call 	Delay_2mS
		BANK	Phase_Bank_hi

	jnb _2mS_Count.5, :LightOff		;update the activity light so long delays show activity
		TurnLightOn
		jmp :FinishedServicingLight
:LightOff
		TurnLightOff 
:FinishedServicingLight

		djnz	_500mS_Count, _Delay_500MS	;offset	;Decrement until all are zero		
:ExitDelay	RETP

;***************************************************************************************************************
_LongDelay ;*****************************************************************************************************
;Delay .5 Min/cycle of LongDelay. Max delay ~2.25 hr
;Count variable _1Min_Count, Phase_Bank_hi. Range 1-255 (1 S- 4.25 min)
		BANK	Phase_Bank_hi	;forget about the little errors here.

:Delay_offset	mov 	_500mS_Count, #120	;value for a 1 Min. cycle

		Page Dispatch_Table
		Call 	Delay_500mS
		BANK	Phase_Bank_hi
		djnz	Long_Count, :Delay_offset	;Decrement until all are zero		
:ExitDelay	RETP

;***************************************************************************************************************
_ReadSwitch ;****************************************************************** read the binary switch position
;								                and return with the value in w
	mov w, Switch
	xor w, #$0F
	
	snz
	mov w, #16		;convert the 'zero' position to 16
	retp

;***************************************************************************************************************
_DebounceButton ;********************************************************************* Debounce the Start Button
ButtonDown
		mov i, #$03		;debounce the button down
		mov j, w

:loop		jb Button, ButtonDown 	;oh oh. a bounce. start over
		djnz j, :Loop
		djnz i, :Loop

:ButtonUp	
		mov i, #$03		;debounce the button up
		mov j, w

:loop2		jnb Button, :ButtonUp	;debounce the button up
		djnz j, :Loop2
		djnz i, :Loop2

		retp

;****************************************************************************************** Start Hardware Initialization
_ClearBuffer ;************************************************************************clear any pending patterns

BANK	Phase_Bank_lo
	mov i, Number_of_Phases
:Loop	mov	FSR, i
	setb fsr.4
	BANK	Phase_Bank_hi
	clr IND
	BANK	Phase_Bank_lo
	clr IND
	djnz i, :Loop
	retp


;*************************************************************************************************************

;****************************************************************************************** END Initialization

;ORG $400
;***************************************************************************************************************
_LoadParameters ;*****************************************************load the parameters for this test position
;the test position is in w

;create the entry index to the tables
mov i, W				;save the switch entry
;mov j, #(Selection_2 - Selection_1)	;load the offset between tables

clr FSR
clc

:loop					;generate the selection offset index
	add FSR, j
	djnz i, :Loop
	mov i, FSR			;save the index into the selection table

LoadTheRAM

	mov FSR, j			;prepare the index into RAM
	BANK Timers				
	setb FSR.4

	dec i 				;decrement the index
	mov W, i			
	Page Dispatch_Table
	call RunParameters		;get the data

	mov IND, W			;save it in RAM

	djnz j, @LoadTheRAM		;loop 'till all done

	mov i, FiringsPerLine		;set up the line firing counter
	mov j, FiringsPerLine+1		
	mov W, LinesPerGroup		;copy the group count parameter...
 
	BANK Phase_Bank_hi
	mov GroupFirings, W		;to the counter & timer variables
	mov LineFiringsLo, i
	mov LineFiringsHi, j

retp

;***************************************************************************************************************
;ORG $400 ;********************************************************************** Prepare the run-time parameters
ORG $400
_RunParameters jmp PC+W
include "Blackout Option Switch Parameters.SRC"

;***************************************************************************************************************
ORG $600 ;************************************************************************ Start Hardware Initialization

_Init   

MODE	$0B			;open mode to ENABLE INTERRUPTs. 0=Enabled , 1=Disabled
	mov	!RB, #%11111111

TurnLightOn	;Set RB and immediately force busy condition on RB3 indicating power on.

teste 
inc $f
nop
nop
jmp teste


	clr	Switch	;preset these to zero before turning on outputs
	clr	RB
	clr	RC

IFDEF Chip52
	clr	RD
	clr	RE
ENDIF

;Setup I/O pins		
MODE	$0F			;open Mode to set i/o ports. 0=output, 1=input.
	mov	!RA, #%00001111	;RA0-3 as input for nibble load
	mov	!RC, #%00000000	;RC to output for pen.

;ifdef Warming_Option
;	RB_Control EQU %00000110
;else
	RB_Control EQU %00000111
;endif

				;RB0 not used
				;RB1 on-off button
				;		lo button pressed
				;RB2 fire strobe
				;		lo - print now! Interrupt.
				;RB3 busy flag	hi -  power on, waiting
				;		cycling - process running
				;		lo -  process end

;TurnLightOn	;Set RB and immediately force busy condition on RB3 indicating power on.

	MODE	$0F			;open Mode to set i/o ports. 0=output, 1=input.
	mov	!RB, #00 ;#RB_Control & %11110111 ;%00000111		;set RB3 busy pin as output

clrb RB.3
;teste nop
nop
jmp teste

IFDEF Chip52
	mov	!RD, #%00001111	;Set RD hi nibble &
	mov	!RE, #%00000000	;RE to output for pen 2. RD lo nibble unused.
ENDIF

MODE	$0E			;open mode to set pullups 0=enabled, 1=disabled.
	mov	!RA, #%00000000	;on
	mov 	!RB, #%11110000	;off/on
	mov 	!RC, #%11111111	;off

IFDEF Chip52
	mov	!RD, #%11110000	;off/on
	mov 	!RE, #%11111111	;off
ENDIF

MODE	$0D			;open mode for TTL/CMOS Input Config. 0=CMOS, 1=TTL
	mov	!RA, #%00001111
	mov	!RB, #%11111111	;ditto	

MODE	$0C			;open mode to set SCHMITT TRIGGER. 0=enabled, 1=disabled.
	mov 	!RB, #%11111000	;off/on

MODE	$0A			;open mode for edge detection. 0=Rising , 1=Falling
	mov	!RB, #%00000010	;1 = button

MODE	$09			;open mode for PENDING REGISTER access. 0=Clear , 1=Set
				;This sequence is required as part of interrupt processing too.
	mov	!RB, #%00000000	;clear everything	

;****************************************************************************************** Start Firmware Initialization
;***************************************************************************************************************
_Warm_Start

IFDEF testing			;----for test------clear out all the registers

mov FSR, #$10		;first the page resisters
:loop clr ind
	inc fsr
	setb fsr.4		;set banking and expect it for the rest of the initialization
	stc
	cjne fsr, #$10, :loop	;10
	
	clr $08		;now the GP registers
	clr $09
	clr $0A
	clr $0B
	clr $0C
	clr $0D
	clr $0E
	clr $0F

ENDIF		;----for test------
;*******************************************


DEFAULT ;Variable initiation 
mov	Interrupts, #$00	;preset to 'no pending interrupts'

BANK	Phase_Bank_hi
;load dead time in 100nS (Phase delay 300nS min)
;	mov	Dead_Time, #2	;1 			;*100+200nS

BANK	Bit_Bank_lo

;load rate (full firing period) in Hz (everybody uses Hz)
;	mov 	Cycle_Time_lo, #100000//3000//10	;100000/f//10 where f = freq in Hz

;	mov 	Cycle_Time_hi, #100000/3000		;100000/f where f = freq in Hz

BANK	Phase_Bank_lo
;load pulse width in uS (4.5uS)
;	mov	Pulse_Time, #45 - Delay_Overhead		;in 100nS

;load number of half-dot phases (6)
	mov Number_of_Phases, #12	;allows dots to be cleared before run parameters are loaded

;***************************************************************************** Pen Firing Patterns
;*************************************************************************************************
Default_Pen_Firing_Pattern

IF Socket = 1; Coiner Connector Socket

	IF Pattern = 1		; Coiner ThinkJet

BANK	Bit_Bank_hi				;ALL PATTERNS ARE LEFT JUSTIFIED IN THE HI-LO BYTE PAIR
	mov Bit_Pattern_hi,   #%00000100
	mov Bit_Pattern_hi+1, #%00001000
	mov Bit_Pattern_hi+2, #%00010000
	mov Bit_Pattern_hi+3, #%00100000
	mov Bit_Pattern_hi+4, #%01000001
	mov Bit_Pattern_hi+5, #%10000010
BANK	Bit_Bank_lo
	mov Bit_Pattern_lo,   #%00010000
	mov Bit_Pattern_lo+1, #%00100000
	mov Bit_Pattern_lo+2, #%01000000
	mov Bit_Pattern_lo+3, #%10000000
	mov Bit_Pattern_lo+4, #%00000000
	mov Bit_Pattern_lo+5, #%00000000
	ENDIF

	IF Pattern = 2		; Coiner QuietJet
BANK	Bit_Bank_hi
	mov Bit_Pattern_hi,   #%00100000
	mov Bit_Pattern_hi+1, #%00001000
	mov Bit_Pattern_hi+2, #%10000010
	mov Bit_Pattern_hi+3, #%00010000
	mov Bit_Pattern_hi+4, #%00000100
	mov Bit_Pattern_hi+5, #%01000001
BANK	Bit_Bank_lo
	mov Bit_Pattern_lo,   #%10000000
	mov Bit_Pattern_lo+1, #%00100000
	mov Bit_Pattern_lo+2, #%00000000
	mov Bit_Pattern_lo+3, #%01000000
	mov Bit_Pattern_lo+4, #%00010000
	mov Bit_Pattern_lo+5, #%00000000
	ENDIF
ENDIF

IF Socket = 2; Ribbon Connector 
	
	IF Pattern = 1		; Ribbon Connector ThinkJet
BANK	Bit_Bank_hi
	mov Bit_Pattern_hi,   #%00001000
	mov Bit_Pattern_hi+1, #%00000100
	mov Bit_Pattern_hi+2, #%00100000
	mov Bit_Pattern_hi+3, #%00010000
	mov Bit_Pattern_hi+4, #%10000010
	mov Bit_Pattern_hi+5, #%01000001
BANK	Bit_Bank_lo
	mov Bit_Pattern_lo,   #%00100000
	mov Bit_Pattern_lo+1, #%00010000
	mov Bit_Pattern_lo+2, #%10000000
	mov Bit_Pattern_lo+3, #%01000000
	mov Bit_Pattern_lo+4, #%00000000
	mov Bit_Pattern_lo+5, #%00000000
	ENDIF

	IF Pattern = 2		; Ribbon Connector QuietJet
BANK	Bit_Bank_hi
	mov Bit_Pattern_hi,   #%00010000
	mov Bit_Pattern_hi+1, #%00000100
	mov Bit_Pattern_hi+2, #%01000001
	mov Bit_Pattern_hi+3, #%00100000
	mov Bit_Pattern_hi+4, #%00001000
	mov Bit_Pattern_hi+5, #%10000010
BANK	Bit_Bank_lo
	mov Bit_Pattern_lo,   #%01000000
	mov Bit_Pattern_lo+1, #%00010000
	mov Bit_Pattern_lo+2, #%00000000
	mov Bit_Pattern_lo+3, #%10000000
	mov Bit_Pattern_lo+4, #%00100000
	mov Bit_Pattern_lo+5, #%00000000
	ENDIF
ENDIF

;assemble for timing test. fires all nozzles all the time *************************************
;BANK	Bit_Bank_hi
;	mov Bit_Pattern_hi,   #%11111111
;	mov Bit_Pattern_hi+1, #%11111111
;	mov Bit_Pattern_hi+2, #%11111111
;	mov Bit_Pattern_hi+3, #%11111111
;	mov Bit_Pattern_hi+4, #%11111111
;	mov Bit_Pattern_hi+5, #%11111111
;BANK	Bit_Bank_lo
;	mov Bit_Pattern_lo,   #%11110000
;	mov Bit_Pattern_lo+1, #%11110000
;	mov Bit_Pattern_lo+2, #%11110000
;	mov Bit_Pattern_lo+3, #%11110000
;	mov Bit_Pattern_lo+4, #%11110000
;	mov Bit_Pattern_lo+5, #%11110000
;**********************************************************************************************

	BANK	Phase_Bank_Lo
	setb	Phase1Lo.0			;signal to skip a phase

DefaultIO_Flags		EQU %00000011	  	; Set 	 ? undefined
						;0 1 = RTCC clock divide by 256
						;1 1 = Phases busy
						;2 0 = Lines available
						;3 0 = Address' available 
						;4 0 = Char_code is available   
						;5 0 = prohibit release of a byte from FIFO 
						;6 0 = permit a character to load to FIFO
						;7 0 = Byte not ready
;	mov	IO_Flags, #DefaultIO_Flags

DefaultProcessFlag	EQU %00000000		; Set
						;0 0 = escape immediately
						;1 0 = phases good	
						;2 0 = have not skipped a phase
						;3 0 = do not flush buffers 
						;4 0 = do not inhibit printing
						;5 0 = printing left to right
						;6 0 = printing character
						;7 0 = printing upright

	mov	Process_Flags, #DefaultProcessFlag

	call 	@ClearBuffer

	BANK	Bit_Bank_Lo			;define line to print
	mov	Line_Definition_Lo, #$F0
	BANK	Bit_Bank_Hi
	mov	Line_Definition_Hi, #$FF
;	BANK	Timers				;collect the power-on switch position for selecting data page
;	mov	W, Switch
;	xor	w, #$0F
;	mov	ProcessSelectPage, W

	clrb run
MODE	$0B			;open mode to ENABLE INTERRUPTs. 0=Enabled , 1=Disabled
	mov	!RB, #%11111101	;bit 1 = button

;teste jmp teste
jmp @Main	;begin

;*************************************************************************************************************
;IFNDEF testing			;----for Run------
;ORG	$7f0 ;********************************************************************************* Revision Date
;DW 'ROGER'
;DW 10,12,05		;Rev. Date
;DW $001			;Serial #

;ENDIF			;----for test------
;***************************************************************************************************************
