; PIC16F690 Configuration Bit Settings

; Assembly source line config statements

#include "p16F690.inc"

	__CONFIG _FOSC_INTRCIO & _MCLRE_OFF &_WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _CPD_OFF & _CP_OFF & _IESO_OFF & _FCMEN_OFF
    
    errorlevel    -302    


;******************************************************************
;****************** P R O M E N N E *******************************
;******************************************************************
    
    cblock 0x20
	d1			;registry pro cekaci subrutiny
	d2
	d3
	hiByte
	loByte
	i2c_i
	i2c_tmp	
	tmp
	numSecs
	numMilis
	char
	i				;writeByte	
	j				;LCD_draw_*
	tens			;desitky - bin2ascii
	ones			;jednotky - bin2ascii
	;number			;vypisovana cislice
	textPointer:2	;Ukazatel do textu
	fontPointer:2	;Ukazatel do dat fontu
	X
	X_copy
	Y
	Y_copy
	
	putCharOnly		;T/F
	cislo
	
	JOY_ADresultH
	JOY_ADresultL	
	JOY_increment	;255=-1
	JOY_tmp			;8 -> 0, -1 -> 7
	JOY_whichAdjust ;0-BOARD_x, 1-BOARD_y
	
	GAME_playerTurn ;0-X(player), 1-O(CPU)
	
	BOARD_x			;pozice [x,y] na boardu [0,0]-[7,7]
	BOARD_y
	BOARD_x_old		;Predchozi pozice
	BOARD_y_old		
	BOARD_x_tmp
	BOARD_y_tmp
	BOARD_i
	BOARD_j
	BOARD_piece		;1-X, 2-O, kamen na pozici
	BOARD_direction	;Pohyb do smeru 0-2
	BOARD_tmp
	BOARD_threat	;Misto, kde musim zabranit rade
	BOARD_empty_left

	XX:.4
	BOARD:.9		;1-empty, 2-X, 4-O
    endc

;******************************************************************
;****************** K O N S T A N T Y *****************************
;******************************************************************

FALSE				equ 0x00
TRUE				equ 0x01

;LCD NOKIA 5110
SCREEN_WIDTH		equ .84
SCREEN_HEIGHT		equ .48
LCD_BYTES			equ .504 ;(84 x 6 = 84 x 48px)
LCD_CHAR_WIDTH		equ .6

;HRACI PLOCHA
BOARD_SIZE			equ .3		;3x3 plocha
BOARD_PLACES		equ BOARD_SIZE * BOARD_SIZE
SIGN_SIZE_X			equ .12 	;px
SIGN_SIZE_Y			equ .1 		;1*8px	

SIGN_X				equ 'X'
SIGN_O				equ 'O'
SIGN_EMPTY			equ ' '
SIGN_MOVE			equ '*'

;AD limity
AD_LIMIT_LOWER_H	equ HIGH 	.342
AD_LIMIT_LOWER_L	equ LOW		.342
AD_LIMIT_UPPER_H	equ HIGH 	.682
AD_LIMIT_UPPER_L	equ LOW		.682

BOARD_LEFT_X		equ (SCREEN_WIDTH - (.5 * LCD_CHAR_WIDTH)) / .2

;Hraci
PLAYER_X			equ 0x00
PLAYER_O_CPU		equ 0x01

;Deska
BOARD_EMPTY			equ 0x01
BOARD_SIGN_X		equ 0x02
BOARD_SIGN_O		equ 0x04

;Soucet (5), ktery znamena, ze v danem sloupci/radku/diagonale existuje
;moznost, ze souper (X), kdyz obsadi volne misto, zvitezi. 
;Tento soucet muze nastat jen v techto kombinacich:
; X[]X, XX[], []XX - vzdy je soucet stejny (5) 
BOARD_X_THREAT		equ BOARD_SIGN_X + BOARD_SIGN_X + BOARD_EMPTY

;Soucet pro hledani vyherniho tahu
BOARD_O_CHANCE		equ BOARD_SIGN_O + BOARD_SIGN_O + BOARD_EMPTY

;Joystick
JOY_X_ADC			equ b'10000001' ;ADC Frc clock, right justify, AN0, ADC ON
JOY_Y_ADC			equ b'10000101' ;ADC Frc clock, right justify, AN1, ADC ON

;******************************************************************
;****************** D E F I N I C E *******************************
;******************************************************************
   
;Nokia 5110 LCD display SPI
#define LCD_RESET	PORTB, RB7
#define LCD_SCLK	PORTB, RB4
#define LCD_SDIN	PORTB, RB5
#define LCD_DC		PORTB, RB6

;Joystick vstupy
#define JOY_VRX		PORTA, RA0
#define JOY_VRY		PORTA, RA1
#define JOY_SW		PORTA, RA5

#define LED			PORTC, RC7

;******************************************************************
;****************** M A K R A *************************************
;******************************************************************
 
BANK0 macro
    bcf STATUS, RP0 ;Select memory bank 0
    bcf STATUS, RP1 
    endm
    
BANK1 macro
    bsf STATUS, RP0 ;Select memory bank 1
    bcf STATUS, RP1 
    endm   
    
BANK2 macro
    bcf STATUS, RP0 ;Select memory bank 2
    bsf STATUS, RP1 
    endm   
    
BANK3 macro
    bsf STATUS, RP0 ;Select memory bank 3
    bsf STATUS, RP1 
    endm
    
   
;******************************************************************    
;*************************** S T A R T ****************************
;******************************************************************
    
	org 0x00
    goto main
	
; ******************************************************************
; ************************** M A I N *******************************
; ******************************************************************

main

	clrwdt
	nop
	
	BANK1
	movlw b'01100100'	;4MHz internal
	movwf OSCCON
	movlw b'11001000'
	movwf OPTION_REG

	;*** PORTA NASTAVENI - joystick ***
	BANK1
	movlw b'00100011'; RA0,RA1-Joystick, RA5-Joystick switch
	movwf TRISA 

	BANK0 	
	clrf PORTA
	
	banksel ADCON1
	movlw b'01110000' ; ADC Frc clock
	movwf ADCON1	
		
	BANK2
	movlw b'00000011'; AN0-RA0, AN1-RA1 - Joystick - analog
	movwf ANSEL
	clrf ANSELH
	clrf CM1CON0
	clrf CM2CON0
	
	;*** PORTB NASTAVENI - Nokia LCD 5110 ***	
	BANK1
	clrf TRISB
	BANK0
	clrf PORTB   
	clrf CCP1CON 		; Turn CCP module off
	
	;*** PORTC NASTAVENI ***
	
	BANK1
	clrf TRISC		
	BANK0
	clrf PORTC
	

	;Inicializace Timer0
	clrf INTCON
			
;*******************************************************************
;******************* M A I N   L O O P *****************************
;*******************************************************************

	movlw .100
	call waitMilis
	
	call LCD_init	

GAME_START

	call GAME_INIT
	
	;DEBUG
	;movlw BOARD_SIGN_O
	;movwf BOARD+8
	;movwf BOARD+0
	;movwf BOARD+3
	
	call LCD_clear
	
	;Uvodni obrazovka
	call LCD_write_t1
	call LCD_write_t2
	call LCD_write_t3
	call LCD_write_t4
	call LCD_write_t5
	
	call JOY_waitButton
		
	call LCD_clear
	
	call LCD_showBoard
	
;	call LCD_showPosition
	
	call LCD_write_hrajes
	
GAME_LOOP

	movf BOARD_empty_left, f
	btfsc STATUS, Z
	goto GAME_DRAW

	btfsc GAME_playerTurn, 0 ;Hraje CPU?
	goto GAME_computersTurn  ;ANO
	
