// PrintOrbitInit.bcpl -- calculates various Orbit parameters, but does
//	not operate the hardware

// errors 1100
//

get "PDInternals.d"
get "Orbit.d"

// outgoing procedures
external
	[
	OrbitInit
	]

//outgoing statics
external
	[
	nLeadingBands
	nVisibleBands
	nTrailingBands
	FA
	orbitSignalBand

	BitClock
	BitScale
	MotorSpeed
	MotorScale
	LineSyncDelay
	PageSyncDelay
	VideoGate
	]
static
	[
	nLeadingBands
	nVisibleBands
	nTrailingBands
	FA=0
	orbitSignalBand

	BitClock
	BitScale
	MotorSpeed
	MotorScale
	LineSyncDelay
	PageSyncDelay
	VideoGate
	]

// incoming procedures
external
	[
	PDError

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

//PDML
	MulDiv

//OS
	Zero
	MoveBlock
	StartIO
	]

// incoming statics
external
	[
	printerDevice
	rosDevice
	ResolutionS
	ResolutionB
	PaperDimensionB
	PaperDimensionS
	ScanMarginAdjust
	BitMarginAdjust
	PaperSpeedInches
	SLOTScanLength

	Debug
	]

// internal statics

// File-wide structure and manifest declarations.

manifest RTC=430b
manifest OrbitBandWidth=16

// Procedures



let OrbitInit() be
[
//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);
	if rosDevice eq printerPuffin then
		nScanLines=nScanLines*2	//scan line doubling
	nVisibleBands=(nScanLines+OrbitBandWidth-1)/OrbitBandWidth

// Parameters of printer mentioned in Orbit writeup:
//	Paper speed: PaperSpeedInches (inches/second * 10)
//	Duty cycle: d (percent)
//	ScanLength: SLOTScanLength (in bits)
//	Facets: f
//	Clocks/revolution: r
	let d,f,r=nil,nil,nil
	let t = selecton rosDevice into	//d;f;r
	  [
	  case printerDover:		table [ 90; 32; 24 ]
	  case printerSequoia:		table [ 90; 36; 24 ]
	  case printerPuffin:		table [ 99; 22; 24 ]
	  case printerPimlico:		table [ 87; 12; 24 ]
	  default: valof [ PDError(1101) ]
	  ]
	MoveBlock(lv d, t, 3)

// Parameters of the adapter mentioned in the writeup.
//	bcMax:	MHz
//	crystalClock: 250 or 125 (units of 100 KHz)
	let bcMax,crystalClock=20,125

// Parameters relating to choice of band position on page:
	nLeadingBands=4
	nTrailingBands=selecton rosDevice into
	 [	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(2, SLOTScanLength)
	FLDI(3, 100)
	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 PDError(1100)

	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-BitMarginAdjust/4
	PageSyncDelay=4096-ScanMarginAdjust/4

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

	orbitSignalBand=8588

// 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 [ PDError(1102); sl=0 ]
		orbitSignalBand=sl
		]

// Calculate, for Sequoia, the band number in which to issue
// StartPrint (or StopPrint) for the next page
	if printerDevice eq printerSequoia then orbitSignalBand=(3*nBands)/4
]

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)
]