// P R I N T I N I T   
// errors 1100
//

get "Spruce.d"
get "Orbit.d"

// outgoing procedures
external
	[
	PrintInit
	]

// incoming procedures
external
	[
	SpruceError; SpruceCondition
//FLOAT
	FLDI
	FTR; FCM; FLD; FML; FDV
//SPRUCEML
	MulDiv
// SprucePrintRes
	PrintSetParameters
	ROSStatus
//OS
	Zero
	MoveBlock
	StartIO
	CallSwat
	]

// incoming statics
external
	[
	ResolutionS
	ResolutionB

	ScanLengthInches
	PaperSpeedInches
	ScanMarginAdjust
	BitMarginAdjust
	DutyCycle
	Facets
	PolygonRatio
	printerDevice
	Debug
	Func

// Set here, based on above values
	AdapterScales
	BitClock
	MotorSpeed
	LineSyncDelay
	PageSyncDelay
	VideoGate
	scanTicks
	signalBand
	nVisibleBands
	nLeadingBands
	nTrailingBands
	FA
	]

// File-wide structure and manifest declarations.

manifest RTC=430b
// ~~ should be manifest, after correct value known
static gateWidener = 2

// Procedures

// PrintInit
// directive=0 ... standard
// directive=1 ... power on
// directive=2 ... power off

let PrintInit(directive) be
[
// Parameters of printer mentioned in Orbit writeup:
//	Paper speed: PaperSpeedInches (inches/second * 100)
//	Duty cycle: d (percent)
//	ScanLength: ScanLengthInches (inches*10)
//	Facets: f
//		(Code assumes 24 clocks/polygon revolution)

	let d,f,r=DutyCycle, Facets, PolygonRatio
	let printerSimple = printerDevice eq printerSequoia
	let density = (printerDevice eq printerPuffin)?2,1	//orbit doubles scan lines for puffin
	let v = vec 20
	Func = (v+1)&(-2) // For Orbit microcode control table
	let machineSerial = ROSStatus(11) // ~~ interim version differentiation
	if (printerDevice eq printerDover) & ( machineSerial ge SerialDoverHesso) do
		[ d = 90; f = 12; r = 12 ]	/// belongs in installation ~~~~~~~~~~~~~
// Decide which adapter we are using:
	let Tadapter=true
	// if printerDevice eq printerDurango then Tadapter=false
// Parameters of the adapter mentioned in the writeup.
//	bcMax:	MHz
//	crystalClock: 250 or 125 (units of 100 KHz)
	let bcMax,crystalClock=20,125
	unless Tadapter then bcMax,crystalClock=60,250

// Parameters relating to choice of band position on page:
	nLeadingBands=4 // selecton printerDevice into [
		// case printerDurango: 0
		// default: 4
		// ]
	nTrailingBands=2 // selecton printerDevice into [
		// case printerDurango: 0
		// default: 2
		// ]

// Now do some calculations:

// Scan ticks (see SprucePrint) for "laser on test"
	  scanTicks = MulDiv(106, 1000, (ResolutionS*density/10)*(PaperSpeedInches/100)) lshift 6

// Motor speed settings
	FLDI(1, ResolutionS*density)	// scaled by 10
	FLDI(2, PaperSpeedInches) // scaled by 100
	FML(1, 2)
	FLDI(2, f)
	FDV(1, 2)
	Op10(1, -3)		//AC1=MotorRPS (eliminate scale factors)

	FLDI(2, crystalClock)
	Op10(2, 5)
	FDV(2, 1)
	FLDI(3, r*256)	//r * 2**8
	FDV(2, 3)			//AC2= (4096-MotorSpeed)/Scale(MotorScale)
	let motorScale=7
		[
		FLDI(3, 1 lshift motorScale)
		FML(3, 2)
		FLDI(4, 4096)
		if FCM(3, 4) ls 0 then break
		motorScale=motorScale-1
		] repeat
	MotorSpeed=4096-FTR(3)

//BitClock calculation
	FLDI(2, ScanLengthInches)
	FLDI(3, ResolutionB)
	FML(2, 3)			//AC2 = Bh*100
	FLD(3, 2)
	FLDI(4, 4)
	FDV(3, 4)
	Op10(3, -2)
	BitClock=4096-FTR(3)

//Now for BitRate (in MHz)
	FLDI(3, d)
	FDV(2, 3)
	FML(2, 1)
	FLDI(3, f)
	FML(2, 3)
	Op10(2, -6)		//AC2 = BitRate (MHz)

	FLDI(3, 10); FML(3, 2)
	if FTR(3) gr 230 then SpruceCondition(1100,ECFileTerminate)

	let bitScale=7
		[
		FLDI(3, 1 lshift bitScale)
		FLDI(4, bcMax)
		FML(3, 4)
		FDV(3, 2)
		let a=FTR(3)
		if a ls 256 then break
		bitScale=bitScale-1
		] repeat

	
	// set up actual adapter argument here, because both PrintSetParameters() and Print() use it
	AdapterScales = adSetScales + bitScale lshift 9 + motorScale lshift 6

// Adapters with serial numbers less than SerialLineMod count the Scan delay with
// a signal 1/4 the rate of the line counter; later adapters use the line counter directly
// Line delay is still figured in terms of 1/4 the rate of the bit clock

	LineSyncDelay=4096-BitMarginAdjust/4
	PageSyncDelay=4096-(ScanMarginAdjust*density)/(machineSerial<SerialLineMod? 4, 1)

	let nBands=(nVisibleBands+nLeadingBands+nTrailingBands)*density
	// ~~ widen equally for all printers, using a static, for now
	VideoGate=4096-(nBands*4)-gateWidener*density

// Now calculate, for Dover, the band number in which CountH
// should be tested and/or StartPrint for next page sent. First, find
// number of scan-lines in 900 ms. (Note that on Dover now, this
// is a VERY PRECISE NUMBER, even though it doesn't look it.  As
// nearly as I can tell, CountH is on for less than 20 ms.)
	if printerDevice eq printerDover then
		[
		FLDI(1, PaperSpeedInches/10) // 1 is now PaperSpeed*10
		FLDI(2, 90); FML(1, 2); FLDI(2, 10000); FDV(1, 2)	//Inches in 900 ms./10
		FLDI(2, ResolutionS)
		FML(1, 2)		//Scan-lines in 920ms.
		let sl=FTR(1)
		sl=sl-ScanMarginAdjust //less scan lines between PageSync and DelayedPageSync
		sl=(nBands-sl/16)	  // in band units, count down mode
		if sl ls 0 then [ SpruceCondition(1101, ECFileTerminate); sl=0 ]
		signalBand=sl
		]

// Calculate, for Sequoia, the band number in which to issue
// StartPrint (or StopPrint) for the next page
	if printerSimple then
		[
		signalBand=(3*nBands)/4
		]

	PrintSetParameters()	// Now issue the values to the adapter

// Do power-up and down stuff if necessary:
	// if directive ne 0 & printerDevice eq printerDurango then
	// 	Durango(directive)
]

