; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;                                                                     ;
;   This PIC code implements a matchbox-size universal GKOS keyboard  ;
;   for a variety of devices, using several IR formats. All PC qwerty ;
;   functions are available. The key codes are sent e.g. using the    ;
;   IrDA infrared frame structure at 9600bit/s. The same keycodes are ;
;   also sent through the PIC UART port. A simple driver can receive  ;
;   these codes and convert them directly to corresponding key-up and ;
;   key-down codes understood by the device (PDA, PC or alike). Other ;
;   infrared formats available are Sony SIRCS IR code for MiniDisc    ;
;   remote control with a possibility to enter song titles, GKOS key  ;
;   code IR packets and the old GKOS chord packets for compatibility  ;
;   with previous GKOS projects (PS/2 mouse/keyboard PC interface).   ;
;   There is also a TV remote control operation as an example (ASA).  ;
;                                                                     ;
;   As most of the latest GKOS PIC software, this implements also the ;
;   intelligent key scan mechanism to allow for entering of chordons  ;
;   i.e. chord chains (chord on chord without release of common keys).;
;   Ordinary way of GKOS typing is also possible (press keys for one  ;
;   character and release all keys before the next character) allowing;
;   some overlap of successive chords. Shortcuts to whole words       ;
;   have also been included (There are many of them!).                ;
;                                                                     ;
;   Reception of GKOS IR Mouse data is included but a physical mouse  ;
;   can not yet be connected. The GKOS keyboard can, however, be used ;
;   as a pointer control (Press SHIFT/123-abc to enter that mode).    ;
;                                                                     ;
;   IMPORTANT NOTE:                                                   ;
;   This sofware can also receive same types of *GKOS* IR data        ;
;   it can transmit! Just add the TSOP... IR receiver in parallel     ;
;   with the keyboard (different pins of course). Use UART output     ;
;   to read the received Keycodes and Mouse data.                     ;
;                                                                     ;
;                                                                     ;
;   This software implements a GKOS IR keyboard for PDA, MD, PC etc.  ;
;                                                                     ;
;                  "The Universal GKOS IR Keyboard"                   ;
;                                                                     ;
; Assembly code generation on the PICmicro PIC16F876 with 4 MHz clock.;
;                         More at gkos.net                            ;
;                                                                     ;
;                                                                     ;
;             This source code can be used according to               ;
;          the GNU GENERAL PUBLIC LICENSE Version 2, June 1991        ;
;                                                                     ;
;                  Seppo Tiainen, Veikkola, Finland                   ;
; - Visit gkos.com for specs etc and gkos.net for building projects - ;
;                                                                     ;
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;                                                                     *
;    Filename:	    gpda100.asm                                       *
;    Date:          7 Nov 2005                                        *
;    File Version:  1.00                                              *
;                                                                     *
;    Author:        Seppo Tiainen, Veikkola, Finland                  *
;    Website:       gkos.net (building), gkos.com (specification)     *
;    Email:         g k o s @ g k o s . c o m                         *
;                                                                     * 
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;
;   Version history:
;
; gpda100.asm  First version with all functions (= gpda0999.asm), some shortcuts missing
; - This convention is used from this version on, for example:
; - IR receiver: gpda100i.asm; MD IR transm gpda100m.asm and Chord IR transm gpda100c.asm
; - meaning same version but different default parameter settings (=> gpda100m.hex etc. also)
; - i = IrDA, m = MD, c = Chord, g = GKOS Keycodes (referring to IR output)
; - Known bug: Extra characters appear at UART in IrDA mode. Do not use. Use g instead. 
; - See line 740 below for default parameter settings (bsf/bcf) for different usage
;
;   gpda0999.asm <AKU> signal (all keys up) added in UART out
;   gpda0998.asm Possibility to disable SLEEP function (param. SleepMode)
;   gpda0997.asm Bug fix of n+1 error with last alphabet in shortcuts
;   gpda0996.asm:
;   - 'Keyboard as Mouse' function added (Kbd or IR input, UART output);
;   - More reliable IR Mouse Data Packet reception (CheckIRend added) for
;     receiving IR from GKOS kbd with TrackPoint or Stick pointer control.
;   gpda0995.asm Reception of GKOS mouse IR packets and mouse UART output
;   gpda0994.asm Chordon Shortcut functions expanded. 58 shortcuts now.
;   gpda0993.asm IR reception of GKOS Key Code packets added
;   gpda0992.asm MD Bug fixes (space after shortcut, apostrophe)
;   gpda0991.asm National character optimized layout. Some Chordon shortcuts.
;   gpda099.asm Chordon shortcut tables expanded. 40 kHz for MD IR.
;   gpda098.asm Changing operating modes by [SYMB][Ctrl]m[ENTER] etc.
;   gpda097.asm Chordon shortcut example added ('i => international)
;   gpda096.asm TV remote commands; Lower/Upper case + Backspace for MD
;   gpda095.asm IrDA frame format and GKOS key code transmission
;   gpda09.asm  SIRCS timing adjustments
;   gpda08.asm  SIRCS MD remote control working
;   gpda07.asm  UART key code transmission ok
;   gpda06.asm  development
;   ...
;   gpda03.asm  character table updates
;   gpda02.asm  development
;   gpda01.asm  first version to test PDA IR code transmission
;   glcd18.asm  Used for the most part (GKOS LCD communicator)
;
;---------------------------------------------------------------------|
;                                                                     |
;   If interrupts are not used all code presented between the ORG     |
;   0x004 directive and the label main can be removed. In addition    |
;   the variable assignments for 'w_temp' and 'status_temp' can       |
;   be removed.                                                       |                         
;                                                                     |
;   Refer to the MPASM User's Guide for additional information on     |
;   features of the assembler (Document DS33014).                     |
;                                                                     |
;   Refer to the respective PICmicro data sheet for additional        |
;   information on the instruction set.                               |
;                                                                     |
;---------------------------------------------------------------------|
;                                                                     |
;    Files required: p16f876.inc                                      |
;                                                                     |
;---------------------------------------------------------------------|

	list		p=16f876	; list directive to define processor
	#include	<p16f876.inc>	; processor specific variable definitions
	
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;
; turn off crossing page boundary messages while running the assembler:
;	ERRORLEVEL -306, -302
;
; base frequency
XTAL_FREQ	EQU	4000000	; OSC freq in Hz

; caulculates baudrate when BRGH = 1, adjust for rounding errors
#define CALC_HIGH_BAUD(BaudRate)	(((10*XTAL_FREQ/(16*BaudRate))+5)/10)-1

; caulculates baudrate when BRGH = 0, adjust for rounding errors
#define CALC_LOW_BAUD(BaudRate)		(((10*XTAL_FREQ/(64*BaudRate))+5)/10)-1

;
;============= GKOS INFORMATION =================
;
;              http://gkos.com (specifications)
;              http://gkos.net (build project)
;
;--------Infrared control data format:
;
;This procedure is repeated continuously by the remote IR data transmitter:
; scan keys first time > wait 5ms > If needed send Mouse report > wait 5ms >
; scan keys second time > send Chord value packet > repeat
;
;IR DATA PACKET FORMATS:
;
;-Format of Chord value packet:
;[start] D0 D1 D2 D3 D4 D5        - 6 bits -
;        G  1  A0 A1 A2           - 5 bits -  G=toggle, 1=keyboard
;
;-Format of Mouse data packets:
;[start] D0 D1 D2 D3 D4 D5        - 6 bits -
;        G  0  A0 A1 A2 A3 Z(=0)  - 7 bits -  G=toggle, 0=mouse, Z=0: pointer data
;        X0 X1 X2 X3 X4 X5 X6 X7  - 8 bits -  (pointer movement data)
;        Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7  - 8 bits -
; or:
;[start] D0 D1 D2 D3 D4 D5        - 6 bits -
;        G  0  A0 A1 A2 A3 Z(=1)  - 7 bits -  G=toggle, 0=mouse, Z=1: wheel data
;        Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7  - 8 bits -  (scroll wheel data)
;-------------------------------------------
;
;=================== VARIABLES: ==============================

;PIC 16F876 General Purpose Register locations are 0x20...0x7F (Bank 1)

TempB0		EQU     0x20	; Used to store bit locations in chord polling
TempB1		EQU     0x21
TempB2		EQU     0x22
TEMP0           EQU     0x23	; These TEMP1 to TEMP3 are used in the key polling
TEMP1           EQU     0x24	;   timer checks (see KeyTime)
TEMP2           EQU     0x25

;*** GKOS specific definitions

chord		EQU	0x26	; Chord at the reading moment
maxchord	EQU	0x27	; Max pressed combination before all keys released
finalchord	EQU	0x28	; Final key combination
GKOSstatus	EQU	0x29	; GKOS keyboard status bits
				;  bit0=1: chord received
				;  bit1=1 typematic on
				;  bit2=1 activity on GKOS noticed
				;  bit3=IR toggle bit (expected)
				;  bit4= RXchordREADY, IR Chord is ready for output to PS/2
				;  bit7-bit5: 
				;    bit7=1 IR operation (IR receiver connected) NOT USED
				;    bit6=1 IR packet received correctly
				;    bit5=1 'Kbd as Mouse' operation / bit5=0 Keyboard operation
GKOSref		EQU	0x2A	; GKOS character ref.number based on finalchord
                                ;  (the specified GKOS ref.num)
GKOSrefshift	EQU	0x2B	; 0, 63 or 126 (abc, 123 or SYMB tables) + GKOSref
GKOSmode	EQU	0x2C	; bit0:      abc-123 1=123,      0=abc
				; bit2/bit1: SYMB,  10=SYMBon,  11=SYMBlock
				; bit4/bit3: SHIFT, 10=SHIFTon, 11=SHIFTlock (CAPS LOCK)
				; bit5:      CTRL,   1=CTRLon 
				; bit6:      ALT,    1=ALTon  
				; bit7:      Paste on. (Still missing: NUMLOCK)
keycode		EQU	0x2D	; Based on GKOSref, this points to the
				;  proper scan code in table
TempShift1 	EQU	0x2E	; Temporary shift register

;**** Delay

dcount1		EQU	0x2F    ; Used in Delay subroutines 
dcount2		EQU	0x30		 
dcount3		EQU	0x31		 
dcount4		EQU	0x32		 

;**** PS/2 data/clock line communications

COUNTER		EQU	0x33		; bit counter for PS/2 comms
PARITY		EQU	0x34		; parity for PS/2 comms
RECEIVE		EQU	0x35		; PS/2 keyboard receiving buffer
Offset		EQU	0x36		; Table offset (scan codes etc.)
MRECEIVE	EQU	0x37		; PS/2 mouse receiving buffer

;*********

;LoopCounter	EQU	0x38		; Temporary counter in loops
ZeroChords	EQU	0x38		; Zero Chord counter for wired GKOS keyboard polling routine
temp_a		EQU	0x39		; Temporary IR reception delay counters
temp_b		EQU	0x3A
temp_c		EQU	0x3B

				; Mouse bytes to be sent to Host (PC PS/2 lines):
				; bit7 bit6 bit5  bit4  bit3  bit2    bit1    bit0
;MOUSE_BUTTONS	EQU	0x3C	; Yovf Xovf Ysign Xsign '1'  MidButt RButton LButton
;MOUSE_X	EQU	0x3D	; X7... X0
;MOUSE_Y	EQU	0x3E	; Y7... Y0
;MOUSE_Z	EQU	0x3F	; '0'   '0'   5thButton   4thButton   Z3... Z0
				; - Z3...Z0 Scroll Wheel data zzzz, values: -8...+7

;---more PS/2 kbd communications

TEMPY		EQU	0x3f	; a very local variable, LCD and IR TX
TEMPX		EQU	0x40	; A local variable used in IR TX&RX and LCD output

;TXstatus	EQU	0x41	; spare (bit0=1 => Return from ByteOut without sending.)
				; spare (bit1=1 <= There was Reception during ByteOut)

SelectTable	EQU	0x42	; Select Chordon shortcut table based on flag bits
Tmp2		EQU	0x43	; Very temporary variable (for key up/down counter)
Temp		EQU	0x44	; Very temporary variable (UART tx bits; Save at table calls)
tempflags	EQU	0x45	; FLAGS: bit0=IR bit correctly received
				; bit1=1 a Zero Chord must be sent when possible.
				; bit2=1 if character comes from IR link; 0 for own keyboard
				; - this is used to show the character on correct LCD line
				; bit3 follows the value of bit2 to notice the change
				; bit4 SpecialKey, For IR transmissions, indicates that
				;   Shifts are sent and no sub call is made to check Shifts
				; bit5 Command Flag, [SYMB][Ctrl] has been pressed.
				; bit6 <AKU> has been sent for wired kbd
				; bit7 <AKU> has been sent for IR chord reception
;---PS2 flags----
PS2flags	EQU	0x46	; IRTXline: IR TX ouput line state, 1/0 to decide if 0 or 1 will follow
				; bit1=1 (Mouse enable (M_ENABLE) received from Host)
				; bit2=1 SleepMode, go to sleep after 5 min of inactiv. (was: LCD busy)
				; bit3=1 US version of keyboard
				; bit4=1 LCD 8-bit mode on
				; bit7=1 MoreChords (in buffer RXfinalchord2) to be sent via PS2
GKOSref2	EQU	0x47	; GKOS Ref for Chordon shortcut second character
Tmp3		EQU	0x48	; temp chord in check-back
GKOScounter1	EQU	0x49	; Counter for JustScanned indication, Wired GKOS kbd
GKOScounter2	EQU	0x4A	; Counter for JustScanned indication, Wired GKOS kbd
IRCounter	EQU	0x4B	; Count repeats of IR SIRCS frames (for each byte to send)
SCpointer	EQU	0x4C	; Chordon Shortcut pointer
;----------
;spare room
;---------

;---IR parameters---

IR_mode		EQU	0x4F	; bit0=1 => GKOS_IR_mode (just send keyboard status)
				; bit1=1 => Byte_IR_mode (one byte per character)
				; bit2=1 => IrDA_mode
				; bit3=1 => SIRCS_MD_mode
				; bit4=1 => SIRCS_MD_EDIT
				; bit5=1 => GKOS_byte_mode
				; bit6=1 => TV1_mode
				; bit7=1

IRmaxchord	EQU	0x50
RXfinalchord	EQU	0x51
IRflags		EQU	0x52	;bit0=1 SIRCS20 IR frame is 20-bit
				;bit1=1 LCD edge passed
				;bit2=1 RXchordREADY ready to send character to host
				;bit3=1 NoOutput (key polling) even if a key is released
				;bit4=1 NewChar (key polling), output if key is released
				;bit5=1 CheckBackOn
				;bit6=1 TextOnly allowed, chord is within a chordon
				;bit7=1 LCD_busycheck=1 => Busy flag can be tested

RXchord		EQU	0x53	; Chord received from wired keyboard or IR link

KeyTime0	EQU	0x54	; Counter for Key down period (255 > 0)
KeyTime1	EQU	0x55	; Counter for Key down period (255 > 0)
KeyTime2	EQU	0x56	; Counter for Key down period (255 > 0)
KeyTime3	EQU	0x57	; Counter for Key down period (255 > 0)
KeyTime4	EQU	0x58	; Counter for Key down period (255 > 0)
KeyTime5	EQU	0x59	; Counter for Key down period (255 > 0)

RXfinalchord2	EQU	0x5A	; Chord that was left in buffer because two chords must be output
				;  due to checking back in the key polling procedure
				; 
PrevChord1	EQU	0x5B	; Previous chord for key polling procedure
PrevChord2	EQU	0x5C	; 'Previous to previous' chord for key polling procedure
ToggleCounter	EQU	0x5D	; IR reception Toggle timer (polling, autorepeat)
Downs		EQU	0x5E	; Chord value to be output (keys down, polling)

;---Scancode parameters

;scancode	EQU	0x5F	; temp place to store scancode
AKUflags	EQU	0x5F	; Bit 0: Latest received IR chord is Zero chord
				; Bit 1: Latest received wired chord is Zero chord
				; Bit 3: spare
sc_buffer0	EQU	0x60	; Buffer for the 2-character chordon shorcut
sc_buffer1	EQU	0x61	; Buffer for the 2-character chordon shorcut
;sc_buffer2	EQU	0x62

;-----------

;--- more IR parameters

IRdevice	EQU	0x63	; IR Device code in IR RX (xxxa aadg = xxx1 11xx) a:210
;IRinfopart	EQU	0x64	; Received information part of the IR packet:
				; x  x  x D6    D7 A0 A1 A2 (instead: use the IRByte2 received)
				; The received IR data bytes:
				; ---------------------------
IRByte1		EQU	0x65	; - chord value or mouse button etc data (extra bits A3 Z follow)
				; Chord: -  - D5   D4   D3    D2    D1      D0
				; Mouse: -  - Yovf Xovf Ysign Xsign RButton LButton  
IRByte2		EQU	0x66	; Device (A2-A0), mouse/chord bit d, toggle bit G (xxxa aadg)
				; Chord: xxxa aa1g: - - - A2 A1 A0 '1' TOGGLE 
				; Mouse: xxxa aa0g: - - - A2 A1 A0 '0' MTOGGLE
				; (Two bits A3 0/1 are sent here inbetween but not stored)
IRByte3		EQU	0x67	; X movement (X7...X0) or wheel data (0 0 0 0 Z3...Z0)
IRByte4		EQU	0x68	; Y movement data (Y7...Y0)

				; Bytes to send to the PS/2 interface (Send Bit0 first)
				; -----------------------------------
MouseByte1	EQU	0x69	; Yovl Xovl Ysign Xsign  '1'  MButton RButton LButton (pointer)
;MouseByte2	EQU	0x6A	; Similar to IRByte3 (X7...X0)
;MouseByte3	EQU	0x6B	; Similar to IRByte4 (Y7...Y0)
MouseByte4	EQU	0x6C	; '0' '0' 5thButton 4thButton Z3 Z2 Z1 Z0 (Scroll wheel data)
KMouseByte1	EQU	0x6D	; Yovl Xovl Ysign Xsign  '1'  MButton RButton LButton, for kbd as Mouse

WaitCounter	EQU	0x6E	; counter for key polling, no not accept new key releases

IRcode		EQU	0x6F	; IR code info part to send by the remote control

;====
;spare room
;====

;Locations 0x71...0x7F (source: 16F876A template) 

w_temp		EQU	0x71		; variable used for context saving 
status_temp	EQU	0x72		; variable used for context saving
pclath_temp	EQU	0x73		; variable used for context saving
;
temp01		EQU	0x74	; IR Transmission varable
bitcounter	EQU	0x75	; IR Transmission varable

CommandBuffer0	EQU	0x76	; IR mode selection command buffer 0 (> 0 > 1 >)
CommandBuffer1	EQU	0x77	; IR mode selection command buffer 1

SLEEPcnt1	EQU	0x78	;counter to goto sleep when no key activity
SLEEPcnt2	EQU	0x79	;counter to goto sleep when no key activity
SLEEPcnt3	EQU	0x7a	;counter to goto sleep when no key activity


;====
;spare room
;====
;
;(max 0x7F)
;
; ------------------ Program memory pages: ------------------------------
; Page 0:    0h -  7FFh	2k	PCLATH need not be used for CALL and GOTO
; Page 1:  800h -  FFFh	4k	PCLATH<3>   must be used (set PCLATH<3>)
; Page 2: 1000h - 17FFh	6k	PCLATH<4,3> must be used (set PCLATH<4>)
; Page 3: 1800h - 1FFFh	8k	-"-                      (set PCLATH<4,3>)
; See Chapter 6.2.6 of 33023a.pdf for more.
;------------------------------------------------------------------------
;
;=================== DEFINITIONS:

;Note that PS/2 Data and Clock lines are brought to 0 (low) state by changing their
;appropriate I/O pins to output state. Original values must be 0 at those pins.
;Pull up resistors (4k7) are required if testing without connecting to a PC keyb socket.

#define	SLEEPdelay d'100' ;d'3'	; 1 => 3 sec (nx3s) Idle Time before going to sleep
				; 5 min = 300 sec = 100 x 3s => SLEEPdelay = 100
				; For tests: 9 sec => SLEEPdelay = 3

; LCD Data lines D7 D6 D5 D4 = PORTA, 2-5 (PORTA,0-1 are for mouse Yin Xin)

#define SYNCH		PORTC,1		; Testpoint: Synchronisation for oscilloscope
#define	LCD_RS		PORTC,2		; LCD Register Select
#define	LCD_RW		PORTC,3		; LCD R/W
#define	LCD_E		PORTC,4		; LCD Enable
#define	SleepMode	PS2flags,2	; If set, goto to sleep after 5 min of inactivity
;#define	LCD_busy	PS2flags,2	; LCD busy flag
#define	LCD_busycheck	PS2flags,7	; LCD busy flag can be checked

#define TESTPOINT	PORTC,7  ;4	;=4>7 Test point (pin) for IR reception timing

#define	IRTXDATA	PORTC,0		; IR TX data output port pin
;#define MDEVICE		b'00000111' ;A2-A0 = 111 (not used yet in this version)
;				  ---00aaa(- - - Z A3 A2 A1 A0) Z A3 = 00 (pointer data)
					; IR TX device is defined here:
#define DEVICE		b'00011110'	;A2-A0 = 111,  dg = 1 G
;				  xxxaaadg            gdaaa     gdaaa-
;				b'00011110' => scope: 01111, ...011110 (=MD) gdaaa0
;
#define SDEVICE		b'00001111'	; SIRCS MD address is 11110 (reverse order in SDEVICE)

#define	IRDATA		PORTB,6		; IR Data input. Low when IR pulse. Internal pull-up used.
#define	AutoRepeat	GKOSstatus,1	; autorepeat indication
#define GKOS_IR_mode	IR_mode,0	; GKOS IR mode (chords = mode c)
#define Byte_IR_mode	IR_mode,1	; Byte IR mode (one byte per character)
#define IrDA_mode	IR_mode,2	; - IrDA frame mode (of Byte IR mode = mode i)
#define SIRCS_MD_mode	IR_mode,3	; - SIRCS MD mode   (of Byte IR mode = mode m)
#define SIRCS_MD_EDIT	IR_mode,4	; - - SIRCS MD EDIT mode (20-bit codes), see also SIRCS20
#define GKOS_byte_mode	IR_mode,5	; - GKOS byte mode (of Byte IR mode = mode g), 8 data + 3 address bits
#define TV1_mode	IR_mode,6	; - TV1 remote command mode (of Byte IR mode = mode t)



#define SIRCS20		IRflags,0	; SIRCS format is 20-bit (symbols), not 12-bit
;#define LCD_edge	IRflags,1	; LCD display edge has been passed, shift needed
#define AV_mode		IRflags,2	; Remote command mode (any). Use codes 129...255  (IR)
#define NoOutput	IRflags,3	; no character output even if a key is released (IR)
#define NewChar		IRflags,4	; new character output if any key released (IR)
#define CheckBackOn	IRflags,5	; Check-back is enabled.
#define TextOnly	IRflags,6	; Chord is within a chordon. Text only allowed, or space.
#define RXchordREADY	GKOSstatus,4	; bit4=1 IR Chord ready for output to PS/2
#define ZeroChordMissing	tempflags,1	; A zero chord must be sent as soon as possible
;#define RecChar		tempflags,2	; RecChar=1 if the character is received via IR link
					;  -show on LCD top line then
;#define RecCharPrev	tempflags,3	; Follows the value of RecChar to notice the change
					; Next timing periods are N x 30 ms:
#define SpecialKey	tempflags,4	; Do not make a sub call to check Shift status
#define CommandFlag	tempflags,5	; [SYMB] [Ctrl], or just [Ctrl] in remote control mode, have
;					   been pressed. Wait for [Enter] to find out the command.
#define AKUSent_WR	tempflags,6	;  <AKU> has been sent for wired kbd 
#define AKUSent_IR	tempflags,7	;  <AKU> has been sent for IR chords received

#define	ZeroChordIR	AKUflags,0	; Latest received IR chord is Zero chord
#define	ZeroChordWR	AKUflags,1	; Latest received wired chord is Zero chord

#define	TDelay		d'30'		; (d'25') Autorepeat delay (cleverer polling)
#define	MTDelay		d'7'		; (d'8') Mouse Autorepeat delay
#define	WaitPeriods	d'5'	; (d'5'ok) WaitCounter value after key release (key polling)
					;   only valid in case of no check-back in use
#define GKOSdelay	d'25'		; Delay before re-scanning the wired GKOS
#define IRrepeats	d'2'		; Repeat every SICRS etc. frame N times

#define IRTXline	PS2flags,0	; IR TX ouput line state, 1/0 to decide if 0 or 1 will follow
;#define M_ENABLE	PS2flags,1	; spare (Mouse ENABLE received from Host)
#define	US_version	PS2flags,3	; US version of keyboard in use
#define Eight_bit_mode	PS2flags,4	; LCD 8-bit mode ON.
	; ...
#define MoreChords	PS2flags,7	; There is a chord in buffer RXfinalchord2 to be sent via PS2

#define	KBDasMOUSE	GKOSstatus,5	; Mouse operation through GKOS keys is ON

#define	MODE123on	GKOSmode,0	
#define	SYMBlock	GKOSmode,1
#define	SYMBon		GKOSmode,2
#define	SHIFTlock	GKOSmode,3
#define	SHIFTon		GKOSmode,4
#define	CTRLon		GKOSmode,5
#define	ALTon		GKOSmode,6
#define	PASTEon		GKOSmode,7



;**********************************************************************
	ORG     0x000             ; processor reset vector
	nop			  ; nop required for icd
  	goto    main              ; go to beginning of program


;***** INTERRUPT ROUTINE: *********************************************

	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register
	movf	PCLATH,w	  ; move pclath register into w register
	movwf	pclath_temp	  ; save off contents of PCLATH register

;   isr code can go here or be located as a call subroutine elsewhere

	movf	pclath_temp,w	  ; retrieve copy of PCLATH register
	movwf	PCLATH		  ; restore pre-isr PCLATH register contents
	movf    status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f
	swapf   w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt

;================== Macros ======================================= 

Delay   macro   Time            ;Delay instruction cycles 
    if (Time==1) 
          nop 
          exitm 
    endif 
    if (Time==2) 
          goto $ + 1 
          exitm 
    endif 
    if (Time==3) 
          nop 
          goto $ + 1 
          exitm 
    endif 
    if (Time==4) 
          goto $ + 1 
          goto $ + 1 
          exitm 
    endif 
    if (Time==5)  
          goto $ + 1 
          goto $ + 1 
          nop 
          exitm 
    endif 
    if (Time==6) 
          goto $ + 1 
          goto $ + 1 
          goto $ + 1 
          exitm 
    endif 
    if (Time==7) 
          goto $ + 1 
          goto $ + 1 
          goto $ + 1 
          nop 
          exitm 
    endif 
    if (Time%4==0) 
          movlw (Time-4)/4 
          call Delay_Routine 
          exitm 
    endif 
    if (Time%4==1) 
          movlw (Time-5)/4 
          call Delay_Routine 
          nop 
          exitm 
    endif 
    if (Time%4==2) 
          movlw (Time-6)/4 
          call Delay_Routine 
          goto $ + 1 
          exitm 
    endif 
    if (Time%4==3) 
          movlw (Time-7)/4 
          call Delay_Routine 
          goto $ + 1 
          nop 
          exitm 
    endif 
    endm 

;===================== ....more macros...


;======================= ...end of macros ===========================


;********************** MAIN *****************************************
;				Memory blocks
; Reset vector     0000h (RAM)
; Interrupt vector 0004h (RAM)
;
; Program memory Pages (PROM): 
; P0 0005h-07FFh Program...
; P1 0800h-0FFFh Enhanced key polling precedures. LCD encoding. More Program Code
; P2 1000h-17FFh (spare)
; P3 1800h-1FFFh Character and Scancode Tables
; 
;
;*********************************************************************;
;__________________________ P0 0005h-07FFh Program..._________________;

main

;===================== INITIALIZE PARAMETERS =========================
	clrf	PORTB		; clear port B

				; Set Bank 1 registers
				; --------------------
				;
	bsf	STATUS,RP0      ; change to register bank 1
	bcf	STATUS,RP1

	bcf	OPTION_REG,7	; ...for bank 1 OPTION_REG: clear bit 7 for pull-ups
				;  on port B (GKOS keys + IR input line)

	; UART Bank 1 settings are here.
        ; for UART, the TRISC:6 and TRISC:7 must be set
	; (as for output, but operates as input/output)
	bsf	TRISC,6
	bsf	TRISC,7

				; Port C
				; ------
	movlw	b'10100000'	; binary value, 1 bit per port bit
	movwf	TRISC		; RC0 IR TX, (RC1 was LCD_power)
				; RC1 SYNCH for oscilloscope tests
				; RC2 LCD_RS (reg.sel.) RC3 LCD_RW
				; RC4 LCD_enable (was: TEST POINT OUTPUT for IR timing)
				; RC5 UART RXdata input
				; RC6 UART TXdata ouput
		 		; RC7 spare input

				; Port B - GKOS keys
				; ------
	movlw	b'01111111'	; binary value, 1 bit per port bit
	movwf	TRISB		; RB0-RB6 set to digital inputs, GKOS keys + IR data in
				; (RB7 is PORTB output, not used)
				;  RB0-RB5 Keyboard
				;  RB6     IR data input

				; Port A - LCD data bus (+ mouse spare pins)
				; ------
	movlw	b'11111111'	; binary value, 1 bit per port bit
	movwf	TRISA		; RA0,1,6,7 set to inputs (2 spare pins, R0,1)
				; RA2-5 outputs for LCD 4-bit data bus

				;Any other settings for Bank 1 registers?

				; Return to Bank 0
				; ----------------
	bcf	STATUS,RP0	; change to register bank 0


	call	INIT_UART	;*** UART Transmission - write to reg. 19h TXREG

	movlw	b'00111100'
	movwf	PORTA		; ALL LEDS OFF/output to high state (CAPS, 123, SYMB, spare)
	;clrf	TXstatus	; Clear flags and parameter values
	clrf	RECEIVE
	clrf	chord
	clrf	RXchord
	clrf	RXfinalchord2
	clrf	PrevChord1
	clrf	PrevChord2
	clrf	Downs
	clrf	WaitCounter
	clrf	ZeroChords
	clrf	maxchord
	clrf	IRmaxchord
	clrf	finalchord
	clrf	RXfinalchord
	clrf	GKOSstatus
	clrf	GKOSref
	clrf	GKOSrefshift
	clrf	GKOSmode
	clrf	PS2flags
	clrf	IRflags
	clrf	AKUflags
	clrf	tempflags
	clrf	MouseByte1 ; not used
	clrf	KMouseByte1
	clrf	IR_mode

	movlw	IRrepeats	; Repeat every IR frame (SIRCS etc.) N times (3)
	movwf	IRCounter	;  (update the value here too)


	bcf	LCD_E
	clrf	CommandBuffer0	; Clear IR mode command buffers
	clrf	CommandBuffer1	; ...
	;clrf	CommandBuffer2	; ...
	;bsf	LCD_power	; Turn on LCD and IR receiver power

	movlw	TDelay		; Initialize autorepeat down counter.
	movwf	ToggleCounter	; Use the kbd delay value.

		;IR data formats.  SIRCS spec: 01111 = MD
		;MD 0001000 11110 / GKOS: 000100 01111(0) = cccccc gdaaa(0) <on oscilloscope
		;MD: 7 + 5 = 12 bits / GKOS: 6 + 5 = 11 bits. Received order: xxxa aadg
	movlw	b'00011100'	;Set the default IR device code in reverse order (xxxa aadg)
	movwf	IRdevice	;Sending order: x x x A2  A1 A0 D7 D6; SIRCS spec: 01111 = MD 
				;D6=G (character toggle bit).
				;D7=1 for keyboard and 0 for mouse. A0-A2 = device address
				;				RX: Check only bits A0 A1 = 1 1
	movlw	d'100'		;Delay before sending 'GKOS' via UART at 9600 bit/s
	call	DelayWx10ms	; - this will test that debug monitor is working
	
				; FAR CALL address:
				;    X XCCC CCCC CCCC (PC<12:0>)
				;  PCLATH-- -PCLATL--
				;    H HHHH LLLL LLLL
				;   12 1098 7654 3210
	movlw	HIGH TestUART	; Get high 5 bits of address
	movwf	PCLATH		; Load high address in latch
	call	TestUART	; send text: GKOS <CR> to UART (pin RC6)
	movlw	HIGH MainLoop	; Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH

	;movlw	d'50'
	;call	DelayWx10ms


;================== SETTING DEFAULTS FOR MODES AND KEYBOARD LAYOUT =====================
;
;---- Select here whether US or FIN/SWE keyboard layout is used ---
;                         =============================
; US version has word shortcuts instead of the Scandinavian letters of the FIN/SWE layout.
; This sets the default national keyboard layout (US/UK or FIN/SWE) only.
; The layout can always be changed by typing [ALT] [123-ABC] ('Alternative mode')
;
	bsf	US_version	; This selects US keyboard as default layout and
				; must be a commented line for FIN/SWE kbd layout.
				; Use [Alt] [123-ABC] to switch between modes
;--------------------------------------------------------------------------------
	bsf	CheckBackOn	; Enable check-back of missed chords (recommended)
				; - comment the line to disable
;---------------------------------------------------------------------------------
;---- Select here the default IR mode(s), bsf=yes, bcf=no
;     ===================================================
			; **To send IR data, select**:
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
				;  (final key code on UART as well)
				;  This mode is compatible with the PS/2 GKOS IR
				;   interface for the PC.
			; **or**:
			;      {
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
				;  Enable IR transm. of key codes in general
			   ; **and one of these**:
	bsf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
				;    8 data  + 3 address (000) bits
	bcf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
				;    e.g. to a PDA IrDA receiver (driver needed on PDA)
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
				;    a MiniDisc player/recorder
		bcf	SIRCS_MD_EDIT	; - - SIRCS MD EDIT state (20-bit codes), see also SIRCS20
				;    (Select bcf always! Will be turned on automatically.)
	bcf	TV1_mode	; - TV1 remote control mode (ASA)
			;      }
;------------------------------------------------------------------------------------

	; Do not change these:
	; AV_mode = 0 is the normal text entry mode of GKOS, character codes 1...127
	bcf	AV_mode		; Default
	btfsc	SIRCS_MD_mode	; Set AV_mode = 1 for all Remote Control modes
	bsf	AV_mode		; Characters 129...255 will be used as default
	btfsc	TV1_mode	;  at UART. When MD text entry mode is used, AV_mode
	bsf	AV_mode		;  is cleared for that action elswhere.

;-----------------------------------------------------------------------------------------
	; SELECT SLEEP MODE *****
	bcf	SleepMode	; bcf when used as an IR receiver, bsf when as a keyboard
;-----------------------------------------------------------------------------------------
;=========================================================================================
;
;---------
; Details of modes:
;
; IR Packets	D0 D1 D2 D3 D4 D5 G  1  A0 A1 A2 -
; ===================================================
; GKOS chord	x  x  x  x  x  x  X  1  1  1  1	     <= Chord value sent continuously
;							 (6 + 5 = 11 SIRCS-coded bits)
; SIRCS MD	x  x  x  x  x  x  x  1  1  1  1  0   <= Sony MD remote commands
;							 (7 + 5 = 12 SIRCS-coded bits)
; GKOS keycode	x  x  x  x  x  x  x  x  0  0  0	     <= GKOS final key code (0-255) sent
;							 as a single byte (8 + 3 bits);
; 		D0 D1 D2 D3 D4 D5 D6 D7 A0 A1 A2 -         this can be used to send data
;							   to a PC with 3rd party IR
;							   reception software (PC remote
;							   control)
;
; GKOS chord mode: Send IR chords (keyboard status, 6 + 5 bits) continuously +
;			 send final key codes* on UART (8 bits)
; Byte_IR_mode:    Send final key codes on UART (8 bits) + send final key codes
;			 as single bytes on IR (SIRCS, IrDA, GKOS byte or none)
; SIRCS MD mode:   Send Sony MD remote commands (12 SIRCS-coded bits) on IR +
;			 send final key codes on UART (8 bits)**
; IrDA mode:       Send final key codes as 3 IrDA frames (3 x 8 data bits):
;			 Header > IR device address > key code
; 			 + send final key codes on UART (8 bits) as single bytes
;			 both IrDA and UART use 9600 bit/s.
; TV1 mode:        Send ASA TV remote commands (for testing), 8-bit data + 8-bit IR address
;
; *) Final key codes (0-255) are the codes listed in a table. They are determined by
; intelligent key scanning techninques. One code represents one character, or function,
; that has been typed on the GKOS keyboard. Characters may be typed as single entries
; (press and release keys) or within chordons (no release of all keys needed between characters).
;
; **) Not optimal for fast typing (both UART and IR) because sending SIRCS remote commands
; takes time due to repeated IR packets. SIRCS reception only accepts characters if they are
; sent 2 or 3 times, this software sends 2
;------------------------------------------------------------------------


