; ZX81KB - Provides a PS/2 keyboard interface to the ZX81
; Copyright (C) 2004  Ian Cowburn
; 
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
; 
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
; 
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
;

; ***************************************************
; Port Usage
;
; PORT	B0-B7		Data lines for keyboard matrix
; PORT	A0-A4		Line select for keyboard matrix
; PORT	A6			PS/2 Clock
; PORT	A7			PS/2 Data
; ***************************************************

; This code is targeted to the PIC 16F628
;
		list		p=16F628
		include		"p16f628.inc"

; ***************************************************
; PIC Configuration
;
; Modify as required for your keyboard matrix circuit.
; Though, obviously you still need 15 IO pins free.
;
; Configuration:
;		Code protect disabled
;		Watchdog disabled
;		MCLR disabled (as I can't be bothered tying the line!)
;		LVP disabled
;		Brown out detect disabled
;		Power up timer enabled (in case keyboard takes time)
;		Internal oscillator (no clock out)
; ***************************************************
		__config	_BODEN_OFF&_CP_OFF&_DATA_CP_OFF&_PWRTE_ON&_WDT_OFF&_LVP_OFF&_MCLRE_OFF&_INTRC_OSC_NOCLKOUT


; ***************************************************
; Symbols
; ***************************************************

		; File registers
		;
		cblock 0x20
			PS2BYTE
			PS2WORK
			MATRIX1
			MATRIX2
			MATRIX3
			MATRIX4
			MATRIX5
		endc

		; Constants
		;
		constant	PS2PORT=PORTA
		constant	PS2CLOCK=6
		constant	PS2DATA=7
		
		constant	KBPORT=PORTB
		constant	KBSELPORT=PORTA
		
		constant	KBSEL1=0
		constant	KBSEL2=1
		constant	KBSEL3=2
		constant	KBSEL4=3
		constant	KBSEL5=4

; ***************************************************
; Macros
; ***************************************************
PS2BIT	macro
		local	loop1,loop2
		clrw
loop1:	btfsc	PS2PORT,PS2CLOCK
		goto	loop1
		btfsc	PS2PORT,PS2DATA
		movlw	0xff
loop2:	btfss	PS2PORT,PS2CLOCK
		goto	loop2
		endm

WBITSET	macro	port,bit
		local	loop
loop:	btfss	port,bit
		goto	loop
		endm

WBITCLR	macro	port,bit
		local	loop
loop:	btfsc	port,bit
		goto	loop
		endm

; ***************************************************
; Main
; ***************************************************
		org		0
main:

		; Turn off comparators
		;
		movlw	0x07
		movwf	CMCON
		
		; Setup ports
		;
		bsf		STATUS,RP0		; Select bank 1
		clrf	TRISB			; Port B all outputs
		;movlw	b'11100000'		; Port A, bottom 5 output (use for latched version)
		movlw	0xff			; Port A, all inputs
		movwf	TRISA
		bcf		STATUS,RP0		; Select bank 0
		
		; Initialise matrix
		;
		clrf	MATRIX1
		clrf	MATRIX2
		clrf	MATRIX3
		clrf	MATRIX4
		clrf	MATRIX5
		
		; Jump to ZX81 matrix test
		;
		;goto	ZX81MatrixTest
		
mainloop:
		
		; Get a byte from the PS/2
		;
		call	GetPS2Byte
		
		; TODO: Debug by sending byte to Port B
		;
		movf	PS2BYTE,0
		movwf	PORTB
		
		;incf	PORTB,1
		
		goto	mainloop


; ***************************************************
; GetPS2Byte
;
; Gets a byte from the PS/2
; Return is in PS2BYTE
; ***************************************************
GetPS2Byte:

		; Set up
		;
		clrf	PS2BYTE
		movlw	0x01
		movwf	PS2WORK

		; Get the start bit (which must be zero)
		;
ps2bstart:
		PS2BIT
		
		;iorlw	0x00
		;bnz		ps2bstart
		
		; Get the data
		;
ps2bdata:
		PS2BIT
		
		andwf	PS2WORK,0
		iorwf	PS2BYTE,1
		
		bcf		STATUS,C
		rlf		PS2WORK,1
		btfss	STATUS,C
		goto	ps2bdata
		
		; TODO: Check parity bit
		;
		PS2BIT
		
		; Get the stop bit (must be one)
		;
		PS2BIT
		;iorlw	0x00
		;bz		GetPS2Byte
		
		return

; ***************************************************
; ZX81MatrixTest
;
; Concept test to see if the ZX81 matrix can be driven
; directly from the PIC.
; 
; ***************************************************
ZX81MatrixTest:
		movlw	0x11
		movwf	MATRIX1

mtloop:
		WBITSET	KBSELPORT,KBSEL1
		movfw	MATRIX1
		movwf	KBPORT
		WBITCLR	KBSELPORT,KBSEL1
		movlw	0
		movwf	KBPORT

		WBITSET	KBSELPORT,KBSEL1
		WBITCLR	KBSELPORT,KBSEL1
		
		goto	mtloop
		
; ***************************************************
; End
; ***************************************************
		end
