// PrintOrbitInit.bcpl

// last modified by Butterfield, October 13, 1980  3:49 PM
// - ResolutionB, ResolutionS, 1X instead of 10X - 10/13/80

// errors 1100
//

get "Orbit.D"
get "PressInternals.DF"
get "PressParams.DF"

// outgoing procedures
external
	[
	OrbitInit
	]

// outgoing statics
//external
//	[
//	]
//static
//	[
//	]

// incoming procedures
external
	[
	PressError

//FLOAT
	FLDI
	FTR; FCM; FLD; FML; FDV

//PRESSML
	MulDiv

//OS
	Zero
	MoveBlock
	StartIO
	CallSwat
	]

//outgoing statics
external
	[
	nLeadingBands
	nVisibleBands
	nTrailingBands
	FA

	PaperSpeedInches
	ScanLengthInches
	BitClock
	BitScale
	MotorSpeed
	MotorScale
	LineSyncDelay
	PageSyncDelay
	VideoGate
	Tadapter
	]
static
	[
	nLeadingBands
	nVisibleBands
	nTrailingBands
	FA=0	//set to zero so non-orbit devices will do CoordsConvert correctly

	PaperSpeedInches
	ScanLengthInches
	BitClock
	BitScale
	MotorSpeed
	MotorScale
	LineSyncDelay
	PageSyncDelay
	VideoGate
	Tadapter
	]

// incoming statics
external
	[
	ResolutionS
	ResolutionB
	PaperDimensionB
	PaperDimensionS
	SLOTScanMarginAdjust
	SLOTBitMarginAdjust

	signalBand

	Debug
	printerDevice
	]

// internal statics

// File-wide structure and manifest declarations.

manifest RTC=430b

// Procedures

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

let OrbitInit(directive) be
[	//TEST:first reset statics appropriately for "Spruce-style" values
	signalBand=8588

if printerDevice eq printerPuffin then
	PaperDimensionS=PaperDimensionS*2	//scan line doubling

//compute information for image-generation (nVisibleBands,FA)
	let nBitsPerScan = MulDiv(ResolutionB, PaperDimensionB, 10);
	nBitsPerScan=(nBitsPerScan+63)&(-64)	//make multiple of 64
	if nBitsPerScan gr 4096 then nBitsPerScan=4096	//condition report needed....
	FA=(4096-nBitsPerScan)/16

	let nScanLines = MulDiv(ResolutionS, PaperDimensionS, 10);
	nVisibleBands=(nScanLines+BANDWidth-1)/BANDWidth

// Parameters of printer mentioned in Orbit writeup:
//	Paper speed: PaperSpeedInches (inches/second * 10)
//	Duty cycle: d (percent)
//	ScanLength: ScanLengthInches (inches*10)
//	Facets: f
//		(Code assumes 24 clocks/polygon revolution)
	let d,f,r=nil,nil,nil
	let t = selecton printerDevice into	//d;f;r
	  [
	  case printerDover:		table [ 90; 32; 24 ]
	  case printerDurango:	table [ 95; 32; 12 ]
	  case printerSequoia:	table [ 90; 36; 24 ]
	  case printerPuffin:		table [ 99; 22; 24 ]
	  case printerPimlico:		table [ 87; 12; 24 ]
	  default: valof [ CallSwat("Impossible") ]
	  ]
	MoveBlock(lv d, t, 3)

	let printerSimple = printerDevice eq printerSequoia 

// Decide which adapter we are using:
	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=selecton printerDevice into
	 [	case printerDurango: 0
		default: 4
	 ]
	nTrailingBands=selecton printerDevice into
	 [	case printerDurango: 0
		case printerPuffin: (384+192)/16+2
		default: 2
	 ]

// Now do some calculations:
	FLDI(1, ResolutionS); FLDI(2, 10); FML(1, 2);
	FLDI(2, PaperSpeedInches)
	FML(1, 2)
	FLDI(2, f)
	FDV(1, 2)
	Op10(1, -2)		//AC1=MotorRPS

	FLDI(2, crystalClock)
	Op10(2, 5)
	FDV(2, 1)
	FLDI(3, r*256)	//r * 2**8
	FDV(2, 3)			//AC2= (4096-MotorSpeed)/Scale(MotorScale)
	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(3, ResolutionB); FLDI(2, 10); FML(3, 2);
	FLDI(2, ScanLengthInches)
	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 CallSwat("SpruceCondition(1100,ECFileTerminate)")

	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

	LineSyncDelay=4096-SLOTBitMarginAdjust/4
	PageSyncDelay=4096-SLOTScanMarginAdjust/4

	let nBands=nVisibleBands+nLeadingBands+nTrailingBands
	VideoGate=4096-(nBands*4)
	// Widen the gate a bit
	if printerDevice ge printerPimlicoAlt then VideoGate = VideoGate-2

// 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)
		FLDI(2, 90); FML(1, 2); FLDI(2, 1000); FDV(1, 2);	//Inches in 900 ms.
		FLDI(2, ResolutionS)
		FML(1, 2)		//Scan-lines in 920ms.
		let sl=FTR(1)
		sl=sl-4*(4096-PageSyncDelay)	//sl now relative to bands
		sl=(nBands-sl/16)
		if sl ls 0 then [ CallSwat("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
		]

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

and Durango(directive) be
[
	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
[
	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 AdCommand(x) be IFunc(fROSCommand, x)

and IFunc(f, x) be
[
	if Debug then return
	let tab=vec 10
	tab=(tab+1)&(-2)
	tab!0=f
	tab!1=x
// Get microcode to see command:
	@#720=tab
	StartIO(#4)
// Wait for microcode to complete
	while @#720 ne 0 do loop
]

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
// JTM, May 1, 1979  9:48 AM,Puffin