;
; keyboard.inc: handles the "cell phone" style quick
; text input
;
; author: Marko Kanala, raato ]a t[ mulletronic.com
; enters the naming mode - step keys are used in the
; same way as the sms writing in cell phones ie.
; step key 1 == abc
; step key 2 == def
; ...
; step key 9 == number
; step key 14 == delete char
; step key 15 == previous char
; step key 16 == next char
; enter == done
;
; LICENSE
; Creative Commons Attribution-NonCommercial-ShareALike 2.5
;
; You are free:
;
; * to copy, distribute, display, and perform the work
; * to make derivative works
;
; Under the following conditions:
;
; 1. Attribution. You must attribute the work in the manner specified by the
; author or licensor.
; 2. Noncommercial. You may not use this work for commercial purposes.
; 3. Share Alike. If you alter, transform, or build upon this work, you may
; distribute the resulting work only under a license identical to this one.
;
; * For any reuse or distribution, you must make clear to others the license
; terms of this work.
; * Any of these conditions can be waived if you get permission from the
; copyright holder.
;
; Your fair use and other rights are in no way affected by the above.
;
; This is a human-readable summary of the Legal Code.
; See full license at http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
;
; Copyright: Marko Kanala (raato@mulletronic.com).
;
; load FSR1 for destination addr
keyboard:
clrf cursorpos
clrf keyboardbuf
call lcd_cursor_on ; enable cursor
keyboard_loop:
; refresh screen
movff FSR1L, temp2 ; backup FSR1
FORCEDISPLAYREFRESH
call lcd_refresh
movff temp2, FSR1L ; restore FSR1
; refresh cursor position
movf cursorpos, W
addlw LCD_LINE1 + 4
call lcd_set_cursor
CLEAREVENT EVENT_KEY
; wait for "roll presses"
clrf temp
keyboard_waitkey:
IFEVENT EVENT_KEY, keyboard_gotkey
; if no key event delay
call lcd_delay2ms
decfsz temp
bra keyboard_waitkey
; delay passed without key
; if keyboardbuf has a value we need to advance
; to the next position
clrf WREG
cpfsgt keyboardbuf
bra keyboard_loop
; advance
call keyboard_advance
; and clear keyboardbuf
clrf keyboardbuf
bra keyboard_loop
keyboard_gotkey:
KEYEVENT KEY_ENTER, keyboard_done
; decode only step keys
KEYEVENT KEY_S14, keyboard_delete
KEYEVENT KEY_S15, keyboard_prev
KEYEVENT KEY_S16, keyboard_next
KEYEVENT KEY_S10, keyboard_space
; decode keys 1 - 9
movff keypress, temp
movlw KEY_NONE
cpfsgt temp
bra keyboard_loop
; > KEY_NONE
movlw KEY_S10
cpfslt temp
bra keyboard_loop
; key 1 - 9 (key 9 == number)
; check if keyboardbuf matches with the keypress
movf keyboardbuf, W
cpfseq temp
bra keyboard_insertnew
; current keypress == previous keypress, roll key characters
; W == keypress
call get_keyboard_char
; W == upper limit for character roll
movwf temp2
incf INDF1, W ; curr pos char + 1
cpfseq temp2
bra keyboard_setchar
; upper limit reached, roll over
movlw "9" + 1
cpfseq temp2
bra keyboard_normalcharroll
; a number, reset to "0"
movlw "0"
bra keyboard_setchar
keyboard_normalcharroll:
decf temp, W ; keypress - 1
call get_keyboard_char
keyboard_setchar:
; just set the new char without insertion
movwf INDF1
bra keyboard_handled
keyboard_insertnew:
; if keyboardbuf != 0 we need to advance before inserting
tstfsz keyboardbuf
call keyboard_advance
; insert at current position
movff temp, keyboardbuf ; store keypress to keyboardbuf
movlw KEY_S9
cpfseq temp
bra keyboard_insertnormal
; a number, insert "0"
movlw "0"
bra keyboard_doinsert
keyboard_insertnormal:
decf temp, W ; keypress - 1
call get_keyboard_char
keyboard_doinsert:
call keyboard_insert
keyboard_handled:
; loop until enter pressed
CLEAREVENT EVENT_KEY
bra keyboard_loop
; advances to cursor to the next position
keyboard_advance:
movlw 11 ; 12 chars in max
cpfslt cursorpos
return
incf cursorpos
incf FSR1L
return
; insert a char from WREG to the current position
; note: keyboardbuf gets cleared if there is no space
; for the character
keyboard_insert:
movwf temp2 ; temp2 == char
movff FSR1L, temp
; advance to the last char
movf cursorpos, W
subwf FSR1L, W
addlw 11
movwf FSR1L ; FSR1L + 11 - cursorpos
movlw " "
cpfseq POSTINC1 ; "pat_name + 12"
bra keyboard_insnospace
; shift chars after the insertion position
keyboard_insloop:
decf FSR1L
movf temp, W
cpfseq FSR1L
bra keyboard_contins
; shift done, insert char
movff temp2, INDF1
return
keyboard_contins:
decf FSR1L
movf POSTINC1, W
movwf INDF1
bra keyboard_insloop
keyboard_insnospace:
; restore FSR1L
movff temp, FSR1L
clrf keyboardbuf
return
; deletes a character at the previous position
keyboard_delete:
clrf keyboardbuf
clrf WREG
cpfsgt cursorpos
bra keyboard_deletedone
movff FSR1L, temp ; backup FSR1L
movff cursorpos, temp2
; pos > 0, delete ok
; shift chars from this position to the left and
; pad right side with " "
keyboard_delloop:
movlw 12 ; are we done yet ?
cpfslt cursorpos
bra keyboard_delloopdone
movf POSTDEC1, W ; no, move from current to prev
movwf POSTINC1
incf FSR1L ; advance to next
incf cursorpos
bra keyboard_delloop
keyboard_delloopdone:
; shift done, insert " " at the end
decf FSR1L
movlw " "
movwf INDF1
decf temp, W
movwf FSR1L ; restore FSR1L
decf temp2, W
movwf cursorpos
keyboard_deletedone:
CLEAREVENT EVENT_KEY
bra keyboard_loop
; moves cursor to previous position
keyboard_prev:
clrf keyboardbuf
CLEAREVENT EVENT_KEY
; cursorpos from 0 to 12
clrf WREG
cpfsgt cursorpos
bra keyboard_loop
decf FSR1L
decf cursorpos
bra keyboard_loop
; moves cursor to next position
keyboard_next:
clrf keyboardbuf
CLEAREVENT EVENT_KEY
call keyboard_advance
bra keyboard_loop
; enters a space to the current position
keyboard_space:
clrf keyboardbuf
movlw " "
call keyboard_insert
call keyboard_advance
CLEAREVENT EVENT_KEY
bra keyboard_loop
; name enter done!
keyboard_done:
call lcd_cursor_off
return
External Labels :
lcd_cursor_on
lcd_refresh
lcd_set_cursor
lcd_delay2ms
keyboard_advance
get_keyboard_char
keyboard_insert
lcd_cursor_off