	list p=p16f688,f=inhx16,r=hex,w=1
	include "p16f688.inc"
	__CONFIG _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _WDT_OFF

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EEPROM data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	org 0x2100
	DE	'1','2','3','A','B'
	DE	'4','5','6','C','D'
	DE	'7','8','9','E','F'
	DE	'*','0','#','G','H'
		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BANKX0  MACRO
        bcf     STATUS,RP0     ; clear STATUS.RP0 (select f-reg bank 0/2)
        ENDM
BANKX1  MACRO
        bsf     STATUS,RP0     ; set   STATUS.RP0 (select f-reg bank 1/3)
        ENDM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

row		equ     0x20
col		equ	0x21
scancode	equ	0x22
wbcount		equ	0x23
wbtemp		equ	0x24
phtemp		equ	0x25
phctemp		equ	0x26
rsttemp		equ	0x27
char		equ	0x28
colmask		equ	0x29
count1		equ	0x2A
count2		equ	0x2B
scancodetable	equ	0x30

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Dispatch vectors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        org 0x0         ; Main vector origin
        nop             ; good habit to cultivate
        goto main       ; enter code proper

        org 0x4         ; Interrupt vector origin
        retfie          ; should not happen; return + reset GIE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

teststr		da	"This is a test",0
	
; Main begins here
main:	
        BANKX0
	movlw   0x67
	movwf   SPBRG
	
	;movlw   B'00100100' 
	;movwf   TXSTA
	bsf	TXSTA, BRGH	
	bsf	TXSTA, TXEN

	;movlw   B'00001000'
	;movwf   BAUDCTL
	bsf	BAUDCTL, BRG16

	;movlw	B'10010000'
	;movwf	RCSTA
	bsf	RCSTA, CREN
	bsf	RCSTA, SPEN
	
	movlw	0x07
	movwf	CMCON0
	
        BANKX1
	bcf	OPTION_REG, NOT_RAPU
	clrf	ANSEL
	movlw	0xFF
	movwf	WPUA
	movwf	TRISA
	movlw	0xEF
	movwf	TRISC
	
	BANKX0
	clrf	PORTC
        movlw	0x01
	movwf	row

	call	readscantable


prompt:	
	movlw	'>'
	call	printchar
	
keyloop:
	call	keyb
	addlw	0
	btfss	STATUS, Z
	goto	recvchar
	
	bcf	STATUS, C
	rlf	row, F
	movlw	0x01
	btfsc	row, 4
	movwf	row

	comf	row, W
	andlw	0xEF
	BANKX1
	movwf	TRISC
	BANKX0
	
	comf	PORTA, W
	andlw	B'00110111'
	btfsc	STATUS, Z
	goto	keyloop
	
	;; Keypress found
	movwf	colmask
	call	whichbit
	movwf	col
	sublw	3
	btfss	STATUS, C
	decf	col, F
	
	movf	row, W
	call	whichbit
	movwf	scancode
	bcf	STATUS, C
	rlf	scancode, F
	rlf	scancode, F
	addwf	scancode, F

	movf	col, W
	addwf	scancode, F
	movf	scancode, W
	
	call	handlekeypress

	call	sleeploop
	
keyup:	
	comf	PORTA, W
	andwf	colmask, W
	btfss	STATUS, Z
	goto	keyup

	call	sleeploop
	
        goto    keyloop

recvchar:
	call	getc
	movwf	char
	call	printchar

	movf	char, W
	sublw	'P'
	btfsc	STATUS, Z
	goto	doprint

	movf	char, W
	sublw	'R'
	btfsc	STATUS, Z
	goto	doread

	movf	char, W
	sublw	'W'
	btfsc	STATUS, Z
	goto	dowrite

	movf	char, W
	sublw	'N'
	btfsc	STATUS, Z
	goto	donew

	call	printcrlf
	BANKX1
	movlw	errstr
	movwf	EEADR
	movlw	errstr>>8
	movwf	EEADRH
	BANKX0
	call	printpstr
	movf	char, W
	call	printchar
	movlw	'\''
	call	printchar
	call	printcrlf
	goto	prompt
errstr		da	"Unrecognized character:'",0
	
printstr	da	"Current scancode table:",0
doprint:
	call	printcrlf
	BANKX1
	movlw	printstr
	movwf	EEADR
	movlw	printstr>>8
	movwf	EEADRH
	BANKX0
	call	printpstr
	call	printcrlf
	call	printscantable
	goto	prompt

readstr		da	"Reading scancode table from EEPROM:",0
doread:
	call	printcrlf
	BANKX1
	movlw	readstr
	movwf	EEADR
	movlw	readstr>>8
	movwf	EEADRH
	call	printpstr
	BANKX0
	call	printcrlf
	call	readscantable
	call	printscantable
	goto	prompt

writestr	da	"Writing scancode table to EEPROM:",0
dowrite:
	call	printcrlf
	BANKX1
	movlw	writestr
	movwf	EEADR
	movlw	writestr>>8
	movwf	EEADRH
	BANKX0
	call	printpstr
	call	printcrlf
	call	writescantable
	call	printscantable
	goto	prompt

newstr	da	"Enter new scancode table:",0
donew:
	call	printcrlf
	BANKX1
	movlw	newstr
	movwf	EEADR
	movlw	newstr>>8
	movwf	EEADRH
	BANKX0
	call	printpstr
	call	printcrlf
	call	newscantable
	call	printscantable
	goto	prompt
	
			
