;+----------------------------+
;| CALCnet v1.0               |
;| Server Driver              |
;|                            |
;| By Kerm Martian            |
;| Kerm_Martian@yahoo.com     |
;| http://www.cemetech.tk     |
;+----------------------------+
;
.NOLIST
#DEFINE equ .equ
#DEFINE EQU .equ
#DEFINE end .end
#INCLUDE "ti83asm.inc"
#INCLUDE "tokens.inc"
BPORT equ 0
D0LD1H equ 0c1h
D0HD1H equ 0c0h
.LIST
	.org 9327h
	nop				;identifies as Doors CS compatible
	jr START			;go to the beginning of the program
	.dw Description			;pointer to a description
	.dw Icon			;pointer to an 8x8 icon
START:
	call _ClrLCDFull		;clear the screen
	call LOGO_UP			;put up the CALCnet logo
	ld a,57				;put 57 in the accumulator
	ld (PENROW),a			;now at row 57
	ld a,55				;put 55 in the accumulator
	ld (PENCOL),a			;now at column 55
	ld hl,TITLE_MENU_TXT		;the EXIT and START buttons
	call _vputs			;put it onscreen
TITLE_KEY:				;directs the program to Exit or Start
	call _getkey			;get a keypress (low-power mode)
	cp 90d				;is it the TRACE key?
	jp z,EXIT			;if yes, leave the program
	cp 68d				;is it the GRAPH key?
	jr z,INIT_NET			;if it is, start initializing
	jr TITLE_KEY			;invalid key / no key
INIT_NET:				;check for other servers
	call _ClrLCDFull		;clear the screen again
	ld a,1				;put 1 in the accumulator
	ld (PENCOL),a			;put it in the column var
	ld a.1				;1 in the accumulator again
	ld (PENROW),a			;put it in penrow
	ld hl,INITNET_TXT1			;says "Initializing Network..."
	call _vputs			;puts it onscreen
	ld a,0				;put 0 in the accumulator
	ld (loopcount),a		;put it in loopcount
INIT_NET1:
	call _GETCLOCK_A		;get the state of the clock line
	cp 1				;is it low (0=high, 1=low)?
	jp nz,ERR_SERVER		;if not, there is another server
	ld a,(loopcount)		;next three lines increment loopcount
	inc a
	ld (loopcount),a
	cp 256				;256 repetitions?
	jr nz,INIT_NET1			;if not, repeat
	ld a,0
	ld (loopcount),a		;put 0 in loopcount again
INIT_NET2:				;this oscillates the clock line to reset network
	call CLOCKHIGH			;put the clock line high (0)
	call CLOCKLOW			;put the clock line low (1)
	ld a,(loopcount)		;next three lines increment loopcount
	inc a
	ld (loopcount),a
	cp 256				;256 reps?
	jr nz,INIT_NET2			;if not, repeat
	ld a,7				;put 7 in the accumulator
	ld (PENROW),a			;at row 7
	ld a,1				;1 into accumulator
	ld (PENCOL),a			;at column 1
	ld hl,INITNET_TXT2		;"Complete" text
	call _vputs			;put it up!
	ld a,0
	ld (workstations),a		;put 0 in workstations
MAINLOOP:				;beginning of main routines
	ld a,0				;put 0 in accumulator
	ld (loopcount),a		;put 0 in loopcount
DATALOOP:
	ld a,(loopcount)		;put loopcount in the accumulator
	cp (workstations)		;are we past the last workstation?
	jp z,NEWCALC_LOOP		;if yes, check for new calcs
	call CLOCKHIGH			;put the clockline high (0)
	call CLOCKLOW			;put the clockline low (1)
	ld a,(loopcount)		;put the loopcount in the accumulator
	call SENDBYTE			;transmit current workstation ID
	ld a,(loopcount)		;put the loopcount in the accumulator
	ld hl,cache+2*a-2		;check if pending data
	ld a,(hl)			;put it in the accumulator
	cp 0				;is there data?
	jp z,DATALOOP1			;if not, skip sendbyte loop
	ld a,(hl+1)			;load pending data into hl
	call SENDBYTE			;send the data
