' RT990H.BAS - (c) www.rutex.com
' rev:1.0 - March-2003 initial release
' rev:1.1 - Oct-2003 checkSPI() added - to check presence and software revision of drivers
'		     SPI byte out added for rev 2+ of the RT990H chip in ResetCounters() and in StepResp()
''''''''''''''''''''''''''''''''''''''''''''''''''
'	usage: PBC RT990H.BAS		
'			PowerBasic Compiler: www.powerbasic.com 
'
'
''''''''''''''''''''''''''''''''''''''''''''''''''
	$DYNAMIC
	%ISPBU = 0

	$INCLUDE "d:\vision\include\WINDOW.BI"
	$INCLUDE "d:\vision\include\EVENT.BI"
	$INCLUDE "d:\vision\include\MOUSE.BI"
	$INCLUDE "d:\vision\include\FORM.BI"

	TYPE TYPE1
		butn1	AS INTEGER	' button 4
		steps 	AS LONG		' button 1
		speed 	AS LONG		' button 2
		axe 	AS BYTE		' button 3
	END TYPE


	TYPE TYPE2
		Comnd2	AS INTEGER
		Nsteps 	AS LONG		' button 1
		MaxSamp	AS LONG		' button 2
		T0x	AS LONG		' button 3
		StepDly	AS LONG		' button 4
	END TYPE

	DEFLNG A-Z

	DIM X0	AS SHARED TYPE1
	DIM SR	AS SHARED TYPE2

	WINUSEUMB = 1					' use upper memory (UMB) if available
	APP.STATUSATTR = &H70
	APP.GRAPHICSMODE = 1							' adds graphical mapping
	APP.GRAPHICSMOUSE = 1
	APP.PATTERN = 32							' sets desktop fill pattern
	APP.ROWS =  25

	APPINIT
	APPFONTINIT

	GottaMouse% = MOUSEINIT(buttons%)
	MOUSECURSORON

	X0.Steps = 100
	X0.speed = 100

	SR.Nsteps = 1000
	SR.MaxSamp = 2000
	SR.StepDly = 5
	SR.T0x = 12
	
	Nsteps = SR.Nsteps
	MaxSamp = SR.MaxSamp
	T0x = SR.T0x
	StepDly = SR.StePDly

	file$ = "test"

	LPT = &H378	'most likely LPT1:
'	LPT = &H278	'maybe LPT2:
'	LPT = &H3BC	'probably LPT3:

	SHARED wTxtC%, wBdr%, wBdrC%, wTitlC%,wFlags%
	
	wFlags% = %DRAGBAR OR %RESIZE OR %BOTTOMBAR OR %CONTROL OR %MINMAX

	wTxtC%  = &HF1
	wBdr%   = 1
	wBdrC%  = &HF7
	wTitlC% = &H7f

	dly0 = GetSPIdly

	version = CheckSPI


