; PROGRAM:   UTP cable & socket tester
; author: Ondrej Vitous  (c)  1998

		device	pic16c54,xt_osc,wdt_off,protect_off
		reset	start

	        org     8               ;RAM start
                                         ;    8   for  16c54
					 ;    12  for  16c84

;--------------------------------Variables definitions --------------------
count	ds	1	;cycle counter
count2	ds	1	;
wait1	ds	1 	;for delay routines
wait2	ds	1 	;for delay routines
wait3	ds	1 	;for delay routines
outs	ds	1 	;save current output state
;--------------------------------------------------------------------------


                org     0               ;Code start
;--------------------------------------------------------------------------
start		mov	ra,#0
		mov	rb,#0
		mov	!ra, #00011111b	;Port A: all inputs
		mov	!rb, #00000000b ;Port B: all outputs
			; RA.0,1,2,3  used to select mode
			;    switch 1= RA.0, RA.1
			;    switch 2= RA.2, RA.3
			;
;----- mode selection ----------------------------
start2		jnb	ra.2,:next3
		jnb	ra.3,mode20		;one LED at a time (static)
		call	cycle			;mode 0 - 3 times row
		jmp	start
:next3				;mode 1
		jnb	ra.0,:mode11
		jnb	ra.1,:mode12		;mod: 1,2,2,3,3,3,...,8,8
		call	recycl			;all LED on
		jmp	start
:mode11		call	recycl2			;all network LEDs on
		jmp	start
:mode12
;-------------------------------------------------------------------------------
;---- In this mode, led 1 flashes once, led 2 twice, ... led 8 eight times -----
;---- ideal mode for orientation in total chaos  -------------------------------
;-------------------------------------------------------------------------------
		mov	count,#0		;zero counter
:mode12a	mov	w,count
		call	getchar			;read current LED state
		mov	rb,w			;send to port
		call	waitxx			;wait about 0.5 sec
		jb	ra.1,start		;interrupt if mode changed
		jb	ra.2,start		;interrupt if mode changed
		inc	count
		cjne	count,#82,:mode12a	;repeat 82x
		jmp	start

;--------------------------------------------------------------------------
;-----Single LED lights, if SW 1 in one of edge positions, ----------------
;-----it will shift slowly    -----

mode20
		jnb	ra.0,:mode21	;shift one LED right
		jnb	ra.1,:mode22	;shift one lED left
		jmp	start2
:mode21		clrb	c
		rl	rb		
		test	rb
		jnz	:mode21a
		mov	rb,#1		;if end, 1 lights again
		jmp	:mode21a
:mode22		clrb	c
		rr	rb
		test	rb
		jnz	:mode21a
		mov	rb,#128         ;if beginning, LED 8 again
:mode21a	call	waitxx		;delay around .5 sec
		call	waitxx		;delay around .5 sec
		jmp	start2
;--------------------------------------------------------------------------
;---- sequential light up of all LEDs -------------------------------------
;---- 3 speeds, when slowest all LEDS flash shortly in between changes  ---
;---- otherwise, all LEDs flash after cycle ends  -------------------------
;--------------------------------------------------------------------------
cycle
		mov	count,#8	;repeat 8 times
		mov	outs,#1		;start with LED 1
:next		mov	rb,outs		;send to output
		jnb	ra.2,end	;break if mode changed
		jnb	ra.3,end	;break if mode changed
		jb	ra.0,:tim2	;no delay in fast mode
	;slow mode - flash all LEDs before change
		mov	wait2,#5	;
:again2		mov	count2,#8	;
		mov	rb,#1		;light up  LED 1 in multiplex
:next2		djnz	wait1,:next2	;short delay
		clrb	c		
		rl	rb		;shift LED
		djnz	count2,:next2	;repeat 8 times
		djnz	wait2,:again2	;repeat the whole thing 5 times
		mov	rb,outs		;restore current LED state
		mov	wait3,#5	;set time constants to about 500msec
		mov	wait2,#128
		jmp	:again		;continue


	;--------------------------------------
:tim2		jnb	ra.1,:tim3	;fast mode or even faster mode?
		mov	wait3,#2	;set time constants to about 200msec
		mov	wait2,#1
		jmp	:again
	;--------------------------------------
:tim3		mov	wait3,#1	;extra fast mode, delay 100msec
		mov	wait2,#128

	;--------------------------------------All three speeds
:again		djnz	wait1,:again	;perform specified delay
		djnz	wait2,:again
		djnz	wait3,:again
		clrb	c
		rl	outs		;increase LED number by 1
		djnz	count,:next	;repeat for all 8 LEDs

	;--------------------------------
					;flash all LEDs after one cycle
		jb	ra.0,:rcnorm	;according to mode
		mov	wait2,#60	;slow mode,  500msec flash
		jmp	recycl
:rcnorm		jnb	ra.1,:rcfast
		mov	wait2,#15	;fast mode, 140msec flash
		jmp	recycl
:rcfast		mov	wait2,#5	;faster mode, 50msec
	;-------------------------------- This has no sense but I dont remember why I did it this way so I'll leave it....
recycl		mov	wait2,#15	;in mode where all LEDs shine, this routine is used too
:again		mov	count,#8	;8x
		mov	rb,#1		;light LED1
:next		djnz	wait1,:next	;short delay
		clrb	c		
		rl	rb		;shift LED
		djnz	count,:next	;repeat 8x 
		djnz	wait2,:again	;repeat all according to length and mode
end		ret
;--------------------------------------------------------------------------
;---------- All 'computer' LEDs light up in multiplex ---------------------
;---------- LED 1,2,3,6 ---------------------------------------------------
recycl2
		mov	rb,#1			;light up LED 1 and a short delay
:next1		djnz	wait1,:next1
		mov	rb,#2			;light up LED 2 and a short delay
:next2		djnz	wait1,:next2
		mov	rb,#4			;light up LED 3 and a short delay
:next3		djnz	wait1,:next3
		mov	rb,#32			;light up LED 6 and a short delay
:next4		djnz	wait1,:next4
		ret
;--------------------------------------------------------------------------
waitxx		mov	wait2,#150		;dealy 0.5 sec
:waitxx2	nop
		nop
		nop
		nop
		djnz	wait1,:waitxx2		
		djnz	wait2,:waitxx2
		ret	
;--------------------------------------------------------------------------
getchar		jmp	pc+w			;flashing sequence table....
		retw	0,1,0,0,2,0,2,0,0,4,0,4,0,4,0,0,8,0,8,0,8,0,8,0,0,16,0,16,0,16,0,16,0,16,0,0
		retw	32,0,32,0,32,0,32,0,32,0,32,0,0,64,0,64,0,64,0,64,0,64,0,64,0,64,0,0
		retw	128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,0,0,0,0
