Menu wyboru w czystym C


(Marcin Obala) #1

Cześć. Zastanawiam się jak w kodzie zbudować menu. Program jest odpalany na mikrokontrolerze więc nie ma mowy o C++. To co piszę to gra typu refleks.

Menu Główne

Start gry -> rozpoczynamy grę

Opcje -> kolejne podmenu

Autorzy -> informacje o autorach

Wyjście -> Informacja na wyświetlaczu w stylu "Możesz teraz wyłączyć kontroler"

Podmenu opcji

Wybierz głośnik -> Chodzi o to po pisku głośnika trzeba jak najszybciej wcisnąć przycisk

Wybierz diody -> to co wyżej tylko, że po zapaleniu się wszystkich diód

Wybierz wyświetlacz -> j.w. z tym, że po wyświetleniu się jakiegoś komunikatu czy zmianie koloru wyświetlacza na np. zielony.

Powrót -> Powrót do menu głównego.

Jakie są wasze sugestie? Myślałem o strukturach i zbudować coś na zasadzie listy dwukierunkowej ale nie wiem jak podpisać pod konkretne struktury inne funkcje.


(Xeon Bloomfield) #2

http://pl.wikipedia.org/wiki/C_(język_programowania)#Instrukcja_switch


([alex]) #3

Może coś w tym stylu:

#include

(Marcin Obala) #4

Jak się rozbudzę i rozłożę z płytką to sprawdzę. Chodzi o to, że to będzie menu wyboru więc switch w połączeniu ze scanfem odpada. Ale kod alexa można już przerobić :wink: Po menu będę poruszał się joystickiem i aktualne menu zostaje podświetlone ( tak naprawdę zamieniony kolor tła) a po wciśnięciu joysticka zostaje przeniesione do odpowiedniego menu. Co do joysticka przechwycę przerwanie lub po prostu w pętli wykryję

KEY = (LPC_GPIO1->FIOPIN >> 25) & 0x01;

i mam w KEY 1 lub 0 :wink: albo wciśnięto albo nie a pod 'p' po prostu podstawię jakąś zmienną którą będę zmieniać po zdarzeniach JOY_DOWN lub JOY_UP.


([alex]) #5

switch'a jak widzisz tu niema.

scanf'a możesz zastąpić, ilość wierszy menu masz w m->subsize

Prosiłeś o radę jak to zorganizować więc ją masz :smiley:


(Marcin Obala) #6

Ok, menu śmiga ale płytka zawiesza się przy próbie wejścia w opcje :wink: dodatkowo powiem że płytka ma tylko 64 KB ramu.

Kod wygląda tak

void runmenu(struct menuitem *m)

{

	enum JOYSTICK_KEYS {KEY_NOT=32, KEY_DOWN=2, KEY_LEFT=4, KEY_RIGHT=8, KEY_UP = 16, KEY_PUSH=1};

    int p;

	char czas[20]="";

	int i,aktualna_linia;

	int PRESSED=0;

	uint8_t KEY=0;

	char tab[10][50];

    for(;;)

    {

		zeruj_LCD();

        //fflush(stdin);

        for(p=0;psubsize;++p) 

        {									

			char aaa[50]="";

			sprintf(aaa,"%s",m->sub[p].text);

			sprintf(tab[p],"%s",aaa);

            GLCD_DisplayString(p,0,(unsigned char*)(aaa));

        }

		change_Menu(0,tab,m->subsize-1);


		while(1)

		{

			KEY = (LPC_GPIO1->FIOPIN >> 25) & 0x1F;

			KEY = 31-KEY;

			if(KEY==KEY_PUSH)

			{

			break;

			}

			if(KEY==KEY_DOWN || KEY == KEY_UP)

			{

				PRESSED=1;

			}

			if(PRESSED)

			{

				aktualna_linia=change_Menu(KEY,tab,m->subsize-1);

				PRESSED=0;

			}

			delayMs(0,400);

		}

	 	p=aktualna_linia+1;

        if((0
subsize))

        {

            --p;

            if(m->sub[p].subsize) 

            {

                runmenu(m->sub+p);

            }

            else if(m->sub[p].proc)

            {

                m->sub[p].proc();


            }

        }

    }

}

Wiem wiem że można kod zoptymalizować (np. to PRESSED w ogóle jest niepotrzebne) ale nie o to teraz chodzi. Po prostu przy wywołaniu

if(m->sub[p].subsize) 

            {

                runmenu(m->sub+p);

            }

Płytka się wiesza. Po debugowaniu okazało się że płytka się zawiesza przy

char czas[20]="";

podczas drugiego wywołania funkcji runmenu()

-- Dodane 18.01.2011 (Wt) 22:07 --

Wyrzuciłem wszystkie zmienne "do góry" czyli jako zmienne globalne i poszło.


(Airborn) #7

Rozwiązałeś swój problem, ale przedstawię jeszcze jeden sposób który zaproponował niedawno caladan.

Tylko?! Toć to krocie jak na uC :wink:


([alex]) #8

zamień:

         char aaa[50]="";         sprintf(aaa,"%s",m-sub[p].text);         sprintf(tab[p],"%s",aaa);         GLCD_DisplayString(p,0,(unsigned char*)(aaa));[/code]na:


[code=php]         char aaa[50]="";         strcpy(tab[p],m-sub[p].text);         GLCD_DisplayString(p,0,(unsigned char*)(tab[p]));

zaś, to:

       p=aktualna_linia+1;        if((0p)(p=m-subsize))        {            --p;            if(m-sub[p].subsize)            {                runmenu(m-sub+p);            }            else if(m-sub[p].proc)            {                m-sub[p].proc();            }[/code]na:


[code=php]        if((0=aktualna_linia)(aktualna_liniam-subsize))        {            if(m-sub[aktualna_linia].subsize)            {                runmenu(m-sub+aktualna_linia);            }            else if(m-sub[aktualna_linia].proc)            {                m-sub[aktualna_linia].proc();            }Jak masz ograniczenia pamięciowe to staraj się optymalizować w locie.

(Marcin Obala) #9

Ja wiem :wink: po prostu kopiowałem stary kod i nie optymalizowałem go jeszcze :wink: to pressed jeszcze wyrzucić w ifie dać od razu sprawdzanie co zostało wciśnięte.