;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;        Schemat podłączeń programowanego układu
;                       +----v----+
;                 MCLR [| 1     28|] VDD
;                      [| 2     27|] VSS
;                      [| 3     26|] RP15/SDO1 -> DAT 
;                      [| 4     25|] RP14/SCK1OUT -> CLK
;                      [| 5     24|] RP13/SS1OUT -> CS
;                      [| 6     23|] 
;                      [| 7     22|] RB11 -> RST
;                  VSS [| 8     21|] RB10 -> RS
;       (8 MHz) / OSCI [| 9     20|] VCAP/VDDCORE
;               \ OSCO [|10     19|] DISVREG
;                      [|11     18|] RB9 -> BL
;                      [|12     17|] 
;                  VDD [|13     16|] 
;                      [|14     15|] 
;                       +---------+
;                     PIC24FJ64GB002
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	.include "p24FJ64GB002.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ustawienia bitów konfiguracyjnych
;1. 
;FWDTEN_OFF - Watchdog wyłączony
;JTAGEN_OFF - JTAG wyłączony
	config  __CONFIG1,	FWDTEN_OFF & JTAGEN_OFF
;2.
;FNOSC_PRIPLL - układ taktowany zewnętrznym oscylatorem z pętlą PLL
;POSCMOD_XT - częstotliwość taktowania oscylatora 8 MHz
;PLLDIV_DIV2 - konieczność podzielenia przez 2 dla modułu USB PLL
	config  __CONFIG2,	FNOSC_PRIPLL & POSCMOD_XT & PLLDIV_DIV2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; definicje stałych
	.equ	procesorek, 16000-6
	
	.equ S65_CLK, 14	;SCK1OUT 
	.equ S65_DAT, 15	;SDO1
	.equ S65_CS,  13	;SS1OUT
	.equ S65_RS,  10
	.equ S65_RST, 11
	.equ S65_BL,  9

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; deklaracje symboli globalnych
	.global __reset				;etykieta pierwszej linii kodu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; początek kodu
__reset:
	mov		#__SP_init, W15		;inicjalizacja wskaźnika stosu (adres początku stosu)
	mov		#__SPLIM_init, W0	;inicjalizacja SPLIM (adres graniczny stosu)
	mov		W0, SPLIM			;W0 -> SPLIM
	nop                         ;konieczna instrukcja nop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; obsługa SPI1
; remapowanie linii dla interfejsu SPI
; linie wyjściowe
; 1. RP15 -> SDO1 (funkcja nr 7)
; RPOR7bits.RP15R = 7;
	mov		#RPOR7, W0			;załaduj do W0 adres rejestru RPOR7
	mov.b	#7, W1				;załaduj do W1 liczbę 7
	mov.b	W1, [W0+1]			;załaduj zawartość W1 pod adres W0+1
; 2. RP14 -> SCK1OUT (funkcja nr 8)
; RPOR7bits.RP14R = 8;
	mov.b	#8, W1				;załaduj do W1 liczbę 8
	mov.b	W1, [W0]			;załaduj zawartość W1 pod adres W0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;zaczekaj 100 ms
	mov		#100, W1			;W1 <- 1
	rcall	Czekaj_ms			;czekaj W1 ms
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; inicjuj wyświetlacz S65
	rcall	Start_S65
;wypełnij ekran kolorem zielonym
	mov		#0x7E0, W9			;kolor zielony
	rcall	Rysuj_tlo_S65	;zapełnij obszar
; wyświetl mikrokontrolerowe dzieło
; obszar niebieski
	mov		#20, W5				;X1
	mov		#80, W6				;X2
	mov		#50, W7				;Y1
	mov		#95, W8				;Y2
	mov		#0x1F, W9			;kolor niebieski
	rcall	Rysuj_obszar_S65	;zapełnij obszar