;***************************************
;	handlekeypress
;	Print character associated with scancode
;***************************************
handlekeypress:
	addlw	scancodetable
	movwf	FSR
	movf	INDF, W
	call	printchar
	return

;***************************************
;	writescantable
;	Write scancode table to EEPROM from RAM
;***************************************
writescantable:
	movlw	scancodetable
	movwf	FSR
	movlw	0x14
	movwf	rsttemp
	BANKX1
	clrf	EEADR
	clrf	EEADRH
	clrf	EEDATH
	bcf	EECON1, EEPGD
	bsf	EECON1, WREN
	BANKX0

	bcf	PIR1, EEIF
	
wstloop:
	movf	INDF, W
	BANKX1
	movwf	EEDAT
	movlw	0x55
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf	EECON1, WR
	BANKX0

	btfss	PIR1, EEIF
	goto	$-1
	bcf	PIR1, EEIF
	
	incf	FSR, F
	BANKX1
	incf	EEADR, F
	BANKX0
	
	decfsz	rsttemp, F
	goto	wstloop

	BANKX1
	bcf	EECON1, WREN
	BANKX0
	return
	
;***************************************
;	readscantable
;	Read scancode table from EEPROM to RAM
;***************************************
readscantable:
	movlw	scancodetable
	movwf	FSR
	movlw	0x14
	movwf	rsttemp
	BANKX1
	clrf	EEADR
	clrf	EEADRH
	BANKX0
	
rstloop:	
	BANKX1
	bcf	EECON1, EEPGD
	bsf	EECON1, RD
	movf	EEDAT, W
	incf	EEADR, F
	BANKX0
	movwf	INDF
	incf	FSR, F

	decfsz	rsttemp, F
	goto	rstloop
	return

;***************************************
;	printscantable
;	Print scancode table
;***************************************
printscantable:
	movlw	scancodetable
	movwf	FSR
	movlw	0x14
	movwf	rsttemp
	
pstloop:	
	movf	INDF, W
	call	printchar
	incf	FSR, F

	decfsz	rsttemp, F
	goto	pstloop
	call	printcrlf
	return

;***************************************
;	newscantable
;	Get new scancode table
;***************************************
newscantable:
	movlw	scancodetable
	movwf	FSR
	movlw	0x14
	movwf	rsttemp
	
nstloop:	
	call	getc
	movwf	INDF
	call	printchar
	incf	FSR, F

	decfsz	rsttemp, F
	goto	nstloop
	call	printcrlf
	return
		
;***************************************
;	whichbit
;	Find first 1 bit in W, returned in W
;***************************************
whichbit:	
	movwf	wbtemp
	clrf	wbcount
wbloop:	
	rrf	wbtemp, F
	btfsc	STATUS, C
	goto	wbdone
	incf	wbcount, F
	movf	wbcount, W
	sublw	8
	btfss	STATUS, Z
	goto wbloop

wbdone:	
	movf	wbcount, W
	return

;***************************************
;	printcrlf
;	Print CRLF
;***************************************
printcrlf:	
	movlw	0x0D
	call	printchar
	movlw	0x0A
	call	printchar
	return
	
;***************************************
;	printhex
;	Print W as hexadecimal number
;***************************************
printhex:
	movwf	phtemp
	swapf	phtemp, W
	call	phchar
	movf	phtemp, W
	call	phchar
	return

phchar:
	andlw	0x0F
	movwf	phctemp
	sublw	0x09
	btfsc	STATUS, C
	goto phcnum
phclet:
	movf	phctemp, W
	addlw   'A'-0x0A
	call printchar
	return
phcnum:
	movf	phctemp, W
	addlw	'0'
	call	printchar
	return
	
;***************************************
;	printpstr
;	Print a string from program memory
;	pstr address in EEADR+EEADRH
;***************************************
printpstr:
	BANKX1
	bsf	EECON1, EEPGD
	bsf	EECON1, RD
	nop
	nop

	rlf	EEDAT, W
	rlf	EEDATH, W
	BANKX0
	andlw	0x7F
	
	btfsc	STATUS, Z
	return

	call	printchar
	
	BANKX1
	
	movf	EEDAT, W
	BANKX0
	andlw	0x7F

	btfsc	STATUS, Z
	return
	
	call	printchar

	BANKX1
	incf	EEADR, F
	btfsc	STATUS, C
	incf	EEADRH, F
	BANKX0
	
	goto	printpstr

;***************************************
;	printchar
;	Print W as character
;***************************************
printchar:
	btfss	TXSTA, TRMT
	goto	printchar
	movwf   TXREG
	return

keyb:
	call	checkserialerror
	btfss	PIR1, RCIF
	retlw	0
	retlw	1

getc:
	call	checkserialerror
	btfss	PIR1, RCIF
	goto	getc
	movf	RCREG, W
	return

checkserialerror:
	btfsc	RCSTA, OERR
	goto	clearserialerror
	return

clearserialerror:
	bcf	RCSTA, CREN
	bsf	RCSTA, CREN
	return

sleeploop:
	clrf	count2	
s1:	
	clrf	count1
s2:
	decfsz	count1, F
	goto	s2

	return
	
	end