DATALOOP1:
	call CLOCKHIGH			;put the clockline high
	ld a,0				;put 0 in the accumulator
	ld (count),a			;put it in the count
DATALOOP2:
	call RECBYTE			;check if there is data being sent (target)
	ld b,a				;put it in b if yes
	call RECBYTE			;another byte (the data itself)
	ld c,a				;put the byte in c
	ld a,b				;put b back in the accumulator
	cp 0				;is there data?
	jr nz,PUTCACHE			;if yes, go put it in the cache
	call CLOCKLOW			;put the clockline low
	ld a,(count)			;increment the counter
	inc a
	ld (count),a
	cp 4d				;have we waited four loops?
	jp nz,DATALOOP2			;if no, repeat
PUTCACHE:
	ld hl,cache+2*b-2		;get location
	ld (hl),c			;put the data in memory
DATALOOP3:
	ld a,(loopcount)		;next three increment loopcount
	inc a
	ld (loopcount),a		;now next workstation
	jp DATALOOP			;do next workstation
NEWCALC_LOOP:				;check for new workstations
	call CLOCKHIGH			;put the clock line high (0)
	call CLOCKLOW			;put the clock line low (1)
	ld a,255			;put 255 in the accumulator
	call SENDBYTE			;send request for new workstations
	ld a,0				;put 0 in the accumulator
	ld (count),a			;put the accumulator in the count
NEWCALC_LOOP1:
	call RECBYTE			;check for a response
	cp 0				;is there a response?
	jr nz,REGISTERNEW		;if yes, go register it
	ld a,(count)			;next three lines increment the counter
	inc a
	ld (count),a
	cp 16				;have we done 16 repeatitions?
	jr nz,NEWCALC_LOOP1		;if not, repeat
	jp MAINLOOP			;no new calcs
REGISTERNEW:				;register the new workstation
	ld a,(workstations)		;load current number of workstations in the accumulator
	cp 254d				;are we at highest limit?
	jr z,NONEW			;if yes, reject new workstation
	inc a				;increment workstation count
	ld (workstations),a		;put it back in workstations
	call SENDBYTE			;tell workstation new ID
	jp MAINLOOP			;go to the main loop
NONEW:					;already 254 workstations
	ld a,255			;put 255 in the accumulator
	call SENDBYTE			;send it to workstation
	jp MAINLOOP			;go back to the mainloop
CLOCKHIGH:
	ld a,D0LD1H			;load {high,low} into {clock,data}
	out (BPORT),a			;send it
	ret				;return to program
CLOCKLOW:
	ld a,D0HD1H			;load {low,low} into {clock,data}
	out (BPORT),a			;send it
	ret				;return to program
SENDBYTE:				;this probably will need to be modified
	pop a				;move the data to the stack
	ld a,11d			;send mode
	ld (80c8h),a			;put it in the asm link var
	push a				;put the stack back in the accumulator
	call _IO_EXEC			;send the byte
	ret				;return to the program
RECBYTE:
	ld a,22d			;receive mode
	ld (80c8h),a			;put it in the asm link var
	call _IO_EXEC			;get a byte into the accumulator
	ret				;return to the program
EXIT:					;closing routines
	call _ClrLCDFull		;clear the screen
	ld a,1				;put 1 in the accumulator
	ld (CURCOL),a			;homescreen column 1
	ld a,1				;put 1 in the accumulator
	ld (CURROW),a			;homescreen row 1
	ld hl,EXIT_TXT			;first line of text
	call _puts			;put it up
	ld a,2				;put 2 in the accumulator
	ld (CURROW),a			;row 2
	ld a,1				;put 1 in the column
	ld (CURCOL),a			;column 1 on homescreen
	ld hl,EXIT_TXT1			;second line of text
	call _puts			;put it up
	ld a,3				;put 3 in the accumulator
	ld (CURROW),a			;row 3 of the homescreen
	ld a,1				;put 1 in the accumulator
	ld (CURCOL),a			;first column
	ld hl,EXIT_TXT2			;third line of text
	call _puts			;put it on the homescreen
	ret				;all done - end of program