GAME_playersTurn

	call BOARD_savePosition	;uschovej x,y -> x_old, y_old a piece type
	
	movlw SIGN_MOVE
	call LCD_placeSign
	
	call JOY_getReadings
	
	call JOY_wasMove
	btfsc STATUS, Z			;Z-nebyl pohyb
	goto GAME_checkButton	;Zadny pohyb od posledni kontroly
	
;	call LCD_showPosition
	
	call BOARD_saveXY
	
	call BOARD_restorePosition ;x_old, y_old -> x, y
	
	call LCD_pieceValueToChar ;Preved hodnotu na boardu na znak
	call LCD_placeSign
	
	call BOARD_restoreXY	 ;x_tmp, y_tmp -> x, y
	
	movlw SIGN_MOVE			;Zobraz "kurzor" na nove pozici
	call LCD_placeSign
	
GAME_checkButton

	call JOY_getSwitchReading ;Z-byl stisk
	btfss STATUS, Z			;ZERO set - byl stisk u aktualniho hrace
	goto GAME_NEXT
	
	call BOARD_isPlaceEmpty
	btfss STATUS, Z
	goto GAME_NEXT
		
	call BOARD_setValue
	
	movlw SIGN_X
	call LCD_placeSign
	
	call BOARD_winnerCheckX	;Umistil hrac vitezne?
	btfsc STATUS, Z
	goto GAME_X_wins
				
	call GAME_switchPlayers				
	
	goto GAME_NEXT
			
GAME_computersTurn

	btfsc TMR0, 0				;Nekdy zapomen vyhrat :-)
	goto GAME_computersTurnNext
	
	movlw BOARD_O_CHANCE		;Hledej sance (O) na vyherni tah
	call BOARD_isThreat			;Mame sanci vyhrat?
	btfsc STATUS, Z
	goto GAME_chanceToWin		;Ano, poloz na nalezene misto

GAME_computersTurnNext
		
	movlw BOARD_X_THREAT		;Hledej hrozby protihrace na vyherni tah
	call BOARD_isThreat			;Mame hrozbu? 
	btfss STATUS, Z
	call BOARD_findFirstEmpty	;Neni hrozba, umisti libovolne
GAME_chanceToWin	
	call BOARD_setArrayValue	;Je hrozba, zabran
	
	movf BOARD_tmp, w			;v BOARD_tmp je bud hrozba nebo libovolne
	call BOARD_setXY			;0-8 -> BOARD_x, BOARD_y
	
	movlw SIGN_O
	call LCD_placeSign
	
	call BOARD_winnerCheckO
	btfsc STATUS, Z
	goto GAME_O_wins
	
	call GAME_switchPlayers
	
	movf BOARD_empty_left, f	;Pokud je kam, nastav kurzor do volne pozice
	btfsc STATUS, Z
	goto GAME_NEXT
	call BOARD_findEmpty
	movf BOARD_tmp, w			;v BOARD_tmp je prvni volne misto 0-8
	call BOARD_setXY			;0-8 -> BOARD_x, BOARD_y		
					
GAME_NEXT

	movlw .140
	call waitMilis
	
	goto GAME_LOOP	
	
GAME_DRAW
	
	call LCD_write_remiza
	goto GAME_OVER	

GAME_X_wins
	call LCD_write_vyhra
	call wait1s
	call wait1s	
	call LCD_clear	
	call LCD_write_kod
	call LCD_showCode
	call wait1s				;Zobraz kod jen na 2secs
	call wait1s
	goto GAME_START

GAME_O_wins	

	call LCD_write_prohra

GAME_OVER
	
	call JOY_waitButton
	
	goto GAME_START
	
;*******************************************************************
;******************* I N I T   G A M E *****************************
;*******************************************************************

GAME_INIT

	clrf BOARD_x
	clrf BOARD_y
	
	movlw PLAYER_X
	movwf GAME_playerTurn
	
	call BOARD_init
	
	movlw BOARD_PLACES
	movwf BOARD_empty_left
	
	return	

;Prepni mezi hraci
GAME_switchPlayers
;{
	decf BOARD_empty_left, f		;Po umisteni znaku
	
	movf GAME_playerTurn, w
	xorlw 0x01
	movwf GAME_playerTurn
	
	btfss GAME_playerTurn, 0		;0-player (X), 1-CPU (O)
	goto GAME_setPlayerX
	call LCD_write_hrajeO
	return
	
GAME_setPlayerX		
	call LCD_write_hrajes
	return
;}

;Uloz aktualni pozici X,Y kurzoru a aktualni typ zobrazovani
BOARD_savePosition
;{
	movf BOARD_x, w
	movwf BOARD_x_old
	movf BOARD_y, w
	movwf BOARD_y_old
	call BOARD_getValue
	movwf BOARD_piece
	return
;}

;Obnov aktualni pozici X,Y kurzoru a aktualni typ zobrazovani
BOARD_restorePosition
;{
	movf BOARD_x_old, w
	movwf BOARD_x
	movf BOARD_y_old, w
	movwf BOARD_y
	movlw BOARD_piece
	call BOARD_restoreValue
	return
;}



;*******************************************************************
;*************** B O A R D    R U T I N Y **************************
;*******************************************************************

BOARD_init
;{
	movlw BOARD
	movwf FSR
	movlw BOARD_PLACES
	movwf i
	movlw BOARD_EMPTY
BOARD_initL
	movwf INDF
	incf FSR, f
	decfsz i, f
	goto BOARD_initL
	
	return
;}

BOARD_setAndGetAddress
;{
	movf BOARD_y, w
	movwf BOARD_tmp
	bcf STATUS, C		;Vynasob 3
	rlf BOARD_tmp, f    ;x 2
	movf BOARD_y, w
	addwf BOARD_tmp, f
	movf BOARD_x, w
	addwf BOARD_tmp, f	
	movlw BOARD
	movwf FSR
	movf BOARD_tmp, w
	addwf FSR, f
	return
;}

;Vystup: Z- pokud je misto na [BOARD_x, BOARD_y] prazdne
BOARD_isPlaceEmpty
;{
	call BOARD_getValue
	xorlw BOARD_EMPTY
	return
;}

;Vraci hodnotu BOARD[BOARD_tmp]
;Vstup: BOARD_x, BOARD_y
;Vystup: WREG hodnota v poli
BOARD_getValue
;{
	call BOARD_setAndGetAddress
	movf INDF, w
	movwf BOARD_tmp			;kopii sem
	return
;}



;Nastav hodnotu na BOARD_x, BOARD_y
;Vstup: BOARD_x, BOARD_y, W-REG s hodnotou
BOARD_restoreValue
;{
	call BOARD_setAndGetAddress
	movf BOARD_piece, w
	movwf INDF
	return	
;}


;Uloz kamen na pozici x,y - podle toho, kdo hraje
;Vstup: BOARD_x, BOARD_y
BOARD_setValue
;{
	call BOARD_setAndGetAddress

BOARD_set	
	movlw BOARD_SIGN_O
	btfss GAME_playerTurn, 0	;1-X, 2-O
	movlw BOARD_SIGN_X	
	movwf INDF
	return
;}

;Vstup W-reg - 0-8
;Uloz kamen na BOARD[W-reg]
BOARD_setArrayValue
;{
	movwf tmp
	movlw BOARD
	movwf FSR
	movf tmp, w
	addwf FSR, f
	goto BOARD_set
	
;}


;Nastavi BOARD_x a BOARD_y podle array pozice 0-8
;Vstup: W-REG : 0-8
BOARD_setXY
;{
	call BOARD_getXY
	movwf tmp
	andlw b'00000011'
	movwf BOARD_y
	rrf tmp, f
	rrf tmp, w
	andlw b'00000011'
	movwf BOARD_x
	return
;}

;Vstup W-reg[3:2] = BOARD_x, W-reg[1:0] = BOARD_y
BOARD_getXY
;{
	addwf PCL, f
;}

