
;***************************************************************************
;
; Routine to set the Switchclock time 
; by Hugo Vos
;
; E-mail		: hugo@hvos.myweb.nl
;
;***************************************************************************

set_SWklok:


	ldi	Dx ,$00			; clear time counter

	mov	Ax, SWmod_L		; Load available 8574 bit stream into Ax reg.
	cpi	Ax, $00			; and check for modules available
	brne	start_SWtime_set
	
	mov	Ax, SWmod_H		; Load available 8574A bit stream into Ax Reg.	
	cpi	Ax, $00			; and check if modules are available
	brne	start_SWtime_set	; If so , then jump.
					; if NOT then :
	ldi	Ax, Dispclear		; Clear display.
	ldi	Bx, disp_CTRL
	rcall	disp_lcd

	ldi	Ax, low(noSWmod1)	; print "no SW modules found on the I2C bus"
	ldi	Bx, high(noSWmod1)
	ldi	Cx, $00			; message on the LC- display.
	rcall	str2disp		; print first line

	ldi	Ax, low(noSWmod2)
	ldi	Bx, high(noSWmod2)		
	ldi	Cx, $40
	rcall	str2disp		; print second line.

	rcall	Key_released		; check for no key's pressed

readSWkey:
	rcall	input_keyread
	cpi	Ax, return_key		; check for return key read
	brne    readSWkey

	rcall	Key_released

	ret				; return to menu programm

start_SWtime_set:


	ldi	Ax, $00			; Load Ax reg. with display location
	ldi	Bx, $0F			; Load Bx with number of spaces to print
	rcall	disp_space		; Go print spaces

	ldi	Ax, low(cvklok)		; Set "Tijd   MDWDVZZ" on the display
	ldi	Bx, high(cvklok)
	ldi	Cx, $00			; starting at position zero
	rcall	str2disp

SW_klokset:

	rcall	Key_released		; Check for no key pressed

	cpi	Dx, max_SWclktimes	; Check for max. SW timesetting.
	breq	set_SWklok		; if last setting then start at setting one
	cpi	Dx, $ff
	brne	Nomaxtime
	ldi	Dx, max_SWclktimes
	dec	Dx

Nomaxtime:
	
	mov	Ax, Dx			; Load Ax with Set-time counter
	rcall	HEX2DEC			; convert HEX number to DEC number
	mov	Bx, Ax			; move it to Bx reg and
	ldi	Ax, $0E			; load display location in Ax reg.
	rcall	dispDECval		; and display the number

	ldi	Cx, $7B			; EEPROM start address for SW time setting
	mov	Ax, Dx			; is $80

;********************************************************************
;
; Routine to calculate the EEPROM data start address
;
;********************************************************************

add_SWadres:
	subi	Cx, $FB			; calculate klok data start address
	dec	Ax			; in EEPROM with respect to the time
	cpi	Ax, $FF			; set counter in Dx
	brne	add_SWadres	
	
	sts	$0100, Cx		; Save EEPROM start address on SRAM location $0100 
	
;********************************************************************
;
; Routine to load the EEPROM data into SRAM starting at address $0060
;
;********************************************************************

	ldi	Z_high,$00		; Load Z register with $0060 ( SRAM address )
	ldi	Z_low,$60		; SRAM Location to store EERPOM data to.
	mov	Bx, Cx			; Load Bx with calculated EEPROM start address		
	ldi	Cx, $05			; Load total byte read counter.

SWread_data:
	ldi	Ax, X24C02		; copy DATA from EEPROM to SRAM
	cpi	Cx, $00			; check for end SRAM load loop	
	breq	end_SWdataread
	rcall	I2C_regread		; Load EEPROM data at address location given in Bx
	st	Z+, Ax			; Store data in to SRAM

	inc	Bx			; increase EEPROM address
	dec	Cx			; decrease loop counter
	rjmp	SWread_data

;********************************************************************
;
; Routine to check for vallid data read from the EEPROM. Byte 5 is
; 2-comp from byte 1 to 4
;
;********************************************************************