GETCLOCK_A:				;get the state of the clock line
	in a,(BPORT)			;get status of {clock,data}
	cp 08h				;is it 1000 (low,high)?
	jr GETCLOCK_1			;if yes, put 1 in accumulator
	cp 0ch				;is it 1100 (low,low)?
	jr GETCLOCK_0			;if yes, put 0 in accumulator
	ret
GETCLOCK_0:
	ld a,0				;put 0 in the accumulator
	ret				;back to loop
GETCLOCK_1:
	ld a,1				;put 1 in accumulator
	ret				;back to loop
LOGO_UP:
	ld hl,LOGO
	ld de,PLOTSSCREEN 
	ld bc,768 
	ldir 
	call _grbufcpy_v
	ret
ERR_SERVER:
	call EXIT			;put three lines onscreen
	ld a,1				;put 1 in the accumulator
	ld (CURCOL),a			;column 1
	ld a,4				;put 4 in the accumulator
	ld (CURROW),a			;row 4
	ld hl,ERR_TXT			;the text (line 4)
	call _puts			;put it on the homescreen
	ret				;all done
;-------------------------------
;All of this stuff is data/cache
;-------------------------------
;
INITNET_TXT1:
	.db "Analyzing Network...",0
INITNET_TXT2:
	.db "Analysis Complete!",0
LOGO:					;the main logo, 56x22 pixels
	.db %00000000,01111000,00000000,00000000,00000000,00000000,00000000
	.db %00000011,10000000,00000000,00000000,00000000,00000000,00000000
	.db %00001100,00000000,00000000,00000000,00000000,00000000,00000000
	.db %00010000,00000000,00000000,00000000,00000000,00000000,00000000
	.db %00100000,00000000,00000000,00000000,00000000,00000000,00000000
	.db %00100000,00000000,00000000,00000000,00000000,00000000,00000000
	.db %01000111,10000001,10000011,00000011,11000000,00000000,00000000
	.db %01000111,10000011,11000011,00000011,11000000,00000000,00000000
	.db %10001100,11000110,01100011,00000110,01100000,00000000,00000000
	.db %10011000,00001111,11110011,00001100,00000000,00000000,00000000
	.db %10011000,00001111,11110011,00001100,00000000,00000000,01000000
	.db %10011000,00001100,00110011,00001100,00001011,00011100,11100000
	.db %10011000,01001100,00110011,00001100,00101100,10100010,01000000
	.db %10001100,11011000,00011011,00000110,01101000,10111100,01000000
	.db %01000111,10011000,00011011,11100011,11001000,10100000,01000000
	.db %01000111,10011000,00011011,11100011,11001000,10011110,01000100
	.db %00100000,00000000,00000000,00000000,00000000,00000000,00000110
	.db %00010000,00000000,00000000,00001111,11111111,11111111,11111111
	.db %00001000,00000000,00011111,11110000,00000000,00000000,00000110
	.db %00000110,00000111,111,0000,00000000,00000000,00000000,00000100
	.db %00000001,11111000,00000000,00000000,00000000,00000000,00000000
TITLE_MENU_TXT:				;displayed at main screen
	.db "EXIT  START",0
loopcount:				;keeps track of current workstation
	.db 00h
workstations:				;total number of workstations
	.db 00h
count:					;used for loops
	.db 00h
cache:					;255 lines x 2 bytes each = 510 bytes
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
	.db 00h,00h
EXIT_TXT:
	.db "Server Ended",0
EXIT_TXT1:
	.db "CALCnet Server",0
EXIT_TXT2:
	.db "By Kerm Martian",0
Description:				;only used by Doors CS
	.db "CALCnet Server v1.0",0
Icon:					;only used by Doors CS
	.db %00101110
	.db %01001000
	.db %01000100
	.db %10011100
	.db %10000000
	.db %10000111
	.db %01000011
	.db %00111101
ERR_TXT:
	.db "Server Exists",0