;AutoVIDC module source - Module initialisation and finalisation
;---------------------------------------------------------------
;
;VIDC Enhancer software control
;For software controlled VIDC Enhancers
;
;Author: Andreas Barth (1995)
;Author: Paul Vernon (Retro-Kit) (2012-2013)
;   www: http://www.retro-kit.co.uk

; Check the Hardware.
;
; We can only run on hardware with a VIDC1a chip installed.
; Otherwise we fuddle in unknown hardware.
; RO2.xx and RO3.1x are supported.
; We need to check if the Arc has native Acorn, WE or Aux IO VIDC Enhancement.
.AutoVIDC_Initialise
	STMFD	R13!,{R1-R6,R8-R9,R14}

	LDR	R2,[R12,#0]			;are we being reinitialised?
	TEQ	R2,#0
	STRNE	R2,[R2,#0]			;YES, update our internal pointer
	LDMNEFD	R13!,{R1-R6,R8-R9,PC}			;..and exit

;------------------------------------------------------
; Initialise VARS and modeLists
	MOV	R0,#Module_Claim		; claim some RMA
	MOV	R3,#VARS_END-VARS_START
	SWI	XOS_Module                      ; PRM 1-233
	LDMVSFD R13!,{R1-R6,R8-R9,PC}			;exit if we can't claim some RMA space
	STR	R2,[R12,#0]			;point Module workspace at VARS
	MOV	R12,R2

	MOV	R0,#0				;zero workspace
	._zero_loop
		STR	R0,[R2],#4
		SUBS	R3,R3,#4
	BNE	_zero_loop
	STR	R12,[R12,#0]			;set pointer to itself

	ADR	R0,_ModeList_InitValues
	LDMIA	R0!,{R1-R5}			;initialise ModeList tables
	STR	R1,ModeList36
	STR	R2,ModeList25
	STR	R3,ModeList25+4
	STR	R4,MappedModes
	STR	R5,MappedModes+4
	MOV	R9,#NativeType			; R9 = Enhancer type
;------------------------------------------------------
; figure out what the OS/machine is capable of
; RISC OS 2.01 and newer can change the VIDC clock (if IOEB available)
; RISC OS 3.10 and newer passes the Monitor Type and Mode to Service_ModeChange
; RISC OS 2 and 3 use different VIDC timing values for modes

; assume worst case: RISC OS 2, RO can't control, Enhancer not needed, no Watford 25MHz clock
	MOV	R8,#RISCOS3 OR ROcanControl OR ROinControl OR RISCOS310orNewer OR EnhancerNeeded
	MOV	R0,#129
	MOV	R1,#0
	MOV	R2,#&FF
	SWI	XOS_Byte			; OS version
	CMP	R1,#&A3				; are we on RISC OS 3.00 or newer?
	BICHS	R8,R8,#RISCOS3			; YES
	BICHI	R8,R8,#RISCOS310orNewer		; RISC OS 3.10 or newer

; Check if a VIDC1 chip is fitted, and use it to determine if we're on RISC OS 2
	MOV	R0,#2				; Read Chip presence and ID.
	SWI	XOS_ReadSysInfo			; (doesn't exist under RO2) PRM 1-722
	BVS	_test_WatfordSuperVIDC

; Under RO3.5 and above, the high byte of R0 is VIDC1a=0, VIDC20=1
	TST	R0,#&FF000000			; Is the hardware VIDC1?  Top 8 bits will be zero
	LDMNEFD	R13!,{R1-R6,R8-R9,R14}		; NO, we don't need a VIDC Enhancer...
	ADRNE	R0,VIDC1aSupportOnly		; Load up the error message.
	BNE	exitWithError

; Determine if we're on an A4000/A5000/A7000 by checking the I/O chip type
	TST	R1,#&FF				; will be 0 if earlier than an A4000
	BNE	_detectionComplete		; NE if an A4000 or newer

._test_WatfordSuperVIDC
	MOV	R4,#IICAddress_Watford_VIDC_Extender1	; try Type 1 WE VIDC Enhnacer
	ORR	R0,R4,#1				; I2C read
	BL	iic_control
        MOVVS	R4,#IICAddress_Watford_VIDC_Extender2	; try Type 2 WE VIDC Enhancer
	ORRVS	R0,R4,#1				; I2C read
	BLVS	iic_control
	BVS	_detectionComplete		; if either errored, there's no WE Enhancer
        STRB	R4,WEIICAddress			; Store the address
; Now we need to test for a 25.175MHz clock and sync invert
	MOV	R4,R0				;R4=current WE settings

	MOV	R3,#%11110111			;WE is inverted so this writes %1000
	BL	iic_control_write
	BL	iic_control_read
	TEQ	R0,#&FF				;only needed for Arculator
	BEQ	_detectionComplete		;which doesn't fail unsupported IIC reads

	#if Debug==1
	TST	R0,#IIC25MHzFitted
	BEQ	_notFitted1
	SWI	XOS_WriteS
	DCB	"25MHz clock fitted",10,13,0
	ALIGN
	._notFitted1
	TST	R0,#InvertSync
	BEQ	_notFitted2
	SWI	XOS_WriteS
	DCB	"Inverse Sync required",10,13,0
	ALIGN
	._notFitted2
	#endif

	AND	R0,R0,#InvertSync+IIC25MHzFitted
	ORR	R8,R8,R0			

	MOV	R3,R4
	BL	iic_control_write		; reset WE VIDC Enhancer

	MOV	R9,#WatfordType			; Set the EnhancerType

._detectionComplete
; now try changing the VIDC clock to determine what what Enhancer type we'll use
	STRB	R8,internal_flags		; this will be updated by checkEnhancerClocks
						; but store now as some functions read it
	BL	checkEnhancerClocks		; Test Enhancers and clock speeds...
	STRB	R8,internal_flags

	BL	AutoVIDC_doService		; We need to run through the service handler to set the clock

	#if Debug==1
	LDR	R0,detectedClockSpeeds+16
	SWI	XOS_WriteS
	DCB	"Clock when loaded ",0
	ALIGN
	BL	convertCardinal2
	SWI	XOS_Write0
	SWI	XOS_WriteS
	DCB	":",0
	ALIGN
	LDR	R0,detectedClockSpeeds+16
	BL	AutoVIDC_ClockAvailableSWI
	BL	convertCardinal2
	BL	writeStringNewLine
	#endif

	LDRB	R1,EnhancerType
	TEQ	R1,#NativeType			; if we're taking over the clock
	LDMNEFD	R13!,{R1-R6,R8-R9,PC}		; exit

	LDR	R0,detectedClockSpeeds+16	; clock speed before we changed it
	BL	AutoVIDC_ClockAvailableSWI	; R0=clock index

	#if Debug==1
	SWI	XOS_WriteS
	DCB	"Setting Native clock back",13,10,0
	ALIGN
	#endif

	CMP	R0,#4				; if its not 0-3 something went wrong or
						; we're running under RedSquirrel
 	BLLO	AutoVIDC_SetClockSWI		; reset the VIDC clock

	LDMFD	R13!,{R1-R6,R8-R9,PC}		; exit...

._ModeList_InitValues
	DCD	%11100000000000000000000000000000
	DCD	%00011110000000000000000000000000
	DCD	%00000000000000000000111000000000
	DCD	%00000000000000001111111111111111
	DCD	%00000000000000000111000000000000