; obszar czerwony
	mov		#30, W5				;X1
	mov		#50, W6				;X2
	mov		#60, W7				;Y1
	mov		#80, W8				;Y2
	mov		#0xF800, W9			;kolor czerwony
	rcall	Rysuj_obszar_S65	;zapełnij obszar
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; nieskończona pętla
petla:
	bra		petla				;skok bezwarunkowy do etykiety pętla
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; podprogram generujący opóźnienie iczone w milisekundach
; (argument w W1)
Czekaj_ms:
	mov		#procesorek, W2		;W2 <- FCPU-6
	repeat	W2					;powtórz W2 razy
	nop
	dec		W1, W1				;W1--
	bra		NZ, Czekaj_ms		;wróć do pętli, jeśli nie było 0
	return						;powrót z podprogramu
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; konfiguracja i uruchomienie interfejsu SPI1
StartSPI:
	;1. konfiguracja SPI1CON1 i SPI1CON2
	;SPI1CON1bits.MSTEN = 1;	//tryb Master
	bset	SPI1CON1, #MSTEN
	;SPI1CON1bits.MODE16 = 0;	//dane 8-bitowe
	bclr	SPI1CON1, #MODE16
	;prędkość = 8000
	;Primary Prescaler = 1:1
	bset	SPI1CON1, #PPRE1
	bset	SPI1CON1, #PPRE0
	;Secondary Prescaler = 2:1
	bset	SPI1CON1, #SPRE2
	bset	SPI1CON1, #SPRE1
	bclr	SPI1CON1, #PPRE0
	;2. ustawienie bitu SPIEN (włączenie modułu SPI1)
	;SPI1STATbits.SPIEN = 1;	
	bset	SPI1STAT, #SPIEN
	return						;powrót z podprogramu
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; transfer danych poprzez SPI1
; (dane wejściowe W1)
; (dane wyjściowe W2)
TransferSPI1:
    ;SPI1BUF = dane;			//załaduj dane do bufora
	mov		W1, SPI1BUF
    ;while(!SPI1STATbits.SPIRBF);//zaczekaj na zakończenie operacji
TransferSPI1_petla:
	btss	SPI1STAT, #SPIRBF
	goto	TransferSPI1_petla
    ;return SPI1BUF;    		//odczytaj dane
	mov		SPI1BUF, W2
	return						;powrót z podprogramu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; wysłanie bajtu do pamięci S65
; (dane w W1)
Wyslij_dane_S65:
	;sygnalizuj wysyłanie danych (poziom niski CS)
	bclr	LATB, #S65_CS
	;wyślij dane za pośrednictwem interfejsu SPI1
	rcall	TransferSPI1
	;sygnalizuj koniec wysyłania danych (poziom wysoki CS)
	bset	LATB, #S65_CS
	return						;powrót z podprogramu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; inicjalizacja wyświetlacza S65
Start_S65:
	;ustaw kierunek wyjściowy linii obsługujących S65
	bclr	TRISB, #S65_RST		;linia RB11 wyjściowa (RST)
	bclr	TRISB, #S65_RS		;linia RB10 wyjściowa (RS)
	bclr	TRISB, #S65_BL		;linia RB9 wyjściowa (BL)
	bclr	TRISB, #S65_DAT		;linia RB15 wyjściowa (DAT)
	bclr	TRISB, #S65_CS		;linia RB13 wyjściowa (CS)
	bclr	TRISB, #S65_CLK		;linia RB14 wyjściowa (CLK)

	;sekwencja startująca
	bset	LATB, #S65_CS
	bset	LATB, #S65_CLK
	bset	LATB, #S65_DAT
	bset	LATB, #S65_RS
	bclr	LATB, #S65_RST
	bset	LATB, #S65_RST

;inicjuj SPI1
	rcall	StartSPI

;zaczekaj 1 ms
	mov		#1, W1				;W1 <- 1
	rcall	Czekaj_ms			;czekaj W1 ms

;sekwencja 1
	mov.b	#0xFD, W1
	rcall	Wyslij_dane_S65
	mov.b	#0xFD, W1
	rcall	Wyslij_dane_S65
	mov.b	#0xFD, W1
	rcall	Wyslij_dane_S65
	mov.b	#0xFD, W1
	rcall	Wyslij_dane_S65

;zaczekaj 60 ms
	mov		#60, W1				;W1 <- 60
	rcall	Czekaj_ms			;czekaj W1 ms

;sekwencja 2
;for(i=0; i<20; i++) Wyslij_dane_S65(kod2[i]);
	mov		#tblpage(kod2), W3	;W3 <- adres strony pamięci (najstarszy bajt adresu kod2)
	mov		W3, TBLPAG			;TBLPAG <- adres strony
	mov		#tbloffset(kod2), W3;W3 <- adres na stronie pamięci (młodsze 2 bajty adresu kod2)
	mov		#20, W4				;W4 <- 20
Start_S65_petla1:
		tblrdl.b	[W3++], W1	;załaduj do W1 wartość spod adresu W3
		rcall	Wyslij_dane_S65
		dec		W4, W4			;W4--
		bra nz,	Start_S65_petla1;skocz jeśli nie było 0 do etykiety		

;zaczekaj 7 ms
	mov		#7, W1				;W1 <- 7
	rcall	Czekaj_ms			;czekaj W1 ms

;sekwencja 3
;for(i=0; i<40; i++) Wyslij_dane_S65(kod3[i]);
	mov		#tblpage(kod3), W3	;W3 <- adres strony pamięci (najstarszy bajt adresu kod3)
	mov		W3, TBLPAG			;TBLPAG <- adres strony
	mov		#tbloffset(kod3), W3;W3 <- adres na stronie pamięci (młodsze 2 bajty adresu kod3)
	mov		#40, W4				;W4 <- 40