and Durango(directive) be [ compileif false then 
[
	let OnTable=table
			[
//Power up sequence
			#00000;    10;  //adapter buffer reset
			#47760;    10;  //line sync delay
			#57750;   100;  //page sync delay
			#74000;   100;  //turn on polygon
			#76000;   100;  //A/O modulator on
			#77000;   100;  //HeCd laser
			#77400;   100;  //HeNe laser
			#77600;   100;  //PMT
			#77640;   100;  //Fans
			#77650;   100;  //Motor Out
			#77651;  1000;  //turn on 9200
			#77650;    10;  //turn off the on relay
			#63004;    10;  //reset controller
			#61002;    10;  //9200 full sorter
// Enter Dipole mode
			#63004;    10;  //reset controller
			#61004;    10;  //set dipole mode
			#63020;   100;  //clear all
			#63440;   100;  //push aux tray button
			#63400;    10;  //release aux tray button
			#63420;   100;  //push sorter sets button
			#63400;    10;  //release sorter sets button
			#77660;  8000;  //Mirror motor in
			-1;  //terminate
			]

	let OffTable=table
			[
// Enter copy mode
			#00000;    10;  //buffer reset
			#77650;  8000;  //retract mirror motor
			#63004;    10;  //reset controller
			#63020;    10;  //clear all
			#61002;    10;  //9200 full sorter
// Power down Durango
			#70010;  10;
			#63600;  10;
			-1;
			]
	ChangeState((directive eq 1? OnTable, OffTable))
] ]

and ChangeState(tab) be [ compileif false then [
[
	if tab!0 eq -1 then break
	AdCommand(tab!0)
	let done=@RTC+MulDiv(tab!1, 27, 1000)
	while (@RTC-done) le 0 do loop
	tab=tab+2
] repeat  ] ]

and Op10(ac, n) be
[
	FLDI(0, 10)
	test n ge 0 then for i=1 to n do FML(ac, 0) or
		for i=1 to -n do FDV(ac,	0)
]

// DCS, September 19, 1977  11:25 PM, add printerPimlico and printerPimlicoAlt
// September 22, 1977  10:32 AM, correct Pimlico parameters
// September 30, 1977  9:39 PM, Widen Video Gate (for Pimlico)
// October 28, 1977  8:34 AM, Pimlico
// January 18, 1978  10:37 AM, add scanTicks -- "laser on test" for Dover
// January 20, 1978  4:40 PM, remove PimlicoAlt
// January 20, 1978  5:33 PM, disable Durango
// January 20, 1978  11:33 PM, move adapter setup to Spruceprintres
// March 14, 1978  6:38 PM, Set Signal Band, Scan Adjust based on serial number to detect
//				whether scan line mod has been made
// March 27, 1978  2:44 PM, add gateWidener static, to test Dover problems
// April 17, 1978  5:02 PM, calculate adapter command AdapterScales, replacing BitScale and MotorScale
// June 13, 1978  8:19 AM, PaperSpeedInches scaled by 100, for "accuracy" to hundredths
// October 17, 1978  3:13 PM, add Puffin. BWB
// December 6, 1978  11:37 AM use DutyCycle, Facets, PolygonRatio instead of local table
// February 28, 1979  12:27 PM add factor for orbit's doubling of scanlines on puffin
// April 25, 1979  2:29 PM, use SerialDoverHesso to detect Dover with Hesso ROS
// September 17, 1979  3:11 PM, get order right on PageSyncDelay calculation
//