Div3table
;{
	retlw b'00000000'	; [0,0]
	retlw b'00000100'   ; [1,0]
	retlw b'00001000'   ; [2,0]
	retlw b'00000001'	; [0,1]
	retlw b'00000101'   ; [1,1]
	retlw b'00001001'   ; [2,1]
	retlw b'00000010'	; [0,2]
	retlw b'00000110'   ; [1,2]
	retlw b'00001010'   ; [2,2]		
;}
	
BOARD_winnerCheckX
;{
	movlw BOARD_SIGN_X
	movwf BOARD_tmp
	
	goto BOARD_winnerCheckCommon
	
;}

BOARD_winnerCheckO
;{
	movlw BOARD_SIGN_O
	movwf BOARD_tmp
	
	goto BOARD_winnerCheckCommon
;}


;Projdu vsechny radky sloupce a 2 diagonaly.
;Sectu hodnoty v kazdem tomto radku a sloupci a zORuju je,
;pokud je vysledny soucet != hodnota pole, pak tam nejsou 3
;stejne symboly. Tzn. napr. X O X = 2 OR 4 or 2 != 2,
;nebo O <empty> O = 4 OR 1 OR 4 != 4. 
;Vstup: BOARD_tmp - symbol X/O ke kontrole, jestli je nekde
;vitezna serie 3 stejnych symbolu.
;Vystup - STATUS - ZERO - ano
;Vystup - STATUS - NONZERO - ne
BOARD_winnerCheckCommon
;{
	;0,1,2 - radek1
	clrf tmp
	movf BOARD+0, w
	iorwf tmp, f
	movf BOARD+1, w
	iorwf tmp, f
	movf BOARD+2, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return
	
	;3,4,5 - radek2
	clrf tmp
	movf BOARD+3, w
	iorwf tmp, f
	movf BOARD+4, w
	iorwf tmp, f
	movf BOARD+5, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return	
	
	;6,7,8 - radek3
	clrf tmp
	movf BOARD+6, w
	iorwf tmp, f
	movf BOARD+7, w
	iorwf tmp, f
	movf BOARD+8, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return
	
	;0,3,6 - sloupec1
	clrf tmp
	movf BOARD+0, w
	iorwf tmp, f
	movf BOARD+3, w
	iorwf tmp, f
	movf BOARD+6, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return	
	
	;1,4,7 - sloupec2
	clrf tmp
	movf BOARD+1, w
	iorwf tmp, f
	movf BOARD+4, w
	iorwf tmp, f
	movf BOARD+7, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return
	
	;2,5,8 - sloupec3
	clrf tmp
	movf BOARD+2, w
	iorwf tmp, f
	movf BOARD+5, w
	iorwf tmp, f
	movf BOARD+8, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return	
	
	;0,4,8 - diagonala1
	clrf tmp
	movf BOARD+0, w
	iorwf tmp, f
	movf BOARD+4, w
	iorwf tmp, f
	movf BOARD+8, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return	
	
	;2,4,6 - diagonala2
	clrf tmp
	movf BOARD+2, w
	iorwf tmp, f
	movf BOARD+4, w
	iorwf tmp, f
	movf BOARD+6, w
	iorwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	return	
		
	bcf STATUS, Z
	return
			
;}


;Vystup - ZERO flag a cislo pozice 0-8 ve W-REG, kde je hrozba soupere (X)
;	    - nebo totez, ale jako sance provest vyherni tah pro (O)
;Vystup - BOARD_tmp kopie W-reg
;Vystup - Non-ZERO - neni hrozba / sance na vyhru
;Vstup: W-reg BOARD_X_THREAT nebo BOARD_O_CHANCE
BOARD_isThreat
;{
	call BOARD_isThreatFindSequence
	btfss STATUS, Z
	return			;neni hrozba

	;Ziskej cislo pozice hrozby a vrat ZERO	
	call BOARD_findEmptyInSequence
	movwf BOARD_tmp		;kopie do BOARD_tmp
	bsf STATUS, Z
	return
;}


;Vstup: Cislo sekvence k prohledani.
;Vystup - W-reg pozice, kde je v sekvenci prazdne misto,
;kde musim zabranit trojici
BOARD_findEmptyInSequence
;{

BOARD_isThreat0
	;Najdi prazdne misto v sekvenci, to je misto, kam je potreba dat kamen
	movwf tmp
	movf tmp, f
	btfss STATUS, Z
	goto BOARD_isThreat1
	
						;0.bit == 1 == prazdne misto
	btfsc BOARD+0, 0	;Vrat ZERO a cislo pozice, ktera je prazdna
	retlw .0
	btfsc BOARD+1, 0
	retlw .1
	btfsc BOARD+2, 0
	retlw .2
	
BOARD_isThreat1
	decfsz tmp, f
	goto BOARD_isThreat2
	
	btfsc BOARD+3, 0
	retlw .3
	btfsc BOARD+4, 0
	retlw .4
	btfsc BOARD+5, 0
	retlw .5	
	
BOARD_isThreat2
	decfsz tmp, f
	goto BOARD_isThreat3
	
	btfsc BOARD+6, 0
	retlw .6
	btfsc BOARD+7, 0
	retlw .7
	btfsc BOARD+8, 0
	retlw .8	
	
BOARD_isThreat3
	decfsz tmp, f
	goto BOARD_isThreat4
	
	btfsc BOARD+0, 0
	retlw .0
	btfsc BOARD+3, 0
	retlw .3
	btfsc BOARD+6, 0
	retlw .6
	
BOARD_isThreat4
	decfsz tmp, f
	goto BOARD_isThreat5
	
	btfsc BOARD+1, 0
	retlw .1
	btfsc BOARD+4, 0
	retlw .4
	btfsc BOARD+7, 0
	retlw .7
	
BOARD_isThreat5
	decfsz tmp, f
	goto BOARD_isThreat6
	
	btfsc BOARD+2, 0
	retlw .2
	btfsc BOARD+5, 0
	retlw .5
	btfsc BOARD+8, 0
	retlw .8	
	
BOARD_isThreat6
	decfsz tmp, f
	goto BOARD_isThreat7
	
	btfsc BOARD+0, 0
	retlw .0
	btfsc BOARD+4, 0
	retlw .4
	btfsc BOARD+8, 0
	retlw .8	
			
BOARD_isThreat7

	btfsc BOARD+2, 0
	retlw .2
	btfsc BOARD+4, 0
	retlw .4
	btfsc BOARD+6, 0
	retlw .6
		
	retlw .255		;Nemelo by nastat
;}

;Zjisti, zda je muze souper nekde vyhrat, resp. najdi prvni misto,
;kde musim zabranit rade. Hledam v kazde rade/sloupci/diagonale
;soucet BOARD_X_THREAT.

;Vystup: ZERO - ano, nekde ma souper moznost mit tri v rade
;Vystup: W-reg - cislo sekvence, kde musim polozit kamen.

;Sekvence je cislo trojice prohledavanych mist na desce:

;0 - 0,1,2
;1 - 3,4,5
;2 - 6,7,8
;3 - 0,3,6
;4 - 1,4,7
;5 - 2,5,8
;6 - 0,4,8
;7 - 2,4,6