end_SWdataread:
	ldi	Z_high,$00		; Load Z-register with $0060 ( SRAM address )
	ldi	Z_low,$60
	ldi	Cx, $04
	ldi	Ax, $00
	
chk_SW2comp:
	ld	Bx, Z+			; check readed data for real settings

	add	Ax, Bx			; fifth byte is 2COMP from four pref.
	dec	Cx			; bytes
	cpi	Cx, $00
	brne	chk_SW2comp		

	com	Ax			; create 2comp of value in Ax reg.
	subi	Ax, $FF
	ld	Bx, Z			; Read 2-comp value stored in EEPROM
	cp	Ax, Bx			; check for C-comp
	breq	SWcomp2_ok

	ldi	Ax, $2B			; if not the load SRAM with default vallues
	st	-Z, Ax			; defuald vallue  defined in Ax register
	ldi	Ax, $00
	st	-Z, Ax
	st	-Z, Ax
	st	-Z, Ax

SWcomp2_ok:
;********************************************************************
;
; Display SW switch time onto display
;
;********************************************************************

	ldi	Z_low,$60		; reload Z register with address $0060
	
	ld	Bx, Z+			; Load hour vallue for SRAM $0060 and inc Z-pointer
	ldi	Ax, $40			; Load Ax with proper display position and
	rcall	DispDECval


	ldi	Bx, $3a			; set ":" in LCD	
	ldi	Ax, $42			;
	rcall	dispCHR

	ldi	Ax, $43			; Load Ax with new display position
	ld	Bx, Z+			; and load RTC minute vallue for SRAM address
	rcall	DispDECval		; $0061 and increase Z -pointer to $0062

	ldi	Ax, $45
	ldi	Bx, $20			; display a " " on the LCD
	rcall	dispCHR
	
	ld	Cx, Z			; load Cx with day switch day vallue located on SRAM address
	subi	Cx, Tot_daypatrn

	brcs	goodSWval		; check for vallid vallue
	ldi	Cx, $F5			; set to zero if vallue is not vallid
goodSWval:
	subi	Cx, $F5			; else restore org vallue
	st	Z+, Cx			; store day vallue to SRAM addres $0062 and ic Z-pointer  
					; to $0063
;********************************************************************
;
; display selected switch days onto display
;
;********************************************************************

	push	Ax
	push	Bx

	mov	Ax, Cx			; load Ax with selected day information
	ldi	Bx, $45			; load Bx with start position on LCD

	rcall	disp_days

	pop	Bx
	pop	Ax

;********************************************************************
;
; Display three spaces on the display spacting at position 4D
;
;********************************************************************

	ldi	Ax, $4D
	ldi	Bx, $03
	rcall	disp_space

SW_readkey:
;********************************************************************
;
; Routine to check the pressed key command
;
;********************************************************************

	rcall	input_keyread
	
	cpi	Ax, plus_key		; check for "+" key pressed
	brne	SW_min_key
	inc	Dx
	rjmp	SW_klokset

SW_min_key:
	cpi	Ax, min_key		; check for "-" key pressed
	brne	SW_retkey
	dec	Dx
	rjmp	SW_klokset

SW_retkey:
	cpi	Ax, return_key		; check for "Return" key pressed
	brne	SW_selectkey
	rjmp	SW_endset

SW_selectkey:
	cpi	Ax, select_key		; check for "Select" key pressed
	brne	SW_readkey

	rcall	Key_released

	ldi	Ax, Dispinit		; Set cursor on and Char at cursor
	ori	Ax, $03			; position to blink
	ldi	Bx, disp_CTRL
	rcall	Disp_lcd
	
	ldi	Z_low, $60		; Set Z register in start position 
	ldi	Z_high, $00		; data pointer in SRAM to manipulate

	ld	Cx, Z			; Load Cx with SRAM data form Address $0060

;********************************************************************
;
; Start SW hour switch setting
;
;********************************************************************

