	TITLE	'Bit Banger for CompuPro DISK1'
;	Bit Banger for CompuPro DISK1.
;
; 81-03-28	phm


;	7 Data bits, no parity
;	For 2 MHz 8085, use 300 Baud.
;	For 5 MHz,	use 600 Baud.
	space	4,10
;	Normal bit timings.
;				___ TICK ___
;	Baud	uSec/bit	2MHz	5MHz
;	4800	208		<<<	25
;	2400	416		18	46
;	1200	833		38	92
;	600	1667		75	216
;	300	3333		102	>>>
;	110	can't		>>>	>>>
;
;	Restriction on higher rates is due to the fact
;	that we can only adjust speed by integral TICK
;	counts: Unless number > 100, cannot tune in closer
;	than one percent.
 
 
 
 
;	Timing for the Bit Banger is via programmed delays,
;	so be very careful if changes are contemplated.
;	Baud =	Bit per second of serial data.
;	Cycle =	Machine cycle (clock period, T-State).
;	Tick =	1/n of a bit time (PERIOD of sample).
;
;	1200 baud	= 833 uSec/bit
;	* 2 MHz		= 1667 cycles/bit
;	/ 16 sample rate= 104  cycles/Tic

yBANG:	EQU	SER	;Serial bit latch port


SAMP:	DB	-1	;dummy pre-store
	DS	10	;buckets for Space counts
	DB	-1
	space	4,10
;	CONSOLE STATUS
;	BitBanger has no status available, so always
;		replies NO.  This means that Ctrl-S will
;		not work when using the BitBanger.
;	Exit	A= FFh	means character available.
KONST:
	XOR	A	;A=0, clear Carry
	RET
	space	4,10
;	Output 1 Character.
;	Entry	C= Character to output.
;		Line assumed marking.
;	Exit	Line marking, but stop time not elapsed.
;	Transmission format:
;		Data bits inverted;
;		Start(0), D0, D1, ..., D6, Stop(1), Leaves marking
;	Note: Cannot destroy DE or HL.
;	Uses	AF, BC.
KONOUT:	proc
	PUSH	HL
	PUSH	DE
	MOV	A,C
	AND	7Fh	;use Bit7 as Start bit (0)
	XOR	0FFh	;invert data
	RLC		;adjust
	MOV	C,A
	LDK	B,7+1+1	;7 bit data, 1 Start, 1 fudge

