====== LED snake 8x8 na FRDM-KL25Z ====== ===== Zadání ===== * Displej použitý [[http://www.urel.feec.vutbr.cz/MIA/2009/divin/index.html|v rámci staršího projektu]] pro hru LED SNAKE připojte k vývojové desce FRDM-KL25Z a aplikaci portujte na tuto desku. * Využijte prostředí KDS nebo mbed. ===== Provedení ===== Hra snake má několik možných variant. Vzhledem k velikosti a rozlišení displeje jsou vhodné následující parametry: * Had začíná na velikosti 3. * Had se může pohybovat všemi směry a může procházet přes okraj displeje. * Pokud had sežere jablko prodlouží se o jednu kuličku a nedojde k jeho zrychlení. * Had je ovládán čtveřicí tlačítek a kdykoli v průběhu hry je možné měnit jeho rychlost pomocí kapacitního slideru. * Pokud se had kousne do svého těla dojde k ukončení hry a zobrazeni dosažené délky hada. Možnosti pohybu hada a jeho chování jsou zobrazeny na animaci níže. Také je zobrazeno číslování jednotlivých diod jak bylo použito pro mapování displeje v programu. {{ :2014:led-snake:matice.gif?200 |}} {{ :2014:led-snake:matice.png?200 |Prehled dvou mapovani disp.}} ===== Hardware ===== Pro aplikaci hada je využita vývojová deska FRDM-KL25Z. Na této desce jsou využity následující periferie. * Piny **PTC<0-7>** pro řízení sloupců displeje zelené barvy. * Piny **PTC<8,9,10,11,12,13,16,17>** jsou využity pro řízení sloupců červené barvy. * Piny **PTB<0-2>** jsou využity pro řízení řádků matice pro obě barvy. * Piny **PTD6, PTD7, PTE0 a PTE1** jsou využívány jako vstupní piny pro tlačítka. * Pin **PTB3** je nastaven na analogový vstup sloužící pro generování náhodných čísel. * Poslední využitou periferií je kapacitní slider, který slouží pro nastavení rychlosti hada. Tu lze proti základní rychlosti zpomalit, ale i zrychlit. {{ :2014:led-snake:diagram1.png?300 |Blokové schéma}} Vývojová deska je s displejem propojena pomocí redukčního přípravku, který má možnost připojení dvou tlačítek a rozhraní UART. Jelikož je had ovládán pomocí 4 tlačítek byla tlačítka vyvedena mimo na nepájivé kontaktní pole. Uspořádání tlačítek bylo zvoleno jako uspořádání kurzorových šipek na PC klávesnici.\\ {{ :2014:led-snake:schema_redukce.png?300 |Redukce KL25Z na disp.}}{{ :2014:led-snake:schema_tlacitka.png?200 |Schéma zapojení tlačítek}} {{ :2014:led-snake:deska_redukce.png?200 |}} Vzhledem k umístění kapacitního slideru na desce a jeho překrytí redukční deskou byly piny na tuto desku napájené v maximální délce. Ovládání rychlosti je tedy možné, ale špatně dosažitelné. {{:2014:led-snake:sam_0996.jpg?200|}} {{:2014:led-snake:sam_0998.jpg?200|}} {{:2014:led-snake:sam_10092.jpg?200|}} ===== Software ===== K psaní kódu bylo použito webové prostředí www.mbed.org. Použití tohoto prostředí skýtá některé výhody, ale i nevýhody. Mezi výhody patří: * Množství example a knihoven * Dostupnost odkudkoli kde je internetové připojení * Rychlé zprovoznění, není nutné řešit potíže * Zvýrazňování syntaxe * Možnost provést automatické formátování kódu Mnou pozorované nevýhody jsou následující: * Nutnost stahování bin souboru - zdržuje * Nemožnost sbalení funkcí nebo cyklů * Tabulátor odskakuje příliš daleko (4 mezery) * Občasná nedostupnost kompilátoru - vytížení (minimálně) Vzhledem k popsaným nevýhodám byla konečná vizuální podoba kódu upravena v textovém editoru kate. ==== KOD ==== Program je tvořen několika funkcemi jejich zaměření lze rozdělit na funkce starající se o zobrazení, generování dat a řízení hada. Do programu byly importovány knihovny TSI (kapacitní slider) a knihovna mbed. Kompletní program, binárka a soubory pro kompilaci jsou v archivu {{:2014:led-snake:snake.zip|}}. Řízení hada probíhá pomocí pole o rozměru 64 bodů. Pole s názvem h[64] o definovaném rozměru je naplněno číslem 65. Toto číslo nemůže nikdy nastat a složí jako informace o nepřítomnosti hada. Jednotlivé segmenty pole představují pořadové číslo článku hada a jejich hodnota udává pozici tohoto článku. Platí tedy že hlava bude vždy v h[0] a bude se lišit číselná hodnota. Pohyb hada je řešeny vytvořením nové hlavy na příslušné pozici podle zvoleného směru pohybu a vymazáním posledního článku ocasu hada. void pohyb() //pohyb hada v pracovnich souradnicich h[] { unsigned char i; switch (posun){ //na zaklade velikosti posunu rozhodne o smeru, funkce v case jsou temer totozne case 0: if(h[0]==7 || h[0]==15 || h[0]==23 || h[0]==31 || h[0]==39 || h[0]==47 || h[0]==55 || h[0]==63){ //osetreni projeti hada okrajem for(i=0;i Další zajímavou částí programu je generování pozice jablka. To probíhá pomocí srand a rand. Pro zajištění maximální náhodné hodnoty je vstupem funkce srand 1000 násobek hodnoty na pinu PTB3, který je nastaven jako analogový vstup a součet času od spuštění desky. void genj() // funkce generujici pozici jablka { char i; // pomocna ja = rand() % 64; //pozice jablka od 0 do 63 for(i = 0;i<=63;i++){ //kontrola zda neni jablko v hadovi if(h[i] == ja){ ja = rand() % 64; i = 0; } } s++; // pricteni jablka do skore - o jedno spozdeno } Poslední podrobně rozebranou částí kódu budou dvě funkce starající se o zobrazení hada na displeji. První z nich převede hodnoty z h[i] vyjádření do maticového zápisu had[8][8]. Druhá potom provede samotné zobrazení na displeji nastavením příslušných pinů. void dejmat() // prepocet pracovnich souradnic na souradnice na dipleji { unsigned char i,t1,t2; for(i = 0; i <= 65; i++){ if(h[i] != 65){ t1 = h[i] % 8; //sloupek t2 = h[i] / 8; //radek had[t2][t1] = 0; //vlozeni priznaku o pritomnosti do matice } } t1 = h[0] % 8; t2 = h[0] / 8; hlava[t2][t1] = 0; t1 = ja % 8; t2 = ja / 8; jablko[t2][t1] = 0; } void ukaz() //funkce zobrazeni zobrazovacich souradnic na displej provede několik zobrazeni po sobe { char i,j; for(i = 0; i < 8; i++){ for(j=0;j<8;j++){ // pro zamezeni blikani if(i == 0){ A=1;B=1;C=1; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 1){ A=0;B=1;C=1; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 2){ A=1;B=0;C=1; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 3){ A=0;B=0;C=1; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 4){ A=1;B=1;C=0; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 5){ A=0;B=1;C=0; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 6){ A=1;B=0;C=0; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } if(i == 7){ A=0;B=0;C=0; c0=had[i][0];c1=had[i][1];c2=had[i][2];c3=had[i][3];c4=had[i][4];c5=had[i][5];c6=had[i][6];c7=had[i][7]; z0=jablko[i][0]*hlava[i][0];z1=jablko[i][1]*hlava[i][1];z2=jablko[i][2]*hlava[i][2];z3=jablko[i][3]*hlava[i][3];z4=jablko[i][4]*hlava[i][4];z5=jablko[i][5]*hlava[i][5];z6=jablko[i][6]*hlava[i][6];z7=jablko[i][7]*hlava[i][7]; wait(0.0001); } } } } Funkce main probíhá celá v nekonečné smyčce, pro zajištění opakování hry. Následuje plnění pracovních polí příznakem o nepřítomnosti hada, nulování displeje a definice hada do výchozí polohy. Následuje smyčka hry která trvá tak dlouho dokud funkce konec nevrátí 0. Následují funkce pro zablikání hada po zakousnutí, výpočet a zobrazení skóre. Poslední smyčka while probíhá dokud není stisknuté tlačítko UP. int main() { while(1){ int i,k=0,kk=40,t1,t2; srand (time(NULL)+ran*1000); //pro skoronahodnou posloupnost for(i=0;i<65;i++){ //nulovani pracovnich poli h[i] = 65; hh[i] = 65; } nuldisp(); //na zacatku vynuluj displej for (i = 0; i < size; i++){ //pocatecni delka hada v zobrazovaci matici had[0][i] = 0; } h[0]=2;h[1]=1;h[2]=0; // pocatecni had v pracovnim poli genj(); //generovani jablka while(konec()){ //smycka vlastni hry tlac(); //obsluha tlacitek dejmat(); //prevod z prac do matic ukaz(); //zobrazeni matice if(100*tsi.readPercentage() > 10){ // ovladani rychlosti hada, pokud se dotknu slideru ulozi se aktualni hodnota do promene kk = 110-100*tsi.readPercentage(); // doleva pomalejsi doprava rychlejsi } if(k >= kk ){ // zajisteni pohybu hada danou rychlosti pohyb(); chlamst(); k = 0; } k++; } // zablikani hada pokud se zakousne nuldisp(); cekej(); dejmat(); cekej(); nuldisp(); cekej(); dejmat(); cekej(); nuldisp(); cekej(); nuldisp(); score(s); // prepocet skore for(i = 0; i <= 65; i++){ // prevedeni do maticove podoby if(h[i] == 66){ t1 = i % 8; t2 = i / 8; had[t2][t1] = 0; } } while(1){ //smycka zobrazujici skore az do stisku reset nebo sipky nahoru ukaz(); if(up ==0){ size = 3;s=2;posun = 0; wait(0.5); break; } } } } ===== Videoukázka ===== Na videu jsou ukázané všechny funkce. Je ukázána krátká hra s hadem pohybujícím se všemi směry, sežrání jablka, zakousnutí hada a zobrazení skóre. Následuje restart hry a ukázka změny rychlosti. {{ youtube>XWr7cuOYZPU?medium }} ===== Zhodnocení ===== V programu jsou implementovány všechny důležité funkce a hra je plně funkční. Program je připraven pro možnost implementování dalších funkcí jako výpočet skóre s ohledem na rychlost hada nebo náhodné generování překážek případně zrychlování hada po sežrání jablka. Tato vylepšení hry by vyžadovala implementaci jednoduchého menu které by umožnilo zapnout různé funkce.