SW_start_hourset:

	rcall	Key_released		; Check for no key's pressed.
	
	mov	Bx, Cx			; display low nibble of vallue
	ldi	Ax, $40
	rcall	DispDECval

	mov	Ax, Cx			; Load DEC clock vallue into Ax
	ldi	Bx, $00			; Load Bx with min DEC vallue ( decimal )
	ldi	Cx, $24			; Load Cx with max DEC vallue ( decimal )

	rcall	moddecval			 
	mov	Cx, Ax			; Save new vallue into Cx

	cpi	Bx, $00
	breq	SW_start_hourset

	st	Z+, Cx			; Store the new hour vallue in SRAM position $0060
	ld	Cx, Z			; and inc Z-pointer to $0061
					; load Cx with minute vallue

;********************************************************************
;
; Start SW minutes switch setting
;
;********************************************************************

SW_start_minset:

	rcall	Key_released		; check for no key's pressed
	
	mov	Bx, Cx			; display low nibble of vallue
	ldi	Ax, $43
	rcall	DispDECval

	mov	Ax, Cx			; Load DEC clock vallue into Ax
	ldi	Bx, $00			; Load Bx with min DEC vallue
	ldi	Cx, $60			; Load Cx with max DEC vallue

	rcall	moddecval			 
	mov	Cx, Ax			; Save new vallue into Cx

	cpi	Bx, $00
	breq	SW_start_minset

	st	Z+, Cx			; Save new Min. vallue into SRAM location $0061
	ld	Cx, Z			; and inc Z-pointer to location $0062
					; load Cx with selected day vallue

;********************************************************************
;
; Start SW day switch setting
;
;********************************************************************

SW_switchday:

	rcall	Key_released		; check for no key's pressed

	mov	Ax, Cx			; Load Ax with selected day info
	ldi	Bx, $45			; Load Bx with display location
	rcall	disp_days

	ld	Ax, Z			; Load Ax with SRAM value ( address  $0062 )
	ldi	Bx, $00			; Load Bx with min vallue
	ldi	Cx, Tot_daypatrn	; Load Cx with number of day bit steams
					; defined in DEFDATA.ASM pointer dayinfo
	rcall	modHEXval		; modify dec val
	st	Z, Ax			; sav new value to SRAM location $0062
	mov	Cx, Ax					
	cpi	Bx, $00
	breq	SW_switchday

;*****************************************************************************
;
; START OFF SCREEN TWO MODIFICATION
;
;*****************************************************************************
;
; Routine to display current Channel and status information.
;
;***************************************************************************** 

	ldi	Ax, Dispclear		; Set display cursor function
	ldi	Bx, disp_CTRL
	rcall	disp_lcd
	
	ldi	Ax, low(chanstate)	; Print the defined message on the LCD
	ldi	Bx, high(chanstate)
	ldi	Cx, $00			; screen
	rcall	Str2disp

	ld	Ax, Z+			; load Ax with SRAM address $0062 ( day information ) and
	ld	Ax, Z			; inc Z-pointer to $0063. Load Ax with channel information
	andi	Ax, $F0			; delete channel state information
	swap 	Ax
	rcall	HEX2DEC
	
	mov	Bx, Ax
	ldi	Ax, $4B
	rcall	DispDECval
	
;*****************************************************************************
;
; Start for channel status information.
;
;	located in the LSB : "1" is channel on, "0" is channel off
;
;*****************************************************************************

Start_channelstat:

	rcall	Key_released		; Check for no key's pressed

	ldi	Cx, $42			; Load display position into Cx reg.

	ld	Ax, Z			; Load Ax with SRAM position $0063 containing
					; channel and channelstatus information.
	sbrs	Ax, 0			; check if bit 0 is set or clear indication
	rjmp	channeloff

	ldi	Ax, low(on)
	ldi	Bx, high(on)
	rcall	Str2disp
	rjmp	end_statecheck

channeloff:

	ldi	Ax, low(off)
	ldi	Bx, high(off)
	rcall	Str2disp

end_statecheck:


	rcall	input_keyread		; Read key's.

	cpi	Ax, plus_key		; check for "+" key.
	brne	minkeycheck

	ld	Ax, Z			; If "+" key is selected then
	sbr	Ax, 1			; Set LSB in SRAM location
	st	Z, Ax
	rjmp	Start_channelstat	; loop again