;	Write 8 bits.
; outer loop time:
;	N = 8
;	NT = (N * MT+6) + (N+1)*(37) - 3
;	N = 8
;	NT = 8*MT + 48+333-3
;		= 378 + 8*(43*TICK-3)
;		= 378 - 24 + (344*TICK)
;		= 354 + 344*TICK
;		= 10 + 344*(TICK+1)
; for each bit:
;	N1 = 43*M-3 + 6 + 37 - 3
;		= 37 + 43*M
;		= -6 + 43*(TICK+1)
:N:
	LD	A,TICK	;(7	7
	MOV	E,A	;(5	4
;r	STO	D,[hl]	;(7	7
;r	LDK	D,0	;(7	7
	MOV	A,C	;(5	4
	RRC		;(4	4
	MOV	C,A	;(5	4
	DEC	B	;(5	4
	JZ	:6	;if enuf bits read
	INC	HL	;(5	6

;	Begin output loop for this bit.
:M:
	OUT	yBANG	;(10	10	11)
	AND	80h	;(7	7
	RLC		;(4	4
	RRC		;(4	4
	MOV	D,A	;(5	4
	DEC	E	;(5	4	4)
	JNZ	:M	;(10	10(7)	10)
;			;(22*M
; inner loop=			43*M-3
;					21*M)
	JMP	:N


:6:
	LDK	B,2	;2 Stop bits
:62:
	LD	A,TICK
	MOV	E,A
	INC	E
:65:
	LDK	A,0	;Stop bit= Mark= 1
	OUT	yBANG	;(10	10	11)
	AND	80h	;(7	7
	RLC		;(4	4
	RRC		;(4	4
	MOV	D,A	;(5	4
	DEC	E	;(5	4	4)
	JNZ	:65	;(10	10(7)	10)
	DEC	B
	JNZ	:62	;if more stoppers
	POP	DE
	POP	HL
	RET
	space	4,10
;	Bit Banger Input.
;
;	Exit	A= Character read.
;			Bit7 clear.
;	Uses	AF, BC, DE, HL.

;	Timing for	8080	8085	z80
KONIN:	proc
	LDK	HL,SAMP
	LDK	B,9+1

;	Wait for Start bit.
:L0:
	IN	yBANG
	RLC
	JNC	:L0	;if line still Marking

;	Now take 7 uniform samples.
;	The number of peeks in each determines the sample width.
:N:
	LD	A,TICK	;(13	13
	MOV	E,A	;(5	4
	STO	D,[hl]	;(7	7
	LDK	D,0	;(7	7
	DEC	B	;(5	4
	JZ	:6	;(10)	if enuf bits read
	INC	HL	;(5	6

;	Begin sampling loop for this bit.
:M:
	IN	yBANG	;(10	10	11)
	AND	80h	;(7	7
	RLC		;(4	4
	ADD	A,D	;(4	4
	MOV	D,A	;(5	4
	DEC	E	;(5	4	4)
	JNZ	:M	;(10	10(7)	10)
	JMP	:N	;(10	10	10)
;			;(22*M
; inner loop=			43*M-3
;					21*M)


;	Reduce sample counts to data bits.
;	Note that due to DISK1 inversion,
;	0  Space =	Count[i]  >  Threshold
;	1  Mark  =	Count[i]  <  Threshold
;	Actually, all counts "near" mid-range are probably
;	errors.
:6:
	LDK	HL,SAMP+8	;-> Data bit 6
	LD	A,TICK-1
	MOV	D,A	;C= Threshold for Mark versus Space
	LDK	BC,rev 7
:64:
	MOV	A,C
	RLC
	MOV	C,A
	LD	A,[hl]
	CMP	D
	JNC	:66	;if large count
	INC	C	;set bit for Mark
:66:
	DEC	HL
	DEC	B
	JNZ	:64	;if more bits to reduce
	MOV	A,C
	RET
	space	4,10
;	Determine speed of terminal.
;	User must input a 'U'
;	Relies on being able to measure the width of the
;	Start bit.  Therefore, needs an odd-numbered Ascii
;	to be input.
;	Consecutive samples look like this:
;		...11111111111110000..001xxxxxxx...
;		Mark		Space	Mark
;		...Idle		Start	Data0	(ignore...)
BAUD:	proc
	LDK	HL,SAMP
	LDK	B,3
	LDK	DE,1

;	Wait for Start bit.
:L0:
	IN	yBANG
	RLC
	JNC	:L0	;if line still Marking

;	Now measure width of next several pulses.
;	The number of peeks in each determines the sample width.
:N:
	MOV	C,E	;(5	4
	LD	A,TICK	;(13	13
	STO	D,[hl]	;(7	7
	LDK	D,0	;(7	7
	DEC	B	;(5	4
	JZ	:6	;(10)	if enuf bits read
	INC	HL	;(5	6


;	Begin sampling loop for this bit.
:M:
	INC	D	;(5	4	4)
	IN	yBANG	;(10	10	11)
	AND	80h	;(7	7
	RLC		;(4	4
	CMP	C	;(4	4
	MOV	E,A	;(5	4
	JZ	:M	;(10	10(7)	10)
	JMP	:N	;(10	10	10)
;			;(22*M
; inner loop=			43*M-3
;					21*M)


;	Reduce sample counts to data bits.
:6:
	LD	A,SAMP+1
	STO	A,TICK	;set nominal bit width
	CLC
	RAR		;width / 2 = threshold
	STO	A,TICK-1
	RET



;	Endx	GBcbiot3.asm