;============================== END OF SETTINGS ===========================================


	; Prepare for SLEEP operation

	bcf	INTCON, RBIF	; Clear Port B interrupt flag (just to make sure)
	bsf	INTCON, RBIE	; Enable Port B interrupts

	movlw	d'255'
	movwf	SLEEPcnt1
	movwf	SLEEPcnt2
	movlw	SLEEPdelay	; This defines the ilde time before going to sleep
	movwf	SLEEPcnt3  ; 1=> 5s, 5=> 26s, 50=> 4:10 60=> 5 min, 100=> 8:20


;============================ PROGRAM ==================================

; The device should check 'request to send' from host (=DATA pulled low)
; at least every 10ms!

MainLoop

	; Delay	d'100'		;delay 100us

;------------------------
;===== PS/2 KEYBOARD ====
;------------------------
MainL_Keyboard

	; Principle: Cut out characters that cannot be within a chordon
	; In case previous chord was zero, any next character must be allowed next
	;bsf	TextOnly	; <<<test
	incf	RXfinalchord,f	; RXfinalchord=0?
	decfsz	RXfinalchord,f
	goto	ML_K0
	bcf	TextOnly	; Allow any character next because it is not part of a chordon.

ML_K0

;---------------------
;===== PS/2 MOUSE ====
;---------------------
;MainL_Mouse

;------------------------------
;==== Wired GKOS keyboard =====
;------------------------------
	;goto	MainL_GKOS_0	; <<<<<TEST

MainL_GKOS

		; Any chords in buffer to send?

	btfss	MoreChords	; More chords to be sent? Due to Check-back.
	goto	MainL_GKOS_2	; No. Check wired GKOS and IR reception next.
				; Yes.

	movf	RXfinalchord2,W	; Get the chord from buffer.
	movwf	RXfinalchord	; Save it for transmission.
	clrf	RXfinalchord2	; Clear buffer to make sure...
				; (MoreChords variable sometimes may be '1' in error!)

	call	UARTSendChord_2	; Send RXfinalchord2 (now in RXfinalchord) to
	bcf	MoreChords	; Clear flag to avoid repeating this.
	goto	MainLoop	;   LCD and IR.

MainL_GKOS_2
	call	CheckAKU	; AKU to be sent for IR reception? If yes, send it here.
	call	CheckAKU_WR	; AKU to be sent for wired kbd? If yes, send it here.

		; =============================
		; Check the wired GKOS keyboard: Any keys pressed.
		; =============================
	; Zero Chords are indicated in the scanning routine for param ZeroChordWR

	call	ReadGKOSchord   ; No. Scan, return with param. finalchord
	btfsc	GKOSstatus,0	; Was there any key pressed? bit0 = 1?
	goto	MainL_GKOS_2b	; Yes. Go on.
				; No.
	goto	MainL_IR	; Continue by POLLING IR reception

MainL_GKOS_2b
				; Any key has been pressed so...

	; Send the GKOS keyboard status after each scan, non-zero chords + zero tails
	; Chord IR packet - takes about 18 ms to send

	btfss	Byte_IR_mode	; Byte IR mode?
	goto	GKOS_IR		; No.
				; Yes.
	btfsc	KBDasMOUSE	; Keyboard as mouse ON?
	goto	GKOS_IR		; Yes. Send Chords in all modes anyway.
				; No.

	; These two routines are alternatives
	; Either skip sending the chord value and have a delay...

Other_IR			; Compensate delay from IR packet
	btfsc	AutoRepeat	; Is this autorepeat?
	goto	GKOS_IRX	; Yes. Forget the delay then.	
	movlw	d'16'		; No. Delay.
	call	DelayWx1ms
	goto	GKOS_IRX
GKOS_IR
	; ... or send the chord value as defined for GKOS IR
	call	SendStart	; 2200us pulse
	movf	chord,W		; chord must be in W
	call	SendChord_W	; 6 bits
	call	SendDevice	; 5 bits
GKOS_IRX
	call	UARTSendChord	; Scan RXchords and send to UART and possibly to IR

; ------------

;----------------------
;==== IR RECEPTION ====
;----------------------
MainL_IR
		; ======================
		; Check the IR reception: any start pulse detected?
		; ======================
	call	CheckIR		; Check IR reception.
				; ==================
	movwf	TEMPX		; bits 0,1,2 and 7 in W indicate results of IR reception
	btfsc	TEMPX,7		; No proper IR data received? (Use TEMPX to store W)
	goto	MainLoopX	;  -Right. Skip the rest.

	; IR data received

	btfss	TEMPX,0		; Chord IR data received?
	goto	MainL_IRa	; No.
	call	UARTSendChord	; Scan RX chords and send to IR.

	bcf	ZeroChordIR	; Default = Not a ZeroChord
	incf	RXchord,f	; RXchord = 0?
	decfsz	RXchord,f	; 
	goto	MainL_IRa0	; Not a Zero chord.
				; Yes. Zero IR Chord received.
	bsf	ZeroChordIR	; 
	goto	MainLoop
MainL_IRa0
	bcf	AKUSent_IR	; Set default. AKU not sent for the next Zero Chord.
MainL_IRa
	btfss	TEMPX,1		; Movement IR data received?
	goto	MainL_IRb	; No.
	goto	UARTSendMov	; Yes. Send it via UART.
			; Remember to send Zero Chord first if needed.(???PS/2 thing)
MainL_IRb
	btfss	TEMPX,2		; Scroll wheel IR data received?
	goto	MainL_IRc	; No.
	goto	UARTSendScroll	; Yes. Send it via PS2 mouse data/clock lines.

MainL_IRc
	btfss	TEMPX,3		; GKOS Keycode IR data received?
	goto	MainLoop	; No.
	movf	IRByte1,w	; Yes.
	call	SerTx1		; Send via UART (always send key code as received by IR)
	call	StayAwake
	goto	MainLoop

;---------
MainLoopX
	btfsc	SleepMode	; Planning to sleep at all?
	call 	SLEEP_loop	; Yes. Time to go to sleep? ***************
	goto	MainLoop


CheckAKU
	; Was a zero chord received. vbvbvbvb	
	btfss	ZeroChordIR	; Latest received IR chord was a Zero Chord?
	return			; Not a Zero chord.
				; Yes. Zero Chord.
	btfsc	AKUSent_IR	; AKU Already sent?
	return			; Yes.
	movlw	d'253'		; No, send it. Keycode indicating all keys up = <AKU>
	call	SerTx1		;
	bsf	AKUSent_IR	; Set sent flag
	return

CheckAKU_WR 	; Same as above for the wired keyboard
	; Was a zero chord received.	
	btfss	ZeroChordWR	; Latest received IR chord was a Zero Chord?
	return			; Not a Zero chord.
				; Yes. Zero Chord.
	btfsc	AKUSent_WR	; AKU Already sent?
	return			; Yes.
	movlw	d'253'		; No, send it. Keycode indicating all keys up = <AKU>
	call	SerTx1		;
	bsf	AKUSent_WR	; Set sent flag
	return

;-----------------------------------------------------------
;-----MOUSE FUNCTIONS---------------------------------------
;-----------------------------------------------------------

UARTSendMov	; W = 0x02 POINTER MOVEMENT IR data received (bit1=1)

	; Build MouseByte1 for sending to the host:

; IRByte1:    -    -    Yovf  Xovf  Ysign Xsign   RButton  LButton  <= Received from IR or local keyboard
; MouseByte1: Yovl Xovl Ysign Xsign  '1'  MButton RButton  LButton  <= To send to UART (= PS/2 format)

	movf	IRByte1,W	; Get IRByte1 into TEMPX for actions
	movwf	TEMPX
	movlw	b'00001000'	; First, set the 'Allways 1'
	movwf	MouseByte1	;                      0 0 0 0  1 0 0 0
	movf	TEMPX,W		; Second, move RButton and LButton bits
	andlw	b'00000011'	; clear the rest       0 0 0 0  0 0 b b
	addwf	MouseByte1,F	; and add the two bits 0 0 0 0  1 0 b b
	rlf	TEMPX,F		; Next, Yovf  Xovf Ysign Xsign
	rlf	TEMPX,F		;                      y x y x  b b 0 0
	movf	TEMPX,W
	andlw	b'11110000'	;                   W: y x y x  0 0 0 0
	addwf	MouseByte1,F	;          MouseByte1: y x y x  1 0 b b



	clrf	MouseByte4	; Clear Wheel data in this case
UARTSendMov_1
	; Send the IR Mouse data packet to UART almost as received

	movlw	d'128'		; Keycode indicating 4 bytes of Mouse Data
	call	SerTx1		;

	movf	MouseByte1,W	; Buttons pressed etc
	call	SerTx1		;
	movf	IRByte3,W	; X movement data
	call	SerTx1		;
	movf	IRByte4,W	; Y movement data
	call	SerTx1		;

	movf	MouseByte4,W	; Z = Scroll Wheel data
	call	SerTx1		;

	movlw	d'255'		; Keycode indicating end of Mouse Data
	call	SerTx1		;

	goto	MainLoop

;--------------------------------------------------------------

UARTSendScroll	; W = 0x04 SCROLL WHEEL IR data received (bit2=1)

	movlw	b'00001000'	; First, set the 'Allways 1'
	movwf	MouseByte1	;                      0 0 0 0  1 0 0 0
				; No buttons checked in this simple implementation
	; Other bytes are then empty
	clrf	IRByte3
	clrf	IRByte4

	movf	IRByte3,W	; Put the received Z data to last UART byte
	movwf	MouseByte4	;

	goto	UARTSendMov_1	; Send all 4 bytes plus start and stop


;**********************************************************************





;------END OF MOUSE FUNCTIONS---------------------------------
SendZeroChord
	;call	SendPause	; Pause 10 ms
	;clrf	finalchord

	;Idle chord IR packet (chord=W=0) - takes about 18 ms to send
	call	SendStart		;2200us pulse
	movlw	d'0'
	call	SendChord_W		;6 bits
	call	SendDevice		;5 bits (00010 = Betamax)
	bcf	ZeroChordMissing	; clear flag

	return
;------------- STRING OUTPUT ------------


Word_shortcuts	; For US layout and MD edit modes only

	btfsc	MODE123on	; return if this is set
	goto	Word_shortcuts_X
	btfsc	SYMBon		; return if this is set
	goto	Word_shortcuts_X
	btfsc	CTRLon		; return if this is set
	goto	Word_shortcuts_X
	btfsc	ALTon		; return if this is set
	goto	Word_shortcuts_X

		; MD: Backspace = Left Arrow + Delete (MD edit mode)

	btfss	SIRCS_MD_mode	; MD mode?
	goto	Word_shortcuts_1b ; No.
				; Yes.
	btfss	SIRCS_MD_EDIT	; Editing MD song titles?
	goto	Word_shortcuts_X ; No. Forget shortcuts.
				; Yes, editing. Backspace = Left Arrow + Delete
	movf	finalchord,W	;
	xorlw	d'7'		; Test if chord = Backspace
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	goto	TXword_MD_backspace	;

Word_shortcuts_1b
	btfss	US_version	; If US version, check for other shortcuts too
	goto	Word_shortcuts_X


	movf	finalchord,W	;
	xorlw	d'5'		;Test if chord=th
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_th	;

	movf	finalchord,W	;
	xorlw	d'13'		;Test if chord=and_
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_and	;

	movf	finalchord,W	;
	xorlw	d'21'		;Test if chord=the_
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_the	;

	movf	finalchord,W	;
	xorlw	d'37'		;Test if chord=of_
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_of	;

	movf	finalchord,W	;
	xorlw	d'29'		;Test if chord=a_
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_a	;

	movf	finalchord,W	;
	xorlw	d'53'		;Test if chord=to_
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	TXword_to	;

	movf	finalchord,W	; chord must be in W
	goto	Word_shortcuts_X
; ---
TXword_MD_backspace
	movlw	d'47'	; Left Arrow
	call	CharOutput
	movlw	d'100'	; Extra delay
	call	DelayWx1ms
	bcf	TextOnly	; This would otherwise be set
	movlw	d'57'	; Delete
	call	CharOutput
	return
TXword_th
	movlw	d'20'	; t ; 'th' (this was 'with' before)
	call	CharOutput
	movlw	d'8'	; h
	call	CharOutput
	return
TXword_and
	movlw	d'1'	; a
	call	CharOutput
	movlw	d'14'	; n
	call	CharOutput
	movlw	d'4'	; d
	call	CharOutput
	movlw	d'50'	; space
	call	CharOutput
	return
TXword_the
	movlw	d'20'	; t
	call	CharOutput
	movlw	d'8'	; h
	call	CharOutput
	movlw	d'5'	; e
	call	CharOutput
	movlw	d'50'	; space
	call	CharOutput
	return
TXword_of
	movlw	d'15'	; o 'of' (his was 'that' before)
	call	CharOutput
	movlw	d'6'	; f
	call	CharOutput
	movlw	d'50'	; space
	call	CharOutput
	return
TXword_a
	movlw	d'1'	; a 'a' (this was 'have' before)
	call	CharOutput
	movlw	d'50'	; space
	call	CharOutput
	return
TXword_to
	movlw	d'20'	; t 'to' (this was 'which' before)
	call	CharOutput
	movlw	d'15'	; o
	call	CharOutput
	movlw	d'50'	; space
	call	CharOutput
	return
		; Send Chordon Shortcut words from table
TXshortcutword	; Enter with SCpointer start value in W
	; call ShortcutToGKOSrefs with SCpointer, result in Temp, end = 0
	bcf	MoreChords	; Do not send the original character
	movwf	SCpointer	; Point to table (start of shortcut word first)
TXshortcutword_1
	call	ShortcutToGKOSrefs	; Call the table => get one character of sc word
	incf	Temp,f			; Result in Temp
	decfsz	Temp,f			; = 0?
	goto	TXshortcutword_C	; No. Continue by sending the character.
					; Yes.
	movlw	d'50'			; Send GKOSref for space at the end.
	call	CharOutput
	clrf	RXfinalchord		; Clear chord buffers
	clrf	RXfinalchord2
	return				; Exit. The whole word was sent.
TXshortcutword_C
	movf	Temp,W			; Send GKOSref.
	call	CharOutput
	incf	SCpointer,f

	movf	GKOSref,W		; Was it ShiftON?
	xorlw	d'59'
	bnz	$ + 2
	bsf	SHIFTon			; Yes. Set parameter SHIFTon so that it will be cleared

	goto	TXshortcutword_1