minkeycheck:
	cpi	Ax, min_key		; check for "-" key pressed.
	brne	nextkeycheck
	
	ld	Ax, Z			; If "-" key is selected then
	cbr	Ax, 1			; Reset LSB in SRAM location
	st	Z, Ax
	rjmp	Start_channelstat	; loop agian

nextkeycheck:
	cpi	Ax, select_key		; Check for "Select" key.
	brne	Start_channelstat	; if not pressed then loop again

;********************************************************************
;
; Start for channel select routine
;
;	located in the high nibble
;
;********************************************************************

start_channelsel:

	rcall	Key_released		; Check for no key pressed

	ld	Ax, Z			; Load Ax with Channel selected information
	andi	Ax, $F0			; delete channel state information
	swap 	Ax			; move info to low nibble
	mov	Cx, Ax			; and save it into Reg. Cx
	
	rcall	HEX2DEC			; convert HEX channel nr. info DEC value
	mov	Bx, Ax			; and move it into Bx
	ldi	Ax, $4B			; Load display location into Ax reg.
	rcall	DispDECval

;******** CHECK FOR PRINTING SPACE OF STAR **********

	mov	Ax, Cx			; Load selected channel number into Ax
	rcall	checkIOmod

	cpi	Ax, $00			; Ax = "00" is device is NOT available
	brne	Nodev
	
	ldi	Ax, $4E
	ldi	Bx, $20			; display " " to indicate channel not available
	rcall	dispCHR	
	rjmp	enddevcheck
	
Nodev:
	ldi	Ax, $4E
	ldi	Bx, $2A			; display "*" to indicate channel not available
	rcall	dispCHR		

enddevcheck:

	mov	Ax, Cx			; Load Ax with current selected channel
	ldi	Bx, $00			; Load Bx with lowest channel number
	ldi	Cx, max_SWchannels	; Load max channel number
	inc	Cx			; increase Cx by one the get 16 channels 
	rcall	modHEXval

	push	Bx			; save last pressed key information on stack
					; restore channel inforamtion
	swap	Ax
	ld	Bx, Z			; load old data from RAM
	andi	Bx, $0F
	or	Bx, Ax			; replace old inforamtion
	st	Z, Bx			; store new data in SRAM

	pop	Bx			; restore last pressed key information
	cpi	Bx, $00			; check for end of modification
	breq	start_channelsel

;********************************************************************
;
; Start of new setting save routine
;
;********************************************************************

	rcall	Key_released

	ldi	Ax, Dispinit		; Set cursor on and Char at cursor
	ldi	Bx, disp_CTRL
	rcall	Disp_lcd

	ldi	Ax, low(cvsave)		; Set the save message on the display
	ldi	Bx, high(cvsave)
	ldi	Cx, $40			; ( defined in Cx )
	rcall	Str2disp

SWsavekey:
	rcall	input_keyread		; Check for no key's pressed.

	cpi	Ax, plus_key		; check for "+" key
	brne	SW_saveminkey

	ldi	Z_low, $60		; Set Z register in start position SRAM data
	ldi	Z_high, $00

	lds	Bx, $0100		; Load EEPROM start adres for SRAM location $0100
	ldi	Cx, $00			; load Cx with "00" for starting 2-comp calcutation

SW_save_lus:

	ld	Ax, Z+			; Store Hour, Min, Days and Temp
	add	Cx, Ax			; value into EEPROM
	push	Cx
	mov	Cx, Ax
	ldi	Ax, X24C02

	rcall	I2C_regstore		; Store vallue (Ax) into EEPROM at address Bx
	rcall	delay_5mS		; 5mS delay to let the EEPROM save the value
	pop	Cx
	inc	Bx

	cpi	Z_low, $64		; check for end of Save 
	brne	SW_save_lus

	com	Cx			; Calculate 2 Comp of new data
	subi	Cx, $FF
	ldi	Ax, X24C02
	rcall	I2C_regstore		; Store into EEPROM	
	rcall	delay_5mS		; 5 mS delay to let the EEPROM save the value
	rjmp	start_SWtime_set