;Jakmile mam cislo sekvence, tak projdu vsechny 3 pozice v sekvenci
;a kde je prazdne misto, tak tam musim zabranit.
;Vstup: W-reg: BOARD_X_THREAT - kdyz hledam hrozby X
;            : BOARD_O_CHANCE - kdyz hledam sanci na vyhru O
BOARD_isThreatFindSequence
;{
	movwf BOARD_tmp
	
	;0,1,2 - radek1
	clrf tmp
	movf BOARD+0, w
	addwf tmp, f
	movf BOARD+1, w
	addwf tmp, f
	movf BOARD+2, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .0	;Hrozba v sekvenci 0, pak najdu prazdne misto v ni
	
	;3,4,5 - radek2
	clrf tmp
	movf BOARD+3, w
	addwf tmp, f
	movf BOARD+4, w
	addwf tmp, f
	movf BOARD+5, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .1
	
	;6,7,8 - radek3
	clrf tmp
	movf BOARD+6, w
	addwf tmp, f
	movf BOARD+7, w
	addwf tmp, f
	movf BOARD+8, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .2
	
	;0,3,6 - sloupec1
	clrf tmp
	movf BOARD+0, w
	addwf tmp, f
	movf BOARD+3, w
	addwf tmp, f
	movf BOARD+6, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .3
	
	;1,4,7 - sloupec2
	clrf tmp
	movf BOARD+1, w
	addwf tmp, f
	movf BOARD+4, w
	addwf tmp, f
	movf BOARD+7, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .4
	
	;2,5,8 - sloupec3
	clrf tmp
	movf BOARD+2, w
	addwf tmp, f
	movf BOARD+5, w
	addwf tmp, f
	movf BOARD+8, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .5
	
	;0,4,8 - diagonala1
	clrf tmp
	movf BOARD+0, w
	addwf tmp, f
	movf BOARD+4, w
	addwf tmp, f
	movf BOARD+8, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .6
	
	;2,4,6 - diagonala2
	clrf tmp
	movf BOARD+2, w
	addwf tmp, f
	movf BOARD+4, w
	addwf tmp, f
	movf BOARD+6, w
	addwf tmp, w
	xorwf BOARD_tmp, w
	btfsc STATUS, Z
	retlw .7
		
	bcf STATUS, Z	;Nikde nic
	return
	
;}

;Najdi pro mne prvni volne misto, kam umistit znacku.
;Pouzivam TMR0 bit 0 pro nahodny prvek hledani mista odpredu(1)/odzadu(0)
;Vystup - W-REG s cislem prazdne pozice, kopie W-reg v BOARD_tmp
BOARD_findFirstEmpty
;{	
	;Pokud hraju svuj prvni tah a je-li volno uprostred,
	;umisti tam O, je to strategicka pozice
	btfss BOARD+4, 0		;je tam prazdno?
	goto BOARD_findNext
	movf BOARD_empty_left, w
	xorlw (BOARD_PLACES - .1)
	btfss STATUS, Z
	goto BOARD_findNext
	movlw .4
	movwf BOARD_tmp
	return
	
BOARD_findNext
	
	btfss TMR0, 0
	goto BOARD_findBackward

BOARD_findEmpty

	movlw BOARD_PLACES
	movwf i

	clrf BOARD_tmp
	
	movlw BOARD
	movwf FSR
BOARD_findL1
	btfsc INDF, 0			;1=prazdne misto
	goto BOARD_findReturn 	;mame neco
	incf BOARD_tmp, f
	incf FSR, f
	decfsz i, f
	goto BOARD_findL1
	return

BOARD_findBackward

	movlw BOARD_PLACES
	movwf i

	movlw BOARD_PLACES - .1
	movwf BOARD_tmp
	
	movlw BOARD+8
	movwf FSR
BOARD_findL2
	btfsc INDF, 0			;1=prazdne misto
	goto BOARD_findReturn	;mame neco
	decf BOARD_tmp, f
	decf FSR, f
	decfsz i, f
	goto BOARD_findL2
	return

BOARD_findReturn
	movf BOARD_tmp, w
	return
;}

;*******************************************************************
;*************** J O Y S T I C K   R U T I N Y *********************
;*******************************************************************

;Cekej na stisk joystick button - pozor obracena logika
;Vrat se, az nejaky byl
JOY_waitButton
;{
	btfsc JOY_SW
	goto JOY_waitButton
	
	movlw .10
	call waitMilis
	
JOY_waitB
	btfss JOY_SW	
	goto JOY_waitB
	
	return
;}


;Vraci Z-nebyl pohyb, NZ-byl
JOY_wasMove
;{
	movf BOARD_x_old, w
	xorwf BOARD_x, w
	btfss STATUS, Z
	return
	movf BOARD_y_old, w
	xorwf BOARD_y, w
	return
;}

JOY_getReadings
;{
	clrf JOY_whichAdjust	;BOARD_x
	call JOY_getAnalogX		
	call JOY_handleMoveX
	
	incf JOY_whichAdjust, f	;BOARD_y
	call JOY_getAnalogY
	call JOY_handleMoveY
		
	call JOY_stopADC

	return
;}

;Byl stisk joysticku - pozor obracena logika!
;Vystup: ZERO set: byl, ZERO unset nebyl
JOY_getSwitchReading
;{
	bcf STATUS, Z
	btfsc JOY_SW
	return
	
	movlw .10
	call waitMilis
	
	bcf STATUS, Z
	btfsc JOY_SW
	return
	
JOY_getSwitchL
	btfss JOY_SW
	goto JOY_getSwitchL
	
	bsf STATUS, Z
	return
;}
	
JOY_stopADC
;{
	banksel ADCON0
	movlw b'10000000'		;ADC Frc clock, AN0, ADC OFF	
	movwf ADCON0
	BANK0
	return
;}

JOY_getAnalogX
;{
	movlw JOY_X_ADC
	goto JOY_readAnalog
;}
JOY_getAnalogY
;{
	movlw JOY_Y_ADC
	goto JOY_readAnalog
;}		
JOY_readAnalog
;{		
	banksel ADCON0
	movwf ADCON0   ; Vdd Vref, On
	call wait30us  ; Acquisiton delay
	bsf ADCON0, GO ; Start conversion
	btfsc ADCON0, GO ;Is conversion done?
	goto $-1 ;No, test again
	banksel ADRESH
	movf ADRESH, w ;Read upper 2 bits
	BANK0
	movwf JOY_ADresultH
	banksel ADRESL
	movf ADRESL, w ;Read lower 8 bits
	BANK0
	movwf JOY_ADresultL	
	return
;}

;Nastavi JOY_increment podle JOY_ADresultH:JOY_AdresultL
;Vystup:
;JOY_increment = 0		  AD result <342,  681>
;JOY_increment = 255 (-1) AD result <  0,  341>
;JOY_increment = 1		  AD result <681, 1023>
;Vystup: uprav BOARD_x, BOARD_y podle pohybu joysticku

JOY_handleMoveX
;{
	movlw .1			 	;Default +1
	movwf JOY_increment		
	
	;1) AD result >= 342?
    movlw AD_LIMIT_LOWER_L  ;move low byte of constant to wreg
    subwf JOY_ADresultL, w  ;subtract low bytes  
    movlw AD_LIMIT_LOWER_H  ;move high byte of constant to wreg
    btfss STATUS,C     	    ;borrow from the low bytes subtraction?
    addlw .1           	    ;yes, add one
    subwf JOY_ADresultH, w  ;subtract high bytes
    
    btfss STATUS, C    	    ;AD result >= 342
    goto JOY_checkRollOver  ;<342, nothing more to compare 
 	
 	decf JOY_increment, f	;0 now

	;2) AD result >= 682?
    movlw AD_LIMIT_UPPER_L  ;move low byte of constant to wreg
    subwf JOY_ADresultL, w  ;subtract low bytes  
    movlw AD_LIMIT_UPPER_H  ;move high byte of constant to wreg
    btfss STATUS,C     	    ;borrow from the low bytes subtraction?
    addlw .1           	    ;yes, add one
    subwf JOY_ADresultH, w  ;subtract high bytes
    
    btfss STATUS, C    	    ;AD result >= 682
    return 					;>=342 && <682, we are done, no roll-over possible
 	
	decf JOY_increment, f	;-1
	goto JOY_checkRollOver