; ---
CharOutput
	movwf	GKOSref
	movlw	d'3'
	call	DelayWx1ms	; minimum delay between chords
	bcf	TextOnly	; Send all types of characters this time (like 'don't')
	goto	Output_GKOSref
;----------------------------------------

	; From IR reception and from wired GKOS:
	; NOTE This is a SUB since version gkp21.asm !!!

UARTSendChord	; W = 0x01 CHORD VALUE IR data received (bit0=1)
	;movlw	d'1'		;debug
	;call	SerTx		;


;------
; THIS IS A FAR CALL, SO PROGRAM MEMORY PAGE MUST BE CHANGED
	movlw	HIGH GetChordParams	; Get high 5 bits of address
	movwf	PCLATH			; Next Page...
	call	GetChordParams		; Do the common IR/wired keyboard procedure
	movlw	HIGH UARTSendChord 	; Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH

;------zxcvb
	btfss	RXchordREADY	; A chord to send?
	return			; No.
				; Yes.

UARTSendChord_2


				; Check if NUL (due to polling back in time)
	movf	RXfinalchord,W	;
	xorlw	d'0'		; Test if chord=NUL
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	return			; Return to MainLoop

	movf	RXfinalchord,W
	movwf	finalchord

		; ----------------------------
		; The chord has been confirmed
		; ----------------------------


	btfss	KBDasMOUSE	; Is the GKOS keyboard simulating a mouse?
	goto	UARTSendChord_3	; No.  Send scan codes via UART and IR
				; Yes. Send corresponding button/movement data via UART

	movlw	HIGH KeyboardMouse	; Get high 5 bits of address
	movwf	PCLATH			; Calling Next Code Page...
	call	KeyboardMouse		; According to chord received, send corresponding mouse data (UART)
	movlw	HIGH UARTSendChord_3 	; Make sure PCLATH is pointing back to this Page (0)
	movwf	PCLATH			; Hopefully not too many nested calls!
	return	; goto	MainLoop	; Return to MainLoop

UARTSendChord_3




; ------------------------


	movf	finalchord,W	; is this really needed?
	call	SerTx		;debug
	
		; In all cases, Chord is in W and finalchord



		; finalchord must be in W

	btfsc	US_version	; If US version, check for national word shortcuts
	goto	Word_shortcuts

	btfsc	SIRCS_MD_EDIT	; MD remote control EDIT mode?
	goto	Word_shortcuts	; Yes. Always use shortcuts.


Word_shortcuts_X

; ---------------------------------------------------------
		; Test if IR mode change command expected
; ---------------------------------------------------------

	btfss	CommandFlag		; Has [SYMB] [Ctrl] been pressed?
	goto	Word_shortcuts_X1	; No.
	;movf	CommandBuffer1,w	; Yes. Buffer the command until [ENTER] received
	;movwf	CommandBuffer2	; this 3rd buffer has not yet been defined
	movf	CommandBuffer0,w
	movwf	CommandBuffer1
	movf	finalchord,w
	movwf	CommandBuffer0

; e.g. [SYMB] [Ctrl] m [ENTER] sets SIRCS MD remote control mode
; At the moment, IR mode commands are only one character long (c, i, m, g, t or r):
; mode c	GKOS_IR_mode (chords = mode c), compatibility mode for PS/2 rec.
; mode i	IrDA_mode (of Byte IR mode = mode i)
; mode m	SIRCS_MD_mode  (of Byte IR mode = mode m)
; mode g	GKOS_byte_mode (of Byte IR mode = mode g), 8 data + 3 address bits
; mode t	TV1_mode (of Byte IR mode = mode t)
; mode r	RS232 mode = the same as IrDA mode


Word_shortcuts_X1

	btfss	SIRCS_MD_mode	; MD mode?
	goto	Word_shortcuts_X11 ; No. Just continue.
				; Yes.
	btfss	SIRCS_MD_EDIT	; Editing MD song titles?
	goto	W_s_X_1		; No. Forget also chordon shortcuts,
				; and check the special functions.
Word_shortcuts_X11

; -----------------------------------------------------
		; Test for Chordon Shortcuts
; -----------------------------------------------------

	;btfss	MoreChords	; two chords waiting for ouput? (NOT ALWAYS CORRECT!)
	;goto	W_s_X_1		; No. Check the special functions.

				; Yes.

	; Check if RXfinalchord2 exists

	incf	RXfinalchord2,f	; = 0?
	decfsz	RXfinalchord2,f
	goto	$ + 2		; It does. Check chordon shortcuts	
	goto	W_s_X_1		; Does not. Check the special functions.
	

;TEST  without the table: 'for' = .r
;	movf	RXfinalchord,w	; RXfinalchord = . ?
;	xorlw	d'34'		; Test if chord = .
;	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
;	goto	SC_period	; Yes.

; GKOSref to SCpointer (set SelectTable=1) >
; TXshortcutword: ShortcutToGKOSrefs, chars output >
; return
				; No.
;END OF TEST




	; Chordon Shortcut tables need parameters GKOSref and GKOSref2

	movf	RXfinalchord,w	; RXfinalchord =>
	call	WtoGKOSref	;
	movwf	GKOSref		; Corresponding GKOSref
	movf	RXfinalchord2,w	; RXfinalchord2 =>
	call	WtoGKOSref	;
	movwf	GKOSref2	; Corresponding GKOSref2

;TEST  without the table: 'are' = ?r
;	movf	GKOSref,w	; GKOSref = '?' ?
;	xorlw	d'33'		; Test if char = '?'
;	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
;	goto	SC_question	; Yes.
				; No.
;END OF TEST




	;  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z  u  å  ä  ö
	;  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 34 35 36 27 28 29 30
	;
	;  .  ,  !  ?  -  '     Up Dn     Shift
	;  31 32 33 34 35 36    42 43     59

	; SUBWF: C=1 if result is positive or zero; C=0 if negative (borrow); Z=1 only when zero

	; GKOSref or GKOSref2 > 30? If not, this is not a chordon shortcut (goto W_s_X_1 then)

	movlw	d'31'		; GKOSref >= 31?
	subwf	GKOSref,W	; GKOSref - 31 = positive or zero?
	btfsc	STATUS,C	; Carry staying zero? Note: C = complement of Borrow
	goto	SpecCharFirst	; GKOSref >= 31 (No borrow)
				; GKOSref < 31 (Borrow)

	movlw	d'31'		; GKOSref2 >= 31?
	subwf	GKOSref2,W	; GKOSref2 - 31 = positive or zero?
	btfsc	STATUS,C	; Carry staying zero? Note: C = complement of Borrow
	goto	SpecCharLast	; GKOSref2 >= 31 (No borrow)
				; GKOSref2 < 31 (Borrow)

	goto	W_s_X_1		; No special character included, just letters


SpecCharFirst	; -a  ,v  's  -i  '-  ?Up  !.  ,<the>   (spec char + letter OR spec char)

	movf	GKOSref,w	; (GKOSref = 31...63)
	movwf	Temp		; Temp = 31...63
	movlw	d'30'		; Temp = 1...33
	subwf	Temp,f		; sub w from file
	call	SetShortcutFlags
	btfss	Temp,7		; Is this special char included in shortcut spec chars?
	goto	W_s_X_1		; No.

	btfsc	Temp,6
	goto	Arrows_etc

	btfsc	Temp,0
	goto	SC_period
	btfsc	Temp,1
	goto	SC_comma
	btfsc	Temp,2
	goto	SC_exclamation
	btfsc	Temp,3
	goto	SC_question
	btfsc	Temp,4
	goto	SC_hyphen
	btfsc	Temp,5
	goto	SC_asterisk

Arrows_etc
	btfsc	Temp,0
	goto	SC_uparrow
	btfsc	Temp,1
	goto	SC_downarrow
	btfsc	Temp,2
	goto	SC_SHIFT
	goto	W_s_X_1		; just to make sure


SpecCharLast	; a-  v.  f!   (ONLY the last one is a spec char)

	movf	GKOSref2,w	; (GKOSref2 = 31...63)
	movwf	Temp		; Temp = 31...63
	movlw	d'30'		; Temp = 1...33
	subwf	Temp,f		; sub w from file
	call	SetShortcutFlags
	btfss	Temp,7		; Is this special char included in shortcut spec chars?
	goto	W_s_X_1		; No.

	btfsc	Temp,6
	goto	Arrows_etc2

	btfsc	Temp,0
	goto	SC_period2
	btfsc	Temp,1
	goto	SC_comma2
	btfsc	Temp,2
	goto	SC_exclamation2
	btfsc	Temp,3
	goto	SC_question2
	btfsc	Temp,4
	goto	SC_hyphen2
	btfsc	Temp,5
	goto	SC_asterisk2

Arrows_etc2
	btfsc	Temp,0
	goto	SC_uparrow2
	btfsc	Temp,1
	goto	SC_downarrow2
	btfsc	Temp,2
	goto	SC_SHIFT2
	goto	W_s_X_1		; just to make sure


	; Set flags for shortcut tables a-ö + spec.char. and spec.char + a-ö. Bit7 = 1 for shortcut char's

SetShortcutFlags	; Offset in Temp (GKOSref or GKOSref2) => result in Temp
	; Convert GKOSref to flags indicating group (, . ! ?...)
	; This code allows accessing a table anywhere in program memory
	movlw	LOW Table_SetSCFlags	;Get low 8 bits of address
	addwf	Temp,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_SetSCFlags	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	Temp,W			;load computed Offset in W reg
	call	Table_SetSCFlags	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SetShortcutFlags	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH
	return	

	; 



		; Chordon shortcuts are checked here if MoreChords = 1
		; Check RXfinalchord + RXfinalchord2, e.g. _ + i makes: international, SCpointer=1...
		; Goto TXshortcutword with SCpointer start value in W
		; it will call ShortcutToGKOSrefs with SCpointer and send the characters


	;goto	PS2SC_2b	; Skip the special functions
	; goto	W_s_X_1		; Check the special functions next


; First character is the special char, second char may also be (=> Table length 43 to find the char)

SC_asterisk			; ' + <character> as a chordon
	;0                    10                  20                      30
	; 1 2 3 4 5 6 7 8 9    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5     6 7 8 9 0 
	; a b c d e f g h i=is j k l m n o p q r s t u v w x y=you z ü x y z
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table_SC_asterisk	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_asterisk	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_asterisk	;call table on another Page
	movwf	Temp			;save SCpointer 
	movlw	HIGH SC_asterisk	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (SCpointer=0 -> no shortcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_hyphen
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table_SC_hyphen	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_hyphen	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_hyphen		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_hyphen		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


SC_period
	; a b c d e f g h i j k l m n o p q r=for s t u v w x y z ü å ä ö
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table_SC_period	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_period	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_period		;call table on another Page, GKOSref to SCpointer
	movwf	Temp			;save 
	movlw	HIGH SC_period		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


SC_comma
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table_SC_comma	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_comma	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_comma		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_comma		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_exclamation
	; a b c d e f g h i j k l m n o p q r s t u v w x y=yes z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table_SC_exclamation ;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_exclamation ;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_exclamation	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_exclamation	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_question
	; a b c d e f g h i j k l m n o p q r=are s t u v w x=what y z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table_SC_question	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_question	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_question	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_question	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_uparrow
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table_SC_uparrow	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_uparrow	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_uparrow		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_uparrow		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_downarrow
	; a b c d e f g h i j k l m n=not o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table_SC_downarrow	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_downarrow	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_downarrow	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_downarrow	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_SHIFT
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table_SC_shift	;Get low 8 bits of address
	addwf	GKOSref2,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_SC_shift	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref2,W		;load computed Offset in W reg
	call	Table_SC_shift		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_SHIFT		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


; Only the second character is the special character  (=> Table length 30 to find the first char)

SC_asterisk2			; <character> + ' as a chordon
	;0                    10                  20                      30
	; 1 2 3 4 5 6 7 8 9    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5     6 7 8 9 0 
	; a b c d e f g h i=is j k l m n o p q r s t u v w x y=you z ü x y z
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table2_SC_asterisk	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_asterisk	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_asterisk	;call table on another Page
	movwf	Temp			;save SCpointer
	movlw	HIGH SC_asterisk2	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (SCpointer=0 -> no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_hyphen2
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table2_SC_hyphen	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_hyphen	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_hyphen		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_hyphen2		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


SC_period2
	; a b c d e f g h i j k l m n o p q r=for s t u v w x y z ü å ä ö
	movlw	b'00000001'		; Select Table A (' - .)
	movwf	SelectTable
	movlw	LOW Table2_SC_period	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_period	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_period		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_period2		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_comma2
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table2_SC_comma	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_comma	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_comma		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_comma2		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_exclamation2
	; a b c d e f g h i j k l m n o p q r s t u v w x y=yes z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table2_SC_exclamation ;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_exclamation ;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_exclamation 	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_exclamation2	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_question2
	; a b c d e f g h i j k l m n o p q r=are s t u v w x=what y z ü å ä ö
	movlw	b'00000010'		; Select Table B (, ? !)
	movwf	SelectTable
	movlw	LOW Table2_SC_question	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_question	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_question		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_question2	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


SC_uparrow2
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table2_SC_uparrow	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_uparrow	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_uparrow		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_uparrow2	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table

SC_downarrow2
	; a b c d e f g h i j k l m n=not o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table2_SC_downarrow	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_downarrow ;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_downarrow	;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_downarrow2	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


SC_SHIFT2
	; a b c d e f g h i j k l m n o p q r s t u v w x y z ü å ä ö
	movlw	b'00000100'		; Select Table C (Up Dn Shift)
	movwf	SelectTable
	movlw	LOW Table2_SC_shift	;Get low 8 bits of address
	addwf	GKOSref,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table2_SC_shift	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSref,W		;load computed Offset in W reg
	call	Table2_SC_shift		;call table on another Page
	movwf	Temp			;save 
	movlw	HIGH SC_SHIFT2		;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH

	incf	Temp,f			; Temp = 0? (no shorcut word)
	decfsz	Temp,f
	goto	$ + 2
	goto	PS2SC_2b		; Yes. Exit.
					; No. Do the output.
	movf	Temp,w			; Set Shortcut start address
	goto	TXshortcutword		; Output from table


; -----------------------------------------------------------

W_s_X_1
	movf	finalchord,W	;
	xorlw	d'63'		;Test if chord=123-abc
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	abc123Pressed	;

	movf	finalchord,W	;
	xorlw	d'45'		;Test if chord=SYMB
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	SymbPressed		;

	movf	finalchord,W	;
	xorlw	d'18'		;Test if chord=SHIFT
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	ShiftPressed		;

	movf	finalchord,W	;
	xorlw	d'47'		;Test if chord=CTRL
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	CtrlPressed		;

	movf	finalchord,W	;
	xorlw	d'55'		;Test if chord=ALT
	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	goto	AltPressed		;

	movf	finalchord,W	;
	xorlw	d'59'		;Test if chord=ENTER
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	PS2SC_2b	; No.
				; Yes.

EnterPressed
	bcf	SIRCS_MD_EDIT	; Yes. After entering song title, return
	btfsc	SIRCS_MD_mode	; In case of MD remote control...
	bsf	AV_mode		; ...use codes 129...255.

	btfss	CommandFlag	; Is a command expected before [Enter]?
	goto	PS2SC_2b	; No.
				; Yes.
	; READ IR MODE SELECTION COMMAND HERE
	; e.g. [SYMB] [Ctrl] c [ENTER]
; mode c	GKOS_IR_mode (chords = mode c), compatibility mode for PS/2 rec.
; mode i	IrDA_mode (of Byte IR mode = mode i)
; mode m	SIRCS_MD_mode  (of Byte IR mode = mode m)
; mode g	GKOS_byte_mode (of Byte IR mode = mode g), 8 data + 3 address bits
; mode t	TV1_mode (of Byte IR mode = mode t)
; mode u	UART mode (RS232 mode) = the same as IrDA mode

;CommandBc
	movf	CommandBuffer1,w ;
	xorlw	d'4'		;Test if command = c (GKOS_IR_mode, compatible chord mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBi	; No.
				; Yes.
	bsf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bcf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bcf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bcf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bcf	TV1_mode	; - TV1 remote control mode (ASA)
	goto	CommandBX
CommandBi
	movf	CommandBuffer1,w ;
	xorlw	d'26'		;Test if command = i (IrDA_mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBm	; No.
				; Yes.
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bcf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bsf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bcf	TV1_mode	; - TV1 remote control mode (ASA)
	goto	CommandBX
CommandBm
	movf	CommandBuffer1,w ;
	xorlw	d'50'		;Test if command = m (SIRCS_MD_mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBg	; No.
				; Yes.
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bcf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bcf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bsf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bcf	TV1_mode	; - TV1 remote control mode (ASA)
	goto	CommandBX
CommandBg
	movf	CommandBuffer1,w ;
	xorlw	d'24'		;Test if command = g (GKOS_byte_mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBt	; No.
				; Yes.
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bsf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bcf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bcf	TV1_mode	; - TV1 remote control mode (ASA)
	goto	CommandBX
CommandBt
	movf	CommandBuffer1,w ;
	xorlw	d'14'		;Test if command = t (TV1_mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBr	; No.
				; Yes.
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bcf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bcf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bsf	TV1_mode	; - TV1 remote control mode (a rare brand: ASA)
	goto	CommandBX
CommandBr
	movf	CommandBuffer1,w ;
	xorlw	d'22'		;Test if command = u (UART_mode, same as IrDA mode)
	btfss	STATUS,Z	;Skip if Z=1. Skip if equal.
	goto	CommandBX	; No.
				; Yes.
	bcf	GKOS_IR_mode	; GKOS IR mode = send CHORD VALUES continuously,
			; **or**:
	bsf	Byte_IR_mode	; Byte IR mode = send a one-byte KEY CODE per character = 
			   ; **and one of these**:
	bcf	GKOS_byte_mode	; - GKOS Byte Mode, send IR using 11 SIRCS-coded bits:
	bsf	IrDA_mode	; - IrDA frame mode (of Byte IR mode) to send key codes
	bcf	SIRCS_MD_mode	; - SIRCS MD mode  (of Byte IR mode) to remote control
	bcf	TV1_mode	; - TV1 remote control mode (a rare brand: ASA)
CommandBX
	bcf	CommandFlag

PS2SC_2b

;====================== USE THE TABLES =========================



CharOutput_0	; Enter here when Sending a character of a shortcut string (chord in W)


	;*** Check the tables for proper scan codes ***

;Functioning like this: finalchord => GKOSref => key code (for IrDA etc.) => SIRCS character (in IRcode)

			;Based on finalchord:
	call	FinalChordToGKOSref 	; Get the corresponfing GKOS Reference number
	movwf	GKOSref		; result in W -> save in GKOSref

			; Key Polling: test if GKOSref > 30
			; If TextOnly=1 then do not accept functions (within chordons)
Output_GKOSref
	clrf	GKOSrefshift	; Clear table shift (offset) to start with
	btfss	TextOnly	; Chord within a chordon?
	goto	ChordonOK	; No. Accept any character.
				; Yes. 
	movlw	d'31'		; Discard characters if GKOSref > 30
	subwf	GKOSref,W	; GKOSref - 31 = positive or zero?
	btfss	STATUS,C	; Carry staying zero? Note: C = complement of Borrow
	goto	ChordonOK	; No. Carry set. Then GKOSref < 31. No more action.
				; Yes. GKOSref > 30.
				; Check if 'space': GKOSref = 50?
	movf	GKOSref,W	;
	xorlw	d'50'		; GKOSref=50?
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	goto	ChordonOK	; Send, this is Space.
	return			; GKOSref <> 50. Just send nothing.


ChordonOK
	bsf	TextOnly	; Set default for next character:
				; Send only GKOS chars 1-30 or space until zero chord found.
				; Assumed: chord is within a chordon.

	;Select proper GKOS character set based on SYMB and 123-abc

;************* Choose GKOS symbol set *************

	btfss	MODE123on	;123-mode on?
	goto	CheckSymb	;if not, continue
	movlw	d'63'		;if yes, use next table (123-table)
	movwf	GKOSrefshift	;Move down to 123-mode table
	btfss	SYMBon		;In addition to 123 mode, is SYMB on?
	goto	CheckX		;No. No more action then.
	movlw	d'0'		;Yes, SYMB is on in addition to 123 on. <> 26.4.2002
	movwf	GKOSrefshift	;...move back to abc set then
	movlw	d'31'		; but still use SYMB table if GKOSref>30 (:;_ etc)
	subwf	GKOSref,W	;GKOSref - 31 = positive or zero?
	btfss	STATUS,C	;Carry staying zero? Note: C = complement of Borrow
	goto	CheckX		;No. Carry set. Then GKOSref < 31. No more action.
	movlw	d'126'		;Yes. Use SYMB set (GKOSref .
	movwf	GKOSrefshift	;Shift to SYMB set.
	goto	CheckX
CheckSymb			;This SYMB check is in abc mode only (see above for 123 mode)
	btfss	SYMBon		;bits2&1: 10,11
	goto	CheckShift	;no, just continue
	movlw	d'126'		;yes, use SYMB table
	movwf	GKOSrefshift	;Mode two sets down to SYMB table
	goto	CheckX
CheckShift			; GKOSref = 1...30?
	movlw	d'31'		; 
	subwf	GKOSref,W	; GKOSref - 31 = positive or zero?
	btfsc	STATUS,C	; Carry staying zero? Note: C = complement of Borrow
	goto	CheckX		; Carry not set. Then GKOSref > 31. No more action.
	btfss	SHIFTon		;
	goto	CheckX
	movlw	d'189'		; yes, use SHIFT table
	movwf	GKOSrefshift	; 
CheckX
	movf	GKOSref,W	;use the selected shift in tables (abc,123,SYMB)
	addwf	GKOSrefshift,F	;GKOSrefshift The final pointer = ref + shift now
	call	GKOSrefToKeycode	;Get the corresponding key code
				; keycode = scancode



; ******************************** UART TRANSMISSION *****************************
; txtxtxtx
; ------------------------------- Always send via UART ---------------------------
UART_Send
	movf	keycode,W	; Different codes for UART and IR!
	btfsc	AV_mode		; AV mode?
	addlw	d'128'		; Yes. Use remote commands keycodes 129...255
	call	SerTx1		; Send via UART (always send key code)
	call	StayAwake
		
	btfsc	Byte_IR_mode	; Any IR character transmission in general?
	goto	Byte_IR_TX	; Yes.
				; No. Only IR chords might be sent (if GKOS_IR_mode is set).

	btfss	SpecialKey	; Sendig a Shift?
	call	ClearModes	; No. Remove shifts but keep CAPS
	bcf	SpecialKey

	return			;
;-----
SendSpecKey	; enter this with key code in W (shifts...)
	bsf	SpecialKey	; This is a shift so do not make certain sub calls
	movwf	keycode		; All shifts, too, must be sent via UART
	goto	UART_Send

; ******************************** BYTE IR TRANSMISSIONS **************************
Byte_IR_TX
	btfsc	IrDA_mode	; IrDA mode?
	goto	IRDA_Send	; Yes.
				; No.
	btfsc	SIRCS_MD_mode	; SIRCS MD mode?
	goto	SIRCS_Send	; Yes.
				; No.
	btfsc	GKOS_byte_mode	; GKOS byte mode? 8 + 11 bits
	goto	Byte_GKOS_Send	; Yes.
	
	btfsc	TV1_mode	; TV1 mode?
	goto	TV1_Send	; Yes.
				; No.
			
				; No mode active:
	btfss	SpecialKey	; Sendig a Shift?
	call	ClearModes	; Remove shifts but keep CAPS
	bcf	SpecialKey

	return			; No.

; ******************************** GKOS Byte Send ********************************
Byte_GKOS_Send
		; 11 bits = 8 data bits + 3 address bits
		; [start] dddddddd 000

	call	SendStart	; Send IR Start Pulse of 2200us pulse
	movf	keycode,W	; ** Send keycode = Key Code to send
	;	call	SendByte <= this cannot be used because of too many nested sub calls!
	movwf	TEMPX		;TEMPX = byte to send (bit0 first)
	movlw	d'8'
	movwf	bitcounter	;set counter for 8 bits (data byte)
	call	SendChord_a
				; W contents will be sent
	movlw	b'00000011'	; ** Send Address bits of GKOS byte mode (110)
	movwf	TEMPX		; TEMPX = byte to send (bit0 first)
	movlw	d'3'
	movwf	bitcounter	; set counter for 3 bits (data byte)
	call	SendChord_a	; Send 1 1 0 (A0 A1 A2)

	;call	Send_1		; Send Address bits of GKOS byte mode (000)
	;call	Send_1		; A0 A1 A2
	;call	Send_0		; 1  1  0 for key code packet (chord packet: 1 1 1)

	movlw	d'7'		; Have a 10ms pause after each IR packet
	call	DelayWx1ms

	btfss	SpecialKey	; Sending a Shift?
	call	ClearModes	; No. Remove shifts but keep CAPS
	bcf	SpecialKey
	return
; ******************************** SIRCS TRANSMISSION ****************************
SIRCS_Send

	btfsc	SIRCS_MD_EDIT	; SIRCS MD EDIT mode? (entering letters, numbers and symbols)
	goto	CheckX_EDIT	; Yes.
				; No.
	bcf	SIRCS20		; Clear SIRCS20 to indicate 15-bit transmissions
	movf	keycode,W	 ; Convert keycode into IR remote ctrl code
	call	ScanCodeToIRCode_S ; value is in IRcode after return - CONTROL MODE TABLE
	goto	CheckXX
	; NOTE: codes 42-63 WILL BE SENT IN 15-BIT MODE BUT FROM EDIT MODE TABLE

CheckX_EDIT
	bsf	SIRCS20		; Set SIRCS20 to indicate 20-bit transmissions
	movf	keycode,W	 ; Convert keycode into IR remote ctrl code
	call	ScanCodeToIRCode ; value is in IRcode after return - EDIT MODE TABLE (ASCII)

				; If keycode = 1...30 (a...zuåäö) then check case
				; Upper Case: bit5=0 in IRcode
	movlw	d'31'		; No more action if keycode > 30
	subwf	keycode,W	; keycode - 31 = positive or zero?
	btfsc	STATUS,C	; Carry staying zero? Note: C = complement of Borrow
	goto	CheckXX		; Yes. No more action
				; No. Carry set. Then keycode < 31. Check case.
	btfsc	GKOSmode,4	; bit4 in GKOSmode is 0 for CAPS or SHIFT
	bcf	IRcode,5	; Send Upper Case MD 20-bit letter IR code


CheckXX	
	; SIRCS code to send is now in IRcode

	movlw	IRrepeats	; Repeat every SIRCS IR frame 3 times
	movwf	IRCounter	;
; -------------------------------------------
	call	SendSIRCS	; Send IRcode

	btfss	SpecialKey	; Sendig a Shift?
	call	ClearModes	; No. Remove shifts but keep CAPS
	bcf	SpecialKey
	return

; ******************************** IrDA TRANSMISSION ****************************
IRDA_Send
	movlw	b'00111100'	; Send Header
	call	Send_IRDA
	movlw	b'11110000'	; Send IR Device Address
	call	Send_IRDA
	movf	keycode,W	; Send Key Code
	call	Send_IRDA

	movlw	d'3'		; Delay after each byte
	call	DelayWx1ms

	btfss	SpecialKey	; Sendig a Shift?
	call	ClearModes	; No. Remove shifts but keep CAPS
	bcf	SpecialKey
	return
; ********************************* TV1 IR TRANSMISSION *************************
TV1_Send
	; TV1 / Control mode / 129-255, (send only these key codes?)
	; but first subtract 128



		; Convert keycode into IR remote ctrl code
	movf	keycode,W	; This is a common TV table to point to specific tables
	call	Keycode_to_TVcode ; TV TABLE
		; result in IRcode

			;  If IRcode = 0xff then do not send anything	
	movf	IRcode,W	; IRcode
	xorlw	0xff		; Test if IRcode = 0xff (nothing to send)
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	goto	TV1_Send_X	; Yes. Equal. Do not send.
				; Not equal

	movf	IRcode,W	; These device-specific tables are shorter.
	call	TVcode_to_TV1code ; TV1 TABLE
		; result in IRcode


	movlw	b'00000000'	; Device Address = 0000 0000
	movwf	TEMPY	
	movlw	b'00000011'	; First transmission is always 1100 0000 0000 0000
	call	Send_TV1

	movlw	d'14'
	call	DelayWx1ms
		;one repeat after 14ms

	movlw	b'00000011'	; Device Address = real device address
	movwf	TEMPY	
	movf	IRcode, W
	call	Send_TV1

TV1_Send_X

	movlw	d'14'		; Delay after each IR packet.
	call	DelayWx1ms


	btfss	SpecialKey	; Sendig a Shift?
	call	ClearModes	; No. Remove shifts but keep CAPS
	bcf	SpecialKey
	return

; ********************************************************************************

SendSIRCS			; Send via IR, SIRCS format (send IRcode)

			;  If IRcode = 0xff then do not send anything	
	movf	IRcode,W	; IRcode
	xorlw	0xff		; Test if IRcode = 0xff (nothing to send)
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	goto	SendSIRCS_SX	; Yes. Equal. Do not send. Just check the chord.
				; Not equal

;------	; If 41<keycode<64 or >105 then use always 5 bits device (SIRCS20=0)
;öäöäöä

;------ ; Check first if it is a space (keycode = d'50')
	; If space and EDIT mode then change IRcode 0x4c to 0x20
	movf	keycode,W	; keycode
	xorlw	d'50'		; Test if keycode = d'50' (space)
	btfss	STATUS,Z	; Skip if Z=1. Skip if equal.
	goto	SendSIRCS_01	; No. Not equal. Leave SIRCS20=1
				; Equal. Send space always with SIRCS20=0
				;	
	btfss	SIRCS_MD_EDIT	; SIRCS MD EDIT mode? (entering letters, numbers and symbols)
	goto	SendSIRCS_S	; No.  (space, 13 bits, IRcode = 0x4c)
	movlw	0x20		; Yes. (space, 20 bits, IRcode = 0x20)
	movwf	IRcode
	goto	SendSIRCS_S
SendSIRCS_01

;------

	movf	keycode,W	; keycode = Key Code
	movwf	TEMPX		; 
	movlw	d'42'		; values larger than 42
	subwf	TEMPX,W		; TEMPX-42<0?
	btfsc	STATUS,C	; Carry?
	goto	SendSIRCS_1	; No. TEMPX>=42
	goto	SendSIRCS_S	; Yes. TEMPX<42. Leave SIRCS20=1 (if it is =1)
SendSIRCS_1
	movf	keycode,W	; keycode = Key Code
	movwf	TEMPX		; 
	movlw	d'64'		; values larger than 64
	subwf	TEMPX,W		; TEMPX-64<0?
	btfsc	STATUS,C	; Carry?
	goto	SendSIRCS_2	; No. TEMPX>=64
	bcf	SIRCS20		; Yes. 41<TEMPX<64.  Use SIRCS20=0
	goto	SendSIRCS_S
SendSIRCS_2
	movf	keycode,W	; keycode = Key Code
	movwf	TEMPX		; 
	movlw	d'106'		; larger than 105 values
	subwf	TEMPX,W		; TEMPX-106<0?
	btfsc	STATUS,C	; Carry?
	bcf	SIRCS20		; No. TEMPX>=106. Always SIRCS20=0 then
	goto	SendSIRCS_S	; Yes. TEMPX<106. Leave SIRCS20=1 (if it is =1)
;------

SendSIRCS_S
	btfsc	AutoRepeat	; Autorepeat on?
	goto	SendSIRCS_S0	; Yes. Send as fast as possible.
				; No.
;	btfss	MoreChords	; More chords to be sent? Due to Check-back.
;	goto	SendSIRCS_S0	; No. No extra delay needed between IR packets
	movlw	d'50'		; Yes. Add SIRCS delay between IR packets (different chars)
	call	DelayWx1ms
SendSIRCS_rpt
	movlw	d'24'		; Add SIRCS delay between IR packets (same char)
	call	DelayWx1ms

SendSIRCS_S0
	;call	SendStart	; 2200us pulse 36 kHz
	call	SendStart40	; 2200us pulse 40 kHz
	movf	IRcode,W	; IRcode info part must be in W
	call	SendSChord_W	; 7 bits
	call	SendSDevice	; 5 or 13 bits depending on bit SIRCS20

; <><><>
				; Repeat IR frames?
	decfsz  IRCounter,f	; IR counter reached zero? (4...1)
	goto	SendSIRCS_rpt	; No. Repeat same RXfinalchord as before.
				; Yes. No more need to resend IR frame.
	incf	IRCounter,f	; Leave counter as it was (0).

SendSIRCS_SX
		; Was it a 'T'? If yes. EDIT mode must be ON now.
	movf	finalchord,W	;
	xorlw	d'14'		; Test if chord='T'
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	bsf	SIRCS_MD_EDIT	; Yes. Set MD EDIT mode ON (20-bit, ASCII).

		; Was it 'Esc'? If yes. EDIT mode must be OFF now.
	movf	finalchord,W	;
	xorlw	d'31'		; Test if chord='Esc'
	btfsc	STATUS,Z	; Skip if Z=0. Skip if not equal.
	bcf	SIRCS_MD_EDIT	; Yes. Set MD EDIT mode OFF (15-bit, remote codes).

				; Update AV mode
	bsf	AV_mode		; Use codes 128-255 at UART
	btfsc	SIRCS_MD_EDIT	; MD Edit mode = 1 => AV mode = 0
	bcf	AV_mode		; Use codes 1-127 at UART

	return



StayAwake
	; display is used => initialize SLEEP counters
	movlw	d'255'
	movwf	SLEEPcnt1
	movwf	SLEEPcnt2
	movlw	SLEEPdelay	; This defines the ilde time before going to sleep
	movwf	SLEEPcnt3  	; 1 => 3 sec
	return



; ------------- call a procedure on Code Page 2----------------

;	movlw	HIGH Page2_proc	; Get high 5 bits of address
;	movwf	PCLATH		; Load high address in latch
;	call	Page2_proc	; Call a Page2 precedure
;	movlw	HIGH MainL_IR	; Make sure PCLATH is pointing to this Page (0)
;	movwf	PCLATH

;--------------------- THE TABLE CALLS ARE HERE ---------------
			;Read data

;Table_ChordToRef => Table_GKOSrefToKeycode => Table_ScanCodeToIRCode

FinalChordToGKOSref
	;FIRST convert finalchord to GKOSref
	;This code allows accessing a table anywhere in program memory

	movf	finalchord,W
WtoGKOSref
	movwf	Temp
TempToGKOSref
	movlw	LOW Table_ChordToRef	;Get low 8 bits of address
	addwf	Temp,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_ChordToRef	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	Temp,W			;load computed Offset in W reg
	call	Table_ChordToRef	;call table on another Page
	movwf	Temp			;returning with value in W, save it first in Temp
					;calling Table on Page 3
	movlw	HIGH FinalChordToGKOSref ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	movf	Temp,w		; Result saved in Temp and W (= value for GKOSref)
	return

GKOSrefToKeycode
	;THEN convert the GKOSref to keycode
	;This code allows accessing a table anywhere in program memory
	movlw	LOW Table_GKOSrefToKeycode	;Get low 8 bits of address
	addwf	GKOSrefshift,F		;Offset, do an 8-bit add operation
	movlw	HIGH Table_GKOSrefToKeycode	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	GKOSrefshift,W		;load computed Offset in W reg
	call	Table_GKOSrefToKeycode ;call table on another Page
	movwf	keycode		;save keycode
				;calling FIN/SWE version Table on Page 3
	movlw	HIGH GKOSrefToKeycode ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	return

ShortcutToGKOSrefs	; Offset in SCpointer

	btfsc	SelectTable,1	; Select one of the sc word tables
	goto	ScTGr_B	; b'0000 0001
	btfsc	SelectTable,2
	goto	ScTGr_C	; b'0000 0010

	;ELSE: SelectTable,0 = 1

	;THEN convert SCpointer to finalchord value
	;This code allows accessing a table anywhere in program memory
	;	'a -a .a
	movlw	LOW TableA_shortcuts	;Get low 8 bits of address
	addwf	SCpointer,F		;Offset, do an 8-bit add operation
	movlw	HIGH TableA_shortcuts	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	SCpointer,W		;load computed Offset in W reg
	call	TableA_shortcuts	;call table on another Page
	movwf	Temp			;save for sending
	movlw	HIGH ShortcutToGKOSrefs	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH
	return
ScTGr_B	; 	,a ?a !a
	movlw	LOW TableB_shortcuts	;Get low 8 bits of address
	addwf	SCpointer,F		;Offset, do an 8-bit add operation
	movlw	HIGH TableB_shortcuts	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	SCpointer,W		;load computed Offset in W reg
	call	TableB_shortcuts	;call table on another Page
	movwf	Temp			;save for sending
	movlw	HIGH ShortcutToGKOSrefs	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH
	return

ScTGr_C	; 	<Up>a <Dn>a <Shift>a = Ua Da Sa
	movlw	LOW TableC_shortcuts	;Get low 8 bits of address
	addwf	SCpointer,F		;Offset, do an 8-bit add operation
	movlw	HIGH TableC_shortcuts	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	SCpointer,W		;load computed Offset in W reg
	call	TableC_shortcuts	;call table on another Page
	movwf	Temp			;save for sending
	movlw	HIGH ShortcutToGKOSrefs	;Make sure PCLATH points back to this Page (0)
	movwf	PCLATH
	return


ScanCodeToIRCode
	; Symbols area - EDIT MODE
	;LAST convert the keycode to Scan Code
	;This code allows accessing a table anywhere in program memory
	movf	keycode,W
	movwf	TEMPX
	movlw	LOW Table_ScanCodeToIRCode	;Get low 8 bits of address
	addwf	TEMPX,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_ScanCodeToIRCode	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	TEMPX,W		;load computed Offset in W reg
				;
	call	Table_ScanCodeToIRCode
	movwf	IRcode		;store IRcode
				;calling Table on Page 3
	movlw	HIGH ScanCodeToIRCode ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	return


ScanCodeToIRCode_S
	; Remote control code area - CONTROL MODE
	;LAST convert the keycode to Scan Code
	;This code allows accessing a table anywhere in program memory
;	movf	keycode,W	; max 253, SYMB => 254

	movf	keycode,W
	movwf	TEMPX
	movlw	LOW Table_ScanCodeToIRCode_S	;Get low 8 bits of address
	addwf	TEMPX,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_ScanCodeToIRCode_S	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	TEMPX,W		;load computed Offset in W reg
				;
	call	Table_ScanCodeToIRCode_S
	movwf	IRcode		;store IRcode
				;calling Table on Page 3
	movlw	HIGH ScanCodeToIRCode_S ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	return

			;Use Table_Keycode_to_TVcode
Keycode_to_TVcode
	; TV Remote commands
	; Enter with code in W
	;This code allows accessing a table anywhere in program memory
	movwf	TEMPX
	movlw	LOW Table_Keycode_to_TVcode	;Get low 8 bits of address
	addwf	TEMPX,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_Keycode_to_TVcode	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	TEMPX,W			;load computed Offset in W reg
					;
	call	Table_Keycode_to_TVcode
	movwf	IRcode		;store IRcode
				;calling Table on Page 3
	movlw	HIGH Keycode_to_TVcode ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	return

			;Use Table_TVcode_to_TV1code
TVcode_to_TV1code
	; TV Remote commands
	; Enter with code in W
	;This code allows accessing a table anywhere in program memory
	movwf	TEMPX
	movlw	LOW Table_TVcode_to_TV1code	;Get low 8 bits of address
	addwf	TEMPX,F			;Offset, do an 8-bit add operation
	movlw	HIGH Table_TVcode_to_TV1code	;get high 5 bits of address
	btfsc	STATUS,C		;Page crossed?
	addlw	1			;Yes. Then increment high address
	movwf	PCLATH			;load high address in latch
	movf	TEMPX,W		;load computed Offset in W reg
				;
	call	Table_TVcode_to_TV1code
	movwf	IRcode		;store IRcode
				;calling Table on Page 3
	movlw	HIGH Keycode_to_TVcode ;Make sure PCLATH is pointing to this Page (0)
	movwf	PCLATH
	return





	; ******************* SHIFTs PRESSED ******************
;-----sub------
	; Only FIN/SWE and US/UK modes can be selected
AltModes
	btfsc	MODE123on	; return if this is set
	return
	btfsc	SYMBon		; return if this is set
	return
	btfsc	CTRLon		; return if this is set
	return
	bcf	PASTEon
	bcf	ALTon		; Forget ALT

	btfss	US_version	; US/UK mode already on?
	goto	AltModes_1	; No. Turn it on.
	bcf	US_version	; Yes. Back to FIN/SWE mode.
	return
AltModes_1
	bsf	US_version	; Set US/UK mode
	return
;--------------
abc123Pressed			;bit0
	movlw	d'61'
	call	SendSpecKey

	bcf	KBDasMOUSE 	;Always clear this flag 'Keyboard as Mouse' operation

	btfsc	ALTon		;Alt on?
	goto	AltModes	;Alternative modes...

	;btfss	CTRLon		;Ctrl on?
	;goto	Braille mode...

	;btfss	SYMBon		;Symb on?
	;goto	<reserved for.....>

	btfss	SHIFTon		;SHIFT on?
	goto	abc123Pressed_a
	btfsc	SHIFTlock	;But not SHIFT LOCK?
	goto	abc123Pressed_a
			;Yes. *** START KBDasMOUSE OPERATION ***
	bcf	SHIFTon		;Clear SHIFT
	bcf	PASTEon		;Clear pasting also

	movlw	d'187'		;SHIFT OFF 
	call	SendSpecKey

	bsf	KBDasMOUSE 	;Flag 'Keyboard as Mouse' operation
	return 	;goto	MainLoop
abc123Pressed_a
	btfss	MODE123on	;123mode already on?
	goto	Setabc123	;No, set it.
	bcf	MODE123on	;Yes, so clear it 123-abc=>0
	;bsf	ABC123_LED		; Turn GKOS 123 LED OFF
	return	; goto	MainLoop	;
Setabc123
	bsf	MODE123on
	;bcf	ABC123_LED		; Turn GKOS 123 LED ON
	return	; goto	MainLoop

MenuPressed
	movlw	d'121'
	call	SendSpecKey
	call	ClearModes
	return ; goto	SendMenuKey
;---
SymbPressed			;bits2&1 10 / 11(LOCKED)
	movlw	d'126'
	call	SendSpecKey

	btfsc	ALTon		;Alt on?
	goto	WinKeyPressed	;Yes. System menu.
				; bit4/bit3: SHIFT, 10=SHIFTon, 11=SHIFTlock
	btfss	SHIFTon		;SHIFT on?
	goto	SymbPressed_a
	btfsc	SHIFTlock	;But not SHIFT LOCK?
	goto	SymbPressed_a
	goto	MenuPressed	;Yes, application menu.	

SymbPressed_a
	btfss	SYMBon		;Symb already on?
	goto	SetSymb		;No, set it.
				;
	btfss	SYMBlock	;Yes, Symb is on but is it LOCKED?. (11?)
	goto	LockSymb	;It is not LOCKED. Go lock it. (01->11)
	bcf	SYMBon		;Yes, LOCKED. Clear both Symb bits =>00
	;bsf	SYMB_LED	; Turn GKOS SYMB LED OFF
	bcf	SYMBlock	;
	return	; goto	MainLoop	;(no need to send anything)
SetSymb
	bsf	SYMBon
	;bcf	SYMB_LED	; Turn GKOS SYMB LED ON
	return	; goto	MainLoop
LockSymb
	bsf	SYMBlock
	return	; goto	MainLoop

WinKeyPressed
	movlw	d'122'
	call	SendSpecKey
	call	ClearModes
	return ; goto	SendWinKey
;---
ShiftPressed

				;SHIFT: bits4&3 10 / 11
	btfsc	SHIFTlock	;SHIFT LOCK ON?
	goto	ClearShiftLock	;Yes. Clear SHIFT LOCK.

	btfsc	PASTEon		;Was Pasting on?
	goto	ClearShift	;Yes. Clear SHIFT.

	btfss	SHIFTon		;No. Shift already on? (x1?)
	goto	SetShift	;No (x0), set it.
				;
	bsf	SHIFTon		;Yes. Set SHIFT LOCK.
	bsf	SHIFTlock
	movlw	d'187'		; SHIFT OFF
	call	SendSpecKey
	movlw	d'119'		; CAPS ON
	call	SendSpecKey

	;bcf	CAPS_LED	; Turn GKOS CAPS LED ON
;	call	SendCapsMake
		; Note that here inbetween, the LEDs will be turned on.
;	call	ByteIn		; receive LED order
;	call	SendACK
;	call	ByteIn		; receive LED status byte
;	call	SendACK

;	call	SendCapsBreak

	;call	SendShiftMake	;corresponds to press and release SHIFT key
	;call 	SendShiftBreak	;send just Shift here

	return	; goto	MainLoop

ClearShift
	bcf	PASTEon		;Clear pasting also!
	bcf	SHIFTon
	bcf	SHIFTlock
	movlw	d'187'
	call	SendSpecKey

	;bsf	CAPS_LED	; Turn GKOS CAPS LED OFF
	return	; goto	MainLoop
ClearShiftLock
	;bsf	CAPS_LED	; Turn GKOS CAPS LED OFF
;	call	SendCapsMake
		; Note that here inbetween, the LEDs will be turned off.
;	call	ByteIn		; receive LED order
;	call	SendACK
;	call	ByteIn		; receive LED status byte
;	call	SendACK

;	call	SendCapsBreak
	bcf	SHIFTon
	bcf	SHIFTlock
	movlw	d'247'
	call	SendSpecKey
	;bsf	CAPS_LED	; Turn GKOS CAPS LED OFF
	return	; goto	MainLoop

SetShift
	bsf	SHIFTon
	movlw	d'59'
	call	SendSpecKey
	return	; goto	MainLoop

;---
CtrlPressed			;bit5
	btfss	CTRLon		;Ctrl on?
	goto	SetCtrl		;No, set it.
	bcf	CTRLon		;Yes, so clear it Ctrl=>00
	movlw	d'190'
	call	SendSpecKey

;	call	SendCtrlMake	;corresponds to press and release Ctrl key
;	call	SendCtrlBreak	;SEND Ctrl here
	return	; goto	MainLoop	;

SetCtrl
		; SYMB ON?	If yes, start looking for a command
		; [SYMB] [Ctrl] .......xxx [Enter] => xxx = command

	btfsc	SYMBon		; Symb on?
	bsf	CommandFlag	; Yes. Set Command Flag. Clear it after [Enter]
				; No.

	btfsc	SIRCS_MD_mode	; Remote control mode?
	bsf	CommandFlag	; Yes. Set Command Flag. Clear it after [Enter]
				; No.
	bsf	CTRLon
	movlw	d'62'
	call	SendSpecKey
	return	; goto	MainLoop
;---
AltPressed			;bit6
	btfss	ALTon		;Alt on?
	goto	SetAlt		;No, set it.
	bcf	ALTon		;Yes, so clear it Alt=>0
	movlw	d'191'
	call	SendSpecKey
	;call	SendAltMake	;correponds to pres and release Alt key
	;call	SendAltBreak	;SEND Alt
	return	; goto	MainLoop	;
SetAlt
	bsf	ALTon
	movlw	d'63'
	call	SendSpecKey
	return	; goto	MainLoop



	; bit0: abc-123 1=123, 0=abc
	; bit2/bit1: SYMB,  10=SYMBon,  11=SYMBlock
	; bit4/bit3: SHIFT, 10=SHIFTon, 11=SHIFTlock
	; bit5: CTRL, 1=CTRLon - bit6: ALT, 1=ALTon  
	; bit7: Used for Paste On (it was reserved for CAPSLOCK or NUMLOCK)
ClearModes
	;clrf	GKOSmode
	btfss	CTRLon		; Ctrl on?
	goto	CM_1X		; No, next.
	bcf	CTRLon		; clear CTRL
	movlw	d'190'
	call	SendSpecKey
CM_1X
	btfss	ALTon		; Alt on?
	goto	CM_2X		; No, next.
	bcf	ALTon		; clear ALT
	movlw	d'191'
	call	SendSpecKey
CM_2X
	btfsc	SYMBlock 	; SYMBlock on?
	goto	CM_3X		; Yes, next.
	btfss	SYMBon		; SYMB on?
	goto	CM_3X		; No, next.
	bcf	SYMBon		; Yes. Clear SYMBon.
	;movlw	d'126'		; SYMB pressed (=IR info)
	;call	SendSpecKey

CM_3X
	;bcf	SYMBon		;No.
	;bsf	SYMB_LED	; Turn GKOS SYMB LED OFF 

	btfsc	SHIFTlock	;SHIFT lock on?


	return			;Yes. Continue and leave SHIFT LOCK on.
		;No. Clear SHIFT unless arrows/words/PgUp&PgDn (pasting)

	btfss	SHIFTon		;..but is SHIFT on?!
	return			;No. Might return as well...
				;Yes SHIFT is ON:

	;GKOSref: 42...53 are navigating except 50 and 46 (=space, backsp)

	;PASTE function
	movlw	d'42'		;Test if GKOSref is lower than 42 
	subwf	GKOSref,W	;GKOSref - 42
	btfss	STATUS,C	;Note: C = complement of Borrow
	goto	ClearModesX_C	;Yes, lower, clear SHIFT and exit
				;No. not lower, might be pasting.
	movf	GKOSref,W	;Test if higher than 53
	sublw	d'53'		; 53 - W (=GKOSref)
	btfss	STATUS,C	;Note: C = complement of Borrow
	goto	ClearModesX_C	;Yes, higher, clear SHIFT and exit
	
			;test if 50 or 46
	movlw	d'50'
	xorwf	GKOSref,W
	btfsc	STATUS,Z	;equal?
	goto	ClearModesX_C	;yes, exit and clear SHIFT

	movlw	d'46'
	xorwf	GKOSref,W
	btfsc	STATUS,Z	;equal?
	goto	ClearModesX_C	;yes, exit and clear SHIFT
				;leave SHIFT ON (pasting)
	bsf	PASTEon		;Yes. Leave SHIFT ON. Set Pasting on. Paste.
	return
ClearModesX_C
	bcf	SHIFTon		;Clear SHIFT if not pasting	
	movlw	d'187'
	call	SendSpecKey
	return
;--------------------------------------------------------------

	; bit0: abc-123 1=123, 0=abc
	; bit2/bit1: SYMB,  10=SYMBon,  11=SYMBlock
	; bit4/bit3: SHIFT, 10=SHIFTon, 11=SHIFTlock
	; bit5: CTRL, 1=CTRLon - bit6: ALT, 1=ALTon  
	; bit7: Used for Paste On (it was reserved for CAPSLOCK or NUMLOCK)

;********************* IR RECEPTION ***********************************
CheckIR
	btfsc	IRDATA		; IR Pulse there? TEST FOR ANY IR PULSE
	goto	CheckIRX	; No. Exit.
	call	ReadIRstart	; Yes. Is it a Start pulse?
	xorlw	0x00		; Start pulse ok?
	bnz	CheckIRX	; No. Exit.

	clrf	IRByte1		; Yes. Clear the first IR byte buffer
	call	ReadIR6bits	; Receive 6 bits: --54 3210 (D5...D0)
	xorlw	0x00		; 6 bits received ok?
	bnz	CheckIRX	; No. Exit.

	movf	TEMPX,w		; Yes. Save value. === IRByte1 ===
	movwf	IRByte1		;
	clrf	IRByte2		; Clear rest of the IR byte buffers
	clrf	IRByte3
	clrf	IRByte4
	call	ReadIR5bits	; Receive 5 bits: xxxa aadg (A2 A1 A0 1/0 toggle) 1=chord
	xorlw	0x00		; 5 bits received ok?
	bnz	CheckIRX	; No. Exit.
				;
				; IRByte1: --54 3210 (D5...D0)
				; IRByte2: xxxa aadg (A2 A1 A0 1/0 toggle)
				;                     ^ A2=0: Key code packet 
				;   ... A2 A1 A0 1/0...
				;       1  x  x  0 ... 	Mouse packet
				;       1  x  x  1 ...	Chord value packet
				;   ... 0  x  x  D7...	Key code packet
				;0 0 0  A2 A1 A0 D7 D6	The received IRByte2
				;0 0 D5 D4 D3 D2 D1 D0	The received IRByte1 
				;          1  1         = default (of x x)
				
	movf	TEMPX,w		; Yes. Save value. === IRByte2 ===
	movwf	IRByte2		; (if 1/0 = 0, continue receiving mouse packet)


				; ** Check if GKOS Key Code byte received
	bcf	IRdevice,4	; xxx0 aadg (A2 A1 A0 1/0 toggle)
	movf	IRByte2,w	; While IRByte2 in W, check if device info is correct.
	andlw	b'00011100'	; 000a aa00 = 0000 1100? (in IRByte2 for Key Code packet)
	xorwf	IRdevice,w	; (IRdevice = 0001 1100 for chord or mouse packets)
	bnz	CheckIR_1	; If not, check for other GKOS IR packet formats (chord/mouse)
				; Yes. This is GKOS Key Code packet.
	btfsc	IRByte2,0	; Move two bits from IRbyte2 to IRbyte1
	bsf	IRByte1,6	; 0 0 0  A2 A1 A0 D7 D6	The received IRByte2
	btfsc	IRByte2,1	; 0 0 D5 D4 D3 D2 D1 D0	The received IRByte1 
	bsf	IRByte1,7	; Now, IRByte1 is the GKOS Key Code byte
	bsf	IRdevice,4	; Change back the A2 bit in IRdevice
	retlw	0x08		; KEY CODE data received OK EXIT. bit3=1
				; IRByte1 = 8-bit GKOS Key Code received by IR

CheckIR_1			; ** Check if GKOS Chord or Mouse data received
	bsf	IRdevice,4	; Change back the A2 bit in IRdevice
	movf	IRByte2,w	; While IRByte2 in W, check if device info is correct.
	andlw	b'00011100'	; 000a aa00 = 0001 1100? in IRByte2
	xorwf	IRdevice,w	; (IRdevice = 0001 1100 for chord or mouse packets)
	bnz	CheckIRX

	btfss	IRByte2,1	; bit1=1? (1=chord IR packet)	
	goto	CheckIRMouse	; No. Continue by receiving mouse packet data.

				; Yes. Chord value has been received OK.
	movf	IRByte1,W	; Save Chord in param. RXchord
	movwf	RXchord		;
	;call	ShowIRpackets	;debug

	retlw	0x01		; CHORD value received OK EXIT => bit0=1



CheckIRMouse
				; Two extra bits A3 and Z are received here for deciding 
				; whether XY movement (Z=0) or wheel data (Z=1)follows
	call	ReadIRbit	; Read bit A3 (for future use)
	btfsc	tempflags,0	; Error in bit reception?
	goto	CheckIRX	; Yes. IR bit error ***
	call	ReadIRbit	; Read bit Z (0/1 = movement/wheel data indication)
	btfsc	tempflags,0	; Error in bit reception?
	goto	CheckIRX	; Yes. IR bit error ***

				;'1' => 1000 0000 in W (0x80) scroll wheel
				;'0' => 0000 0000 in W (0x00) movement

	xorlw	0x80		; Decide on movement or scroll wheel reception
	bz	CheckIRscroll

	; Receive Movement data
	; =====================

	call	ReadIR8bits	; Receive 8 bits. X movement data.
	xorlw	0x00		; 8 bits received ok?
	bnz	CheckIRX	; No. Exit.
	movf	TEMPX,w		; Yes. Save value. === IRByte3 ===
	movwf	IRByte3		;

	call	ReadIR8bits	; Receive 8 bits. Y movement data.
	xorlw	0x00		; 8 bits received ok?
	bnz	CheckIRX	; No. Exit.
	movf	TEMPX,w		; Yes. Save value. === IRByte4 ===
	movwf	IRByte4		;

	call	CheckIRend	; Check that IR transmission has ended correctly
	xorlw	0x00		; Silence after last IR data bits?
	bnz	CheckIRX	; No. Error exit.

CheckIRmovOK
	;call	ShowIRpackets	;debug
	retlw	0x02		; MOVEMENT data received OK EXIT => bit1=1


	; Receive Scroll Wheel Data
	; =========================

CheckIRscroll
	call	ReadIR8bits	; Receive 8 bits. Wheel data.
	xorlw	0x00		; 8 bits received ok?
	bnz	CheckIRX	; No. Exit.
	movf	TEMPX,w		; Yes. Save value. === IRByte3 ===
	movwf	IRByte3		;

	call	CheckIRend	; Check that IR transmission has ended correctly
	xorlw	0x00		; Silence after last IR data bits?
	bnz	CheckIRX	; No. Error exit.

	;call	ShowIRpackets	;debug
	retlw	0x04		; SCROLL WHEEL data received OK EXIT. bit2=1

CheckIRX
	retlw	0x80		;IR reception UNSUCCESSFUL EXIT => bit7=1


;****************** IR TRANSMISSION *********************************
; Start of SIRCS

	; MD 0001000 11110 / GKOS: 000100 01111(0) = cccccc gdaaa(0)
	; MD: 7 + 5 = 12 bits / GKOS: 6 + 5 = 11 bits. Received order: xxxa aadg
	; GKOS:
	; movlw	b'00011100'	;Set the default IR device code in reverse order (xxxa aadg)
	; movwf	IRdevice	;Sending order: x x x A2  A1 A0 D7 D6; SIRCS spec: 01111 = MD 
				;D6=G (character toggle bit)
				;D7=1 for keyboard and 0 for mouse. A0-A2 = device address

	;			  xxxaaadg            gdaaa     gdaaa-
	;			b'00011110' => scope: 01111, ...011110 (=MD) gdaaa0
	; SIRCS set device to b'00001111' (MD)
	;                              ^sending starts here, 5 bits sent: 11110
;**********************
SendSChord	; Send SIRCS info bits
	movf	finalchord,w	; Sends finalchord through IR link
SendSChord_W			;Enter here if only W contents will be sent
	movwf	TEMPX		;TEMPX = byte to send (7 bits only, bit0 first)
	movlw	d'7'
	movwf	bitcounter	;set counter for 6 bits
SendSChord_a
	btfss	TEMPX,0		;bit0=1?
	goto	SendSChord_0	;No

	call	Send_1		;Yes SEND '1'
	;call	Send40_1	;Yes SEND '1'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 7 bits sent?
	goto	SendSChord_a	;No.
	return			;yes, return
SendSChord_0
	;call	Send_0		;SEND '0'
	call	Send40_0
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 7 bits sent?
	goto	SendSChord_a	;No.
	return			;Yes, return
;-------------------
SendSDevice	; either 12-bit or 20-bit SIRCS frames
	btfss	SIRCS20		; is this SIRCS 20-bit frame?
	goto	SendS12Device	; No
				; Yes.
SendS20Device		
	; For symbols, numbers and letters (ASCII), SIRCS 20-bit frames: 
	; Send SIRCS 13-bit Device information (+ 7 info bits = 20 bits)
	; 0110 0001 1101 0010 0000 (LSB first) e.g.[space] = 010 0000
	; 5555 5333 aaaa addd dddd 7 data + 5 device + 8 device

	movlw	d'5'		; N=5 aaaa a
	movwf	bitcounter	; Set counter for 5 bits
				;(the IR controlled device ID)
	movlw	b'00011010'	; Use SIRCS device (SDEVICE) definition in IR TX
	movwf	TEMPX		; 01011... (LSB first)
	call	SendSDevice_a

	movlw	d'8'		; N=8 0110 0001
	movwf	bitcounter	; Set counter for 8 bits
				;(the IR controlled device ID)
	movlw	b'01100001'	; Use SIRCS device (SDEVICE) definition in IR TX
	movwf	TEMPX		; ...1000 0110... (LSB first)
	call	SendSDevice_a

	return


SendS12Device		;Send SIRCS 5-bit Device information
	movlw	d'5'		; N=5
	movwf	bitcounter	; Set counter for 5 bits
				;(the IR controlled device ID)
	movlw	SDEVICE		; Use SIRCS device (SDEVICE) definition in IR TX
	movwf	TEMPX		; 00001111 (LSB first)

SendSDevice_a
	btfss	TEMPX,0		;bit0=1?
	goto	SendSDevice_0	;No

	;call	Send_1		;Yes
	call	Send40_1		;Yes
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All N bits sent?
	goto	SendSDevice_a	;No.
	return			;yes, return
SendSDevice_0
	;call	Send_0
	call	Send40_0
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All N bits sent?
	goto	SendSDevice_a	;No.
	return			;Yes, return

; End of SIRCS

;**********************
; ------------- GKOS BYTE -----------
		; Send GKOS IR BYTE info bits + address
		; Sends just the Key Code through IR link, once
		; Enter with keycode in W
SendByte			;Enter here, W contents will be sent
	movwf	TEMPX		;TEMPX = byte to send (bit0 first)
	movlw	d'8'
	movwf	bitcounter	;set counter for 8 bits (data byte)
	call	SendChord_a
	return

; ------------- GKOS CHORD ---------- For compatibility with old GKOS IR receivers
SendChord	; Send GKOS IR format info bits
	movf	finalchord,w	; Sends finalchord through IR link
SendChord_W			;Enter here if only W contents will be sent
	movwf	TEMPX		;TEMPX = byte to send (6 bits only, bit0 first)
	movlw	d'6'
	movwf	bitcounter	;set counter for 6 bits
SendChord_a
	btfss	TEMPX,0		;bit0=1?
	goto	SendChord_0	;No

	call	Send_1		;Yes SEND '1'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 3/6/8 bits sent?
	goto	SendChord_a	;No.
	return			;yes, return
SendChord_0
	call	Send_0		;SEND '0'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 6/8 bits sent?
	goto	SendChord_a	;No.
	return			;Yes, return
;-------------------
SendDevice		;Send GKOS IR Device information
				;(the IR controlled device ID)
	movlw	DEVICE		; Use DEVICE definition in IR TX
	;movf	IRdevice,W	; IRdevice does not have the mouse/kbd bit defined
	movwf	TEMPX
	movlw	d'5'
	movwf	bitcounter	;set counter for 5 bits
SendDevice_a
	btfss	TEMPX,0		;bit0=1?
	goto	SendDevice_0	;No

	call	Send_1		;Yes
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 5 bits sent?
	goto	SendDevice_a	;No.
	return			;yes, return
SendDevice_0
	call	Send_0
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 5 bits sent?
	goto	SendDevice_a	;No.
	return			;Yes, return

;*************************** 40 kHz *************************************
SendStart40		;gap T (550us), pulse 4T (2200us) 
	bcf	IRTXDATA
	call	Delay40T
			; 19 cycles per T -> 35.7kHz (19.5 => 36kHz)
			; 
			; One cycle: 14us high + 14us low
			; Cycle counter for 40 kHz: 40/36 x 78 = 86,6 = ca.87
	movlw	d'87' ;d'78'	;**<78<=Oscilloscope** ;set cycle counter to 4T = 4 x 19.5 = 78
	movwf	temp01	;78 x 28us = 2184 (16us missing) 
	goto	SendPulse40
;-----------
Send40_1			;gap T (550us), pulse 2T (1100us)
	bcf	IRTXDATA
	call	Delay40T
			;19 cycles per T -> 35.7kHz
			;One cycle: 14us high + 14us low
			; cycle counter for 40 kHz: 40/36 x 43 = 47,8 = ca.48
	movlw	d'48' ;d'43';**<43<=Oscilloscope**	;set cycle counter to 2T = 2 x 19 = 38
	movwf	temp01	;38 x 28us = 1064us (36us missing)
	goto	SendPulse40
;----------------------
Send40_0			;gap T (550us), pulse T (550us)
	bcf	IRTXDATA
	call	Delay40T
			;19 cycles per T -> 35.7kHz
			;One cycle: 14us high + 14us low 
			; Cycle counter for 40 kHz: 40/36 x 22 = 24,4 = ca.24
	Delay	d'11' ;'10'	;the missing 18us - 8us for program lines calling
	movlw	d'25' ;d'22';**<22<=Oscilloscope**  ;set cycle counter to T = 1 x 19 = 19
	movwf	temp01	;19 x 28us = 532us (18us missing)
	goto	SendPulse40
;-----------------------
	; This sets the Carrier Frequency! Adjusted by Oscilloscope. Do not change!
	; temp01 sets pulse length (d'??' gives SIRCS pulse length)
SendPulse40	;Common procedure to send n cycles (n = temp01)
	bsf	IRTXDATA	;1
	Delay	0x0c ;0x0d; **0x0d>14us<=Oscilloscope** 13 ;1+13 = 14us
	bcf	IRTXDATA	;1
	Delay	0x08 ;0x0a; **0x0a>14us<=Oscilloscope** ;>14us;  ;1+11
	decfsz	temp01,f		;1+1+11
	goto	SendPulse40	;1+1+1+11 = 14us
	return


;*************************** 36 kHz *************************************
SendStart		;gap T (550us), pulse 4T (2200us) 
	bcf	IRTXDATA
	call	DelayT
			;19 cycles per T -> 35.7kHz (19.5 => 36kHz)
			;One cycle: 14us high + 14us low
	movlw	d'78'	;**<78<=Oscilloscope** ;set cycle counter to 4T = 4 x 19.5 = 78
	movwf	temp01	;78 x 28us = 2184 (16us missing) 
	goto	SendPulse
;-----------
Send_1			;gap T (550us), pulse 2T (1100us)
	bcf	IRTXDATA
	call	DelayT
			;19 cycles per T -> 35.7kHz
			;One cycle: 14us high + 14us low
	movlw	d'43';**<43<=Oscilloscope**	;set cycle counter to 2T = 2 x 19 = 38
	movwf	temp01	;38 x 28us = 1064us (36us missing)
	goto	SendPulse
;----------------------
Send_0			;gap T (550us), pulse T (550us)
	bcf	IRTXDATA
	call	DelayT
			;19 cycles per T -> 35.7kHz
			;One cycle: 14us high + 14us low 
	Delay	d'10'	;the missing 18us - 8us for program lines calling
	movlw	d'22';**<22<=Oscilloscope**  ;set cycle counter to T = 1 x 19 = 19
	movwf	temp01	;19 x 28us = 532us (18us missing)
	goto	SendPulse
;-----------------------
	; This sets the Carrier Frequency! Adjusted by Oscilloscope. Do not change!
	; temp01 sets pulse length (d'43' gives SIRCS pulse length)
SendPulse	;Common procedure to send n cycles (n = temp01)
	bsf	IRTXDATA	;1
	Delay	0x0d; **0x0d>14us<=Oscilloscope** 13 ;1+13 = 14us
	bcf	IRTXDATA	;1
	Delay	0x0a; **0x0a>14us<=Oscilloscope** ;>14us;  ;1+11
	decfsz	temp01,f		;1+1+11
	goto	SendPulse	;1+1+1+11 = 14us
	return

;*******************************************************************
DelayT			;GKOS IR pulse Basic time period T = 550us
	Delay	d'200'
	Delay	d'200'
	Delay	d'150';<150
	return
Delay40T			;SIRCS 40 kHz IR pulse Basic time period T = 550us
	Delay	d'200'
	Delay	d'200'
	Delay	d'160'
	return

;DelayTplus		;IR pulse data bit check period = 825us
;	Delay	d'200'
;	Delay	d'200'
;	Delay	d'200'
;	Delay	d'200'
;	Delay	d'25'
;	return
;****************************************************************
;SendIRPause24		;Pause between chord packets = 24ms
;	bcf	IRTXDATA
;	movlw	d'24'
;	call	DelayWx1ms
;	return
;------

;-------------------------------------------------------------------
;                          TV1 (ASA)
;-------------------------------------------------------------------
;
; Phase shift keying, 36kHz carrier (||||) pulses (= bursts)
; 1 = half cycle of 2kHz (pulse or pause)
; 0 = one cycle of 1kHz  (pulse+pause or pause+pulse)
; |||_________________||______||__||||__||____||__||
; ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^1^ ^0^ ^1^ ^0^ ^1^ ^0^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 
;0.5ms     3ms       0.5ms
;----------------------------------------------------------------------

; This is the IR frame for an ASA television

TestW		;<<<TEST!!!
	movwf	TEMPX	; TEMPX = byte to send (8 bits, bit0 first)
	bsf	SYNCH	; Oscilloscope SYNCHRONISATION
	movlw	2
	call	DelayWx1ms
	bcf	SYNCH
	movlw	2
	call	DelayWx1ms

Send_TV1
	; Enter here with 8-bit data in W
	; 0.5ms 18 or 17
	; 1.0ms	35
	; 3.0ms 108

	movwf	TEMPX	; TEMPX = byte to send (8 bits, bit0 first)

	; IR START indication:
	movlw	d'18'	; Pulse 0.5ms
	call	SendPulseW	
	;movlw	d'108'	; Pause 3.0ms
	movlw	d'90'	; Pause 2.5ms
	call	SendPauseW	
	movlw	d'18'	; Pulse 0.5ms
	call	SendPulseW	

	bsf	IRTXline	; latest state is Pulse

; Send one byte of data (in TEMPX)
	movlw	d'8'
	movwf	bitcounter	; set counter for 8 bits
	call	Send_W

; Send one byte of device/address information
	;movlw	b'00000011'	; Send 8 device bits, LSB first
	movf	TEMPY,W		; Get the device address (in TEMPY)
	movwf	TEMPX		; TEMPX = byte to send (6 bits only, bit0 first)
	movlw	d'8'
	movwf	bitcounter	; set counter for 8 bits
	call	Send_W

	;movlw	d'30'		;<<<<TEST!!!!
	;call	DelayWx1ms

	;goto	TestW

	return
;-------------
Send_W
	btfss	TEMPX,0		;bit0=1?
	goto	Send_W_0	;No
	call	SendW1		;Yes SEND '1'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 8 bits sent
	goto	Send_W		;No.
	return			;yes, return
Send_W_0
	call	SendW0		;Yes SEND '0'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 8 bits sent?
	goto	Send_W		;No.
	return			;yes, return
; ---
SendW0
	btfsc	IRTXline
	goto	SW0Pa
	nop
	movlw	d'18'	; Pulse 0.5ms
	call	SendPulseW	
	movlw	d'17'	; Pause 0.5ms
	call	SendPauseW
	nop
	return
SW0Pa
	movlw	d'18'	; Pause 0.5ms
	call	SendPauseW	
	movlw	d'17'	; Pulse 0.5ms
	call	SendPulseW	
	nop
	return
; ---
SendW1
	btfsc	IRTXline
	goto	SW1Pa
	nop
	movlw	d'37' ;d'35'	; Pulse 1.0ms
	call	SendPulseW	
	bsf	IRTXline
	return
SW1Pa
	movlw	d'37' ;d'35'	; Pause 1.0ms
	call	SendPauseW	
	bcf	IRTXline
	return

;----------------------------------------------------------------
;		36kHz IR Carrier
;----------------------------------------------------------------
; Enter SendPauseW or SendPulseW with number of 36kHz pulses in W
; - examples: 18 or 17 => 0.5ms, 35 => 1.0ms, 108 => 3.0ms
;
;_____________|||||||||||||________________|||||||||||||____________
; Pause          Pulse         Pause          Pulse       Pause

SendPauseW	; Pause value in W (2us + W x 28us)
		; W=35 => 0.9804ms (+ other delays 20us = 1.0ms)
		; W=17 => 0.4762ms (+ other delays 24us = 0.5ms)
	movwf	temp01	; 1us
SendPauseW_1	; (Same delays as in SendPulseW)
	bcf	IRTXDATA	;1, Turn OFF IR LED
	Delay	0x0d		;1+13
	nop			;14+1
	Delay	0x0a		;15+10
	decfsz	temp01,f	;25+1
	goto	SendPauseW_1	;+2 = 28us x W
	return		; 1us
;----------
SendPulseW	; Common procedure to send W cycles of 36kHz (35,7kHz)
		; W=35 => 0.9804ms (+ other delays 20us = 1.0ms)
		; W=17 => 0.4762ms (+ other delays 24us = 0.5ms)
	movwf	temp01	; 1us	
SendPulseW_1	; This sets the carrier frequency!!! (35,7kHz = ca.36kHz)
	bsf	IRTXDATA	;1
	Delay	0x0d		; <=Oscilloscope** 13 ;1+13 = 14
	bcf	IRTXDATA	;14+ 1
	Delay	0x0a		; <=Oscilloscope** ; 15+10
	decfsz	temp01,f	;25+1
	goto	SendPulseW_1	;+2 = 28us x W
	return		; 1us
;------------------------------------------------
;SendPulse40W	; Common procedure to send W cycles of 40kHz
;		; W=39 => (0.9750ms) (+ other delays 20us = 1.0ms)	30
;		; W=19 => (0.4750ms) (+ other delays 24us = 0.5ms)	19/20
;		;    sum = 1.450ms ; 0.475+0.5=0.975 (+25) Pulse=19, Pause=20
;		;    		     0.975+0.5=1.475
;	movwf	temp01	; 1us	
; 40kH carrier: (1/0.028 = 35,7; 1/0.025 = 40kHz, 3 cycles less)
;SendPulse40W_1	; This sets the carrier frequency!!! (35,7kHz = ca.36kHz)
;	bsf	IRTXDATA	;1
;	Delay	0x0c; 0x0d		; 13 ;1+13 = 14		(14 => 13)
;	bcf	IRTXDATA	;14+ 1
;	Delay	0x08 ;0x0a		; 15+10
;	decfsz	temp01,f	;25+1
;	goto	SendPulse40W_1	;+2 = 28us x W			(14 => 12)
;	return		; 1us
;
;------------------------------------------------




;-----------------------------------
;		IrDA:
;-----------------------------------
Send_IRDA			; Send one IrDA frame of 10 bits (0 + 8 data bits + 1)
				; Byte to send is in W
	movwf	TEMPX
	call	Send_0i		; Send START BIT (= '0')
	;movf	finalchord,w	; Send 8 info bits
	;movwf	TEMPX		; TEMPX = byte to send (6 bits only, bit0 first)
	movlw	d'8'		; 8 data bits to send
	movwf	bitcounter	; set counter for 8; 6 bits
Send_IRDA_a
	btfss	TEMPX,0		;bit0=1?
	goto	Send_IRDA_0	;No
	call	Send_1i		;Yes SEND '1'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 8 bits sent?
	goto	Send_IRDA_a	;No.
	call	Send_1i		; SEND STOP BIT (= '1')
	return			;yes, return
Send_IRDA_0
	call	Send_0i		;SEND '0'
	rrf	TEMPX,f		;Next bit
	decfsz	bitcounter,f	;All 8 bits sent?
	goto	Send_IRDA_a	; No.
				; Yes.
	call	Send_1i		; SEND STOP BIT (= '1')
	return
;----------------------
Send_1i			; Send no Pulse, 1/1 bit time (0,0001042s = 0,1042 ms = 104,2us)
	bcf	IRTXDATA
	Delay	d'95'	; 104us pause (bit time 1/9600 = 0,000104167 = 104,167us)
	return		;  (subtract 7 + 2 command lines per bit)
;----------------------
Send_0i			; Send a Pulse, 3/16 bit time (19,5us) + no pulse 13/16 (84,66us) bit time
	bsf	IRTXDATA
	Delay	d'20'	; 20us pulse
	bcf	IRTXDATA
	Delay	d'74'	; 84us pause  (subtract 7 + 3 command lines per bit)
	return
;-----------------------
;************************* END OF IR RX & TX **********************************


;======================= GKOS & Mouse SUBROUTINES ======================

;-----
			; WIRED GKOS SCANNING
			; ===================

ReadGKOSchord			;-LATEST KEY POLLING ROUTINE- 4/2004
				; This can use the same enhanced chord
				; detection routines as with IR reception

	clrf	maxchord	; Default: no chord
	clrf	RXchord		; Default: no chord
	bcf	GKOSstatus,0	; Default: chord received indicator bit0 = 0

	decfsz	GKOScounter1,f	; Too soon to re-scan?
	return			; Yes, no scan yet.
	movlw	GKOSdelay	; No. It may be time to scan.
	movwf	GKOScounter1	; Initialize counter.	

	decfsz	GKOScounter2,f	; Too soon to re-scan?
	return			; Yes, no scan yet.
	movlw	GKOSdelay	; No. It's be time to scan now.
	movwf	GKOScounter2	; Initialize counter.	


;----- NEW CODE to use the same key polling procedure as with IR reception


	movf	PORTB,W		; Read GKOS Chord into param. chord
	xorlw	0xFF		; invert bits (pull-up function)
	andlw	b'00111111'	; clear RB7 & RB6 positions	
	movwf	chord		; store chord pressed at the moment
	movwf	maxchord	; save chord for re-check
	movlw	0x00		; Is it zero (no keys down at the moment)
	xorwf	chord,W		;
	btfss	STATUS,Z	; chord equal to 0? 
	goto	ReadGKOSchord_1	; No.
				; Yes.
	bsf	ZeroChordWR	; For <AKU>: Zero chord

	; Send 32 (was 5) zero chords after release of keys due to enhanced key polling

	clrf	RXchord		; Indicate zero in RXchord too
	incf	ZeroChords,f	; Zero Chord counter (5...0)
	decfsz	ZeroChords,f	; was it zero already?
	btfsc	STATUS,Z	; ZeroChord counter Equal to 0?
	return			; Yes. Exit right away. All GKOS keys are up.
				; No.
	decf	ZeroChords,f	; Decrement counter and send a Zero Chord.
	goto	ReadGKOSchord_1b

	; Non-zero chord value received

ReadGKOSchord_1
	bcf	ZeroChordWR	; For <AKU>: Non-zero chord
	bcf	AKUSent_WR	; Set default: AKU not sent for the next wired kbd Zero Chord.

	movlw	d'32'		; Initialize Zero Chord counter
	;movlw	d'5'		; Initialize Zero Chord counter
	movwf	ZeroChords	; when non-zero chords are detected

ReadGKOSchord_1b 
	movf	chord,w
	movwf	RXchord		; Save the chord as parameter RXchord
	bsf	GKOSstatus,0	; Chord received indicator bit0 = 1
	return


;------------------------------------------------------------------------------

		; IR RECEPTION
		; ============

ReadIRstart		;Sony Format (SIRCS)
		;IR data formats.  SIRCS spec: 01111 = MD
		;MD 0001000 11110 / GKOS: 000100 01111(0) = cccccc gdaaa(0) <on oscilloscope
		;MD: 7 + 5 bits / GKOS: 6 + 5 bits. Received byte order: xxxa aadg
		;      
		;__   if a continuous pulse lasts 1,6 ms it should be a start pulse
	bcf	TESTPOINT	;--TP: IR burst (low)
	;bcf	GKOSstatus,0	;indicate no chord received as a deafault
	bcf	GKOSstatus,6	;Flag: No packet received yet. Pulse = line low. (NOT USED)
				;Is this the START PULSE of 2200us (1.1ms - 2.2ms) 1.65ms
	movlw	d'16'		;Number of 100us loops
	movwf	temp_a		;Set counter. 16 x 103us = 1.648ms
ReadIRstart_a
	btfsc	IRDATA		;Pulse still there? TEST START PULSE	-   1us -
	retlw	0xEE		;No. UNSUCCESSFUL RETURN W=0xEE ******
	Delay	d'100'		;Delay of 100us (16 x 100us = 1.6ms)	- 100us -
	decfsz	temp_a,f	;Counter=0?					-   1us -
	goto	ReadIRstart_a	;No.						-   1us - (103us)
				;Yes. Pulse length was at least 1.6 ms (IR START PULSE).
				;Information part: 	'1'= 0.55ms high + 1.1 ms low
				;			'0'= 0.55ms high + 0.55ms low
				;Wait for a pulse > Check at 0.825ms: high=>'0', low=>'1'
				;then wait for no pulse (high) and again for a pulse,
				;7 bits (chord value) + 5 bits (device = 00010, Betamax)
;(Timing: 275/550/825/1100)
;          ___
;_________/	  pulse =0 / no pulse =1
;      ^	  ======================

ReadIRstart_b			;=Wait for no pulse=
	btfss	IRDATA		;Low? (=pulse?)
	goto	ReadIRstart_b	;Yes. Still wait... PULL-UPs required else FREEZING HERE
				;No. The Start Pulse has reached the end. Line is high.
;          ___     _____
;_________/   \___/___\_ pulse =0 / no pulse =1
;          ^   |--first bit

	Delay	d'275'		; Wait until middle of the first gap to match timing ahead
	bsf	TESTPOINT	;--TP: high (no burst)

;          ___     _____
;_________/   \___/___\_ pulse =0 / no pulse =1
;           ^  |--first bit

	retlw	0x00		;SUCCESSFUL RETURN W=0x00 ******
;-------------------

;---IR Receive 8 bits

ReadIR8bits
	clrf	TEMPX		;Clear register for byte reception
	movlw	d'8'		;Set Counter (temp_b) to 6 (bits), GKOS Chord value
	movwf	temp_b
ReadIR8bits_a
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0

	call	ReadIRbit	;Read one bit into W (b000 0000)
	btfsc	tempflags,0	;Error in bit reception?
	retlw	0xEE		;Yes.   *** ERROR RETURN W=0xEE ***
	addwf	TEMPX,f		;No, add the received bit to the byte

	decfsz	temp_b,f	;All 8 bits received?
	goto	ReadIR8bits_a	;No.
				;Yes.
	movf	TEMPX,w		;
	  ;movf	   TEMPX,w	;debug
	  ;call	   SerTx	;debug
	retlw	0x00		;SUCCESSFUL RETURN W=0x00, bits in TEMPX: 7654 3210
;--------

;--IR receive 7 bits

ReadIR7bits
	clrf	TEMPX		;Clear register for byte reception
	movlw	d'7'		;Set Counter (temp_b) to 7 (bits), GKOS Chord value
	movwf	temp_b
ReadIR7bits_a
	call	ReadIRbit	;Read one bit into W (b000 0000)
	btfsc	tempflags,0	;Error in bit reception?
	retlw	0xEE		;Yes.  *** ERROR RETURN W=0xEE ***
	addwf	TEMPX,f		;No, add the received bit to the byte
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	decfsz	temp_b,f	;All 7 bits received?
	goto	ReadIR7bits_a	;No.
				;Yes. 
	movf	TEMPX,w		;
	  ;movf	   TEMPX,w	;debug
	  ;call	   SerTx	;debug
	retlw	0x00		;SUCCESSFUL RETURN W=0x00, bits in TEMPX: -654 3210
;-------

;---IR Receive 6 bits

ReadIR6bits
	clrf	TEMPX		;Clear register for byte reception
	movlw	d'6'		;Set Counter (temp_b) to 6 (bits), GKOS Chord value
	movwf	temp_b
ReadIR6bits_a
	call	ReadIRbit	;Read one bit into W (b000 0000)
	btfsc	tempflags,0	;Error in bit reception?
	retlw	0xEE		;Yes.  *** ERROR RETURN W=0xEE ***
	addwf	TEMPX,f		;No, add the received bit to the byte
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	decfsz	temp_b,f	;All 6 bits received?
	goto	ReadIR6bits_a	;No.
				;Yes. One more shift (6 bits of data)
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	movf	TEMPX,w		;
	  ;movf	   TEMPX,w	;debug
	  ;call	   SerTx	;debug
	retlw	0x00		;SUCCESSFUL RETURN W=0x00, bits in TEMPX: --54 3210
;-------

;---IR Receive 5 bits

ReadIR5bits
	;Receive the Toggle bit G (=D7) and Device information part correctly
	clrf	TEMPX		;Clear register for byte reception
	movlw	d'5'		;Set Counter (temp_b) to 5 (bits), Device info
	movwf	temp_b
ReadIR5bits_a	
	call	ReadIRbit	;Read one bit into W (b000 0000)
	btfsc	tempflags,0	;Error in bit reception?
	retlw	0xEE		;Yes.  *** ERROR RETURN W=0xEE ***
	addwf	TEMPX,f		;No, add the received bit to the byte
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	decfsz	temp_b,f	;All 5 bits received?
	goto	ReadIR5bits_a	;No.
				;Yes. Two more shifts (5 bits of data)
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	rrf	TEMPX,f		;rotate right
	bcf	TEMPX,7		;Make sure bit7=0
	movf	TEMPX,w		;
	  ;movf	   TEMPX,w	;debug
	  ;call	   SerTx	;debug

	retlw	0x00		;SUCCESSFUL RETURN W=0x00, bits in TEMPX: ---4 3210
;---------
;---------
ReadIRbit
	bcf	tempflags,0	;Set flag: Default = 0 = Success

;low = IR pulse, high = no IR
;    ___     ___
;___/   \___/   \___/
;       |---0---|
;    ___         ___
;___/   \_______/   \___/
;       |-----1-----|
;             ^decide here if 0 or 1
;
; Starting points:
;low = IR pulse, high = no IR
;    ___
;___/
;     ^ after Start Pulse or '0'
;    ___
;___/
; ^ after '1'


	;Make sure there is no pulse first

	; Make sure not to have to wait too long (it would be a reception error)
	; - max 375us (>275us) - (if previous bit was a '1', else it is no pulse already) 

	movlw	d'29'		;Number of 13us loops: 29 x 13us = 377us (gap = 0,550ms)
	movwf	temp_a		;Set counter to around 375us (375us/13us = 29)

ReadIRbitNP
	btfsc	IRDATA		;Pulse (line low) still there?	 1us
	goto	ReadIRbitNX	;No. No more pulse.
	Delay	d'10'		;Yes, ... loop back.			 10us
	decfsz	temp_a,f	;No. Counter=0?			 1us
	goto	ReadIRbitNP	;No.					 1us => 13us 
	bsf	tempflags,0	;Yes. Timeout. Flag the error
	return			;This is an ERROR return. No end of IR pulse found.
ReadIRbitNX

; Wait for a new pulse (low), then wait 825 us and check state (low='1', hight='0')

				;No more pulse. Line high now.
	bsf	TESTPOINT	;--TP: no burst (high)

	;movlw	d'100'		;Number of 10us loops: 100 x 10us = 1ms (gap = 0,550ms)
	movlw	d'54'		;Number of 13us loops: 54 x 13us = 702us (gap = 0,550ms)
	movwf	temp_a		;Set counter to around 700us (700us/13us = 54)
ReadIRbit_a

;low = IR pulse, high = no IR
;    ___
;___/   \_
;       ^
	; Wait for IR pulse (low) to start

	; Make sure not to have to wait too long (it would be a reception error)
	; max - 700us -

	Delay	d'10'		;Check it every 10us			 10us
	btfss	IRDATA		;Any pulse (low) appearing there?	 1us
	goto 	ReadIRbit_b	;Yes! Data bit starting...
	decfsz	temp_a,f	;No. Counter=0?			 1us
	goto	ReadIRbit_a	;No.					 1us => 13us 
	bsf	tempflags,0	;Yes. Timeout. Flag the error
	return			; This is an ERROR return. IR pulse start missing.

ReadIRbit_b

;    ___     ___
;___/   \___/___
;             ^
;       |----->
;        825us (delay counter value = 70)

	bcf	TESTPOINT	;--TP: burst (low)
	; Wait 825us and check IR data line state -----------
	movlw	d'70'		; Number of 10us's to wait (4 MHz XT OSC)
				; 70 = Oscilloscope-adjusted value using TESTPOINT
	movwf	temp_a		;Set counter	

ReadIRbit_bb
	Delay	d'10'		; Wait 10us each time	 10us
	decfsz	temp_a,f	; Counter=0? (70 => 0)	 1us + 1us
	goto	ReadIRbit_bb	; No. loop back		 70 x 12us = 840us
				; Yes.
	bsf	TESTPOINT	;--TP: no burst (high) to test reading time point
	btfss	IRDATA		; Pulse(=low) ended? => '0'
	goto	ReadIRbit_1	; No.  '1' received
	retlw	0x00		; Yes. '0' received
;    ___     ___
;___/   \___/   \___
;       |-------|
;             ^test=>'0'    (Timing: 275/550/825/1100)

ReadIRbit_1			;'1' => 1000 0000 in W (0x80)
	retlw	0x80		;'0' => 0000 0000 in W (0x00)
;    ___         ___
;___/   \_______/   \___
;       |-----------|
;             ^test=>'1'

;*********************

		; Make sure the transmission ends (checked after mouse data)
		; Low = IR pulse
CheckIRend			;=Wait for ending of last pulse=

	btfss	IRDATA		;Low? (=pulse?)
	goto	CheckIRend	;Yes. Still wait... PULL-UPs required else FREEZING HERE
				;No. The last IR pulse has reached the end. Line is high.
;          ___     _____
;_________/   \___/___\_ pulse =0 / no pulse =1
;          ^   |--first extra bit will start here latest
;          |   |   |   |
;          0 0.55 1.1 1.65ms

; Check that there are no more IR pulses during 1.1 ms after end of the last pulse

	movlw	d'84'		; Number of 13us loops: 84 x 13us = 1092us (gap = 1.1 ms)
	movwf	temp_a		; Set counter to around 1100us (1100us/13us = 84)
				; 1650us/13us = 126
ReadIRendNP
	btfss	IRDATA		; Silence (line up) still there?	 1us
	goto	ReadIRendNX	; No, a pulse was found!
	Delay	d'10'		; Yes, silence... loop back.		 10us
	decfsz	temp_a,f	; Counter=0?				 1us
	goto	ReadIRendNP	; No.					 1us => 13us 
	retlw	0x00		; Yes. This OK return. No more IR pulses found.
ReadIRendNX
	;bsf	tempflags,0	; Flag the error (this flag may not be needed)
	retlw	0xEE		; ERROR return. There are still IR pulses after the end of transm.

;---------------------------------------------------------------------------------------------
;PS/2 Keyboard Byte Transmission

ByteOut
; FUNCTION DELETED
		return		

;*********************
;PS/2 Keyboard Byte Reception
; FUNCTION DELETED

ByteIn0
		return
ByteIn	
		return
ByteIn1
		return

;==================== PS/2 MOUSE COMMUNICATIONS:
;---------------------------------------------------------------------------------------------
; PS/2 Mouse Byte Transmission
; FUNCTION DELETED
; MByteOut ; This is on Page 1 now (UART used)!		
;		return

;***************************************************
;PS/2 Mouse Byte Reception
; FUNCTION DELETED

;MByteIn0
;		return
;MByteIn           
;		return
;MByteIn1
		return
;======================= COMMON SUBROUTINES ===============================

DelayWx10ms
	movwf	dcount1 	; dcount1 = W
	movlw	0x64
	movwf	dcount2 
	movlw	0x20
	movwf	dcount3 
	decfsz	dcount3,F	; delay of > ((((3 * dcount3)+3)*dcount2)+3*W)
	goto 	$ - 1		;    * instruction cycle time (1us for 4MHz)
	decfsz	dcount2,F
	goto 	$ - 5		; so currently W x 10ms
	decfsz	dcount1,F
	goto 	$ - 9		
	return

;*********************

; Delays 4w+4 cycles (including call,return, and movlw) (0=256) 
Delay_Routine   addlw   -1              ;Precise delays used in I/O 
                btfss   STATUS, Z  
                goto    Delay_Routine 
                return     

;*********************

DelayWx1ms
	movwf	dcount1 	; dcount1 = W
	movlw	0x0a
	movwf	dcount2 
	movlw	0x20
	movwf	dcount3 
	decfsz	dcount3,F	; delay of > ((((3 * dcount3)+3)*dcount2)+3*W)
	goto 	$ - 1		;    * instruction cycle time (1us for 4MHz)
	decfsz	dcount2,F
	goto 	$ - 5		; so currently W x 1ms
	decfsz	dcount1,F
	goto 	$ - 9		
	return

;*******************************************************************

;  INIT_UART - Initialises UART
;  Enables COM Port receiver and transmitter
;  Make sure to be at Bank 0

INIT_UART
	;Page 357 of 33023a.pdf (PIC Manual):

	BSF	STATUS, RP0	; Go to Bank1
				; ===========
	MOVLW	d'25'		; Set Baud Rate to 9600 (BRGH=1) or 2400 (BRGH=0)
	MOVWF	SPBRG
	;        7     6    5     4    3    2     1     0
	;TXSTA: CSRC  TX9  TXEN  SYNC  -   BRGH  TRMT  TX9D
	;  TXEN= Transmit Enable bit
	;  BRGH= High Baud Rate Select bit (1= High speed)
	;RCSTA: SPEN  RX9  SREN  CREN  -   FERR  OERR  RX9D
	;  SPEN= serial Port Enable bit
	;  CREN= Continuous Receive Enable bit
	MOVLW	0x24 		; 8-bit transmit, transmitter enabled, BRGH=1
	MOVWF	TXSTA		; Asynchronous mode, high speed mode
	;BSF	PIE1, TXIE	; Enable transmit interrupts
	;BSF	PIE1, RCIE	; Enable receive interrupts
	BCF	STATUS, RP0	; Go to Bank 0
				; ============
	MOVLW	0x80		; (8-bit receive, receive enabled > 0x90)
	MOVWF	RCSTA		; Just Serial Port enabled > 0x80
;-----
			;*** UART Transmission - write to reg. 19h TXREG (Bank 0)


        ; enable recevier
        ;MOVLW   (1<<SPEN)|(1<<CREN) ; preset serial port enable and continous receive
        ;MOVWF   RCSTA   ; set it

        ; enable receiver interrupt
        ;MOVLW   PIE1    ; get adress for periphial irq's
        ;MOVWF   FSR     ; setup fsr
        ;BSF     INDF,RCIE ; enable receiver irq
        ;BSF     INTCON,PEIE ; and periphial irq must also be enabled

			;*** UART Receive Register is 1Ah RCREG (Bank 0)
   	return
;---------------

; Serial Transmission of data via UART
	; This is for PS/2 monitoring
SerTx
	RETURN	; DISABLE THIS DEBUG FUNCTION
SerTx1
	btfss	PIR1, TXIF	; check if ready
	goto	$-1
	movwf	TXREG		; transmit byte

	return


;----------------
; LCD CODES
;
;	<user RAM>	0x00 - 0x0f
;	<not used>	0x10 - 0x1f
;	sp! " # $ % & '	0x20 - 0x27
;	( ) * + , - . /	0x28 - 0x2f
;	0 1 2... 9	0x30 - 0x39
;	: ; < = > ?	0x3a - 0x3f
;	@ A B C ... O	0x40 - 0x4f
;	P Q R S ... Z	0x50 - 0x5a
;	[ <yen> ] ^ _	0x5b - 0x5f
;	` a b c ... o	0x60 - 0x6f
;	p q r s ... z	0x70 - 0x7a
;	{ | } -> <-	0x7b - 0x7f
;	<laatikko>	0xdb
;	ä		0xe1
;	ü		0xf5
;	ö		0xff
;
;
;----------------
; ASCII CODES:
;000  (nul)  016  (dle)  032 sp  048 0  064 @  080 P  096 `  112 p
;001  (soh)  017  (dc1)  033 !   049 1  065 A  081 Q  097 a  113 q
;002  (stx)  018  (dc2)  034 "   050 2  066 B  082 R  098 b  114 r
;003  (etx)  019  (dc3)  035 #   051 3  067 C  083 S  099 c  115 s
;004  (eot)  020  (dc4)  036 $   052 4  068 D  084 T  100 d  116 t
;005  (enq)  021  (nak)  037 %   053 5  069 E  085 U  101 e  117 u
;006  (ack)  022  (syn)  038 &   054 6  070 F  086 V  102 f  118 v
;007  (bel)  023  (etb)  039 '   055 7  071 G  087 W  103 g  119 w
;008  (bs)   024  (can)  040 (   056 8  072 H  088 X  104 h  120 x
;009  (tab)  025  (em)   041 )   057 9  073 I  089 Y  105 i  121 y
;010  (lf)   026  (eof)  042 *   058 :  074 J  090 Z  106 j  122 z
;011  (vt)   027  (esc)  043 +   059 ;  075 K  091 [  107 k  123 {
;012  (np)   028  (fs)   044 ,   060 <  076 L  092    108 l  124 |
;013  (cr)   029  (gs)   045 -   061 =  077 M  093 ]  109 m  125 }
;014  (so)   030  (rs)   046 .   062 >  078 N  094 ^  110 n  126 ~
;015  (si)   031  (us)   047 /   063 ?  079 O  095 _  111 o  127 (del)


ShowIRpackets
	movf	IRByte1,w	;
	call	SerTx		;
	movf	IRByte2,w	;
	call	SerTx		;
	movf	IRByte3,w	;
	call	SerTx		;
	movf	IRByte4,w	;
	call	SerTx		;
	movlw	d'219'		; end sign
	call	SerTx		;
	return

;********************************************************************************

SLEEP_loop

	decfsz	SLEEPcnt1,f	; 
	return	

	movlw	d'255'
	movwf	SLEEPcnt1

	decfsz	SLEEPcnt2,f	; 
	return			;

	movlw	d'255'
	movwf	SLEEPcnt2

	decfsz	SLEEPcnt3,f	; 
	return	

	movlw	SLEEPdelay	; This defines the ilde time before going to sleep
	movwf	SLEEPcnt3	; 1 => 3 seconds  


;	decfsz	SLEEPcnt3,f
;	return	

	; Clear all lines to LCD
	; - bus lines are in input state already
	bcf	LCD_RS
	bcf	LCD_RW
	bcf	LCD_E

	;bcf	LCD_power	; turn off LCD and IR receiver power

	; let IR input settle before sleep
	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms

	; Define RB6 as output for sleep period because
	; it is pulled low by the IR receiver and would
	; cause the wakeup.

	bsf	STATUS,RP0      ; change to Register bank 1
	bcf	STATUS,RP1	;           ===============
	movlw	b'00111111'	; binary value, 1 bit per port bit
	movwf	TRISB		; RB0-RB6 set to digital inputs, GKOS keys + IR data in
	bcf	STATUS,RP0	; change back to Register bank 0
				;                ===============

;	bcf	PORTB,6		; Pin RB6 = 0 (same as IR data from IR receiver)

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		


	bcf	INTCON, RBIF	; Clear Port B interrupt flag (just to make sure)

	;bcf	ADCON0,ADON	; turn off D/A converter to save power

	SLEEP
	nop

	; *** ROUTINES for wakeup:

	; Change 'IR data in' back to input
	bsf	STATUS,RP0      ; change to Register bank 1
	bcf	STATUS,RP1	;           ===============
	movlw	b'01111111'	; binary value, 1 bit per port bit
	movwf	TRISB		; RB0-RB6 set to digital inputs, GKOS keys + IR data in
	bcf	STATUS,RP0	; change back to Register bank 0
				;                ===============



	; Read port RB
	movf	PORTB,W		; Read GKOS chord into W

	; Clear flag bit RBIF
	bcf	INTCON, RBIF	; 

	; ***

	;bsf	LCD_power	; turn back on LCD power

	; Delay 1s for key release (4 x 255ms)

	;bsf	ADCON0,ADON	; turn back on D/A converter

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	; call	SetMouseBias	; Initialize TrackPoint mouse bias voltage
				; to provide 1.8V at Yin when mouse is idle

	; INITIALIZE LCD
	; parameters
	bcf	LCD_E
	clrf	CommandBuffer0	; Clear IR mode command buffers
	clrf	CommandBuffer1	; ...
	;clrf	CommandBuffer2	; ...
	;bcf	LCD_edge	; Display window edge not passed.

	;bsf	LCD_power	; Turn on LCD and IR receiver power

	; Wait 1 seconds for the LCD to start
	;movlw	d'100'
	;call	DelayWx10ms

	;movlw	HIGH LCD_set	; Get high 5 bits of address
	;movwf	PCLATH		; Next Page...
	;call	LCD_set		; Init procedure
	;movlw	HIGH SLEEP_loop	; Make sure PCLATH is pointing to this Page (0)
	;movwf	PCLATH

	movlw		d'255'		;1/4 sec DELAY
	call		DelayWx1ms		

	return





;=== KEYBOARD AS MOUSE operation ====
; FUNCTION DELETED
;KeyboardMouse ; it is now on Page 1
;	return

;********************************************************************************
;===END OF SUBROUTINES===
;mmmmmmm

;=====================================================================================;
;_____________________ Page1 0800h-0FFFh More Program code____________________________;
; PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP11111111111111111111111111111111111111111111111
		org	0x800	; Start of program memory page 1

;-------------------------------------------------------------------------------------

	; This is for check-back timer monitoring
SerTx2
	RETURN	; DISABLE THIS DEBUG FUNCTION

SerTxM	; This sends Mouse data via UART (KeyboardMouse)
	btfss	PIR1, TXIF	; check if ready
	goto	$-1
	movwf	TXREG		; transmit byte
	return

TestUART
	;Send text 'GKOS' and a carriage return
	movlw	d'71' ;0x47	;'G'
	call	SerTx2
	movlw	d'75' ;0x4B	;'K'
	call	SerTx2
	movlw	d'79' ;0x4F	;'O'
	call	SerTx2
	movlw	d'83' ;0x53	;'S'
	call	SerTx2
	movlw	d'13' ;0x0D	;<CR>
	call	SerTx2
	return

ClearAutorepeat
		; Mouse simulation?
		; Keyboard/mouse delay
	movlw	TDelay		; Initialize Toggle counter because chord = 0.
	btfsc	KBDasMOUSE	; Is Keyboard operating as mouse (mouse simulation)?
	movlw	MTDelay		; Yes. Use a different delay value.
	movwf	ToggleCounter	; No. Use the kbd delay value as planned.
	bcf	AutoRepeat	; clear autorepeat indication

	movlw	HIGH ClearModes	; Get high 5 bits of address
	movwf	PCLATH		; Previous Page...
	call	ClearModes	; clear SYMB, Alt etc.
	movlw	HIGH GetChordParams ;Make sure PCLATH is pointing to this Page (1)
	movwf	PCLATH

	return

;=======================================================================================
;		START OF The intelligent keyboard scanning procedure
;=======================================================================================

; BETTER WAY OF POLLING KEYBOARD STATUS received from IR and wired GKOS keyboard
; xxxxxxx (<= to find this point by search)

GetChordParams
	bcf	RXchordREADY	; Default: Tell GKOSloop that no output shall not be made

	;movf	PrevChord2,w	; Get the chord (may be NUL sometimes!) 2 steps back
	movf	Downs,w		; Get the chord = PrevChord1 AND PrevChord2 (may be NUL!)
	movwf	RXfinalchord	; update IR final chord ****THE CHORD TO SEND****

		; Zero cord?

	incf	RXchord,f	; RXchord = 0?
	decfsz	RXchord,f
	goto	GCP1		; No.
	goto	GCP2		; Yes.

		; Repeated chords?
GCP1				; For AUTOREPEAT, check if previous chord is equal (<>0)
	movf	RXchord,w
	movwf	Temp
	movf	PrevChord1,w
	subwf	Temp,w
	btfss	STATUS,2	; Z=1?, Equal?
	goto	UCP0		; No.
				; Yes.
		; Autorepeat?

	decfsz ToggleCounter,f	; Toggle counter reached zero?
	goto	UCP0		; No.
	incf	ToggleCounter,f	; Yes. Leave as it was.
	bsf	RXchordREADY	; Indicate that char will be output in any case
	bsf	AutoRepeat	; set autorepeat indication
	bcf	TextOnly	; Repeat any character
	goto	UCP0_1


GCP2
		; RXchord = 0

; Update Key down Timer for each key (decreasing values)

UCP0
		; Previous chord is not equal (RXchord<>PrevChord1)

	btfsc	AutoRepeat	; Autorepeat on?
	call	ClearAutorepeat	; Yes. Turn it off.
UCP0_1
	btfss   RXchord,0	; Chord bit0 = 1?
	goto	UCP1		; No. Go on with the next chord bit.
	incf	KeyTime0,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime0,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime0,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.
UCP1
	btfss   RXchord,1	; Chord bit1 = 1?
	goto	UCP2		; No. Go on with the next chord bit.
	incf	KeyTime1,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime1,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime1,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.
UCP2
	btfss   RXchord,2	; Chord bit2 = 1?
	goto	UCP3		; No. Go on with the next chord bit.
	incf	KeyTime2,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime2,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime2,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.
UCP3
	btfss   RXchord,3	; Chord bit3 = 1?
	goto	UCP4		; No. Go on with the next chord bit.
	incf	KeyTime3,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime3,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime3,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.
UCP4
	btfss   RXchord,4	; Chord bit4 = 1?
	goto	UCP5		; No. Go on with the next chord bit.
	incf	KeyTime4,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime4,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime4,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.
UCP5
	btfss   RXchord,5	; Chord bit5 = 1?
	goto	UCP6		; No. Go on.
	incf	KeyTime5,f	; add 1 in order to set key counter to 1 if 0
	decfsz	KeyTime5,f	; Decrement key time counter (127...0 !), Zero?
	decf	KeyTime5,f	; Not zero. Decrement if not zero in the beginning
				; Zero. The key has been down long. Do not decrement.

;----
UCP6

;============ new code in Paris, September 2003 ============

; This key polling procedure allows some overlapping of chords as well as
; holding down keys between chords supposing at least one key is released.

KeyPoll

		; Check-back enabled?

;	CHECK-BACK IS ALWAYS DONE BUT SELECT LATER IF THE RESULT WILL BE OUTPUT

;----
		; Any key released? (Check-back enabled)
KeyPoll_CB
	;btfss	NoOutput	; Is this too soon after previous output?
	incf	WaitCounter,f	; Is WaitCounter = 0 or...
	decfsz	WaitCounter,f	; ...is this too soon after previous output?
	goto	KP0		; Yes. To soon.
	;bcf	NoOutput	; Output allowed from now on
	goto	KP1		; 
KP0
	;bcf	NoOutput	; Yes. Too soon.
	decf	WaitCounter,f	;
	goto	KP_newchar
KP1
				; Is there any change in chord?
	movf	RXchord,w	; RXchord = PrevChord1?
	movwf	Temp		; PrevChord1             011100
	movf	PrevChord1,w	; RXchord                001101
	XORWF	Temp,f		; bits that changed      010001 (XOR)
	ANDWF	Temp,f		; bits that were cleared 010000 (AND)
	btfsc	STATUS,2	; Z=0?, non-zero?, Keys released?
	goto	KP_newchar	; No.
				; Yes. 

	bsf	RXchordREADY	; Indicate to GKOSloop that output shall be made.
	movlw	WaitPeriods	; Ignore a key release next N periods. ** ONLY VALID IF NO CHECK-BACK **
	movwf	WaitCounter	; WaitCounter is made relative to chord period C now!
	bsf	NoOutput	; Ignore a key release next time (just 1 period).
	bcf	NewChar		; No more output before a new key is pressed.

		; Keyboard/mouse autorepeat delay

	movlw	TDelay		; Initialize Toggle counter due to output of character.
	btfsc	KBDasMOUSE	; Is Keyboard operating as mouse (mouse simulation)?
	movlw	MTDelay		; Yes. Use a different delay value.
	movwf	ToggleCounter	; No. Use the kbd delay value as planned.
	bcf	AutoRepeat	; clear autorepeat indication

KP_newchar
		; Any new key pressed?

	movf	PrevChord2,w	; PrevChord1 = PrevChord2?
	movwf	Temp		; PrevChord2             011100
	movf	PrevChord1,w	; PrevChord1             001101
	XORWF	Temp,f		; bits that changed      010001 (XOR)
	ANDWF	Temp,f		; bits that were set     000001 (AND)
	btfss	STATUS,2	; Z=0?, non-zero?, New keys pressed?
	bsf	NewChar		; Yes. Indicate that next key release will cause char output.
				; No. A key release will not result in outputting a character.
UpdateDowns
		; Update the chord value that might be output next time

	movf	PrevChord1,w	; RXchord AND PrevChord1
	movwf	Downs		; PrevChord1             011100
	movf	RXchord,w	; RXchord                001101
	ANDWF	Downs,f		; bits that were common  001100 (AND)
	
	; The previous Downs will be the chord to send! Not yet this ANDed value above.
	; The previous Downs has already been moved to RXfinalchord for sending

;============ end of new code in Paris 9/2003 =====

; Check back for double values to indicate missed characters (due to no key released)

;=========================== Code for check-back starts here ===========================
; ADD: control functions like PageUp, UpArrow shall not be accepted unless preceded
;      by all keys up. Also if check back gives PageUp atc. they shall be rejected.

; ccccccc
	btfss	RXchordREADY	; Is it time to output a character?
	goto	KP_X		; No. Just skip the check-back procedure.
				; Yes. Then check back if there was a missed chord
				;   before the actual one to send.


; 1) Find the shortest KeyTime in PrevChord1 (=C).
;	They must be below 127 because they have been decremented at least once.
;	It is in fact the largest value of KeyTime *down* counters 
;	(max 3 counters for letters/numbers/punctuation).

	; defaults:
	clrf	Tmp3		; Clear temp storage of check-back chord value
	bcf	MoreChords	; Indicate that there is no second chord to send
				;   in the buffer.

	clrf	TempB0	; single keys in chord
	clrf	TempB1
	clrf	TempB2
	movlw	d'127'
	movwf	TEMP0	; Three timers in chord. Set initial values
	movwf	TEMP1	;   for down counters (127...0)
	movwf	TEMP2

	; Code below is long but fast!
	; check PrevChord1 because it does not yet include the key release

CheckBit5
	btfss	RXfinalchord,5
	goto	CheckBit4
	movlw	b'100000'	
	movwf	TempB0
	movf	KeyTime5,W
	movwf	TEMP0
	goto	CheckBit4B
CheckBit4		
	btfss	RXfinalchord,4
	goto	CheckBit3
	movlw	b'010000'	
	movwf	TempB0
	movf	KeyTime4,W
	movwf	TEMP0
	goto	CheckBit3B
CheckBit3		
	btfss	RXfinalchord,3
	goto	CheckBit2
	movlw	b'001000'	
	movwf	TempB0
	movf	KeyTime3,W
	movwf	TEMP0
	goto	CheckBit2B
CheckBit2		
	btfss	RXfinalchord,2
	goto	CheckBit1
	movlw	b'000100'	
	movwf	TempB0
	movf	KeyTime2,W
	movwf	TEMP0
	goto	CheckBit1B
CheckBit1		
	btfss	RXfinalchord,1
	goto	CheckBit0
	movlw	b'000010'	
	movwf	TempB0
	movf	KeyTime1,W
	movwf	TEMP0
	goto	CheckBit0B
CheckBit0		
	btfss	RXfinalchord,0
	goto	CheckBitX
	movlw	b'000001'	
	movwf	TempB0
	movf	KeyTime0,W
	movwf	TEMP0
	goto	CheckBitX
;------------------
CheckBit4B		
	btfss	RXfinalchord,4
	goto	CheckBit3B
	movlw	b'010000'	
	movwf	TempB1
	movf	KeyTime4,W
	movwf	TEMP1
	goto	CheckBit3C
CheckBit3B		
	btfss	RXfinalchord,3
	goto	CheckBit2B
	movlw	b'001000'	
	movwf	TempB1
	movf	KeyTime3,W
	movwf	TEMP1
	goto	CheckBit2C
CheckBit2B		
	btfss	RXfinalchord,2
	goto	CheckBit1B
	movlw	b'000100'	
	movwf	TempB1
	movf	KeyTime2,W
	movwf	TEMP1
	goto	CheckBit1C
CheckBit1B		
	btfss	RXfinalchord,1
	goto	CheckBit0B
	movlw	b'000010'	
	movwf	TempB1
	movf	KeyTime1,W
	movwf	TEMP1
	goto	CheckBit0C
CheckBit0B		
	btfss	RXfinalchord,0
	goto	CheckBitX
	movlw	b'000001'	
	movwf	TempB1
	movf	KeyTime0,W
	movwf	TEMP1
	goto	CheckBitX
;-------------------
CheckBit3C		
	btfss	RXfinalchord,3
	goto	CheckBit2C
	movlw	b'001000'	
	movwf	TempB2
	movf	KeyTime3,W
	movwf	TEMP2
	goto	CheckBitX
CheckBit2C		
	btfss	RXfinalchord,2
	goto	CheckBit1C
	movlw	b'000100'	
	movwf	TempB2
	movf	KeyTime2,W
	movwf	TEMP2
	goto	CheckBitX
CheckBit1C		
	btfss	RXfinalchord,1
	goto	CheckBit0C
	movlw	b'000010'	
	movwf	TempB2
	movf	KeyTime1,W
	movwf	TEMP2
	goto	CheckBitX
CheckBit0C		
	btfss	RXfinalchord,0
	goto	CheckBitX
	movlw	b'000001'	
	movwf	TempB2
	movf	KeyTime0,W
	movwf	TEMP2
	;goto	CheckBitX
;----------

; 3) Find those KeyTime values that exceed (P% x C  =  50% x C to start with). 
;    They will define a second character that must be output before the actual RXfinalchord.
;	C = the shortest KeyTime in the original chord

CheckBitX

	; Here is now each of the one-to-three keys and the correponding timer values
	; Keys: 	TempB0, TempB1, TempB2, e.g. 010000,   000100, 000010 (FECDBA)
	; Timer values: TEMP0,  TEMP1,   TEMP2, e.g. 119(min), 115,    103(max)
	; subwf examples:
	; reg=3, w=2 => C=1, Z=0 (+)
	; reg=2, w=2 => C=1, Z=1 (0)
	; reg=1, w=2 => C=0, Z=0 (-)

	; Subtract each TEMPn from 127 to get real length

	movlw	d'255'	; movlw	d'13' ;0x0D = <CR> To show start of data in debug window
	call	SerTx2	;Debug

	movf	TEMP0,W
	sublw	d'127'	; 127-119=8 (subtract W *from* literal)
	movwf	TEMP0	; (min in the example)
	call	SerTx2	;Debug

	movf	TEMP1,W
	sublw	d'127'	; 127-115=12 (subtract W *from* literal)
	movwf	TEMP1
	call	SerTx2	;Debug


	movf	TEMP2,W
	sublw	d'127'	; 127-103=24 (subtract W *from* literal)
	movwf	TEMP2	; (max in the example)
	call	SerTx2	;Debug


;------	



CTEMP0_TEMP1
	; Compare TEMP0 and TEMP1

	movf	TEMP0,W		; TEMP0=0?
	XORLW	d'0'
	btfsc	STATUS,Z
	goto	CTEMP1_TEMP2	; Yes.
				; No.

	movf	TEMP1,W		; TEMP1=0?
	XORLW	d'0'
	btfsc	STATUS,Z
	goto	CTEMP0_TEMP2	; Yes.
				; No.
	movf	TEMP1,W
	subwf	TEMP0,W		; compare TEMP1 and TEMP0: TEMP0-TEMP1
	btfsc	STATUS,Z 	;
	goto	CTEMP1_TEMP2	; Z=1 (TEMP0=TEMP1) ???
	btfsc	STATUS,C
	goto	CTEMP1_TEMP2	; C=1 (TEMP0>TEMP1)
	goto	CTEMP0_TEMP2	; C=0 (TEMP0<TEMP1)

CTEMP1_TEMP2
	; Compare TEMP1 and TEMP2

	movf	TEMP2,W		; TEMP2=0?
	XORLW	d'0'
	btfsc	STATUS,Z
	goto	T1smallest	; Yes.
				; No.
	movf	TEMP2,W
	subwf	TEMP1,W		; compare TEMP2 and TEMP1: TEMP1-TEMP2
	btfsc	STATUS,Z 	;
	goto	T2smallest	; Z=1 (TEMP1=TEMP2) ???
	btfsc	STATUS,C
	goto	T2smallest	; C=1 (TEMP1>TEMP2)
	goto	T1smallest	; C=0 (TEMP1<TEMP2)

CTEMP0_TEMP2
	; Compare TEMP0 and TEMP2

	movf	TEMP2,W		; TEMP2=0?
	XORLW	d'0'
	btfsc	STATUS,Z
	goto	T0smallest	; Yes.
				; No.
	movf	TEMP2,W
	subwf	TEMP0,W		; compare TEMP2 and TEMP0: TEMP0-TEMP2
	btfsc	STATUS,Z 	;
	goto	T0smallest	; Z=1 (TEMP0=TEMP2) ???
	btfsc	STATUS,C
	goto	T2smallest	; C=1 (TEMP0>TEMP2)
	goto	T0smallest	; C=0 (TEMP0<TEMP2)


;------

T0smallest
	movf	TEMP0,W		; divide TEMP0 by two and save into Tmp2
	movwf	Tmp2		; xxxx xxxx
	movwf	WaitCounter	; Update Guard time
	rrf	WaitCounter,f	; divide by 2 *** THIS MAY BE FURTHER DEVELOPED
	bcf	WaitCounter,7	; 0xxx xxxx   *********************************
	clrf	WaitCounter	; Use fixed value
	bsf	WaitCounter,1	; Make sure it is at least 3 (0xxx xx1x)
	bsf	WaitCounter,0	; Make sure it is at least 3 (0xxx xx11)
				; If Tmp2>4 then decrement by one
	movlw	d'4'		; to adjust larger than 4 values
	subwf	Tmp2,W		; Tmp2-4<0?
	btfsc	STATUS,C	; Carry?
	decf	Tmp2,f		; No. Tmp2>=4
				; Yes. Tmp2<4.
	movf	TEMP0,W		; TEMP1-TEMP0>0.5 x TEMP0?
	subwf	TEMP1,W		; TEMP1=TEMP1-TEMP0 (result)
	subwf	Tmp2,W		; Tmp2 - result =?
	btfsc	STATUS,C	; Second chord found?
	goto	T0s2		; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB1 into second chord
	movf	TempB1,W
	movwf	Tmp3	
T0s2
	movf	TEMP0,W		; TEMP2-TEMP0>0.5 x TEMP0?
	subwf	TEMP2,W		; TEMP2=TEMP2-TEMP0 (result)
	subwf	Tmp2,W		; Tmp2 - result =?
	btfsc	STATUS,C	; Second chord found?
	goto	PrepareOutput	; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB2 into second chord
	movf	TempB2,W
	addwf	Tmp3,F
	goto	PrepareOutput	; Output two chords

T1smallest
	movf	TEMP1,W		; divide TEMP1 by two and save into Tmp2
	movwf	Tmp2		; xxxx xxxx
	movwf	WaitCounter	; Update Guard time
	rrf	WaitCounter,f	; divide by 2
	bcf	WaitCounter,7	; 0xxx xxxx
	clrf	WaitCounter	; Use fixed value
	bsf	WaitCounter,1	; Make sure it is at least 3 (0xxx xx1x)
	bsf	WaitCounter,0	; Make sure it is at least 3 (0xxx xx11)
				; If Tmp2>4 then decrement by one
	movlw	d'4'		; to adjust larger than 4 values
	subwf	Tmp2,W		; Tmp2-4<0?
	btfsc	STATUS,C	; Carry?
	decf	Tmp2,f		; No. Tmp2>=4
				; Yes. Tmp2<4.
	movf	TEMP1,W		; TEMP0-TEMP1>0.5 x TEMP1?
	subwf	TEMP0,W		; TEMP0=TEMP0-TEMP1 (result)
	subwf	Tmp2,W		; Tmp2 - result < 0 ?
	btfsc	STATUS,C	; Second chord found?
	goto	T1s2		; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB0 into second chord
	movf	TempB0,W
	movwf	Tmp3	
T1s2
	movf	TEMP1,W		; TEMP2-TEMP1>0.5 x TEMP1?
	subwf	TEMP2,W		; TEMP2=TEMP2-TEMP1 (result)
	subwf	Tmp2,W		; Tmp2 - result =?
	btfsc	STATUS,C	; Second chord found?
	goto	PrepareOutput	; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB2 into second chord
	movf	TempB2,W
	addwf	Tmp3,F
	goto	PrepareOutput	; Output two chords



T2smallest
	movf	TEMP2,W		; divide TEMP2 by two and save into Tmp2
	movwf	Tmp2		; xxxx xxxx
	movwf	WaitCounter	; Update Guard time
	rrf	WaitCounter,f	; divide by 2
	bcf	WaitCounter,7	; 0xxx xxxx
	clrf	WaitCounter	; Use fixed value
	bsf	WaitCounter,1	; Make sure it is at least 3 (0xxx xx1x)
	bsf	WaitCounter,0	; Make sure it is at least 3 (0xxx xx11)
				; If Tmp2>4 then decrement by one
	movlw	d'4'		; to adjust larger than 4 values
	subwf	Tmp2,W		; Tmp2-4<0?
	btfsc	STATUS,C	; Carry?
	decf	Tmp2,f		; No. Tmp2>=4
				; Yes. Tmp2<4.
	movf	TEMP2,W		; TEMP1-TEMP2>0.5 x TEMP2?
	subwf	TEMP1,W		; TEMP1=TEMP1-TEMP2 (result)
	subwf	Tmp2,W		; Tmp2 - result =?
	btfsc	STATUS,C	; Second chord found?
	goto	T2s2		; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB1 into second chord
	movf	TempB1,W
	movwf	Tmp3	
T2s2
	movf	TEMP2,W		; TEMP0-TEMP2>0.5 x TEMP2?
	subwf	TEMP0,W		; TEMP0=TEMP0-TEMP2 (result)
	subwf	Tmp2,W		; Tmp2 - result =?
	btfsc	STATUS,C	; Second chord found?
	goto	PrepareOutput	; C=1 Tmp2 > result (not found)
	bsf	MoreChords	; C=0 Tmp2 < result ***FOUND

	; get the bit from TempB0 into second chord
	movf	TempB0,W
	addwf	Tmp3,F
	;goto	PrepareOutput	; Output two chords

; ...


; 4) Prepare to output two charaters!
	; First, change RXfinalchord to the previous character and then
	; put the actual RXfinalchord to a buffer (RXfinalchord2) that
	; must be output first thing when polling (MainLoop) starts again.

PrepareOutput
	btfsc	CheckBackOn	; Is check-back output in use?
	goto	PrO_1		; Yes.
	bcf	MoreChords	; No. Indicate no additional chord to send
	goto	CLT_0		;
PrO_1
	btfss	MoreChords	; Second chord found?
	goto	CLT_0		; No.
	movf	RXfinalchord,W	; Yes. Get the actual chord to send.
	movwf	Temp		; Save temporarily the original chord
	movwf	RXfinalchord2	; Put it on hold into the buffer for a while.
	movf	Tmp3,W		; get the second chord found through check-back
	movwf	RXfinalchord	; This is the chord to be sent first instead.
				; Sedn order: RXfinalchord > RXfinalchord2
	goto	ClearKeyTimes
; ...

	; Clear counters for keys in the original chord (includes the second
	;  chord also) Original chord must be in Temp
CLT_0
	; This is when only the original chord is sent
	movf	RXfinalchord,W	; Get the actual chord to send.
	movwf	Temp		; Save temporarily original chord

	; This is both cases
	; Clear counters of keys in the original chord
ClearKeyTimes
	movlw	d'127'		; Counter is running 127 -> 0 if key is held down 
	btfsc   Temp,0		; Chord bit0 = 1? (Key up?)
	movwf	KeyTime0	; Yes. Init counter. (set to 127 if up)
	btfsc   Temp,1		; Chord bit1 = 1?
	movwf	KeyTime1	; Yes. Init counter.
	btfsc   Temp,2		; Chord bit2 = 1?
	movwf	KeyTime2	; Yes. Init counter.
	btfsc   Temp,3		; Chord bit3 = 1?
	movwf	KeyTime3	; Yes. Init counter.
	btfsc   Temp,4		; Chord bit4 = 1?
	movwf	KeyTime4	; Yes. Init counter.
	btfsc   Temp,5		; Chord bit5 = 1?
	movwf	KeyTime5	; Yes. Init counter.

KP_X

; ======================= Code for check-back ends here =============================


	; Update consecutive chord values

	movf	PrevChord1,w	; Two chords back
	movwf	PrevChord2	; Save chord as previous chord for next time

	movf	RXchord,w	; One chord back
	movwf	PrevChord1	; Save chord as previous chord for next time

	; Initialize the key counter values for those keys that were up

	movlw	d'127'		; Counter is running 127 -> 0 if key is held down 
	btfss   RXchord,0	; Chord bit0 = 1?
	movwf	KeyTime0	; No. Init counter.
	btfss   RXchord,1	; Chord bit1 = 1?
	movwf	KeyTime1	; No. Init counter.
	btfss   RXchord,2	; Chord bit2 = 1?
	movwf	KeyTime2	; No. Init counter.
	btfss   RXchord,3	; Chord bit3 = 1?
	movwf	KeyTime3	; No. Init counter.
	btfss   RXchord,4	; Chord bit4 = 1?
	movwf	KeyTime4	; No. Init counter.
	btfss   RXchord,5	; Chord bit5 = 1?
	movwf	KeyTime5	; No. Init counter.

	return

;=============================================================================
;		END OF The intelligent keyboard scanning procedure
;=============================================================================


; second time for this page (in fact this now on Page1 and not needed, use DelayWx1ms)
DelayWx1ms2
	movwf	dcount1 	; dcount1 = W
	movlw	0x0a
	movwf	dcount2 
	movlw	0x20
	movwf	dcount3 
	decfsz	dcount3,F	; delay of > ((((3 * dcount3)+3)*dcount2)+3*W)
	goto 	$ - 1		;    * instruction cycle time (1us for 4MHz)
	decfsz	dcount2,F
	goto 	$ - 5		; so currently W x 1ms
	decfsz	dcount1,F
	goto 	$ - 9		
	return

; Page 1 continues...
;==================================================================================
;          START OF KEYBOARD AS MOUSE (...on Page 1: 800-8FF, far call needed)
;==================================================================================
;=== KEYBOARD AS MOUSE operation ====

; SUBS (do not enter here first):
MByteOutS		; 0x80 d'128' = 4 mouse bytes follow at UART
	movwf	Temp	; Send first mouse byte... 			=START=
	movlw	d'128'
	call	SerTxM
			;
	movf	Temp,W	; Restore mouse byte in W 
MByteOut		; Send button and dx mouse bytes via UART 	=1,2=
	call	SerTxM
	return

MByteOutE	; Send dy mouse byte followed by scroll wheel data (=0)	 =3=
	call	SerTxM	; ...and end of mouse data indication 0xff

	movlw	d'0'	; Scroll wheel data (0 for the moment) 		 =4=
	call	SerTxM

	movlw	d'255'	; 0xff d'255' = end of 4 mouse bytes at UART 	=END=
	call	SerTxM
	return

;==================================================================
; Bit KBDasMOUSE must be set to end up here.
; Chord in finalchord

; ----------------- ENTER HERE BY A FAR CALL FROM PAGE 0 ----------

KeyboardMouse

	movlw	d'63'		; End of mouse operation pressed?
	xorwf	finalchord,w	;
	bnz	KeybMouse2	; No. Go ahead.
	bcf	KBDasMOUSE	; Yes. End this mouse simulation.

	movlw	d'50'	;This dealay is required! Still!!!
	call	DelayWx10ms	;Do not be too hasty....

XMainLoop			; Exit to MainLoop and clear chord buffer
	clrf	PrevChord1	; not to send more chords right away
	clrf	PrevChord2
	clrf	Downs
	return	; goto	MainLoop

KeybMouse2

;	btfss	M_ENABLE	; Are the mouse PS/2 lines ready for mouse data?
;	goto	MBAT		; No. Try doing the Mouse BAT then (0,5 sec).
;	;goto	MainLoop	; No. Do not send movement data.
				; Yes. Movement data can be sent via mouse lines.

	movlw	d'63'		; End of mouse operation?
	xorwf	finalchord,w	;
	bnz	MouseAction	; No.
	bcf	KBDasMOUSE	; Yes. End the mouse simulation.
				; No. Go on...
	;goto	MainLoop

;===============================================
;MOUSE OPERATION
;Chord values for the Mouse
;up 		= a+d = 1+8  	= 9
;right up	= d   		= 8
;right		= e   		= 16
;right down	= f   		= 32
;down		= c+f = 4+32 	= 36
;left down	= c   		= 4
;left		= b   		= 2
;left up	= a   		= 1
;Press and Release Left button	= a+b+c = 1+2+4 	= 7 (left click)
;Press and Release Middle button= b+e (shift) = 2+16 	= 18
;Press and Release Right button	= d+e+f = 8+16+32 = 56 (right click)
;Press and Hold Left Button	= a+c = 1+4 	= 5 (now used for left click)
;Press and Hold Right Button	= d+f = 8+32 	= 40(now used for right click)
;Esc	= 31
;Enter	= 59 (double click)
;123-abc= 63

;======= MOVING MOUSE POINTER WITH KEYBOARD =====

;MouseOperation
	;call	MouseAction
	;goto	MainLoop
;	nop
;MouseAction
;	movf	finalchord,W	;abc-123 (to exit Mouse Operation)
;	xorlw	d'63'		;Test if chord=123-abc
;	btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
;	goto	MouseExit	;

	;movf	finalchord,W	;Esc (to exit Mouse Operation)
	;xorlw	d'31'		;Test if chord=123-abc
	;btfsc	STATUS,Z	;Skip if Z=0. Skip if not equal.
	;goto	MouseExit	;
	
;	btfss	AutoRepeat	;Typematic repeat (Autorepeat on)?
;	goto	MouseAction_aa
;	movlw	0x01		;Faster Autorepeat steps
;	movwf	YstepUp
;	movwf	XstepRight
;	movlw	0xff
;	movwf	YstepDown
;	movwf	XstepLeft
;	goto	MouseAction_a
;MouseAction_aa
;	movlw	0x01		;Default steps
;	movwf	YstepUp
;	movwf	XstepRight
;	movlw	0xff
;	movwf	YstepDown
;	movwf	XstepLeft
;MouseAction_a

MouseAction
	movf	finalchord,W;	;Up?
	xorlw	d'9'		;	
	btfsc	STATUS,Z	;
	goto	MoveUp		;Yes.

	movf	finalchord,W;	;FUp?
	xorlw	d'27'		;A+B+D+E=1+2+8+16=27
	btfsc	STATUS,Z	;
	goto	FMoveUp		;Yes.

	movf	finalchord,W;	;UpRight?
	xorlw	d'8'		;'D'	
	btfsc	STATUS,Z	;
	goto	MoveUpRight	;Yes.

	movf	finalchord,W;	;FUpRight?
	xorlw	d'25'		;'A'+'D'+'E' 1+8+16
	btfsc	STATUS,Z	;
	goto	FMoveUpRight	;Yes.

	movf	finalchord,W;	;UpRRight?
	xorlw	d'24'		;'D+E' 8+16	
	btfsc	STATUS,Z	;
	;goto	MoveUpRRight	;Yes.
	goto	FMoveUpRight	;Yes.

	movf	finalchord,W;	;Right?
	xorlw	d'16'		;	
	btfsc	STATUS,Z	;
	goto	MoveRight	;Yes.

	movf	finalchord,W;	;FRight?
	xorlw	d'56'		;D+E+F=56
	btfsc	STATUS,Z	;
	goto	FMoveRight	;Yes.

	movf	finalchord,W;	;DownRRight?
	xorlw	d'48'		;'F'+'E' 16+32	
	btfsc	STATUS,Z	;
	;goto	MoveDRRight	;Yes.
	goto	FMoveDRight	;Yes.

	movf	finalchord,W;	;DownRight?
	xorlw	d'32'		;'F'	
	btfsc	STATUS,Z	;
	goto	MoveDRight	;Yes.

	movf	finalchord,W;	;FDownRight?
	xorlw	d'52'		;E+F+C=16+32+4=52
	btfsc	STATUS,Z	;
	goto	FMoveDRight	;Yes.

	movf	finalchord,W;	;Down?
	xorlw	d'36'		;	
	btfsc	STATUS,Z	;
	goto	MoveDown	;Yes.

	movf	finalchord,W;	;FDown?
	xorlw	d'54'		;B+C+E+F=2+4+16+32=54
	btfsc	STATUS,Z	;
	goto	FMoveDown	;Yes.

	movf	finalchord,W;	;DownLeft?
	xorlw	d'4'		;'C'	
	btfsc	STATUS,Z	;
	goto	MoveDownLeft	;Yes.

	movf	finalchord,W;	;FDownLeft?
	xorlw	d'38'		;B+C+F=2+4+32=38
	btfsc	STATUS,Z	;
	goto	FMoveDownLeft	;Yes.

	movf	finalchord,W;	;DownLLeft?
	xorlw	d'6'		;'B'+'C' 2+4
	btfsc	STATUS,Z	;
	;goto	MoveDownLLeft	;Yes.
	goto	FMoveDownLeft	;Yes.

	movf	finalchord,W;	;Left?
	xorlw	d'2'		;	
	btfsc	STATUS,Z	;
	goto	MoveLeft	;Yes.

	movf	finalchord,W;	;FLeft?
	xorlw	d'7'		;A+B+C=1+2+4=7
	btfsc	STATUS,Z	;
	goto	FMoveLeft	;Yes.

	movf	finalchord,W;	;UpLLeft?
	xorlw	d'3'		;'A'+'B' 1+2
	btfsc	STATUS,Z	;
	;goto	MoveUpLLeft	;Yes
	goto	FMoveUpLeft	;Yes.

	movf	finalchord,W;	;UpLeft?
	xorlw	d'1'		;'A'	
	btfsc	STATUS,Z	;
	goto	MoveUpLeft	;Yes.

	movf	finalchord,W;	;FUpLeft?
	xorlw	d'11'		;A+B+D=1+2+8=11
	btfsc	STATUS,Z	;
	goto	FMoveUpLeft	;Yes.

				;Typematic on?
	btfsc	AutoRepeat	;For chords below this point NO AUTOREPEAT please!
	return	; goto	MainLoop

;--- alternatives 1 for left and right mouse buttons: ENTER and ESC ----
;yyyyy
	movf	finalchord,W;	;Left Button pressed&released?
	xorlw	d'59'		;ENTER = A+B+D+E+F=1+2+8+16+32=59
	btfsc	STATUS,Z	;A+C=5
	goto	PressLeftButton	;Yes.

	movf	finalchord,W;	;Right Button pressed&released?
	xorlw	d'31'		;D+E+F=56; ESC = 31
	btfsc	STATUS,Z	;D+F=8+32=40
	goto	PressRightButton	;Yes.

;--- alternatives 2 for left and right mouse buttons: A+C (U-uml) and D+F (W)----

	movf	finalchord,W;	;Left Button pressed&released?
	xorlw	d'5'		;
	btfsc	STATUS,Z	;A+C=5
	goto	PressLeftButton	;Yes.

	movf	finalchord,W;	;Right Button pressed&released?
	xorlw	d'40'		;
	btfsc	STATUS,Z	;D+F=8+32=40
	goto	PressRightButton	;Yes.

;--- alternative 3 for left mouse button: SHIFT ----

	movf	finalchord,W;	;Left Button pressed&released?
	xorlw	d'18'		;SHIFT = B+E=2+16=18
	btfsc	STATUS,Z	;A+C=5
	goto	PressLeftButton	;Yes.

;	movf	finalchord,W;	;Right Button pressed&released?
;	xorlw	d'40'		;D+E+F=56; ESC = 31
;	btfsc	STATUS,Z	;D+F=8+32=40
;	goto	PressRightButton	;Yes.

;--- Just press left button down for dragging etc.

	movf	finalchord,W;	;Left Button pressed down?
	xorlw	d'45'		;A+C+D+F = 1+4+8+32 = 45
	btfsc	STATUS,Z	; '?'
	goto	LeftButtonDown	;Yes.

;--- Release left (or any) any button

	movf	finalchord,W;	;Left (or any) Button released?
	xorlw	d'12'		;C+D = 12 
	btfsc	STATUS,Z	; '!'
	goto	ReleaseAnyButton	;Yes.


; ADD POSSIBLE OTHER MOUSE FUNCTIONS HERE...

	return	; goto	XMainLoop

;MouseExit

;	movlw	d'50'	;This dealay is required! Still!!!
;	call	DelayWx10ms	;Do not be too hasty....
;Else there will be possily keystrokes sent before Keyboard operation is enabled

;	bcf	KBDasMOUSE	  ;***Exit Mouse mode***
;	call	SendBATsuccessful ;Reset into Keyboard mode!!!
;	goto	MainLoop

MoveUp
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x05 ;YstepUp
	call	MByteOutE
	return	; goto	MainLoop
FMoveUp
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x0F ;YstepUp
	call	MByteOutE
	return	; goto	MainLoop


MoveUpRight
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x03
	call	MByteOut
	movlw	0x03 ;YstepUp
	call	MByteOutE
	return	; goto	MainLoop

FMoveUpRight
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x0a
	call	MByteOut
	movlw	0x0a ;YstepUp
	call	MByteOutE
	return	; goto	MainLoop


MoveUpRRight
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x04
	call	MByteOut
	movlw	0x02 ;YstepUp
	call	MByteOutE
	return	; goto	MainLoop

; Up/Right: 1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  
;Down/Left: F  E  D  C  B  A  9  8  7  6  5  4  3  2  1

MoveRight
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x05 ;XstepRight
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	return	; goto	MainLoop
FMoveRight
	;movlw	0x08 (no buttons pressed)
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x08
	call	MByteOutS
	movlw	0x0F ;XstepRight
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	return	; goto	MainLoop

MoveDRRight
	;movlw	0x28 	;bit7  bit6  bit5  bit4    bit3  bit2  bit1  bit0
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x28
	call	MByteOutS;Yovf  Xovf  Ysign Xsign   =1   middle right left Buttons
	movlw	0x04	;            2                          8
	call	MByteOut
	movlw	0xFE ;YstepDown
	call	MByteOutE
	return	; goto	MainLoop

MoveDRight ;0010 1000	; 0     0     1     0       1     0     0     0
	;movlw	0x28 	;bit7  bit6  bit5  bit4    bit3  bit2  bit1  bit0
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x28
	call	MByteOutS;Yovf  Xovf  Ysign Xsign   =1   middle right left Buttons
	movlw	0x03	;            2                          8
	call	MByteOut
	movlw	0xFD ;YstepDown
	call	MByteOutE
	return	; goto	MainLoop

FMoveDRight ;0010 1000	; 0     0     1     0       1     0     0     0
	;movlw	0x28 	;bit7  bit6  bit5  bit4    bit3  bit2  bit1  bit0
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x28
	call	MByteOutS;Yovf  Xovf  Ysign Xsign   =1   middle right left Buttons
	movlw	0x0a	;            2                          8
	call	MByteOut
	movlw	0xF6 ;YstepDown
	call	MByteOutE
	return	; goto	MainLoop

MoveDown
	;movlw	0x28	;0010 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x28
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0xFB ;YstepDown
	call	MByteOutE
	return	; goto	MainLoop
FMoveDown
	;movlw	0x28	;0010 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x28
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0xF0 ;YstepDown
	call	MByteOutE
	return	; goto	MainLoop

MoveDownLeft
	;movlw	0x38	;0011 1000 OK
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x38
	call	MByteOutS
	movlw	0xFD ;XstepLeft
	call	MByteOut
	movlw	0xFD
	call	MByteOutE
	return	; goto	MainLoop
FMoveDownLeft
	;movlw	0x38	;0011 1000 OK
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x38
	call	MByteOutS
	movlw	0xF6 ;XstepLeft
	call	MByteOut
	movlw	0xF6
	call	MByteOutE
	return	; goto	MainLoop

MoveDownLLeft
	;movlw	0x38	;0011 1000 OK
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x38
	call	MByteOutS
	movlw	0xFC ;XstepLeft
	call	MByteOut
	movlw	0xFE
	call	MByteOutE
	return	; goto	MainLoop

MoveLeft
	;movlw	0x18	;0001 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x18
	call	MByteOutS
	movlw	0xFB ;XstepLeft
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	return	; goto	MainLoop
FMoveLeft
	;movlw	0x18	;0001 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x18
	call	MByteOutS
	movlw	0xF0 ;XstepLeft
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	return	; goto	MainLoop

MoveUpLLeft
	;movlw	0x18	;0001 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x18
	call	MByteOutS
	movlw	0xFC ;XstepLeft
	call	MByteOut
	movlw	0x02
	call	MByteOutE
	return	; goto	MainLoop

MoveUpLeft
	;movlw	0x18	;0001 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x18
	call	MByteOutS
	movlw	0xFC ;XstepLeft
	call	MByteOut
	movlw	0x04
	call	MByteOutE
	return	; goto	MainLoop
FMoveUpLeft
	;movlw	0x18	;0001 1000
	movf	KMouseByte1,W	; Buttons pressed etc
	ADDLW	0x18
	call	MByteOutS
	movlw	0xF6 ;XstepLeft
	call	MByteOut
	movlw	0x0A
	call	MByteOutE
	return	; goto	MainLoop

PressLeftButton
	movlw	d'30'		; reduced from 50 to 30 for making double click possible
	call	DelayWx10ms	; Do not be too hasty to resend
	movlw	0x09		; Due to frequent key scanning
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	movlw	0x01
	movwf	KMouseByte1
;;ReleaseAnyButton
	movlw	0x08
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	clrf	KMouseByte1
	goto	XMainLoop	; Exit and clear chord buffer

LeftButtonDown
	movlw	d'30'		; reduced from 50 to 30
	call	DelayWx10ms	; Do not be too hasty to resend
	movlw	0x09		; Due to frequent key scanning
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	movlw	0x01
	movwf	KMouseByte1
	goto	XMainLoop	; Exit and clear chord buffer

PressMiddleButton
	movlw	d'50'
	call	DelayWx10ms	;Do not be too hasty to resend
	movlw	0x0c
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	movlw	0x04
	movwf	KMouseByte1
	goto	XMainLoop	; Exit and clear chord buffer

PressRightButton
	movlw	d'50'
	call	DelayWx10ms	;Do not be too hasty to resend

	movlw	0x0a
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	movlw	0x01
	movwf	KMouseByte1
;;ReleaseAnyButton
	movlw	0x08
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	clrf	KMouseByte1
	goto	XMainLoop	; Exit and clear chord buffer

ReleaseAnyButton
	movlw	d'50'
	call	DelayWx10ms	;Do not be too hasty to resend
	movlw	0x08
	call	MByteOutS
	movlw	0x00
	call	MByteOut
	movlw	0x00
	call	MByteOutE
	clrf	KMouseByte1
	goto	XMainLoop		; Exit and clear chord buffer

;********************************************************************************





;==============================================================================
;                   END OF KEYBOARD AS MOUSE
;==============================================================================


;-------------------------------------------------------------------------------


;                        (<= intelligent key scanning)
;___________________________end of Page1 0800h-07FFf__________________________________________
;Page0: main program
;Page1: intelligent key scanning
;Page2: Shortcut tables
;Page3: Tables
;PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP222222222222222222222222222222222222222222222


;___________________________ Page2 1000h-17FFh ____________________________________
;                             shortcut tables

	     org	0x1000	;Start of Program Memory Page2
;Page2_proc
;		return


	; CHORDON SHORTCUT TABLES ON THIS PAGE
	; Space for one table is 256 bytes: e.g. 1000 - 10FF

Table_SetSCFlags
		movwf	PCL
		retlw	0x81	; 31 .	1000 0001
		retlw	0x82	; 32 ,	1000 0010
		retlw	0x84	; 33 !	1000 0100
		retlw	0x88	; 34 ?	1000 1000
		retlw	0x90	; 35 -	1001 0000
		retlw	0xa0	; 36 '	1010 0000
		retlw	0x00	; 37
		retlw	0x00	; 38
		retlw	0x00	; 39
		retlw	0x00	; 40
		retlw	0x00	; 41
		retlw	0xc1	; 42 Up Arrow	1100 0001
		retlw	0xc2	; 43 Down Arrow 1100 0010
		retlw	0x00	; 44
		retlw	0x00	; 45
		retlw	0x00	; 46
		retlw	0x00	; 47
		retlw	0x00	; 48
		retlw	0x00	; 49
		retlw	0x00	; 50
		retlw	0x00	; 51
		retlw	0x00	; 51
		retlw	0x00	; 53
		retlw	0x00	; 54
		retlw	0x00	; 55
		retlw	0x00	; 56
		retlw	0x00	; 57
		retlw	0x00	; 58
		retlw	0xc4	; 59 SHIFT	1100 0100
		retlw	0x00	; 60
		retlw	0x00	; 61
		retlw	0x00	; 62
		retlw	0x00	; 63
		return	; not needed when this works ok (no n+1 error)


Table_SC_asterisk		; 'a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	d'5'	; i 'is'
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	d'1'	; p 'put'
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	d'8'	; t 'that'
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	d'13'	; y 'you'
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_asterisk		; a'
		movwf	PCL
		retlw	0x00	; a
		retlw	d'17'	; b 'but'
		retlw	0x00	; c
		retlw	d'21'	; d 'do'
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow



Table_SC_hyphen			; -a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	d'30'	; h 'he'
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	d'33'	; l 'like'
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	d'24'	; q 'quite'
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	d'38'	; ä 'they'
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_hyphen		; a-
		movwf	PCL
		retlw	d'43'	; a 'am'
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	d'46'	; e 'every'
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow
		; ...0x10CE

	     ;org	0x1100	;Start of Table TEST!!!!
Table_SC_period			; .a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	d'57'	; m	'much' .m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	d'62'	; r	'right' .r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	d'52'	; v	'very' .v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	d'68'	; y	'yes' .y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_period		; a.
		movwf	PCL
		retlw	0x00	; a
		retlw	d'72'	; b	'been'
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	d'77'	; f	'from'
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow



Table_SC_comma			; ,a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	d'7'	; j	'certain'
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	d'4'	; n	'no'
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	d'1'	; u	'up'
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	d'15'	; ä	'there' ,the_
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_comma			; a,
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	d'21'	; c	'come'
		retlw	0x00	; d
		retlw	d'89'	; e	'every'
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow


Table_SC_question		; ?a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	d'35'	; l	'long'
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	d'31'	; r	'are' 
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	d'40'	; x	'example'
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	d'48'	; ö	'off'
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_question		; a?
		movwf	PCL
		retlw	d'52'	; a	'all'
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	d'56'	; f	'first'
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow



Table_SC_exclamation		; !a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	d'66'	; j	'just'
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	d'0'	; r
		retlw	0x00	; s
		retlw	d'62'	; t	'too'
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	d'75'	; z	'we'
		retlw	0x00	; ü
		retlw	d'71'	; å	'any'
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_exclamation		; a!
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	d'78'	; c	'came'
		retlw	d'83'	; d 	'don't'
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow


Table_SC_uparrow		; <up>a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	d'8'	; h	'have'
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	d'1'	; p	'people'
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	d'13'	; x	'excuse'
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	d'20'	; å	'an'
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_uparrow		; a<Up>
		movwf	PCL
		retlw	d'23'	; a	'at'
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	d'26'	; d	'during'
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow


Table_SC_downarrow		; <Dn>a
		movwf	PCL
		retlw	0x00	; a 1
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	d'39'	; n	'not'
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	d'33'	; v	'visit'
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	d'49'	; z	'when'
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	d'43'	; ö	'often'
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_downarrow		; a<Dn>
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	d'54'	; c	'change'
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	d'61'	; f	'for'
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow


Table_SC_shift			; <shift>a
		movwf	PCL
		retlw	0x00	; a
		retlw	0x00	; b
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	0x00	; e
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	d'74'	; i	'I'
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	d'81'	; m	'me'
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	d'65'	; q 	'question'
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	d'78'	; u	'us'
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

Table2_SC_shift		; a<shift>
		movwf	PCL
		retlw	0x00	; a
		retlw	d'84'	; b	'be'
		retlw	0x00	; c
		retlw	0x00	; d 
		retlw	d'87'	; e	'even'
		retlw	0x00	; f
		retlw	0x00	; g
		retlw	0x00	; h
		retlw	0x00	; i
		retlw	0x00	; j
		retlw	0x00	; k
		retlw	0x00	; l
		retlw	0x00	; m
		retlw	0x00	; n
		retlw	0x00	; o
		retlw	0x00	; p
		retlw	0x00	; q 
		retlw	0x00	; r
		retlw	0x00	; s
		retlw	0x00	; t
		retlw	0x00	; u
		retlw	0x00	; v
		retlw	0x00	; w
		retlw	0x00	; x
		retlw	0x00	; y
		retlw	0x00	; z
		retlw	0x00	; ü
		retlw	0x00	; å
		retlw	0x00	; ä
		retlw	0x00	; ö
		retlw	0x00	; .
		retlw	0x00	; ,
		retlw	0x00	; !
		retlw	0x00	; ?
		retlw	0x00	; -
		retlw	0x00	; '
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	;
		retlw	0x00	; Up Arrow
		retlw	0x00	; Down Arrow

;----------------------------------------------------------------------------
;  << Room for additional program code and tables for chordon shortcut words
;----------------------------------------------------------------------------

;______________________end of Page2 1000h-17FFf____________________________________
;
;PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP3333333333333333333333333333333333333333333333
;_____________________ Page3 1800h-1FFFh (tables)__________________________________


;================ OTHER TABLES are on Page 3 (1800h-1FFFh) ========================
;
;
; These figures convert the chord value 1-63 to the GKOS character reference number 1-63
; (continues up to 105 in the table)
;
; The GKOS Character set is logically arranged (alphabetical and numerical order) 
;
; Three tables are used to convert the chord all the way to scan codes and IR codes:
; Table_ChordToRef => Table_GKOSrefToKeycode => Table_ScanCodeToIRCode
;
;
;===========================================================================;

; Page3:
; 0x1800	256
; 0x1900	256
; 0x1A00	256
; 0x1B00	256
; 0x1C00	256
; 0x1D00	256
; 0x1E00	256
; 0x1F00	256


	     org	0x1800	;Start of Program Memory Page 3
		; Table space: 1800-18FF

;the GKOS chord value is converted into GKOS ref.num. (GKOS specification) 
Table_ChordToRef		; Table is at 0x1800 to 0x18FF (256 items)
            movwf	 PCL
	    retlw        d'1' ;Convert Chord value to GKOS Reference number
	    retlw        d'2'
            retlw        d'15'
            retlw        d'3'
            retlw        d'27'
            retlw        d'19'
            retlw        d'46'
            retlw        d'4'
            retlw        d'42'
            retlw        d'36';  10
            retlw        d'16'
            retlw        d'33'
            retlw        d'28'
            retlw        d'20'
            retlw        d'47'
            retlw        d'5'
            retlw        d'35'
            retlw        d'59';SHIFT (chord=)18
            retlw        d'17'
            retlw        d'32'; 20
            retlw        d'29'
            retlw        d'21'
            retlw        d'48'
            retlw        d'7'
            retlw        d'8'
            retlw        d'9'
            retlw        d'44'
            retlw        d'10'
            retlw        d'41'
            retlw        d'38'; 30
            retlw        d'56'
            retlw        d'6'
            retlw        d'34'
            retlw        d'31'
            retlw        d'18'
            retlw        d'43'
            retlw        d'30'
            retlw        d'22'
            retlw        d'49'
            retlw        d'23'; 40
            retlw        d'24'
            retlw        d'25'
            retlw        d'58'
            retlw        d'26'
            retlw        d'60';SYMB  (chord=)45
            retlw        d'40'
            retlw        d'62';CTRL (chord=)47
            retlw        d'11'
            retlw        d'12'
            retlw        d'13';  50
            retlw        d'37'
            retlw        d'14'
            retlw        d'39'
            retlw        d'45'
            retlw        d'63';ALT (chord=)55
            retlw        d'50'
            retlw        d'51'
            retlw        d'52'
            retlw        d'54'
            retlw        d'53';  60
            retlw        d'55'
            retlw        d'57'
            retlw        d'61' ;123-abc  (chord=)63
            retlw        d'0'
            retlw        d'0'
;return with offset in register W indicating the GKOS ref.num of the chord

; ********** Here is room for tables (256 - 64 bytes free)

;Common TV commands to device TV-specific IR codes
;tv1tv1tv1
Table_TVcode_to_TV1code		; Table is at 0x1866... (256 - 64 items)
            movwf	 PCL
	    retlw        b'00010101'	; Power ON/OFF	/1
	    retlw        b'00010011'	; P + (programmed channels)
            retlw        b'00010000'	; P - (programmed channels)
            retlw        b'00111011'	; Volume +
            retlw        b'00111000'	; Volume -	/5
            retlw        b'00000000'	; Balance Right
            retlw        b'00000000'	; Balance Left
            retlw        b'01111001'	; Mute
            retlw        b'00000000'	; Bass +
            retlw        b'00000000'	; Bass -	/10
            retlw        b'00000000'	; Treble +
            retlw        b'00000000'	; Treble -
            retlw        b'00000000'	; Color +
            retlw        b'00000000'	; Color -
            retlw        b'00000000'	; Contrast +, Picture +	/15
            retlw        b'00000000'	; Contrast -, Picture -
            retlw        b'00000000'	; Brightness +
            retlw        b'00000000'	; Brightness -
            retlw        b'00000000'	; Hue +
            retlw        b'00000000'	; Hue -		/20
            retlw        b'00000000'	; Scan + (frequencies)
            retlw        b'00000000'	; Scan - (frequencies)
            retlw        b'00000000'	; Navi key Right
            retlw        b'00000000'	; Navi key Left
            retlw        b'00000000'	; Navi key Up	/25
            retlw        b'00000000'	; Navi key Down
            retlw        b'00000000'	; OK
            retlw        b'00000000'	; SELECT
            retlw        b'00000000'	; Enter
            retlw        b'00000000'	; PRG, Program	/30
            retlw        b'00000000'	; Normal (default settings)
            retlw        b'00010110'	; TV (return from Text TV)
            retlw        b'01010100'	; TTN, Text TV, videotext
            retlw        b'01010111'	; TTM, Text TV, videotext, mixed with TV
            retlw        b'00000000'	; Hold		/35
            retlw        b'00000000'	; Step +
            retlw        b'00000000'	; Step -
            retlw        b'00000000'	; Time (clock)
            retlw        b'00000000'	; Guide Menu
            retlw        b'00000000'	; Video Menu	/40
            retlw        b'00000000'	; Audio Menu
            retlw        b'00000000'	; Exit Menu
            retlw        b'00011100'	; P/C, Program<=>Channel
            retlw        b'00000000'	; STR, Store
            retlw        b'00000000'	; TP		/45
            retlw        b'00000000'	; SIZE
            retlw        b'00000000'	; Hold
            retlw        b'00000000'	; INV
            retlw        b'00000000'	; INFO
            retlw        b'00000000'	; 		/50

            retlw        b'00000010'	; 1		/51
            retlw        b'00000111'	; 2
            retlw        b'00000100'	; 3
            retlw        b'00001101'	; 4
            retlw        b'00001110'	; 5
            retlw        b'00001011'	; 6
            retlw        b'00001000'	; 7
            retlw        b'00011001'	; 8
            retlw        b'00011010'	; 9		/59
            retlw        b'00000001'	; 0		/60
            retlw        b'00011111'	; -- / >9	
            retlw        b'00000000'	; AUX
            retlw        b'00000000'	; SAT
            retlw        b'00000000'	; VCR		/64





; ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

		org	0x1900	; Space for a new table of 256 bytes:
		; Starts at Program Memory Page 3 + 2x256 bytes
		; Table space: 1900-19FF
;--------
;The table below converts the GKOS ref.num into Scan Code Pointer value
;In 123 mode, the GKOS character ref.num = GKOS ref.num + 64
;

Table_GKOSrefToKeycode
            movwf	 PCL
;---------------- abc mode ------------------------
            retlw        0x01 ;a /0	SYMB mode table is 128 steps down.
            retlw        0x02 ;b	Add 128 to GKOSref if using SYMB table.
            retlw        0x03 ;c
            retlw        0x04 ;d     Same goes for 123-mode but GKOSref values
            retlw        0x05 ;e	but add only 64 to GKOSref	
            retlw        0x06 ;f
            retlw        0x07 ;g	SHIFT can be only applied to GKOSref
            retlw        0x08 ;h	values 0-30 (a-ö)???
            retlw        0x09 ;i
            retlw        0x0a ;j /10
            retlw        0x0b ;k
            retlw        0x0c ;l
            retlw        0x0d ;m
            retlw        0x0e ;n
            retlw        0x0f ;o
            retlw        0x10 ;p
            retlw        0x11 ;q
            retlw        0x12 ;r
            retlw        0x13 ;s
            retlw        0x14 ;t /20
            retlw        0x15 ;u
            retlw        0x16 ;v
            retlw        0x17 ;w
            retlw        0x18 ;x
            retlw        0x19 ;y
            retlw        0x1a ;z
            retlw        0x1b ;u (umlaut)
            retlw        0x1c ;å <>
            retlw        0x1d ;ä
            retlw        0x1e ;ö /30

            retlw        0x1f  ; .
            retlw        0x20  ; ,
            retlw        0x21 ; !
            retlw        0x22 ; ?
            retlw        0x23  ; - 35
            retlw        0x24  ; '
            retlw        0x25 ; \ 
            retlw        0x26 ; /
            retlw        0x27  ; ¨ <>
            retlw        0x28 ; ~ /40 <>
            retlw        0x29 ; ^ <>
		;ALL MODES
            retlw        0x2a ;Arrow up -- NAVIGATING
            retlw        0x2b ;Arrow down
            retlw        0x2c ;PgUp
            retlw        0x2d ;PgDn
            retlw        0x2e ;Backspace
            retlw        0x2f ;Arrow left
            retlw        0x30 ;Word left
            retlw        0x31 ;Home
            retlw        0x32 ;Space /50 
            retlw        0x33 ;Arrow right
            retlw        0x34 ;Word right
            retlw        0x35 ;End
		;controls
            retlw        0x36 ;Enter
            retlw        0x37 ;Tab
            retlw        0x38 ;Esc 
            retlw        0x39 ;Del1
            retlw        0x3a ;Ins
            retlw        0x3b ;Shift (RIGHT)
            retlw        0x3c ;SYMB /60 (0xe8) GKOS only
            retlw        0x3d ;123-abc  (0xe9) GKOS only
            retlw        0x3e ;Ctrl (LEFT)
            retlw        0x3f ;Alt /64
         ;123 mode, add 64 to GKOS ref.num
;------------------ 123 mode -------------------------
            retlw        0x40 ;1 /65
            retlw        0x41 ;2
            retlw        0x42 ;3
            retlw        0x43 ;4
            retlw        0x44 ;5
            retlw        0x45 ;6 /70
            retlw        0x46 ;0
            retlw        0x47 ;7
            retlw        0x48 ;8
            retlw        0x49 ;9
            retlw        0x4a ; #
            retlw        0x4b ; ½ <>
            retlw        0x4c ; &
            retlw        0x4d ; @
            retlw        0x4e  ; +
            retlw        0x4f ; % /80
            retlw        0x50 ; =
            retlw        0x51  ; Y (yen) just 'y'
            retlw        0x52 ; *
            retlw        0x53 ; € <>
            retlw        0x54 ; $
            retlw        0x55 ; £ <>
            retlw        0x56 ; (
            retlw        0x57 ; [
            retlw        0x58  ; <
            retlw        0x59 ; { /90
            retlw        0x5a ; )
            retlw        0x5b ; ]
            retlw        0x5c ; >
            retlw        0x5d ; }
; 
			;Down from here the same as in abc mode...
            retlw        0x1f  ; .
            retlw        0x20  ; ,
            retlw        0x21 ; !
            retlw        0x22 ; ?
            retlw        0x23  ; - 35
            retlw        0x24  ; '
            retlw        0x25 ; \
            retlw        0x26 ; / <>
            retlw        0x27  ; ¨ <>
            retlw        0x28 ; ~ /40 <>
            retlw        0x29 ; ^ <>

			;ALL MODES
            retlw        0x2a ;Arrow up -- NAVIGATING
            retlw        0x2b ;Arrow down
            retlw        0x2c ;PgUp
            retlw        0x2d ;PgDn
            retlw        0x2e ;Backspace
            retlw        0x2f ;Arrow left
            retlw        0x30 ;Word left
            retlw        0x31 ;Home
            retlw        0x32 ;Space /50 
            retlw        0x33 ;Arrow right
            retlw        0x34 ;Word right
            retlw        0x35 ;End
		;controls
            retlw        0x36 ;Enter
            retlw        0x37 ;Tab
            retlw        0x38 ;Esc 
            retlw        0x39 ;Del1
            retlw        0x3a ;Ins
            retlw        0x3b ;Shift (RIGHT)
            retlw        0x3c ;SYMB /60 (0xe8) GKOS only
            retlw        0x3d ;123-abc  (0xe9) GKOS only
            retlw        0x3e ;Ctrl (LEFT)
            retlw        0x3f ;Alt /64

;--------------------- SYMB mode ----------------------------
            retlw        0x40 ;1 /65
            retlw        0x41 ;2
            retlw        0x42 ;3
            retlw        0x43 ;4
            retlw        0x44 ;5
            retlw        0x45 ;6 /70
            retlw        0x46 ;0
            retlw        0x47 ;7
            retlw        0x48 ;8
            retlw        0x49 ;9
            retlw        0x4a ; #
            retlw        0x4b ; ½ <>
            retlw        0x4c ; &
            retlw        0x4d ; @
            retlw        0x4e  ; +
            retlw        0x4f ; % /80
            retlw        0x50 ; =
            retlw        0x51  ; Y (yen) just 'y'
            retlw        0x52 ; *
            retlw        0x53 ; € <>
            retlw        0x54 ; $
            retlw        0x55 ; £ <>
            retlw        0x56 ; (
            retlw        0x57 ; [
            retlw        0x58  ; <
            retlw        0x59 ; { /90
            retlw        0x5a ; )
            retlw        0x5b ; ]
            retlw        0x5c ; >
            retlw        0x5d ; }
	 ;symbols only in SYMB mode (GKOSref 95-105):
            retlw        0x5e ; : /95
            retlw        0x5f ; ; 
            retlw        0x60 ;inverted ! <> /160
            retlw        0x61 ;inverted ? <>
            retlw        0x62 ; _
            retlw        0x63 ; " 
            retlw        0x64  ; ´ <> apostrophe instead
            retlw        0x65 ; `
            retlw        0x66 ; | 
            retlw        0x67  ; § <>
            retlw        0x68 ; ¤ <>
           ; retlw        0x69 ; inv.^ DOES NOT BELONG HERE BUT IS ON THE IR TABLE


			;ALL MODES
            retlw        0x2a ;Arrow up -- NAVIGATING
            retlw        0x2b ;Arrow down
            retlw        0x2c ;PgUp
            retlw        0x2d ;PgDn
            retlw        0x2e ;Backspace
            retlw        0x2f ;Arrow left
            retlw        0x30 ;Word left
            retlw        0x31 ;Home
            retlw        0x32 ;Space /50 
            retlw        0x33 ;Arrow right
            retlw        0x34 ;Word right
            retlw        0x35 ;End
		;controls
            retlw        0x36 ;Enter
            retlw        0x37 ;Tab
            retlw        0x38 ;Esc 
            retlw        0x39 ;Del1
            retlw        0x3a ;Ins
            retlw        0x3b ;Shift (RIGHT)
            retlw        0x3c ;SYMB /60 (0xe8) GKOS only
            retlw        0x3d ;123-abc  (0xe9) GKOS only
            retlw        0x3e ;Ctrl (LEFT)
            retlw        0x3f ;Alt /63

;------------------- end of SYMB mode -------------------
; ABOVE, THERE IS ROOM FOR AT LEAST 3 CONSECUTIVE TABLES:
;  3 X 64 = 192 (4 X 64 = 256)
; They are the complete abc, 123 and SYMB tables.
; All include the same control codes ENTER, CTRL, TAB, at 
; the end part of each table
;
; This table was LCD application specific (capitals)and used always when SHIFT
; is on and GKOSref = 1...30. For PDA, lower case is sent here too.
;---------------- abc mode ------------------------
            ;/181	SHIFT mode in on and GKOSref = 1...30
            ;Add 180 to GKOSref if using SYMB table.
            retlw        0x01 ;a /0	SYMB mode table is 128 steps down.
            retlw        0x02 ;b	Add 128 to GKOSref if using SYMB table.
            retlw        0x03 ;c
            retlw        0x04 ;d     Same goes for 123-mode but GKOSref values
            retlw        0x05 ;e	but add only 64 to GKOSref	
            retlw        0x06 ;f
            retlw        0x07 ;g	SHIFT can be only applied to GKOSref
            retlw        0x08 ;h	values 0-30 (a-ö)???
            retlw        0x09 ;i
            retlw        0x0a ;j /10
            retlw        0x0b ;k
            retlw        0x0c ;l
            retlw        0x0d ;m
            retlw        0x0e ;n
            retlw        0x0f ;o
            retlw        0x10 ;p
            retlw        0x11 ;q
            retlw        0x12 ;r
            retlw        0x13 ;s
            retlw        0x14 ;t /20
            retlw        0x15 ;u
            retlw        0x16 ;v
            retlw        0x17 ;w
            retlw        0x18 ;x
            retlw        0x19 ;y
            retlw        0x1a ;z
            retlw        0x1b ;u (umlaut)
            retlw        0x1c ;å <>
            retlw        0x1d ;ä
            retlw        0x1e ;ö /30
;------------ END OF SHIFT TABLE ------------


		org	0x1A00
		; Table space: 1A00-1AFF

;   SONY SIRCS codes for MD
;   Convert key scan code value to IRcode
;   In Control mode: add 128

Table_ScanCodeToIRCode		; 

; MD / Edit mode / Write name / 1-63
            movwf	 PCL	;EDIT MODE	/Scan code
; 20-bit SIRCS:
	    retlw        0x61   ;a		/1
	    retlw        0x62	;b		/2
	    retlw        0x63	;c
	    retlw        0x64	;d
	    retlw        0x65	;e
	    retlw        0x66	;f
	    retlw        0x67	;g
	    retlw        0x68	;h
	    retlw        0x69	;i
	    retlw        0x6a	;j		/10
	    retlw        0x6b	;k
	    retlw        0x6c	;l
	    retlw        0x6d	;m
	    retlw        0x6e	;n
	    retlw        0x6f	;o
	    retlw        0x70	;p
	    retlw        0x71	;q
	    retlw        0x72	;r
	    retlw        0x73	;s
	    retlw        0x74	;t		/20
	    retlw        0x75	;u
	    retlw        0x76	;v
	    retlw        0x77	;w
	    retlw        0x78	;x
	    retlw        0x79	;y
	    retlw        0x7a	;z		/26
	    retlw        0x75	;ü (u)
	    retlw        0x61	;å (a)
	    retlw        0x61	;ä (a)
	    retlw        0x6f	;ö (o)		/30
	    retlw        0x2e	;.
	    retlw        0x2c	;,
	    retlw        0x21	;!
	    retlw        0x3f	;?
	    retlw        0x2d	;-
	    retlw        0x27	;'
	    retlw        0x5c	;\ (just ASCII)
	    retlw        0x2f	;/
	    retlw        0x20	;¨ (space)
	    retlw        0x7e	;~ (just ASCII)	/40
	    retlw        0x5e	;^ (just ASCII)
;---- always 13-bit SIRCS:
	    retlw        0xff	;Arrow up
	    retlw        0x1d	;Arrow down	Continue to play
	    retlw        0x16	;Page up	Eject
	    retlw        0x15	;Page down	Power ON/OFF
	    retlw        0x2b	;Backspace	(STOP) Rewind (= cursor left)
	    retlw        0x2b	;Arrow left	(Skip-) Rewind (= cursor left)
	    retlw        0x2b	;Word left	(Skip-)
	    retlw        0x2b	;Home		Rewind
	    retlw        0x4c	;Space 		(Play) Space (= cursor right)
	    retlw        0x2c	;Arrow right	(Skip+)  Forward (= cursor right)
	    retlw        0x2c	;Word right	(Skip-)
	    retlw        0x2c	;End		Forward
	    retlw        0x3c	;Enter		(Enter) Write Name (= store name)
	    retlw        0x18	;Tab		Display/Char
	    retlw        0xff	;Esc		STOP (and return to command mode)
	    retlw        0x0f	;Delete		Clear
	    retlw        0xff	;Insert
	    retlw        0xff	;(Shift ON)
	    retlw        0xff	;(Header for IR link)
	    retlw        0xff	;(123-ABC)
	    retlw        0xff	;(Ctrl ON)
	    retlw        0xff	;(Alt ON)


; MD / Edit mode / Write num / 64-128
; 20-bit SIRCS:
	    retlw        0x31	;1		/64
	    retlw        0x32	;2
	    retlw        0x33	;3
	    retlw        0x34	;4
	    retlw        0x35	;5
	    retlw        0x36	;6
	    retlw        0x30	;0		/70
	    retlw        0x37	;7
	    retlw        0x38	;8
	    retlw        0x39	;9
	    retlw        0x0a	;(0x23 = #) -- / >25
	    retlw        0x20	;½ (Space) (0x1f = Program)
	    retlw        0x26	;&
	    retlw        0x0a	;@  -- / >25
	    retlw        0x2b	;+
	    retlw        0x25	;%
	    retlw        0x20	;=		/80
	    retlw        0x20	;yen
	    retlw        0x2a	;*
	    retlw        0x20	;€
	    retlw        0x24	;$
	    retlw        0x20	;£
	    retlw        0x28	;(
	    retlw        0x28	;[
	    retlw        0x3c	;<
	    retlw        0x29	;{
	    retlw        0x29	;)		/90
	    retlw        0x29	;]
	    retlw        0x3e	;>
	    retlw        0x29	;}
	    retlw        0x3a	;:
	    retlw        0x3b	;;
	    retlw        0x20	;inv.!
	    retlw        0x20	;inv.?
	    retlw        0x20	;_
	    retlw        0x22	;"
	    retlw        0x2a	;´(')		/100
	    retlw        0x2a	;`(')
	    retlw        0x20	;|
	    retlw        0x20	;§
	    retlw        0x20	;¤
	    retlw        0x20	;inv.^
; Always 13-bit SIRCS:
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/110
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/120
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/128

; MD / Control mode / 129-255

Table_ScanCodeToIRCode_S
            movwf	 PCL	;
; 13-bit SIRCS:
	    retlw        0xff	;A Vol+		/129	 ddd dddd
	    retlw        0x20	;B Skip-	/130	0010 0000
	    retlw        0xff	;C Vol-			0001 1001
	    retlw        0xff	;D Ch+
	    retlw        0x21	;E Skip+
	    retlw        0xff	;F Ch-
	    retlw        0xff	;G
	    retlw        0x1e	;H 	Shuffle
	    retlw        0xff	;I
	    retlw        0xff	;J
	    retlw        0x0a	;K	Num (>25)
	    retlw        0x19	;L 	Scroll	/140
	    retlw        0x1f	;M 	Program
	    retlw        0x0a	;N 	Num (>25)
	    retlw        0x29	;O 	Pause
	    retlw        0x29	;P 	Pause
	    retlw        0xff	;Q
	    retlw        0x2d	;R	RECORD
	    retlw        0x19	;S 	Scroll
	    retlw        0x3c	;T	Name (Title)
	    retlw        0xff	;U
	    retlw        0xff	;V		/150
	    retlw        0x2c	;W	Foreward
	    retlw        0xff	;X
	    retlw        0x18	;Y 	Display/Char
	    retlw        0xff	;Z
	    retlw        0x2b	;Ü	Rewind
	    retlw        0xff	;Å
	    retlw        0xff	;Ä
	    retlw        0xff	;Ö
	    retlw        0xff	;.
	    retlw        0xff	;,		/160
	    retlw        0xff	;!
	    retlw        0xff	;?
	    retlw        0xff	;-
	    retlw        0xff	;'
	    retlw        0xff	;\
	    retlw        0xff	;/
	    retlw        0xff	;¨
	    retlw        0xff	;~
	    retlw        0xff	;^
	    retlw        0xff	;Arrow up		/170
	    retlw        0x1d	;Arrow down	Continue to play
	    retlw        0x16	;Page up	Eject
	    retlw        0x15	;Page down	Power ON/OFF
	    retlw        0x28	;Backspace	STOP
	    retlw        0x20	;Arrow left	Skip-
	    retlw        0x20	;Word left	Skip-
	    retlw        0x2b	;Home		Rewind
	    retlw        0x2a	;Space 		Play
	    retlw        0x21	;Arrow right	Skip+
	    retlw        0x21	;Word right	Skip+	/180
	    retlw        0x2c	;End		Forward
	    retlw        0x3b	;Enter		Enter
	    retlw        0x18	;Tab		Display/Char
	    retlw        0x28	;Esc		STOP
	    retlw        0x0f	;Delete		Clear
	    retlw        0xff	;Insert

; next 5 not to be used for Remote control
	    retlw        0xff	;Shift OFF
	    retlw        0xff	;(Header + 128)
	    retlw        0xff	;123-ABC	(just change symbol set)
	    retlw        0xff	;Ctrl OFF	/190
	    retlw        0xff	;Alt OFF
; Remote control mode / numbers
	    retlw        0x00	;1 1...
	    retlw        0x01	;2
	    retlw        0x02	;3
	    retlw        0x03	;4
	    retlw        0x04	;5
	    retlw        0x05	;6
	    retlw        0x09	;0
	    retlw        0x06	;7
	    retlw        0x07	;8		/200
	    retlw        0x08	;9 ...9
	    retlw        0x0a	;#	--/>25 (--/>9)
	    retlw        0xff	;½
	    retlw        0xff	;&
	    retlw        0xff	;@
	    retlw        0xff	;+
	    retlw        0xff	;%
	    retlw        0xff	;=
	    retlw        0xff	;yen
	    retlw        0xff	;*		/210
	    retlw        0xff	;€
	    retlw        0xff	;$
	    retlw        0xff	;£
	    retlw        0xff	;(
	    retlw        0xff	;[
	    retlw        0xff	;<
	    retlw        0xff	;{
	    retlw        0xff	;)
	    retlw        0xff	;]
	    retlw        0xff	;>		/220
	    retlw        0xff	;}
	    retlw        0xff	;:
	    retlw        0xff	;;
	    retlw        0xff	;inv.!
	    retlw        0xff	;inv.?
	    retlw        0xff	;_
	    retlw        0xff	;"
	    retlw        0xff	;´
	    retlw        0xff	;`
	    retlw        0xff	;|		/230
	    retlw        0xff	;§
	    retlw        0xff	;¤
	    retlw        0xff	;inv.^
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;IR Device Address 6
	    retlw        0xff	;IR Device Address 7
	    retlw        0xff	;IR Device Address 0	/240
	    retlw        0xff	;IR Device Address 1
	    retlw        0xff	;IR Device Address 2
	    retlw        0xff	;IR Device Address 3
	    retlw        0xff	;IR Device Address 4
	    retlw        0xff	;IR Device Address 5
	    retlw        0xff	;AltGr OFF 
	    retlw        0xff	;CAPS OFF
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/250
	    retlw        0xff	;		/251
	    retlw        0xff	;		/252
	    retlw        0xff	;		/253
	    retlw        0xff	; Last item is removed because the table must be max 256 bytes long
;	    retlw        0xff	;		/255 (254 = SYMB!!!)
; 255 items + 2 x PCL = 257 => remove one line at the end to fit 256 bytes
; last item is number 254 (SYMB)

;----------------------------------------------

		org	0x1B00	; Space for a new table of 256 bytes:
		; Starts at Program Memory Page 3 + 3x256 bytes
		; Table space: 1B00-1BFF

; TV / Control mode / 129-255
;tktktktk
Table_Keycode_to_TVcode
            movwf	 PCL	;
	    retlw        0x04	;A Vol+		/129	 ddd dddd
	    retlw        0x24	;B Navi key L	/130	0010 0000
	    retlw        0x05	;C Vol-			0001 1001
	    retlw        0x02	;D P+
	    retlw        0x23	;E Navi key R
	    retlw        0x03	;F P-
	    retlw        0xff	;G
	    retlw        0xff	;H	(MD: shuffle)
	    retlw        0xff	;I
	    retlw        0xff	;J
	    retlw        0x0a	;K	Num (>25)
	    retlw        0x19	;L 	Scroll	/140
	    retlw        0x1f	;M 	Program
	    retlw        0x0a	;N 	Num (>25)
	    retlw        0x29	;O 	Pause
	    retlw        0x29	;P 	Pause
	    retlw        0xff	;Q
	    retlw        0x2d	;R	RECORD
	    retlw        0x19	;S 	Scroll
	    retlw        0x3c	;T	Name (Title)
	    retlw        0xff	;U
	    retlw        0xff	;V		/150
	    retlw        0x2c	;W	Foreward
	    retlw        0xff	;X
	    retlw        0x18	;Y 	Display/Char
	    retlw        0xff	;Z
	    retlw        0x2b	;Ü	Rewind
	    retlw        0xff	;Å
	    retlw        0xff	;Ä
	    retlw        0xff	;Ö
	    retlw        0xff	;.
	    retlw        0xff	;,		/160
	    retlw        0xff	;!
	    retlw        0xff	;?
	    retlw        0xff	;-
	    retlw        0xff	;'
	    retlw        0xff	;\
	    retlw        0xff	;/
	    retlw        0xff	;¨
	    retlw        0xff	;~
	    retlw        0xff	;^
	    retlw        0xff	;Arrow up		/170
	    retlw        0x1d	;Arrow down	Continue to play
	    retlw        0x16	;Page up	Eject
	    retlw        0x01	;Page down	Power ON/OFF
	    retlw        0x28	;Backspace	STOP
	    retlw        0x20	;Arrow left	Skip-
	    retlw        0x20	;Word left	Skip-
	    retlw        0x2b	;Home		Rewind
	    retlw        0x2a	;Space 		Play
	    retlw        0x21	;Arrow right	Skip+
	    retlw        0x21	;Word right	Skip+	/180
	    retlw        0x2c	;End		Forward
	    retlw        0x3b	;Enter		Enter
	    retlw        0x18	;Tab		Display/Char
	    retlw        0x28	;Esc		STOP
	    retlw        0x0f	;Delete		Clear
	    retlw        0xff	;Insert

; next 5 not to be used for Remote control
	    retlw        0xff	;Shift OFF
	    retlw        0xff	;(Header + 128)
	    retlw        0xff	;123-ABC	--/>25
	    retlw        0xff	;Ctrl OFF	/190
	    retlw        0xff	;Alt OFF
; Remote control mode / numbers
	    retlw        0x00	;1 1...
	    retlw        0x01	;2
	    retlw        0x02	;3
	    retlw        0x03	;4
	    retlw        0x04	;5
	    retlw        0x05	;6
	    retlw        0x09	;0
	    retlw        0x06	;7
	    retlw        0x07	;8		/200
	    retlw        0x08	;9 ...9
	    retlw        0x0a	;#	--/>25 (--/>9)
	    retlw        0xff	;½
	    retlw        0xff	;&
	    retlw        0xff	;@
	    retlw        0xff	;+
	    retlw        0xff	;%
	    retlw        0xff	;=
	    retlw        0xff	;yen
	    retlw        0xff	;*		/210
	    retlw        0xff	;€
	    retlw        0xff	;$
	    retlw        0xff	;£
	    retlw        0xff	;(
	    retlw        0xff	;[
	    retlw        0xff	;<
	    retlw        0xff	;{
	    retlw        0xff	;)
	    retlw        0xff	;]
	    retlw        0xff	;>		/220
	    retlw        0xff	;}
	    retlw        0xff	;:
	    retlw        0xff	;;
	    retlw        0xff	;inv.!
	    retlw        0xff	;inv.?
	    retlw        0xff	;_
	    retlw        0xff	;"
	    retlw        0xff	;´
	    retlw        0xff	;`
	    retlw        0xff	;|		/230
	    retlw        0xff	;§
	    retlw        0xff	;¤
	    retlw        0xff	;inv.^
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;IR Device Address 6
	    retlw        0xff	;IR Device Address 7
	    retlw        0xff	;IR Device Address 0	/240
	    retlw        0xff	;IR Device Address 1
	    retlw        0xff	;IR Device Address 2
	    retlw        0xff	;IR Device Address 3
	    retlw        0xff	;IR Device Address 4
	    retlw        0xff	;IR Device Address 5
	    retlw        0xff	;AltGr OFF 
	    retlw        0xff	;CAPS OFF
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/250
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;
	    retlw        0xff	;		/255

; last item is number 255



; Table for Chordon Shortcuts
		org	0x1c00	; Space for a table of 256 bytes: 1C00 - 1CFF
				; Chord values for shortcut words, ending with 0x00

TableA_shortcuts		; FOR ' - .
		movwf	PCL
		retlw	d'16'	;'p'	1 'put'	'p
		retlw	d'21'	;'u'
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'
		retlw	d'9'	;'i'	5 'is' 'i
		retlw	d'19'	;'s'
		retlw	d'0'	;'end'
		retlw	d'20'	;'t'	8 'that' 't
		retlw	d'8'	;'h'
		retlw	d'1'	;'a'
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'
		retlw	d'25'	;'y'	13 'you' 'y
		retlw	d'15'	;'o'
		retlw	d'21'	;'u'
		retlw	d'0'	;'end'
		retlw	d'2'	;'b'	17 'but' b'
		retlw	d'21'	;'u'
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'
		retlw	d'4'	;'d'	21 'do' d'
		retlw	d'15'	;'o'
		retlw	d'0'	;'end'
		retlw	d'17'	;'q'	24 'quite' -q
		retlw	d'21'	;'u'
		retlw	d'9'	;'i'
		retlw	d'20'	;'t'
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'
		retlw	d'8'	;'h'	30 'he' -h
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'
		retlw	d'12'	;'l'	33 'like' -l
		retlw	d'9'	;'i'
		retlw	d'11'	;'k'
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'	
		retlw	d'20'	;'t'	38 'they' -the_
		retlw	d'8'	;'h'
		retlw	d'5'	;'e'
		retlw	d'25'	;'y'
		retlw	d'0'	;'end'
		retlw	d'1'	;'a'	43 'am' a-
		retlw	d'13'	;'m'
		retlw	d'0'	;'end'
		retlw	d'5'	;'e'	46 'each' e-
		retlw	d'1'	;'a'
		retlw	d'3'	;'c'
		retlw	d'8'	;'h'
		retlw	d'0'	;'end'
		retlw	d'0'	;'end'
		retlw	d'22'	;'v'	52 'very' .v
		retlw	d'5'	;'e'
		retlw	d'18'	;'r'
		retlw	d'25'	;'y'
		retlw	d'0'	;'end'
		retlw	d'13'	;'m'	57 'much' .m	
		retlw	d'21'	;'u'
		retlw	d'3'	;'c'
		retlw	d'8'	;'h'
		retlw	d'0'	;'end'
		retlw	d'18'	;'r'	62 'right' .r
		retlw	d'9'	;'i'
		retlw	d'7'	;'g'
		retlw	d'8'	;'h'
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'
		retlw	d'25'	;'y'	68 'yes' .y
		retlw	d'5'	;'e'
		retlw	d'19'	;'s'
		retlw	d'0'	;'end'
		retlw	d'2'	;'b'	72 'been' b.
		retlw	d'5'	;'e'
		retlw	d'5'	;'e'
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'
		retlw	d'6'	;'f'	77 'from' f.
		retlw	d'18'	;'r'
		retlw	d'15'	;'o'

		retlw	d'13'	;'m'	80
		retlw	d'0'	;'end'
		retlw	d'0'	;''	82
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	90

		retlw	d'0'	;''	91
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	100

		retlw	d'0'	;''	101
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	110

		retlw	d'0'	;''	111
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	120

		retlw	d'0'	;''	121
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	126




		org	0x1d00	; Space for a table of 256 bytes: 1D00 - 1DFF
TableB_shortcuts		; FOR , ? !
		movwf	PCL
		retlw	d'21'	;'u'	1 'up' ,u	
		retlw	d'16'	;'p'
		retlw	d'0'	;'end'
		retlw	d'14'	;'n'	4 'no' ,n	
		retlw	d'15'	;'o'
		retlw	d'0'	;'end'
		retlw	d'3'	;'c'	7 'certain' ,j
		retlw	d'5'	;'e'	
		retlw	d'18'	;'r'
		retlw	d'20'	;'t'	10

		retlw	d'1'	;'a'	11
		retlw	d'9'	;'i'
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'	
		retlw	d'20'	;'t'	15 'there' ,the_
		retlw	d'8'	;'h'
		retlw	d'5'	;'e'
		retlw	d'18'	;'r'	
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'

		retlw	d'3'	;'c'	21 'come' c, 
		retlw	d'15'	;'o'
		retlw	d'13'	;'m'
		retlw	d'5'	;'e'	
		retlw	d'0'	;'end'
		retlw	d'0'	;''	26
		retlw	d'0'	;''
		retlw	d'0'	;''	
		retlw	d'0'	;''
		retlw	d'0'	;'end'

		retlw	d'1'	;'a'	31 'are' ?r
		retlw	d'18'	;'r'
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'	
		retlw	d'12'	;'l'	35 'long' ?l
		retlw	d'15'	;'o'
		retlw	d'14'	;'n'
		retlw	d'7'	;'g'	
		retlw	d'0'	;'end'
		retlw	d'5'	;'e'	40 'example' ?x

		retlw	d'24'	;'x'	41
		retlw	d'1'	;'a'
		retlw	d'13'	;'m'
		retlw	d'16'	;'p'
		retlw	d'12'	;'l'
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'	
		retlw	d'15'	;'o'	48 'off' ?of_	
		retlw	d'6'	;'f'
		retlw	d'6'	;'f'

		retlw	d'0'	;'end'
		retlw	d'1'	;'a'	52 'all' a?
		retlw	d'12'	;'l'
		retlw	d'12'	;'l'	
		retlw	d'0'	;'end'
		retlw	d'6'	;'f'	56 'first' f?
		retlw	d'9'	;'i'
		retlw	d'18'	;'r'	
		retlw	d'19'	;'s'
		retlw	d'20'	;'t'

		retlw	d'0'	;'end'	61
		retlw	d'20'	;'t'	62 'too' !t
		retlw	d'15'	;'o'
		retlw	d'15'	;'o'	
		retlw	d'0'	;'end'
		retlw	d'10'	;'j'	66 'just' !j
		retlw	d'21'	;'u'
		retlw	d'19'	;'s'	
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'

		retlw	d'1'	;'a'	71 'any' !and_
		retlw	d'14'	;'n'
		retlw	d'25'	;'y'
		retlw	d'0'	;'end'	
		retlw	d'23'	;'w'	75 'we' !z
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'
		retlw	d'3'	;'c'	78 'came' c!	
		retlw	d'1'	;'a'
		retlw	d'13'	;'m'

		retlw	d'5'	;'e'	81
		retlw	d'0'	;'end'
		retlw	d'4'	;'d'	83 'don't' d!
		retlw	d'15'	;'o'
		retlw	d'14'	;'n'
		retlw	d'36'	;'''
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'
		retlw	d'5'	;'e'	89 'every'
		retlw	d'22'	;'v'
		retlw	d'5'	;'e'	90

		retlw	d'18'	;'r'	91
		retlw	d'25'	;'y'
		retlw	d'0'	;'end'
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	100

		retlw	d'0'	;''	101
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	110

		retlw	d'0'	;''	111
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	120

		retlw	d'0'	;''	121
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	126


		org	0x1e00	; Space for a table of 256 bytes: 1E00 - 1EFF
TableC_shortcuts		; FOR Up Dn Shift
		movwf	PCL
		retlw	d'16'	;'p'	1 'people' Up	
		retlw	d'5'	;'e'
		retlw	d'15'	;'o'
		retlw	d'16'	;'p'	
		retlw	d'12'	;'l'
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'
		retlw	d'8'	;'h'	8 'have' Uh	
		retlw	d'1'	;'a'
		retlw	d'22'	;'v'	10

		retlw	d'5'	;'e'	11
		retlw	d'0'	;'end'
		retlw	d'5'	;'e'	13 'excuse' Ux
		retlw	d'24'	;'x'	
		retlw	d'3'	;'c'
		retlw	d'21'	;'u'
		retlw	d'19'	;'s'
		retlw	d'5'	;'e'	
		retlw	d'0'	;'end'
		retlw	d'1'	;'a'	20 'an' Uand_

		retlw	d'14'	;'n'	21
		retlw	d'0'	;'end'
		retlw	d'1'	;'a'	23 'at' aU
		retlw	d'20'	;'t'	
		retlw	d'0'	;'end'
		retlw	d'4'	;'d'	26 'during' Du
		retlw	d'21'	;'u'
		retlw	d'18'	;'r'	
		retlw	d'9'	;'i'
		retlw	d'14'	;'n'

		retlw	d'7'	;'g'	31
		retlw	d'0'	;'end'
		retlw	d'22'	;'v'	33 'visit' Dv
		retlw	d'9'	;'i'	
		retlw	d'19'	;'s'
		retlw	d'9'	;'i'
		retlw	d'20'	;'t'
		retlw	d'0'	;'end'	
		retlw	d'14'	;'n'	39 'not' Dn
		retlw	d'15'	;'o'

		retlw	d'20'	;'t'	41
		retlw	d'0'	;'end'
		retlw	d'15'	;'o'	43 'often' Dof_
		retlw	d'6'	;'f'	
		retlw	d'20'	;'t'
		retlw	d'5'	;'e'
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'	
		retlw	d'23'	;'w'	49 'when' Dz
		retlw	d'8'	;'h'

		retlw	d'5'	;'e'	51
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'
		retlw	d'3'	;'c'	54 'change' cD
		retlw	d'8'	;'h'
		retlw	d'1'	;'a'
		retlw	d'14'	;'n'
		retlw	d'7'	;'g'	
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'

		retlw	d'6'	;'f'	61 'for' fD
		retlw	d'15'	;'o'
		retlw	d'18'	;'r'
		retlw	d'0'	;'end'	
		retlw	d'17'	;'q'	65 'question' fD
		retlw	d'21'	;'u'
		retlw	d'5'	;'e'
		retlw	d'19'	;'s'	
		retlw	d'20'	;'t'
		retlw	d'9'	;'i'

		retlw	d'15'	;'o'	71
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'
		retlw	d'59'	;'ShiftON' 74 'I' Si
		retlw	d'9'	;'i'
		retlw	d'0'	;'ShiftOFF' (186?)
		retlw	d'0'	;'end'
		retlw	d'21'	;'u'	78 'us'	Su
		retlw	d'19'	;'s'
		retlw	d'0'	;'end'

		retlw	d'13'	;'m'	81 'me' Sm
		retlw	d'5'	;'e'
		retlw	d'0'	;'end'
		retlw	d'2'	;'b'	84 'be' bS
		retlw	d'5'	;'e'
		retlw	d'0'	;'and'
		retlw	d'5'	;'e'	87 'even' eS
		retlw	d'22'	;'v'
		retlw	d'5'	;'e'
		retlw	d'14'	;'n'
		retlw	d'0'	;'end'	90

		retlw	d'0'	;''	91
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	100

		retlw	d'0'	;''	101
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	110

		retlw	d'0'	;''	111
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	120

		retlw	d'0'	;''	121
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''
		retlw	d'0'	;''	126



	; Serial port Message example:

;	movwf	PCL
;	retlw	'o'	;ASCII 'o'
;	retlw	'k'	;ASCII 'k'
;	retlw	'!'	;ASCII '!'
;	retlw	d'0'	;decimal zero


; ========== START OF MEMORY PAGE 3 KEYBOARD TABLE====================
;
;
;	    org		 0x1A00	; later in program Memory Page 3, after FIN/SWE table

	END                     ; directive 'end of program'