SW_saveminkey:
	cpi	Ax, min_key		; Check for "-" key
	brne	SWsavekey
	rjmp	start_SWtime_set

SW_endset:

	rcall	SWswitchtime		; create switch time array

	ret



;***************************************************************************
;
; Scans for all PCF8574 and PCF8574A chips on the I2C bus and set all output's to "0"
; if I2C device is pressent ont the bus.
;
;***************************************************************************

ResetSWports:

	push	Ax			; Save registers to stack
	push	Bx
	push	Cx

	ldi	Bx, $00			; set counter to scan eight 8574 device's
	ldi	Ax, PCF8574_SWL		; load startaddres first 8574 in Ax register
	mov	Cx, Ax

Startresetport:

	push	Ax			; Save current I2C address on stack
	inc	Bx
	rcall	I2Cstart		; send I2C start command on I2C bus
	rcall	I2Csend			; send I2C device address on the bus

	sbrs	Ax, 0			; check for aknowledge from device
	rjmp	SWnext8574		; if not, check next I2C device address

	ldi	Ax, $00			; if acknowledge then reset all eight pin's
	rcall	I2Csend
	
	sbrs	Ax, 0
	rcall	no_I2Cresponce		; if no responce the I2C error on display

SWnext8574:

	rcall	I2Cstop			; Send I2c stop sequence on the bus
	pop	Ax			; Restore I2C address from stack
	cpi	Bx, $08			; check for last device address
	breq	HighReset
	
	subi	Ax, $FE			; add two to I2C address to get next
	rjmp	Startresetport		; device address
	
HighReset:	

	cpi	Cx, PCF8574_SWH
	breq	endreset
	
	ldi	Ax, PCF8574_SWH		; load Ax with I2C start address
	ldi	Bx, $00
	mov	Cx, Ax
	rjmp	StartResetport
	
endreset:	
	
	pop	Cx
	pop	Bx
	pop	Ax

	ret

;*********************************************************************
;
; Calculate programm memory address vallue for the address defined
; in Ax ( lowbyte ) and Bx ( highbyte ) and increase address with
; vallue defined in Cx
;
;	Return	: Ax = lowbyte
;		  Bx = Highbyte
;		  Cx = offset variable
;
;*********************************************************************

calcpointer:

	lsl	Bx			; Shift high byte one bit to the left
	clc				; to dubble vallue and clear the carry bit
	rol	Ax			; rotate Ax to the left to doubble the vallue
	brcc	no_bitoverflow		; Check for overflow and set LSB in Bx 
	inc	Bx			; if there is an overflow

no_bitoverflow:
	add	Ax, Cx			; add Cx to the calculated address and add one
	brcc	no_addoverflow		; to high byte address is caary is set.
	inc	Bx

no_addoverflow:	
	
	ret

;*********************************************************************
;
; Display a serie of spaces on the display from location Ax with a
; total of Bx.
;
;*********************************************************************

disp_space:

	push	Cx
	mov	Cx, Bx

next_space:

	ldi	Bx, $20			; load [space] ASCII vallue into Bx
	push	Ax
	rcall	dispCHR			; and display it at location defined in Ax
	pop	Ax

	inc	Ax
	dec	Cx
	cpi	Cx, $00
	brne	next_space

	pop	Cx

	ret	
	
	
;*******************************************************************
;
; Routine to check witch 8574(A) modules are available on I2C bus
;
;*******************************************************************
	
SWmod_press :

	push	Ax			; Save Reg. Ax, Bx and Cx on stack
	push	Bx
	push	Cx

	ldi	Bx, $00			; Init total unit counter
	ldi	Cx, $00			; Init available module bit's to "0"
	
	ldi	Ax, PCF8574_SWL		; Load I2C address to check

Checkifthere:

	push	Ax			; Save current I2C address on stack
	push	Bx

	rcall	I2Cstart		; send I2C start command on I2C bus
	rcall	I2Csend			; send I2C device address on the bus

	sbrs	Ax, 0			; check for aknowledge from device
	rjmp	no_8574there		; if not, check next I2C device address

	sec
	ror	Cx			; Shift "1" in to indicate module available.
	rcall	I2Cstop
	rjmp	Nextmodule
	