;}
;Tady pozor na decf/incf, joystick je otoceny o 90 stupnu	
JOY_handleMoveY	
;{
	movlw .255				
	movwf JOY_increment		;Default -1
	
	;1) AD result >= 342?
    movlw AD_LIMIT_LOWER_L  ;move low byte of constant to wreg
    subwf JOY_ADresultL, w  ;subtract low bytes  
    movlw AD_LIMIT_LOWER_H  ;move high byte of constant to wreg
    btfss STATUS,C     	    ;borrow from the low bytes subtraction?
    addlw .1           	    ;yes, add one
    subwf JOY_ADresultH, w  ;subtract high bytes
    
    btfss STATUS, C    	    ;AD result >= 342
    goto JOY_checkRollOver  ;<342, nothing more to compare 
 	
 	incf JOY_increment, f	;0 now

	;2) AD result => 682?
    movlw AD_LIMIT_UPPER_L  ;move low byte of constant to wreg
    subwf JOY_ADresultL, w  ;subtract low bytes  
    movlw AD_LIMIT_UPPER_H  ;move high byte of constant to wreg
    btfss STATUS,C     	    ;borrow from the low bytes subtraction?
    addlw .1           	    ;yes, add one
    subwf JOY_ADresultH, w  ;subtract high bytes
    
    btfss STATUS, C    	    ;AD result >= 682
    return 					;<=342 && <682, we are done, no roll-over possible
 	
	incf JOY_increment, f	;+1
	goto JOY_checkRollOver
;}
	
;Zkontroluj meze boardu po zmene pozice X, Y
;Vstup JOY_increment - 255(-1) nebo 1
;Nastavi BOARD_x nebo BOARD_y (podle JOY_whichAdjust)
JOY_checkRollOver
;{
	movf JOY_increment, w
	btfss JOY_whichAdjust, 0		;BOARD_x nebo BOARD_y?
	goto JOY_adjustX	
	addwf BOARD_y, f
	goto JOY_checkBoundaries
JOY_adjustX							;BOARD_x
	addwf BOARD_x, f
	
JOY_checkBoundaries					;Zkontroluj jestli jsme <0,2>
	movlw BOARD_SIZE				;Horni mez 3
	btfss JOY_whichAdjust, 0		;BOARD_y
	goto JOY_checkBoundaryX
	xorwf BOARD_y, w
	goto JOY_8done	
JOY_checkBoundaryX
	xorwf BOARD_x, w		
JOY_8done	
	btfss STATUS, Z
	goto check_255
	btfss JOY_whichAdjust, 0		;snizime BOARD_x nebo BOARD_y?		
	goto JOY_checkDecX
	decf BOARD_y, f
	return
JOY_checkDecX
	decf BOARD_x, f	
	return
	
check_255
	movlw .255
	btfss JOY_whichAdjust, 0		;BOARD_y
	goto JOY_checkBoundaryX2
	xorwf BOARD_y, w
	goto JOY_255done
JOY_checkBoundaryX2
	xorwf BOARD_x, w
JOY_255done
	btfss STATUS, Z
	return							;Nic nemenime
	btfss JOY_whichAdjust, 0		;zvysime BOARD_x nebo BOARD_y?		
	goto JOY_checkIncX
	incf BOARD_y, f
	return
JOY_checkIncX
	incf BOARD_x, f	
	return
;}

;*******************************************************************
;*************** B O A R D   R U T I N Y ***************************
;*******************************************************************

;Ulozi BOARD_x a BOARD_y do BOARD_x_tmp a BOARD_y_tmp
BOARD_saveXY
;{
	movf  BOARD_x, w
	movwf BOARD_x_tmp
	movf  BOARD_y, w
	movwf BOARD_y_tmp
	return
;}


;Obnovi BOARD_x a BOARD_y
BOARD_restoreXY
;{
	movf  BOARD_x_tmp, w
	movwf BOARD_x
	movf  BOARD_y_tmp, w
	movwf BOARD_y
	return
;}



;*******************************************************************
;*************** LCD - INICIALIZACE DISPLEJE ***********************
;*******************************************************************
	
LCD_init
;{
	bcf LCD_RESET	
	movlw .250
	call waitMilis
	movlw .250
	call waitMilis
		
	bsf LCD_RESET
	

	; Tohle ma Arduino 5510
	movlw 0x21			; Extended instruction set, H=1, V=0, PD=0
	call LCD_sendCmd
	movlw 0xC4			; Set LCD Vop (Contrast)
	call LCD_sendCmd
	movlw 0x06			; Set Temp coefficient
	call LCD_sendCmd
	movlw 0x13			; LCD Bias system (1:48)
	call LCD_sendCmd
	movlw b'00100000'	;0x20, basic instruction set, H=0, V=0, PD=0
	call LCD_sendCmd
	movlw b'00001100'	;0x0C, normal mode, D=1, E=0
	call LCD_sendCmd
	
	return
;}

;*******************************************************************
;******************* LCD - POSILANI COMMANDU ***********************
;*******************************************************************

LCD_sendCmd
;{
	bcf LCD_DC	
	call LCD_writeByte
	return
;}

;*******************************************************************
;******************* LCD - POSILANI OBRAZOVYCH DAT *****************
;*******************************************************************

LCD_sendData
;{
	bsf LCD_DC
	call LCD_writeByte
	return
;}

;*******************************************************************
;******************* LCD - SPI WRITE BYTE **************************
;*******************************************************************

LCD_writeByte
;{
		movwf i2c_tmp	;uschovej posilany byte

		movlw .8
		movwf i2c_i
		
LCD_wc	bcf LCD_SCLK	 ;clock na log. 0, zaciname prenos data			
		btfss i2c_tmp, 7 ;bit 0 nastaven?
		goto bitNotSet
		bsf LCD_SDIN	;ano, posli log 1
		goto bitChecked
bitNotSet 
		bcf LCD_SDIN	;ne, posli log 0 na vystup
bitChecked			
		bsf LCD_SCLK	;clock na log. 1, skoncili jsme prenos 1 bitu

		rlf i2c_tmp, f
		decfsz i2c_i, f
		goto LCD_wc

		bcf LCD_SCLK
		return
;}

;******************************************************************
;********************* LCD - CLEAR SCREEN *************************
;******************************************************************

LCD_clear
;{
		movlw LOW LCD_BYTES
		movwf loByte
		movlw HIGH LCD_BYTES
		movwf hiByte
LCD_c1	clrw
		call LCD_sendData		
		call decHL
		btfss STATUS, Z
		goto LCD_c1
		return
;}

;******************************************************************
;********************* LCD - BLACK SCREEN *************************
;******************************************************************

LCD_black
;{
		movlw LOW LCD_BYTES
		movwf loByte
		movlw HIGH LCD_BYTES
		movwf hiByte
LCD_b1	movlw 0xFF
		call LCD_sendData		
		call decHL
		btfss STATUS, Z
		goto LCD_b1
		return
;}
;******************************************************************
;********************* LCD - SET X,Y ******************************
;******************************************************************

LCD_setXY
;{
		movf X, w			;Nastav souradnice
		iorlw b'10000000'	;X = 1X6X5X4X3X2X1X0
		call LCD_sendCmd
		movf Y, w
		iorlw b'01000000'	;Y = 0100Y3Y2Y1Y0
		call LCD_sendCmd
		return
;}
	
;******************************************************************
;************ LCD - VYKRESLOVANI TEXTOVYCH RETEZCU ****************
;******************************************************************		

;Vyhrej hru a
LCD_write_t1
;{		
		clrf X
		clrf Y
		call LCD_setXY
		movlw HIGH t1
		movwf textPointer+1
		movlw LOW t1
		movwf textPointer+0
		goto LCD_drawText
;}
	
; TIC-TAC-TOE
LCD_write_t2
;{
		clrf X
		movlw .1
		movwf Y
		call LCD_setXY
		movlw HIGH t2
		movwf textPointer+1
		movlw LOW t2
		movwf textPointer+0
		goto LCD_drawText
;}
		
