Snake na oscyloskop

(jeśli uważasz, że ten tekst jest chaotyczny, to dobrze uważasz; pisałem go na biegu i troche mi się nie chciało...)

(na dole strony jest galeria. i filmik. :))

Wstęp.

Pewnie zastanawiasz się - jak to możliwe? Ano możliwe - sam zobacz. Pomysł na zrobienie gry na oscyloskop lub inną lampę jest stary jak świat (no może bez przesady). Pierwszy był (chyba) Pong - poczytasz o nim i innych grach tutaj. No to zaczynamy.

Konstrukcja

Współczesne gry tego typu składają się zwykle z mikrokontrolera oraz przetworników D/A (cyfrowo/analogowych), których zdaniem jest zamiana wartości podanej na wejście (binarnie) na napięcie, które może posłużyć do odchylenia plamki na ekranie.

Do swojego projektu wybrałem mikrokontoler firmy Maxim/Dallas, model DS89C450. Należy on do rodziny MCS51 (czyli po prostu 8051). Na pokładzie znajdziemy:

O wyborze tego mikrokontrolera zdecydowało kilka aspektów - między innymi jego bogate możliwości, duża szybkość działania (przy maksymalnym zegarze wydajność obliczeniowa wynosi 33MIPS) no i fakt, że akurat miałem go pod ręką. :D

Procek rezyduje na płytce testowej, którą projektowałem przez pół roku. Płytka ta umożliwia programowanie procka przy użyciu jakiegokolwiek programu terminala, np. minicoma, poprzez RS232 (dla linuksiarzy ttySn, dla windziarzy COMn). Taktowany jest zegarem 11.0592MHz, czyli ok. 1/3 częstotliwości maksymalnej. Czemu akurat taka? Bo na niej najlepiej działa komunikacja przez RS232, a kwarc do zegara o takiej wartości kosztuje 1.40zł, a nie np. 5zł, jak te o wyższej częstotliwości.

Jako przetworniki D/A zastosowałem standardowe przetworniki DAC08 firmy Analog Devices. Mają one rozdzielczość 8 bitów, czyli mogą podać na wyjście 256 różnych poziomów napięcia. To raczej proste. Zostały one podłączone w bardzo typowy sposób (w zasadzie to przerysowałem żywcem schemat z karty katalogowej).

Przetworniki są dwa - do odchylania osi X oraz Y.

Jest jeszcze "joypad" zmontowany naprędce z walających się po pokoju części...

Działanie

Tu raczej nie ma wiele filozofii - każdy szanujący się programista chociaż raz napisał (albo próbował napisać) grę typu snake. Implementacja jest moja, pomysł też, chociaż sądzę, że wszystkie snake'i na świecie są napisane właśnie w ten sposób. Silnik działa w następujący sposób:

Odświeżanie ekranu po prostu przemiata węża od głowy do ogona, rysując kolejne kwadraciki. Kwadracik jest rysowany przez bardzo sophisticated procedurę:

#define	BOK	12
#define SQR	16
#define OFF	2
	
void vp_kwadracik(u8 x, u8 y)
{
X= x*SQR + OFF;
Y= y*SQR + OFF;
for (kw_c=BOK; kw_c; kw_c--) { X++; }
for (kw_c=BOK; kw_c; kw_c--) { Y++; }
for (kw_c=BOK; kw_c; kw_c--) { X--; }
for (kw_c=BOK; kw_c; kw_c--) { Y--; }
}

Generator liczb losowych to po prostu kręcący się niezależnie od innych timer, z którego w razie potrzeby odczytuję wartość (8-bitową) i rozbijam ją na dwie 4-bitowe oznaczające współrzędne X i Y punktu, XORując przy okazji z jakimiś innymi przypadkowymi wartościami z programu. Ponieważ odświeżanie minimalnie zależy od wciskania klawiszy, gra jest niepowtarzalna.

Program i kompilator

Co ja się będę rozpisywał... kompilowałem program przy użyciu opensource'owego SDCC. Kompilator jest beznadziejny (na jednym kawałku kodu mi segfaultował...), no ale lepszego nie mam, a za Keila płacić nie zamierzam.

Program powstawał w bólach, a tak poza tym to najpierw miał to być tetris. Lol...

Poza samą grą na początku jest rysowany kwadrat celem kalibracji viewportu. Potem jest jeszcze wybór poziomu trudności... osobiście lubię grać na siódemce. :] Na dziewiątce się nie da, bo timer odświeżający generuje przerwanie nieustannie i wąż porusza się z prędkością naddźwiękową... :D Na koniec pokazuje się liczba punktów. To znaczy powinna, ale kompilator ma problemy z operacjami na liczbach 16-bitowych. Zwłaszcza przesunięciach i and/or logicznych. Mówi się trudno...

Schematy!

Źródełka!

Galeria i filmik!