no_8574there:

	clc				; Shift "0" in to indicate module NOT available
	ror	Cx

Nextmodule:

	pop	Bx			; Reload Bx with device counter val
	pop	Ax			; Reload current I2C address in Ax reg.	
	subi	Ax, $FE			; Increase Ax by 2 to get next I2C address	
	
	inc	Bx			; Increase module check counter
	cpi	Bx, $08			; Check for last module
	breq	high_module	
	
	rjmp	Checkifthere

high_module:

	cpi	Ax, 0b10000000		; Check for end of test
	breq	end_IOtest		; Jump out if last address
	
	ldi	Ax, PCF8574_SWH		; Load Ax witn PCF8574A base address
	ldi	Bx, $00			; Clear mod counter
	mov	SWmod_L, Cx		; Save found modules in Reg.
	ldi	Cx, $00
	
	rjmp	checkifthere
	
	
end_IOtest:	

	mov	SWmod_H, Cx
	
	pop	Cx
	pop	Bx
	pop	Ax

	ret
;*******************************************************************
;
; Routine to display the available modules on I2C bus
;
;*******************************************************************
	
module_list:

	ldi	Ax, Dispclear		; Load display clear command in Ax reg.
	ldi	Bx, disp_CTRL		; Select display control mode
	rcall	disp_lcd

	ldi	Ax, low(PCF8574)	; write "PCF8574" to the display
	ldi	Bx, high(PCF8574)
	ldi	Cx, $00			; starting at the 1st line
	rcall	Str2disp
	
	ldi	Ax, low(PCF8574)	; write "PCF8574" to the display
	ldi	Bx, high(PCF8574)
	ldi	Cx, $40
	rcall	Str2disp
	
	ldi	Ax, $44			; Load new display position into Ax rig.
	ldi	Bx, $41			; and load ASCII "A" info Bx
	rcall	dispCHR			; and go display the CHR.
	

	ldi	Ax, $08			; Load Ax with display position
	ldi	Cx, $08			; Load Cx as cycle counter
	mov	Bx, SWmod_L		; Load Bx with available PCF8574 bitstream

loop2nextmod:

	clc				; clear carry flag
	ror	Bx			; rotate Bx reg. 
	push	Bx
	brcc	nomod			; Branch if carry is clear
	
	ldi	Bx, $2A			; load ASCII "*"
	rcall	dispCHR
	rjmp	outnow
	
nomod:

	ldi	Bx, $2D			; Load ASCII "-"
	rcall	dispCHR
	
outnow:
	pop	Bx
	inc	Ax
	dec	Cx
	cpi	Cx, $00
	brne	loop2nextmod
	cpi	Ax, $50	
	breq	readnextkey
	
	ldi	Ax, $48
	ldi	Cx, $08
	mov	Bx, SWmod_H
	rjmp	loop2nextmod

	
readnextkey:	
	rcall	input_keyread
	cpi	Ax, return_key		; Check for reset key pressed
	brne	readnextkey	

	
	rcall	key_released
	
	ret
	
;*********************************************************************
;
; Send time list to RS-232 port.
;	Ax = Low byte array address
;	Bx = High byte array address
; Return : -
;
;*********************************************************************	
		
SendSWlist:

	push	Z_high		; Save registers on stack
	push	Z_low
	push	Cx
	push	Bx
	push	Ax
	
	mov	Z_low, Ax	; load memory address into Z register
	mov	Z_high, Bx
	ld	Cx, Z+