;A ziskej kod.
LCD_write_t3
;{
		clrf X
		movlw .2
		movwf Y
		call LCD_setXY
		movlw HIGH t3
		movwf textPointer+1
		movlw LOW t3
		movwf textPointer+0
		goto LCD_drawText		
;}
		
;Zmackni
LCD_write_t4
;{
		clrf X
		movlw .4
		movwf Y
		call LCD_setXY
		movlw HIGH t4
		movwf textPointer+1
		movlw LOW t4
		movwf textPointer+0
		goto LCD_drawText
;}
		
;tlacitko
LCD_write_t5
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t5
		movwf textPointer+1
		movlw LOW t5
		movwf textPointer+0
		goto LCD_drawText
;}
		
;Hrajes ty - X
LCD_write_hrajes
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t_hrajes
		movwf textPointer+1
		movlw LOW t_hrajes
		movwf textPointer+0
		goto LCD_drawText
;}
		
;Hraji ja - O
LCD_write_hrajeO
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t_hrajeO
		movwf textPointer+1
		movlw LOW t_hrajeO
		movwf textPointer+0
		goto LCD_drawText
;}
						
;Vyhral jsi! Kod:
LCD_write_vyhra
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t_vyhra
		movwf textPointer+1
		movlw LOW t_vyhra
		movwf textPointer+0
		goto LCD_drawText
;}

;Kod:
LCD_write_kod
;{
		clrf X
		movlw .2
		movwf Y
		call LCD_setXY
		movlw HIGH t_kod
		movwf textPointer+1
		movlw LOW t_kod
		movwf textPointer+0
		goto LCD_drawText
;}
				
;Prohral jsi.
LCD_write_prohra
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t_prohra
		movwf textPointer+1
		movlw LOW t_prohra
		movwf textPointer+0
		goto LCD_drawText
;}
		
;Remiza
LCD_write_remiza
;{
		clrf X
		movlw .5
		movwf Y
		call LCD_setXY
		movlw HIGH t_remiza
		movwf textPointer+1
		movlw LOW t_remiza
		movwf textPointer+0
		goto LCD_drawText
;}

LCD_showPosition
;{
		clrf X
		clrf Y
		call LCD_setXY

		movlw TRUE
		movwf putCharOnly
		
		movf BOARD_x, w
		addlw '0'
		call LCD_drawChar
		movlw ','
		call LCD_drawChar
		movf BOARD_y, w
		addlw '0'
		call LCD_drawChar		
		
		movlw FALSE
		movwf putCharOnly		
		
		return
;}
					
LCD_showBoard
;{
		movlw BOARD_LEFT_X
		movwf X
		movlw .0
		movwf Y
		call LCD_setXY
		movlw HIGH t_row1
		movwf textPointer+1
		movlw LOW t_row1
		movwf textPointer+0
		call LCD_drawText

		movlw BOARD_LEFT_X
		movwf X
		movlw .1
		movwf Y
		call LCD_setXY
		movlw HIGH t_row2
		movwf textPointer+1
		movlw LOW t_row2
		movwf textPointer+0
		call LCD_drawText		
		
		movlw BOARD_LEFT_X
		movwf X
		movlw .2
		movwf Y
		call LCD_setXY
		movlw HIGH t_row1
		movwf textPointer+1
		movlw LOW t_row1
		movwf textPointer+0
		call LCD_drawText		
		
		movlw BOARD_LEFT_X
		movwf X
		movlw .3
		movwf Y
		call LCD_setXY
		movlw HIGH t_row2
		movwf textPointer+1
		movlw LOW t_row2
		movwf textPointer+0
		call LCD_drawText

		movlw BOARD_LEFT_X
		movwf X
		movlw .4
		movwf Y
		call LCD_setXY
		movlw HIGH t_row1
		movwf textPointer+1
		movlw LOW t_row1
		movwf textPointer+0
		goto LCD_drawText
;}
								
LCD_showCode
;{
		movlw .30
		movwf X
		movlw .3
		movwf Y
		call LCD_setXY		
		movlw '8'
		call LCD_drawCislo
		
		movlw .38
		movwf X
		movlw .3
		movwf Y
		call LCD_setXY		
		movlw '4'
		call LCD_drawCislo		
		
		movlw .46
		movwf X
		movlw .3
		movwf Y
		call LCD_setXY				
		movlw '1'
		goto LCD_drawCislo		
;}
		
; **************************************************************************************
; **************  LCD_drawCislo *********************************************************
; **************************************************************************************

;Vstup: BOARD_x, BOARD_y
;Vystup: X a Y
LCD_calculateXY
;{
	;Y = BOARD_y * 2
	bcf STATUS, C
	rlf BOARD_y, w
	movwf Y
	
	;X = (12 (2 znaky, 1 znak = 6 pixelu) * BOARD_X) + BOARD_LEFT_X
	movf BOARD_x, w
	movwf tmp
	bcf STATUS, C
	rlf tmp, f	; x2
	rlf tmp, f 	; x4
	movf tmp, w
	movwf i		;uloz x4, pricteme pak k x8
	rlf tmp, w
	addwf i, f
	movlw BOARD_LEFT_X
	addwf i, w	
	movwf X
	return
;}


;Vstup: GAME_piece = 0x01 empty, 0x02 (X), 0x04 (O)
;Vystup: W-REG - SIGN_EMPTY, SIGN_X, SIGN_O
LCD_pieceValueToChar
;{
	movlw SIGN_EMPTY
	btfsc BOARD_piece, 0
	return
	movlw SIGN_X
	btfsc BOARD_piece, 1
	return
	movlw SIGN_O
	btfsc BOARD_piece, 2
	return
	movlw SIGN_MOVE
	return	
;}

;Vstup: BOARD_x, BOARD_y, W-reg=znak
;Vystup: Nastav spravne misto pro vykresleni znaku
LCD_placeSign
;{
	movwf char
	
	call LCD_calculateXY
	
	call LCD_setXY
	
	movlw TRUE
	movwf putCharOnly

	movf char, w
	call LCD_drawChar
	
	movlw FALSE
	movwf putCharOnly
	
	return
;}


LCD_drawCislo
;{
		movwf cislo

		movf X, w
		movwf X_copy
		movf Y, w
		movwf Y_copy
		
		movlw '0'
		subwf cislo, f
		movlw HIGH font_digits_8x16
		movwf fontPointer+1
		movlw LOW font_digits_8x16
		movwf fontPointer+0		;k fontPointer musime pricit 16x base
		
		bcf STATUS, C			;vynuluj Carry
		rlf cislo, f			;x 2
		rlf cislo, f			;x 4
		rlf cislo, f			;x 8		
		rlf cislo, w			;x 16				
		addwf fontPointer+0, f 	;vlezem se do 256

		movlw .8
		movwf i
LCD_dcF
		call getNextFontByte
		call LCD_sendData
		decfsz i, f
		goto LCD_dcF

		;Posun se o 8px nize
		movf X_copy, w
		movwf X
		incf Y_copy, w
		movwf Y
		call LCD_setXY			
		
		movlw .8
		movwf i
LCD_dcS
		call getNextFontByte
		call LCD_sendData
		decfsz i, f
		goto LCD_dcS
				
		return
;}		
; **************************************************************************************
; **************  LCD_drawText *********************************************************
; **************************************************************************************
		