Start_S65_petla2:
		tblrdl.b	[W3++], W1	;załaduj do W1 wartość spod adresu W3
		rcall	Wyslij_dane_S65
		dec		W4, W4			;W4--
		bra nz,	Start_S65_petla2;skocz jeśli nie było 0 do etykiety

;zaczekaj 50 ms
	mov		#50, W1				;W1 <- 50
	rcall	Czekaj_ms			;czekaj W1 ms

;sekwencja 4
	mov.b	#0x80, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x01, W1
	rcall	Wyslij_dane_S65
	mov.b	#0xEF, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x90, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x00, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x00, W1
	rcall	Wyslij_dane_S65

;włącz podświetlenie
	bset	LATB, #S65_BL

	return						;powrót z podprogramu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; rysuj tło
; kolor (W9)
Rysuj_tlo_S65:
	;sygnalizuj rozkaz (RS = 1)
	bset	LATB, #S65_RS

	;sekwencja uruchamiająca rysowanie tła
	mov.b	#0xEF, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x90, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x05, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x00, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x06, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x00, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x07, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x00, W1
	rcall	Wyslij_dane_S65

	;sygnalizuj dane (RS = 0)
	bclr	LATB, #S65_RS

	;wypełnij kolorem
	mov		#23232, W3			;załaduj do W3 liczbę pikseli wyświetlacza
Rysuj_tlo_S65_petla:
		swap	W9				;zamień miejscami bajty W9
		mov		W9, W1			;W1 <- W9
		rcall	Wyslij_dane_S65	;wyślij starszy bajt koloru
		swap	W9				;zamień miejscami bajty W9
		mov		W9, W1			;W1 <- W9
		rcall	Wyslij_dane_S65	;wyślij młodszy bajt koloru
		dec		W3, W3			;W3--
		;skocz jeśli nie było 0 do etykiety
		bra nz,	Rysuj_tlo_S65_petla

	return						;powrót z podprogramu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; rysowanie obszaru
; X1,Y1 (W5,W7)
;    +------+
;    |      |
;    |      |
;    |      |
;    |      |
;    +------+
;         X2,Y2 (W6,W8)
;
; kolor (W9)
Rysuj_obszar_S65:
	;ustaw wielkość pola
	;obszar = (X2-X1+1)*(Y2-Y1+1);
	sub		W6, W5, W3			;W3 <- W6-W5
	inc		W3, W3				;W3++
	sub		W8, W7, W4			;W4 <- W8-W7
	inc		W4, W4				;W4++
	mul.uu	W3, W4, W0			;W1:W0 <- W3*W4
	mov		W0, W3

	;sygnalizuj rozkaz (RS = 1)
	bset	LATB, #S65_RS

	;sekwencja uruchamiająca rysowanie obszaru
	mov.b	#0xEF, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x90, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x05, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x04, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x08, W1
	rcall	Wyslij_dane_S65
	mov		W7, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x09, W1
	rcall	Wyslij_dane_S65
	mov		W8, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x0A, W1
	rcall	Wyslij_dane_S65
	mov		W5, W1
	rcall	Wyslij_dane_S65
	mov.b	#0x0B, W1
	rcall	Wyslij_dane_S65
	mov		W6, W1
	rcall	Wyslij_dane_S65

	;sygnalizuj dane (RS = 0)
	bclr	LATB, #S65_RS

	;wypełnij kolorem
Rysuj_obszar_S65_petla:
		swap	W9				;zamień miejscami bajty W9
		mov		W9, W1			;W1 <- W9
		rcall	Wyslij_dane_S65	;wyślij starszy bajt koloru
		swap	W9				;zamień miejscami bajty W9
		mov		W9, W1			;W1 <- W9
		rcall	Wyslij_dane_S65	;wyślij młodszy bajt koloru
		dec		W3, W3			;W3--
		;skocz jeśli nie było 0 do etykiety
		bra nz,	Rysuj_obszar_S65_petla

	return						;powrót z podprogramu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; dane w pamięci programu

;sekwencje inicjujące S65
kod2:
	.byte 0xEF, 0x00, 0xEE, 0x04, 0x1B, 0x04, 0xFE, 0xFE, 0xFE, 0xFE 
	.byte 0xEF, 0x90, 0x4A, 0x04, 0x7F, 0x3F, 0xEE, 0x04, 0x43, 0x06

kod3:
	.byte 0xEF, 0x90, 0x09, 0x83, 0x08, 0x00, 0x0B, 0xAF, 0x0A, 0x00
	.byte 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0xEF, 0x00, 0xEE, 0x0C
	.byte 0xEF, 0x90, 0x00, 0x80, 0xEF, 0xB0, 0x49, 0x02, 0xEF, 0x00 
	.byte 0x7F, 0x01, 0xE1, 0x81, 0xE2, 0x02, 0xE2, 0x76, 0xE1, 0x83

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.end							;koniec programu