Start_sendlist:	
	cpi	Cx, $00		; Check for last timer setting send
	breq	end_sendlist
	dec	Cx		; Decrease loop counter by one
	push	Cx
	
	ld	Ax, Z+		; Load Ax with SW hour setting
	rcall	SendDECval	; Send it to the RS-232 port.
	
	ldi	Ax, $3A		; Load ":" ASCII value
	rcall	SendCHR		; and send it to RS-232 port
	
	ld	Ax, Z+		; Load Ax with Sw minute setting
	rcall	SendDECval	; send to the RS-232 port
	
	ldi	Ax, $20
	rcall	SendCHR
	
	ld	Ax, Z+		; load Ax with switch day information
	push	Z_low
	push	Z_high
	mov	Cx, Ax
	ldi	Ax, low(dayinfo)
	ldi	Bx, high(dayinfo)
	rcall	calcpointer
	mov	Z_low, Ax
	mov	Z_high, Bx
	
	lpm
	mov	Ax, R0
	
	pop	Z_high
	pop	Z_low
	
	ldi	Bx, $08		; Load Bx as cycle counter

Nextdaybit:	
	dec	Bx		; decrease loop counter
	cpi	Bx, $00		; Check if loop is complete
	breq	Enddaysend
	
	lsr	Ax		; shift Ax one bit right
	push	Ax
	brcs	dayvalid
	
	ldi	Ax, $2D		; Load Ax with ASCII "-"
	rcall	SendCHR
	pop	Ax
	rjmp	Nextdaybit
Dayvalid:

	ldi	Ax, $2A		; Load Ax with ASCII "*"
	rcall	SendCHR		; and send CHR to RS-232 port
	pop	Ax
	rjmp	Nextdaybit
		 
Enddaysend:
	
	ldi	Ax, $20		; Send "space" to the RS-232 port
	rcall	SendCHR
	
	ld	Ax, Z+
	rcall	send_chanstat
		
	ldi	Ax, $0A
	rcall	SendCHR
	ldi	Ax, $0D
	rcall	SendCHR

	pop	Cx
	rjmp	Start_sendlist
			
			
end_sendlist:			

	pop	Ax
	pop	Bx
	pop	Cx
	pop	Z_low
	pop	Z_high


	ret		
	
;************************************************************************
;
; Routine to set or reset I/O module connected to SW klok bus 
;
;************************************************************************

manual_set:

	push	Ax
	push	Bx
	push	Cx

	ldi	Ax, Dispclear		; Set display cursor function
	ldi	Bx, disp_CTRL
	rcall	disp_lcd
	
	ldi	Ax, low(chanstate)	; Print the defined message on the LCD
	ldi	Bx, high(chanstate)
	ldi	Cx, $00			; screen
	rcall	Str2disp
	
	ldi	Bx, $00			; display channel number on display.
	ldi	Ax, $4B
	rcall	dispDECval

	ldi	Ax, Dispinit		; Set cursor on and Char at cursor
	ori	Ax, $03			; position to blink
	ldi	Bx, disp_CTRL
	rcall	Disp_lcd
	
	ldi	Ax, 0b00000000		; Load Ax with channel "off" state.
	
disp_statagain:

	push	Ax			; save channel status on stack
	
	ldi	Cx, $42			; Load display position into Cx reg.

	sbrs	Ax, 0			; check if bit 0 is set or clear indication
	rjmp	disp_channeloff

	ldi	Ax, low(on)
	ldi	Bx, high(on)
	rcall	Str2disp
	rjmp	end_statedisp

disp_channeloff:

	ldi	Ax, low(off)
	ldi	Bx, high(off)
	rcall	Str2disp

end_statedisp:

	rcall	Key_released		; Check for no key's pressed

	rcall	input_keyread		; Read key's.

	cpi	Ax, plus_key		; check for "+" key.
	brne	stat_minkeycheck

	pop	Ax
	ori	Ax, 0b11111111

	rjmp	disp_statagain		; loop again

stat_minkeycheck:
	cpi	Ax, min_key		; check for "-" key pressed.
	brne	stat_defkeycheck

	pop	Ax
	clr	Ax
	
	rjmp	disp_statagain		; loop again
	
stat_defkeycheck:

	cpi	Ax, select_key		; check for select key is pressed
	brne	end_statedisp

; current stack address contains channal status !!!!!!!
	
	ldi	Cx, $00			; load cx with first module number
	push	Cx