LCD_drawText
;{
		movlw FALSE
		movwf putCharOnly
		
LCD_dt1	call getNextChar

LCD_drawChar
		iorlw 0x00 
		btfsc STATUS, Z
		return
		movwf tmp
		movlw .32
		subwf tmp, f			;x 1		
		movlw HIGH font_5x8_data
		movwf fontPointer+1
		movlw LOW font_5x8_data
		movwf fontPointer+0		;k fontPointer musime pricit 5x base
		bcf STATUS, C			;vynuluj Carry
		rlf tmp, w				;x 2
		movwf fontPointer+0		;uloz primo, nemuze pretect (max znak = 90 * 2 = 180)
		addwf fontPointer+0, f	;x 4
		btfsc STATUS, C
		incf fontPointer+1, f
		incf tmp, w				;x 5 + 1 (1=posun tabulky o 1B)
		addwf fontPointer+0, f	
		btfsc STATUS, C
		incf fontPointer+1, f		
		call getNextFontByte
		call LCD_sendData
		call getNextFontByte
		call LCD_sendData
		call getNextFontByte
		call LCD_sendData
		call getNextFontByte
		call LCD_sendData
		call getNextFontByte
		call LCD_sendData
		clrw					;Mezera mezi pismeny
		call LCD_sendData
		btfsc putCharOnly, 0
		return
		goto LCD_dt1

getNextChar:
		call getNextChar2 		;To je patch kvuli strankovani
		clrf PCLATH
		incfsz textPointer+0,f 	;Inkrementuj pointer
		goto $+2
		incf textPointer+1,f
		return 					;Vrat hodnotu (je stale ve W)
getNextChar2:
		;Zde se pouze skoci na dvoubajtovou adresu v textPointer
		movf textPointer+1,w 	;Zkopiruj HI byte do PCLATHu
		movwf PCLATH
		movf textPointer+0,w 	;Dej LO byte do PCL
		movwf PCL 				;Skoci na adresu, kam ukazuje textPointer
		
getNextFontByte:
		call getNextFontByte2 	;To je patch kvuli strankovani
		;movwf tmp				;Posunu byte doleva, posune pismeno smerem dolu o 1px
		clrf PCLATH
		;bcf STATUS, C			;Nuluj carry, at nam neco neprirotuje zprava
		;rlf tmp, w
		incfsz fontPointer+0,f 	;Inkrementuj pointer
		goto $+2
		incf fontPointer+1,f
		return 					;Vrat hodnotu (je stale ve W)
getNextFontByte2:
		;Zde se pouze skoci na dvoubajtovou adresu v fontPointer
		movf fontPointer+1,w 	;Zkopiruj HI byte do PCLATHu
		movwf PCLATH
		movf fontPointer+0,w 	;Dej LO byte do PCL
		movwf PCL 				;Skoci na adresu, kam ukazuje fontPointer
;}

; *** SUBRUTINA, CEKEJ nuMilis milisekund ***************************

; *** SUBRUTINA, CEKEJ 150us 
wait150us 	
;{
	call wait30us
	call wait30us
	call wait30us
	call wait30us
	call wait30us
	return
;}

; *** SUBRUTINA, CEKEJ 30us (=30 jednotaktovych instrukci)

wait30us	
;{
			nop		;26, 2 na zacatku sezere volani call
			nop
			nop
			nop
			nop
		 	nop
			nop
			nop
			nop
			nop
wait20us	nop
			nop
			nop
			nop
			nop
		 	nop
			nop
			nop
			nop
			nop
wait10us	nop
			nop
			nop
			nop
			nop
wait5us	 	nop
			return;		ta je za 2 cykly
;}

; Delay = 1 seconds
; Clock frequency = 4 MHz

; Actual delay = 1 seconds = 1000000 cycles
; Error = 0 %

wait1s
;{
			;999990 cycles
	movlw	0x07
	movwf	d1
	movlw	0x2F
	movwf	d2
	movlw	0x03
	movwf	d3
wait1s_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	$+2
	decfsz	d3, f
	goto	wait1s_0

	;6 cycles
	goto	$+1
	goto	$+1
	goto	$+1

			;4 cycles (including call)
	return
;}

waitMilis
;{
		movwf numMilis
waitM	call wait1ms
		decfsz numMilis, f
		goto waitM
		return
;}

; Delay = 0.001 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.001 seconds = 1000 cycles
; Error = 0 %

wait1ms
;{
			;993 cycles
	movlw	0xC6
	movwf	d1
	movlw	0x01
	movwf	d2
wait1ms_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	wait1ms_0

			;3 cycles
	goto	$+1
	nop

			;4 cycles (including call)
	return	
;}


; *** SUBRUTINY pro 16bitovy counter ********************************	
; *** Nastavi Zero, pokud jsme na nule

incHL	incfsz loByte, f
		return	
		incf hiByte, f
		return

decHL	movf loByte, f
		btfsc STATUS, Z ;je loByte na nule?
		goto decHL2
		decf loByte, w	;kopie pro nasledny OR (test na 0)
		decf loByte, f
		iorwf hiByte, w ;Z flag nastaven pri 0 (loByte OR hiByte)
		return
decHL2	decf loByte, f
		decf hiByte, f
		bcf STATUS, Z	;Potrebuju vynulovat Zero (aby mi pri lo/hi 0/1 predchozi decf Z nenastavil)
		return
	
; *** SUBRUTINA pro prevod 6bit binary to BCD ********************************	
	
bin2ascii
;{
	clrf tens
	addlw .256 - .100
digit100
	addlw .20
	btfss STATUS,C
	goto  digit40
	bsf   tens,3
	addlw .256 - .20
	goto digit10
digit40
	addlw .40
	btfss STATUS,C
	goto  $+3
	bsf   tens,2
	addlw .256 - .40
	addlw .20
	btfss STATUS,C
	goto  $+3
	bsf   tens,1
	addlw .256 - .20
digit10
	addlw .10
	btfss STATUS,C
	goto  $+3
	bsf   tens,0
	addlw .256 - .10
	
	addlw .10
	movwf ones
	
	movlw '0'
	addwf tens, f
	addwf ones, f
	return	
;}
; *****************************************************************	
; ********************** F O N T  D A T A *************************
; *****************************************************************
			org 0x0500
text_table
t1			dt "  Vyhrej hru  ", 0x00
t2			dt " TIC-TAC-TOE  ", 0x00
t3			dt " a ziskej kod.", 0x00
t4			dt "    Stiskni   ", 0x00
t5			dt "   tlacitko.  ", 0x00

t_hrajes	dt " Hrajes ty - X", 0x00
t_hrajeO	dt " Hraji ja - O ", 0x00

t_vyhra		dt "  Vyhral jsi! ", 0x00
t_kod		dt "     KOD:     ", 0x00
t_prohra	dt "  Prohral jsi.", 0x00
t_remiza	dt "    Remiza.   ", 0x00

t_row1		dt " / / ", 0x00
t_row2		dt "_+_+_", 0x00 

			org 0x0600
			nop		;musi byt kvuli zarovnani na 255 bytes