''''''''''
	%cmCancel =1101
	%cmOK     =1102
	%hcNoHelp = 0
	%cmXcw	 =1200
	%cmXccw	 =1201
	%cmXreg	 =1202
	%cmXtune =1203
	%cmXdump =1204
	%cmYcw	 =1210
	%cmYccw	 =1211
	%cmYreg	 =1212
	%cmYtune =1213
	%cmYdump =1214
	%cmZcw	 =1220
	%cmZccw	 =1221
	%cmZreg	 =1222
	%cmZtune =1223
	%cmZdump =1224
	%cmAcw	 =1230
	%cmAccw	 =1231
	%cmAreg	 =1232
	%cmAtune =1233
	%cmAdump =1234
	%cmReset =1240
	%cmSetup =1241
	%cmExit  =1242

	hForm1% = FORMOPEN(16, 66, 25, &H70,1, 4, "RUTEX R9xH servo drive utility - rev:1.1", &H4F, 0)

	COMMANDBUTTON 	hForm1%, 1,  2, 2, &H7F70, &H7F7F, " X cw  ", 0, 2, 8, %cmXcw
	COMMANDBUTTON 	hForm1%, 2,  5, 2, &H7F70, &H7F7F, " X ccw ", 0, 2, 8, %cmXccw
	COMMANDBUTTON 	hForm1%, 3,  8, 2, &H7F70, &H7F7F, " Regs. ", 0, 2, 8, %cmXreg
	COMMANDBUTTON 	hForm1%, 4, 11, 2, &H7F70, &H7F7F, " Tune  ", 0, 2, 8, %cmXtune
	COMMANDBUTTON 	hForm1%, 5, 14, 2, &H7F70, &H7F7F, " Dump  ", 0, 2, 8, %cmXdump

	COMMANDBUTTON 	hForm1%, 6,  2,13, &H7F70, &H7F7F, " Y cw  ", 0, 2, 8, %cmYcw
	COMMANDBUTTON 	hForm1%, 7,  5,13, &H7F70, &H7F7F, " Y ccw ", 0, 2, 8, %cmYccw
	COMMANDBUTTON 	hForm1%, 8,  8,13, &H7F70, &H7F7F, " Regs. ", 0, 2, 8, %cmYreg
	COMMANDBUTTON 	hForm1%, 9, 11,13, &H7F70, &H7F7F, " Tune  ", 0, 2, 8, %cmYtune
	COMMANDBUTTON 	hForm1%,10, 14,13, &H7F70, &H7F7F, " Dump  ", 0, 2, 8, %cmYdump

	COMMANDBUTTON 	hForm1%,11,  2,24, &H7F70, &H7F7F, " Z cw  ", 0, 2, 8, %cmZcw
	COMMANDBUTTON 	hForm1%,12,  5,24, &H7F70, &H7F7F, " Z ccw ", 0, 2, 8, %cmZccw
	COMMANDBUTTON 	hForm1%,13,  8,24, &H7F70, &H7F7F, " Regs. ", 0, 2, 8, %cmZreg
	COMMANDBUTTON 	hForm1%,14, 11,24, &H7F70, &H7F7F, " Tune  ", 0, 2, 8, %cmZtune
	COMMANDBUTTON 	hForm1%,15, 14,24, &H7F70, &H7F7F, " Dump  ", 0, 2, 8, %cmZdump

	COMMANDBUTTON 	hForm1%,16,  2,35, &H7F70, &H7F7F, " A cw  ", 0, 2, 8, %cmAcw
	COMMANDBUTTON 	hForm1%,17,  5,35, &H7F70, &H7F7F, " A ccw ", 0, 2, 8, %cmAccw
	COMMANDBUTTON 	hForm1%,18,  8,35, &H7F70, &H7F7F, " Regs. ", 0, 2, 8, %cmAreg
	COMMANDBUTTON 	hForm1%,19, 11,35, &H7F70, &H7F7F, " Tune  ", 0, 2, 8, %cmAtune
	COMMANDBUTTON 	hForm1%,20, 14,35, &H7F70, &H7F7F, " Dump  ", 0, 2, 8, %cmAdump

	COMMANDBUTTON 	hForm1%,21,  8,46, &H7F70, &H7F7F, " Reset ", 0, 2, 8, %cmReset
	COMMANDBUTTON 	hForm1%,22, 11,46, &H7F70, &H7F7F, " Setup ", 0, 2, 8, %cmSetup
	COMMANDBUTTON 	hForm1%,23, 14,46, &H7F70, &H7F7F, " EXIT  ", 0, 2, 8, %cmExit

	TEXTBUTTON 	hForm1%,24, 2, 58, 8, 8, 0, &H7079, &HF1, ASC("T"),0, 5, %tLONG
	TEXTBUTTON 	hForm1%,25, 4, 58, 8, 8, 0, &H7079, &HF1, ASC("P"),0, 5, %tLONG

	WINHOTPRINT hForm1%, 4,46, &H7F70,  "~S~peed[pps]"
	WINHOTPRINT hForm1%, 2,46, &H7F70,  "S~t~eps/jog "

	FORMINSTALLTYPE hForm1%, X0
	FORMSHOW hForm1%, 4, 4, 17, 78

''''''''''''	
	'ReDraw

DO
	EventID = GETEVENT(0)
	SELECT CASE EventID
		CASE 102:	EXIT DO			' <ESC> key event
		CASE %cmExit:	EXIT DO

		CASE %cmXcw
			SetX
			Jog 1, X0.steps, X0.speed
		CASE %cmXccw
			SetX
			Jog 0, X0.steps, X0.speed
		CASE %cmXreg
			SetX
			DumpRegs
		CASE %cmXdump
			SetX
			DumpMem
		CASE %cmXtune
			SetX
			IF runPID THEN
				APPPAUSE
				StepResp
				APPRESUME
			END IF

		CASE %cmYcw
			SetY
			Jog 1, X0.steps, X0.speed
		CASE %cmYccw
			SetY
			Jog 0, X0.steps, X0.speed
		CASE %cmYreg
			SetY
			DumpRegs
		CASE %cmYdump
			SetY
			DumpMem
		CASE %cmYtune
			SetY
			IF runPID THEN
				APPPAUSE
				StepResp
				APPRESUME
			END IF

		CASE %cmZcw
			SetZ
			Jog 1, X0.steps, X0.speed
		CASE %cmZccw
			SetZ
			Jog 0, X0.steps, X0.speed
		CASE %cmZreg
			SetZ
			DumpRegs
		CASE %cmZdump
			SetZ
			DumpMem
		CASE %cmZtune
			SetZ
			IF runPID THEN
				APPPAUSE
				StepResp
				APPRESUME
			END IF

		CASE %cmAcw
			SetA
			Jog 1, X0.steps, X0.speed
		CASE %cmAccw
			SetA
			Jog 0, X0.steps, X0.speed
		CASE %cmAreg
			SetA
			DumpRegs
		CASE %cmAdump
			SetA
			DumpMem
		CASE %cmAtune
			SetA
			IF runPID THEN
				APPPAUSE
				StepResp
				APPRESUME
			END IF

		CASE %cmSetup:	SetRecording

		CASE %cmReset:	ResetCounters

		
		CASE ELSE
	END SELECT
LOOP

	WINCLOSE MainW%
	WINCLOSE WireW%
	FORMCLOSE hForm1%
	APPCLOSE
	SCREEN 0
	PRINT
	PRINT " (c) RUTEX - www.rutex.com"
	PRINT
	PRINT " This program can be used for evaluation of RUTEX products only"
	PRINT " Some parts of program written by Stand Logan - [loganjs@midwest.net]."
	END
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetX
	SHARED NewCable, DataBit, ClockBit, AxeT$
	NewCable = 1		' new cable
	DataBit  = 1		' 0b0000.0001
	ClockBit = 2		' 0b0000.0010
	AxeT$ = " X driver " 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetY
	SHARED NewCable, DataBit, ClockBit, AxeT$
	NewCable = 1		' new cable
	DataBit  = 4		' 0b0000.0100
	ClockBit = 8		' 0b0000.1000
	AxeT$ = " Y driver " 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetZ
	SHARED NewCable, DataBit, ClockBit, AxeT$
	NewCable = 1		' new cable
	DataBit  = 16		' 0b0001.0000
	ClockBit = 32		' 0b0010.0000
	AxeT$ = " Z driver " 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetA
	SHARED NewCable, DataBit, ClockBit, AxeT$
	NewCable = 1		' new cable
	DataBit  = 64		' 0b0100.0000
	ClockBit = 128		' 0b1000.0000
	AxeT$ = " A driver " 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetOld
	SHARED NewCable, DataBit, ClockBit, AxeT$
	NewCable = 0		' old cable
	DataBit  = 2		' 0b0000.0010
	ClockBit = 1		' 0b0000.0001
	AxeT$ = "Old cable " 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB ResetCounters
	'rev: 0, 1
	SetX:	SPI16 &H48, 0:	StatusX = SPI(&H40,&H21)
	SetY:	SPI16 &H48, 0:	StatusY = SPI(&H40,&H21)
	SetZ:	SPI16 &H48, 0:	StatusZ = SPI(&H40,&H21)
	SetA:	SPI16 &H48, 0:	StatusA = SPI(&H40,&H21)
	
	SetX:	SPI &H40, &H11
	SetY:	SPI &H40, &H11
	SetZ:	SPI &H40, &H11
	SetA:	SPI &H40, &H11
	
	'rev: 2+
	SetX:	SPI16 &HC8, 0:	StatusX = SPI(&HC0,&H21)
	SetY:	SPI16 &HC8, 0:	StatusY = SPI(&HC0,&H21)
	SetZ:	SPI16 &HC8, 0:	StatusZ = SPI(&HC0,&H21)
	SetA:	SPI16 &HC8, 0:	StatusA = SPI(&HC0,&H21)
	
	SetX:	SPI &HC0, &H01
	SetY:	SPI &HC0, &H01
	SetZ:	SPI &HC0, &H01
	SetA:	SPI &HC0, &H01
	
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SetRecording
	SHARED Nsteps, MaxSamp, T0x, StepDly
	hForm2% = FORMOPEN(15, 50, 6, &H70, 1, 4, "Step Response SetUp", &H4F, 0)
	FORMINSTALLTYPE hForm2%, SR
	COMMANDBUTTON   hForm2%, 1, 12, 30, &H7F70, &H7F7F, "~C~ancel", %hcNoHelp, 1, 8, %cmCancel
	COMMANDBUTTON   hForm2%, 2, 12, 15, &H7F70, &H7F7F,"  ~O~k  ", %hcNoHelp, 1, 8, %cmOK
	TEXTBUTTON 	hForm2%, 3, 2,40, 9, 9, 0, &H7079, &HF1, ASC("S"), %hcNoHelp, 5, %tLONG
	TEXTBUTTON 	hForm2%, 4, 4,40, 9, 9, 0, &H7079, &HF1, ASC("N"), %hcNoHelp, 5, %tLONG
	TEXTBUTTON 	hForm2%, 5, 6,40, 9, 9, 0, &H7079, &HF1, ASC("T"), %hcNoHelp, 5, %tLONG
	TEXTBUTTON 	hForm2%, 6, 8,40, 9, 9, 0, &H7079, &HF1, ASC("D"), %hcNoHelp, 5, %tLONG
	WINHOTPRINT hForm2%, 2, 1, &H7F70,  "StepSize (Encoder ~s~teps)              ="
	WINHOTPRINT hForm2%, 4, 1, &H7F70,  "Max ~n~umber of samples                 ="
	WINHOTPRINT hForm2%, 6, 1, &H7F70,  "Recording ~t~ime (multiples of 1st zero)="
	WINHOTPRINT hForm2%, 8, 1, &H7F70,  "SPI ~d~elay (step response only)        ="
	FORMSHOW hForm2%, 2, 2, 15, 60
	DO
		EventID2 = GETEVENT(0)
		SELECT CASE EventID2
			CASE 102,%cmCancel			' <ESC> key event
				EXIT DO
			CASE %cmOK
				Nsteps = SR.Nsteps
				MaxSamp = SR.MaxSamp
				T0x = SR.T0x
				StepDly = SR.StePDly
				EXIT DO
		END SELECT
	LOOP
	FORMCLOSE hForm2%
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION runPID
	PidW% = WINPOPUP(2, 2, 4, 30, wTxtC%, 1, 4, "Caution, Servo will run!", &H4F, 0)
	'TIME0 = TIMER + 9
	TIME0 = TIMER + 2
	DO
		WINPRINT PidW%, 1, 1, -1, "Kp = " + STR$(SPI16u(&h41, &HFF))+"        "
		WINPRINT PidW%, 2, 1, -1, "Ki = " + STR$(SPI16u(&h43, &HFF))+"        "
		WINPRINT PidW%, 3, 1, -1, "Kd = " + STR$(SPI16u(&h45, &HFF))+"        "
		WINPRINT PidW%, 4, 1, -1, STR$(INT(TIME0 - TIMER))+"        "
		eID = GETEVENT(0)
		IF TIMER > TIME0 THEN eID = %cmXtune
	LOOP WHILE eID = 17
	IF eID = %cmXtune THEN runPID = 1
	WINCLOSE PidW%
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB DoSPI
	SHARED FlagReg
	INPUT "Enter 1st TX byte : ", Tx1
	INPUT "Enter 2nd TX byte : ", dta$
	IF LEN(dta$) = 0 THEN Tx2 = &HFF ELSE Tx2 = VAL(dta$)
	IF Tx1 = 0 THEN Tx1 = 64: Tx2 = &HFF: PRINT "Don't read INDF"
	IF Tx1 = 5 OR Tx1 = 6 THEN Tx1 = 64: Tx2 = &HFF: PRINT "Don't read ports"
	Rx2 = SPI(Tx1, Tx2)
	PRINT "Address :"; Tx1; "("; HEX$(Tx1); ")     ";
	PRINT "Value:"; Tx2; "("; HEX$(Tx2); ") Transmitted"
	PRINT "Flag_Reg:"; FlagReg; "("; HEX$(FlagReg); ")     ";
	PRINT "Value:"; Rx2; "("; HEX$(Rx2); ") Received";
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB StepResp
	SHARED Axis$, Nsteps, MaxSamp, T0x, StepDly, AxeT$' , true, false
	DIM Vh(2005)
	DIM Vl(2005)

	DIM v(2005)

	True = 1 = 1
	False = NOT True
	ax$ = axis$
	da$ = DATE$
	ti$ = TIME$
	Nstepx = Nsteps

	Kp = SPI16u(&H41, &HFFFF)
	Ki = SPI16u(&H43, &HFFFF)
	Kd = SPI16u(&H45, &HFFFF)
	j = 0: m = 0: Zero = False
	T0 = TIMER * 1000

	Rx2 = SPI16(&H48, Nsteps) 'rev: 0,1
	Rx2 = SPI16(&HC8, Nsteps) 'rev: 2 +

	DO									' recording
		j = j + 1
		v(j) = SPI16v(&h48)	

		'stop recording @ t0x times first zero error crossing
		IF NOT Zero AND v(j) < 0 THEN Zero = True: m = j * T0x
		IF Zero THEN m = m - 1
		IF j > MaxSamp OR m < 0 THEN EXIT LOOP
		FOR i = 1 TO StepDly: NEXT
		IF INKEY$ <> "" THEN EXIT LOOP
	LOOP

	Td = TIMER * 1000
	T1 = Td - T0
	
	Samples = j - 1
	
	SCREEN 12
	COLOR 15,1

	LINE (0, 400)-(50, 400), 3
	LINE -(50, 200), 3
	LINE -(550, 200), 3
	LINE (0, 401)-(550, 401), 14

	Cx = 15	
	FOR j = 1 TO Samples		
		X = 50 + (j * 500 / Samples)
		Y = v(j)
		IF Ym > Y THEN Ym = Y
		Y = 200 * (1 +  Y/Nstepx)
		PSET (X, Y), Cx
	NEXT j

	LOCATE  2,60: PRINT AxeT$
	LOCATE  3,45: PRINT USING "           Kp = ######"; Kp
	LOCATE  4,45: PRINT USING "           Ki = ######"; Ki
	LOCATE  5,45: PRINT USING "           Kd = ######"; Kd
	LOCATE  6,45: PRINT USING "      Samples =#######";Samples
	LOCATE  7,45: PRINT USING "Encoder Steps =####### "; Nstepx
	LOCATE  8,45: PRINT USING "    Overshoot =####### steps"; -Ym
	LOCATE  9,45: PRINT USING "Sampling time =###.### sec."; (Td-T0)/1000
	LOCATE 28,60: PRINT "Press any key..."

	SLEEP
	SCREEN 0
	A$ = INKEY$
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB DumpMem
	SHARED AxeT$
	DumpW% = WINPOPUP(2, 2, 9, 65, wTxtC%, 1, 4, "Memory Dump: " + AxeT$, &H4F, 0)
	DO
		WINPRINT DumpW%, 1, 1, -1, "    0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F "
		FOR j = 0 TO 7
			WINPRINT DumpW%, j+2, 1, -1, STR$(j)
			FOR i =  0 to 15
				A$ =  HEX$(SPI((16*j)+i, &HFF))
				IF LEN(a$) < 2 THEN a$ = "0" + a$
				WINLOCATE DumpW%, j+2, (i+1)*4
				WINWRITE DumpW%, A$
			NEXT i	
		NEXT j
		eID = GETEVENT(0)
	LOOP WHILE eID = 17
	WINCLOSE DumpW%
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB DumpRegs
	SHARED AxeT$
	
	DumpW% = WINPOPUP(2, 2, 9, 20, wTxtC%, 1, 4, AxeT$, &H4F, 0)
	DO
		WINPRINT DumpW%, 1, 1, -1, "Revision = " + STR$(SPI   (&h70,   &HFF))+"        "
		WINPRINT DumpW%, 2, 1, -1, "      Kp = " + STR$(SPI16u(&h41, &HFFFF))+"        "
		WINPRINT DumpW%, 3, 1, -1, "      Ki = " + STR$(SPI16u(&h43, &HFFFF))+"        "
		WINPRINT DumpW%, 4, 1, -1, "      Kd = " + STR$(SPI16u(&h45, &HFFFF))+"        "
		WINPRINT DumpW%, 5, 1, -1, "    Step = " + STR$(SPI   (&h47,   &HFF))+"        "
		WINPRINT DumpW%, 6, 1, -1, "   Error = " + STR$(SPI16 (&h48, &HFFFF))+"        "
		WINPRINT DumpW%, 7, 1, -1, "   Peak+ = " + STR$(SPI16 (&h4A, &HFFFF))+"        "
		WINPRINT DumpW%, 8, 1, -1, "   Peak- = " + STR$(SPI16 (&h4C, &HFFFF))+"        "
		WINPRINT DumpW%, 9, 1, -1, "Position = " + STR$(-1+(SPI16u (&h50, &HFFFF))+65536*(SPI16 (&h52, &HFFFF)))+"        "
		eID = GETEVENT(0)


	LOOP WHILE eID = 17
	WINCLOSE DumpW%


END SUB
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION JOG(cw, stps, spd)
	SHARED FlagReg, EnBit, LPT, dly, dly0, NewCable

	dly = dly0 * (15000/spd)				

	IF NewCable THEN
		EnBit = 1						' 0b0000.0001			' /C0
		LPTen = LPT + 2
		OUT LPTen, (INP(LPTen) AND NOT EnBit): SpiDly		' set EnBit (HI) /C0-inverted  
	ELSE	
		EnBit = 64						' 0b0100.0000			' (old cable)
		LPTen = LPT + 0			' (old cable)
		OUT LPTen, (INP(LPTen) OR EnBit): SpiDly		' Set EnBit (HI) - just to make sure (old cable)
	END IF

	FOR i = 1 TO stps
		IF LEN(INKEY$) <> 0 THEN i = stps
		IF cw THEN
			tmp = ClockIt(1)
			PosN = PosN + 1
		ELSE
			tmp = ClockIt(0)
			PosN = PosN - 1
		END IF
	NEXT i
	JOG = PosN
END FUNCTION
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION SPI16v(TxR1) AS INTEGER		' read signed 16-bits

	DO
		Hi1 = SPI(TxR1+1,&HFF)
		Lo1 = SPI(TxR1  ,&HFF)
		Hi2 = SPI(TxR1+1,&HFF)
	LOOP WHILE (Hi1<>Hi2)

	IF Hi1=Hi2 THEN SPI16v = Lo1 + 256 * Hi1 ELSE SPI16V = 0  
END FUNCTION
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION SPI16(TxR1, TxR2) AS INTEGER		' read signed 16-bits

	tmp = TxR2
	SHIFT RIGHT tmp, 8
	tmp = tmp AND &HFF
	SPI16 = SPI(TxR1,TxR2) + 256 * SPI(TxR1 + 1,tmp)  
END FUNCTION
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION SPI16u(TxR1, TxR2) AS WORD		' read unsigned 16-bits
	tmp = TxR2
	SHIFT RIGHT tmp, 8
	tmp = tmp AND &HFF
	SPI16u = SPI(TxR1,TxR2) + 256 * SPI(TxR1 + 1,tmp)  
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION SPI(TxR1, TxR2)
	SHARED FlagReg, EnBit, LPT, dly, dly0, NewCable

	dly = dly0

	IF NewCable THEN
		EnBit = 1		' 0b0000.0001
		LPTen = LPT + 2
		OUT LPTen, (INP(LPTen) OR EnBit): SpiDly		' clr EnBit (LO) /C0-inverted  
	ELSE
		EnBit = 64		' 0b0100.0000			' (old cable)
		LPTen = LPT + 0			' (old cable)
		OUT LPTen, (INP(LPTen) AND NOT EnBit): SpiDly		' clr EnBit (LO)  (old cable)
	END IF

	FlagReg = SHIFT8(TxR1)

	SPI     = SHIFT8(TxR2)

	IF NewCable THEN
		OUT LPTen, (INP(LPTen) AND NOT EnBit): SpiDly		' set EnBit (HI) /C0-inverted  
	ELSE
		OUT LPTen, (INP(LPTen) OR EnBit): SpiDly		' Set EnBit (HI)  (old cable)
	END IF
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION SHIFT8(TXr)            ' TXr shifted out RXr shifted in
	IF (ClockIt(TXr AND 128)) THEN RXr = RXr OR 128
	IF (ClockIt(TXr AND  64)) THEN RXr = RXr OR  64
	IF (ClockIt(TXr AND  32)) THEN RXr = RXr OR  32
	IF (ClockIt(TXr AND  16)) THEN RXr = RXr OR  16
	IF (ClockIt(TXr AND   8)) THEN RXr = RXr OR   8
	IF (ClockIt(TXr AND   4)) THEN RXr = RXr OR   4
	IF (ClockIt(TXr AND   2)) THEN RXr = RXr OR   2
	IF (ClockIt(TXr AND   1)) THEN RXr = RXr OR   1
	SHIFT8 = RXr	
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION ClockIt(HiBit)
	SHARED LPT, ClockBit, DataBit, NewCable	' == StepBit & DirBit

	p = INP(LPT)

	IF HiBit THEN
		p = p OR DataBit		' set STEP/DIR bit 
	ELSE	
		p = p AND NOT DataBit		' clear STEP/DIR bit 
	END IF


		
	OUT LPT,(p OR      ClockBit): SpiDly	' set CLOCK/STEP bit
	OUT LPT,(p AND NOT ClockBit): SpiDly	' clear CLOCK/STEP bit
	OUT LPT,(p OR      ClockBit): SpiDly	' set CLOCK/STEP bit'
	

	IF NewCable THEN
		ClockIt = (INP(LPT+1) AND 64) / 64
	ELSE
		ClockIt = (INP(LPT+1) AND 8) / 8			' (old cable)
	END IF



END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB StpDly
	SHARED Dly
	FOR I = 1 TO Dly: NEXT 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB SpiDly
	SHARED Dly
	FOR I = 1 TO Dly: NEXT 
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION GetSPIdly()		' check PC for speed

	CalW% = WINPOPUP(2, 2, 10, 70, wTxtC%, wBdr%, wBdrC%, "Calibration Window", wTitlC%, wFlags%)

	MTIMER
	FOR i = 1 TO 10000: next i
	t = MTIMER
	IF t > 0 THEN t1 = 200000 / t
	WINPRINT CalW%, 1, 1, -1, STR$(t1)

	MTIMER
	FOR i = 1 TO 10000: next i
	t = MTIMER
	IF t > 0 THEN t2 = 200000 / t
	WINPRINT CalW%, 2, 1, -1, STR$(t2)

	MTIMER
	FOR i = 1 TO 10000: next i
	t = MTIMER
	IF t > 0 THEN t3 = 200000 / t
	WINPRINT CalW%, 3, 1, -1, STR$(t3)

	MTIMER
	FOR i = 1 TO 10000: next i
	t = MTIMER
	IF t > 0 THEN t4 = 200000 / t
	WINPRINT CalW%, 4, 1, -1, STR$(t4)

	MTIMER
	FOR i = 1 TO 10000: next i
	t = MTIMER
	IF t > 0 THEN t5 = 200000 / t
	WINPRINT CalW%, 5, 1, -1, STR$(t5)

	a = (t1 + t2 + t3 + t4 + t5) /  5
	
	IF  (0.7 < (t1/a)) AND ((t1/a) < 1.3) THEN s =     t1: n = n + 1  ' valid sample
	IF  (0.7 < (t2/a)) AND ((t2/a) < 1.3) THEN s = s + t2: n = n + 1  ' valid sample
	IF  (0.7 < (t3/a)) AND ((t3/a) < 1.3) THEN s = s + t3: n = n + 1  ' valid sample
	IF  (0.7 < (t4/a)) AND ((t4/a) < 1.3) THEN s = s + t4: n = n + 1  ' valid sample
	IF  (0.7 < (t5/a)) AND ((t5/a) < 1.3) THEN s = s + t5: n = n + 1  ' valid sample

	IF n > 0 THEN a = s / n ELSE a = 0
	
	WINPRINT CalW%, 6, 1, -1, "avr = "+ STR$(a) +" | "+ STR$(n) + "samples used"
	IF a = 0 THEN
		PRINT
		WINCLS   CalW%
		WINPRINT CalW%, 1, 1, -1, " Cannot determinate correct timing"
		WINPRINT CalW%, 2, 1, -1, " Cannont be used under WIN NT system (NT/2000/XP) - and I have no idea about ME!"
		WINPRINT CalW%, 3, 1, -1, " If you using WIN9x DOS Windows - restart your PC in DOS mode"
		WINPRINT CalW%, 4, 1, -1, " If you using WIN NT - reboot/run your PC from DOS floppy"
		sleep
	END IF

	GetSPIdly = a


	SLEEP 1 

	WINCLOSE CalW%
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION CheckSPI()		' check presence of drivers plus software revision

	shared FlagReg
	
	CalW% = WINPOPUP(3, 3, 10, 70, wTxtC%, wBdr%, wBdrC%, "Checking R9xH drivers", wTitlC%, wFlags%)
	''''''''
	setX: rev = SPI(&H70,&HFF)
	IF (FlagReg<>255) AND (FlagReg<>0) THEN
		WINPRINT CalW%, 1, 1, -1, " X driver detected | Software revision: "+ STR$(rev)
		a = 1
		if rev < 2 then TooOld = 1
	ELSE
		WINPRINT CalW%, 1, 1, &HF4, " X driver not detected.
	END IF	

	''''''''
	setY: rev = SPI(&H70,&HFF)
	IF (FlagReg<>255) AND (FlagReg<>0) THEN
		WINPRINT CalW%, 2, 1, -1, " Y driver detected | Software revision: "+ STR$(rev)
		a = 1
		if rev < 2 then TooOld = 1
	ELSE
		WINPRINT CalW%, 2, 1, &HF4, " Y driver not detected.
	END IF	

	''''''''
	setZ: rev = SPI(&H70,&HFF)
	IF (FlagReg<>255) AND (FlagReg<>0) THEN
		WINPRINT CalW%, 3, 1, -1, " Z driver detected | Software revision: "+ STR$(rev)
		a = 1
		if rev < 2 then TooOld = 1
	ELSE
		WINPRINT CalW%, 3, 1, &HF4, " Z driver not detected.
	END IF	

	''''''''
	setA: rev = SPI(&H70,&HFF)
	IF (FlagReg<>255) AND (FlagReg<>0) THEN
		WINPRINT CalW%, 4, 1, -1, " A driver detected | Software revision: "+ STR$(rev)
		a = 1
		if rev < 2 then TooOld = 1
	ELSE
		WINPRINT CalW%, 4, 1, &HF4, " A driver not detected.
	END IF	

	SLEEP 2
	
	IF a=0 THEN
		WINCLS   CalW%
		WINPRINT CalW%, 2, 1, -1, "              No R9xH driver detected!"
		WINPRINT CalW%, 3, 1, -1, "             (R90H, R990H, R991H, R992H)"
		WINPRINT CalW%, 5, 1, -1, "  Check links: pins 1&2 and 3&4 on J7 (DB15) on R990MB"
		sleep
	ELSEIF TooOld THEN
		WINCLS   CalW%
		WINPRINT CalW%, 2, 1, -1, "         One or more of you drivers have old revision of software"
		WINPRINT CalW%, 4, 1, -1, "             Contact www.rutex.com for upgrade"
		sleep
	END IF

	CheckSPI = a
	WINCLOSE CalW%
END FUNCTION
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SUB Help
	CLS
	PRINT " ... too late for that..."
	SLEEP 1
END SUB
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