select_chan:

	rcall	Key_released		; Check for no key's pressed.
	
	pop	Cx
	mov	Bx, Cx			; move current mod number into Bx
	ldi	Ax, $4B			; Load disp position into Ax
	rcall	DispDECval		; and display vallue
	
	push	Cx			; save current channel number to stack
	mov	Ax, Cx


; check for printing channel available or not
	
	rcall	DEC2HEX			; convert DEC vallue into HEX vallue
	rcall	checkIOmod
	mov	Bx, Ax
	
	ldi	Ax, $4E			; Load display pos. into Ax reg.
	cpi	Bx, $00
	brne	man_dispstar	
	
	ldi	Bx, $20			; load ASCII " "
	rcall	dispCHR
	rjmp	check_manend
	
man_dispstar:

	ldi	Bx, $2A			; Load ASCII "*"
	rcall	dispCHR
	
check_manend:
	
	pop	Cx	
	mov	Ax, Cx			; Load DEC channel vallue into Ax
	ldi	Bx, $00			; Load Bx with min DEC vallue ( decimal )
	ldi	Cx, $16			; Load Cx with max DEC vallue ( decimal )

	rcall	moddecval			 
	mov	Cx, Ax			; Save new vallue into Cx
	push	Cx			; ans store on stack again

	cpi	Bx, $00
	breq	select_chan
	
	ldi	Ax, low(schakel)	; display text on display at pos. 40
	ldi	Bx, high(schakel)	; defined in DATADEF.ASM
	ldi	Cx, $40
	rcall	Str2disp
	
	rcall	Key_released
	rcall	input_keyread		; Read key's.

	cpi	Ax, plus_key		; check for "+" key.
	brne	no_modchannel
	
	pop	Ax			; load channel number from stack
	mov	Cx, Ax
	swap	Cx			; Cx contains channel nr. in high nibble
	rcall	DEC2HEX			; and convert it into HEX vallue
	pop	Bx			; load wanted channel state from stack
	andi	Bx, 0b00000001
	or	Cx, Bx			; LSB Cx contains channel stat
	rcall	sendtime		; Send current time/date to RS-232 port
	
	push	Ax
	mov	Ax, Cx
	rcall	send_chanstat
	
	ldi	Ax, $0D			; send linefeed to RS-232 port
	rcall	sendCHR
	ldi	Ax, $0A			; send CR to RS-232 port
	rcall	sendCHR
	
	pop	Ax
	rcall	activate_channel	
		
	rjmp	end_manualset
	
no_modchannel:

	pop	Ax			; pop two byte from stack to remove
	pop	Ax			; two unused byte from stack.


end_manualset:

	ldi	Ax, Dispinit		; Set cursor off
	ldi	Bx, disp_CTRL
	rcall	Disp_lcd
	
	rcall	Key_released
	
	pop	Cx
	pop	Bx
	pop	Ax
	
	ret
	
;*****************************************************************
;
; Routine to check if selected channel is available
;
;	Ax = HEX number of selected channel
; Return :
;	Ax= 1 if available
;	Ax =0 if NOT available
;
;****************************************************************

checkIOmod:

	push	Bx
	push	Cx

	sbrc	Ax, 3			; check for 8474/8474AA
	rjmp	man_high
	
	mov	Bx, SWmod_L		; Load Bx with 8474 available bit stream
			
	ldi	Cx, $01			; Set LSB of Cx register	
check_manlow:	
	cpi	Ax, $00			; Check Ax for 0 vallue
	breq	end_manbitsetH		; if so, jump out
	dec	Ax			; decrease Ax
	lsl	Cx			; Rotale Cx one bit to the left
	rjmp	check_manlow
	
man_high:
	mov	Bx, SWmod_H
	andi	Ax, 0b00000111
	ldi	Cx, $01			; Set LSB of Cx register	
	
check_manhigh:	
	cpi	Ax, $00			; Check Ax for 0 vallue
	breq	end_manbitsetH		; if so, jump out
	dec	Ax			; decrease Ax
	lsl	Cx			; Rotale Cx one bit to the left
	rjmp	check_manhigh

end_manbitsetH:	
	and	Bx, Cx
	mov	Ax, Bx
	
	pop	Cx
	pop	Bx


	ret