font_5x8_data
;{
		dt 0x00, 0x00, 0x00, 0x00, 0x00; space (32dec)
		dt 0x00, 0x00, 0x2f, 0x00, 0x00; !
		dt 0x00, 0x07, 0x00, 0x07, 0x00; "
		dt 0x14, 0x7f, 0x14, 0x7f, 0x14; #
		dt 0x24, 0x2a, 0x7f, 0x2a, 0x12; $
		dt 0xc4, 0xc8, 0x10, 0x26, 0x46; %
		dt 0x36, 0x49, 0x55, 0x22, 0x50; &
		dt 0x00, 0x05, 0x03, 0x00, 0x00; '
		dt 0x00, 0x1c, 0x22, 0x41, 0x00; (
		dt 0x00, 0x41, 0x22, 0x1c, 0x00; )
		dt 0x14, 0x08, 0x3E, 0x08, 0x14; *
		dt 0x08, 0x08, 0xFF, 0x08, 0x08; +    + - grafika
		dt 0x00, 0x00, 0x50, 0x30, 0x00; ,
		dt 0x10, 0x10, 0x10, 0x10, 0x10; -
		dt 0x00, 0x60, 0x60, 0x00, 0x00; .
		dt 0x00, 0x00, 0xFF, 0x00, 0x00; /    | - grafika
		dt 0x3E, 0x51, 0x49, 0x45, 0x3E; 0
		dt 0x00, 0x42, 0x7F, 0x40, 0x00; 1
		dt 0x42, 0x61, 0x51, 0x49, 0x46; 2
		dt 0x21, 0x41, 0x45, 0x4B, 0x31; 3
		dt 0x18, 0x14, 0x12, 0x7F, 0x10; 4
		dt 0x27, 0x45, 0x45, 0x45, 0x39; 5
		dt 0x3C, 0x4A, 0x49, 0x49, 0x30; 6
		dt 0x01, 0x71, 0x09, 0x05, 0x03; 7
		dt 0x36, 0x49, 0x49, 0x49, 0x36; 8
		dt 0x06, 0x49, 0x49, 0x29, 0x1E; 9
		dt 0x00, 0x36, 0x36, 0x00, 0x00; :
		dt 0x00, 0x56, 0x36, 0x00, 0x00; ;
		dt 0x08, 0x14, 0x22, 0x41, 0x00; <
		dt 0x14, 0x14, 0x14, 0x14, 0x14; =
		dt 0x00, 0x41, 0x22, 0x14, 0x08; >
		dt 0x02, 0x01, 0x51, 0x09, 0x06; ?		
		dt 0x32, 0x49, 0x59, 0x51, 0x3E; @
		dt 0x7E, 0x11, 0x11, 0x11, 0x7E; A
		dt 0x7F, 0x49, 0x49, 0x49, 0x36; B
		dt 0x3E, 0x41, 0x41, 0x41, 0x22; C
		dt 0x7F, 0x41, 0x41, 0x22, 0x1C; D
		dt 0x7F, 0x49, 0x49, 0x49, 0x41; E
		dt 0x7F, 0x09, 0x09, 0x09, 0x01; F
		dt 0x3E, 0x41, 0x49, 0x49, 0x7A; G
		dt 0x7F, 0x08, 0x08, 0x08, 0x7F; H
		dt 0x00, 0x41, 0x7F, 0x41, 0x00; I
		dt 0x20, 0x40, 0x41, 0x3F, 0x01; J
		dt 0x7F, 0x08, 0x14, 0x22, 0x41; K
		dt 0x7F, 0x40, 0x40, 0x40, 0x40; L
		dt 0x7F, 0x02, 0x0C, 0x02, 0x7F; M
		dt 0x7F, 0x04, 0x08, 0x10, 0x7F; N
		dt 0x3E, 0x41, 0x41, 0x41, 0x3E; O
		dt 0x7F, 0x09, 0x09, 0x09, 0x06; P
		dt 0x3E, 0x41, 0x51, 0x21, 0x5E; Q
		dt 0x7F, 0x09, 0x19, 0x29, 0x46; R
		dt 0x46, 0x49, 0x49, 0x49, 0x31; S
		dt 0x01, 0x01, 0x7F, 0x01, 0x01; T
		dt 0x3F, 0x40, 0x40, 0x40, 0x3F; U
		dt 0x1F, 0x20, 0x40, 0x20, 0x1F; V
		dt 0x3F, 0x40, 0x38, 0x40, 0x3F; W
		dt 0x63, 0x14, 0x08, 0x14, 0x63; X
		dt 0x07, 0x08, 0x70, 0x08, 0x07; Y
		dt 0x61, 0x51, 0x49, 0x45, 0x43; Z
		dt 0x00, 0x7F, 0x41, 0x41, 0x00; [
		dt 0x55, 0x2A, 0x55, 0x2A, 0x55; "Yen"
		dt 0x00, 0x41, 0x41, 0x7F, 0x00; ]
		dt 0x04, 0x02, 0x01, 0x02, 0x04; ^
		dt 0x08, 0x08, 0x08, 0x08, 0x08; _  - grafika
		dt 0x00, 0x01, 0x02, 0x04, 0x00; '
		dt 0x20, 0x54, 0x54, 0x54, 0x78; a
		dt 0x7F, 0x48, 0x44, 0x44, 0x38; b
		dt 0x38, 0x44, 0x44, 0x44, 0x20; c
		dt 0x38, 0x44, 0x44, 0x48, 0x7F; d
		dt 0x38, 0x54, 0x54, 0x54, 0x18; e
		dt 0x08, 0x7E, 0x09, 0x01, 0x02; f
		dt 0x0C, 0x52, 0x52, 0x52, 0x3E; g
		dt 0x7F, 0x08, 0x04, 0x04, 0x78; h
		dt 0x00, 0x44, 0x7D, 0x40, 0x00; i
		dt 0x20, 0x40, 0x44, 0x3D, 0x00; j
		dt 0x7F, 0x10, 0x28, 0x44, 0x00; k
		dt 0x00, 0x41, 0x7F, 0x40, 0x00; l
		dt 0x7C, 0x04, 0x18, 0x04, 0x78; m
		dt 0x7C, 0x08, 0x04, 0x04, 0x78; n
		dt 0x38, 0x44, 0x44, 0x44, 0x38; o
		dt 0x7C, 0x14, 0x14, 0x14, 0x08; p
		dt 0x08, 0x14, 0x14, 0x18, 0x7C; q
		dt 0x7C, 0x08, 0x04, 0x04, 0x08; r
		dt 0x48, 0x54, 0x54, 0x54, 0x20; s
		dt 0x04, 0x3F, 0x44, 0x40, 0x20; t
		dt 0x3C, 0x40, 0x40, 0x20, 0x7C; u
		dt 0x1C, 0x20, 0x40, 0x20, 0x1C; v
		dt 0x3C, 0x40, 0x30, 0x40, 0x3C; w
		dt 0x44, 0x28, 0x10, 0x28, 0x44; x
		dt 0x0C, 0x50, 0x50, 0x50, 0x3C; y
		dt 0x44, 0x64, 0x54, 0x4C, 0x44; z
;}


		org 0x0800
		
font_digits_8x16
;{
	dt 0x00, 0xFC, 0xFF, 0xC3, 0xF3, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0x3F, 0x33, 0x30, 0x3F, 0x0F, 0x00; // Code for char 0	    
	dt 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3F, 0x3F, 0x30, 0x30, 0x00; // Code for char 1
	dt 0x00, 0x0C, 0x0F, 0xC3, 0xC3, 0xFF, 0x3C, 0x00, 0x00, 0x3C, 0x3F, 0x33, 0x30, 0x3C, 0x3C, 0x00; // Code for char 2
	dt 0x00, 0x0C, 0x0F, 0xC3, 0xC3, 0xFF, 0x3C, 0x00, 0x00, 0x0C, 0x3C, 0x30, 0x30, 0x3F, 0x0F, 0x00; // Code for char 3
	dt 0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x03, 0x03, 0x33, 0x3F, 0x3F, 0x33, 0x00; // Code for char 4
	dt 0x00, 0x3F, 0x3F, 0x33, 0x33, 0xF3, 0xC3, 0x00, 0x00, 0x0C, 0x3C, 0x30, 0x30, 0x3F, 0x0F, 0x00; // Code for char 5
	dt 0x00, 0xF0, 0xFC, 0xCF, 0xC3, 0xC3, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0x30, 0x30, 0x3F, 0x0F, 0x00; // Code for char 6
	dt 0x00, 0x0F, 0x0F, 0x03, 0xC3, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00; // Code for char 7
	dt 0x00, 0x3C, 0xFF, 0xC3, 0xC3, 0xFF, 0x3C, 0x00, 0x00, 0x0F, 0x3F, 0x30, 0x30, 0x3F, 0x0F, 0x00; // Code for char 8
	dt 0x00, 0x3C, 0xFF, 0xC3, 0xC3, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3C, 0x0F, 0x03, 0x00; // Code for char 9
	dt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00; // Code for char : (space)
;}

; *** KONEC SOUBORU *************************************************	
	end