<span style="font-family: courier new,monospace;">Χαιρετώ τη λίστα!</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Ας φανταστούμε τα εξής αρχεία:</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">/*=============== VS_UI.h ===============*/</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">#ifndef __VS_UI_h__</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define __VS_UI_h__</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">//#include "VS_Core.h"</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#include <stdio.h></span><br>
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define UP ('a')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define DOWN ('b')</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">#define ESC ('c')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define LEFT ('d')</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">#define ENTER ('e')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define RIGHT ('f')</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">typedef const char* Caption_t;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">typedef struct MenuObject* MenuObject_pt;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">typedef void (*MenuFunc_pt) (void);</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">typedef union node</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> MenuFunc_pt task;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> MenuObject_pt menu;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}Node_t;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">typedef struct MenuObject</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Caption_t cap;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Node_t link;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> int8_t isMenu;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}MenuObject_t;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">static uint8_t UI_retFlag = 0;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">extern const MenuObject_t Menu_Main[];</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">extern const MenuObject_t </span><span style="font-family: courier new,monospace;">Menu_Sub</span><span style="font-family: courier new,monospace;">[];</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">void task_a(void);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">void task_b(void);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">void task_C (void);</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">/*=== UI Functions ====*/</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">void UI_Menu (MenuObject_pt mo);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#ifdef __INLINE</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> __INLINE void UI_MenuBack (void) { UI_retFlag = 1; }</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#else</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> #define UI_MenuBack() (UI_retFlag = 1)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#endif</span><br style="font-family: courier new,monospace;">
<br><span style="font-family: courier new,monospace;">#endif //#ifndef __VS_UI_h__</span><br><br><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">/*=============== VS_UI.c ===============*/</span><br>
<span style="font-family: courier new,monospace;">#include "VS_UI.h"<br><br style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">/* Menu Diagram */</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">const MenuObject_t Menu_Main[] =</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{ </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {"",0,0},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {">A ", task_A, 0},</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {"sub", </span><span style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">Menu_Sub</span><span style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">, 1},</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {"ESC", UI_MenuBack, 0},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {0,0,0}</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">};</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">const MenuObject_t </span><span style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">Menu_Sub</span><span style="font-family: courier new,monospace;">[];</span><span style="font-family: courier new,monospace;">[] =</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {"",0,0},</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {">B ", task_B, 0},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {">C ", task_C, 0},</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {0,0,0}</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">};</span><br><br><font face="courier new,monospace">void task_A (void) { printf ("tza"); return; }<br>
</font><font face="courier new,monospace">void task_B (void) { printf ("tza"); return; }<br></font><font face="courier new,monospace">void task_C (void) { printf ("tza"); return; }</font><br><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">void UI_Menu (MenuObject_pt mo)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> </span><span style="font-family: courier new,monospace;">uint8_t</span><span style="font-family: courier new,monospace;"> i;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> int16_t InChar = 0;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> UI_retFlag = 0; //RST flag</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> if (mo[0].link.task) mo[0].link.task(); //Optional function call</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"><br>
for ( printf("\f"), i=1 ; mo[i].link.task ; )<br> {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> printf("\r%s", mo[i].cap); //Print each caption</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> InChar = getchar(); //Get user choice </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"><br> switch (InChar)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case UP: --i; break; //Navigating</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> case DOWN: ++i; break;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case ESC: //Actions </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> case LEFT:<br> UI_retFlag = 0;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> return;<br>
case RIGHT:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case ENTER:<br> if (mo[i].isMenu)<br> UI_Menu( mo[i].link.menu ); //Call menu<br>
else<br> mo[i].link.task(); //Call function</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> default:</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> break;<br> } </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> if (!i) </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> { </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> for ( i=1 ; mo[i].link.task ; ++i); </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> --i;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> }</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> if (! mo[i].link.task) i = 1;</span><span style="font-family: courier new,monospace;"></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> if (UI_retFlag) { UI_retFlag = 0; return; }<br>
}</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> return;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">/*=========== main.c ============*/</span><br style="font-family: courier new,monospace;">
<font face="courier new,monospace">#include "VS_UI.h"<br><br style="font-family: courier new,monospace;"></font><span style="font-family: courier new,monospace;">int main (void)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">{</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> UI_Menu (Menu_Main); //Stop Monitoring </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> while (1) // Main loop</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> ;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">}</span><br><br><font face="courier new,monospace">Να απολογηθώ εδώ ότι έχω ψαλιδίσει "αρκετά" τον κώδικα για να χωρέσει αλλά ίσως κάποιος να έλεγε ότι έπρεπε να κάνω καλύτερη δουλειά.<br>
<br><span style="font-family: courier new,monospace;">Το παραπάνω κομμάτι κώδικα υποτίθεται πως εμφανίζει ένα υποτυπώδες μενού σε μια μικροσκοπική συσκευή με έναν ARM Cortex-M3.</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Η λογική είναι η εξής. Κάνοντας πίνακες με ένα συγκεκριμένο τρόπο έτσι ώστε να αρχικοποιείται σωστά η δομή MenuObject μπορείς να δημιουργήσεις ότι δομή θέλεις στο menu σου. Η UI_Menu() δέχεται ένα δείκτη στον πίνακα με αντικείμενα τύπου MenuObject_t που έκανες και εμφανίζει τις επιλογές που υπάρχουν εκεί μέσα. O χρήστης(το πλάσμα που χειρίζεται το τελικό προϊόν) μπορεί να πλοηγηθεί στο τρέχον μενού (τρέχον πίνακας) βλέποντας ένα μήνυμα στην κάθε τρέχουσα επιλογή. Αν επιλέξει μία (πατήσει ENTER) τότε ελέγχεται αν το member isMenu είναι true. Αν ναι τότε το τρέχον αντικείμενο είναι υπομενού και έχουμε recursive call της UI_Menu() με τον νέο πίνακα. Αν το isMenu είναι false τότε κάνουμε call σαν συνάρτηση μέσω του δείκτη σε void (*) (void) στο τρέχον task που εμφανιζόταν εκείνη τη στιγμή.</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><font size="2"><span style="font-family: courier new,monospace;">Το παραπάνω </span></font></font><span style="font-family: courier new,monospace;">κομμάτι κώδικα το έχω χρησημοποιήσει παλιότερα με τον compiler keil για 8051 και δούλευε μια χαρά (απλά εκεί έπρεπε να δηλώσεις ότι τη UI_Menu() σαν reentrant).<br>
<br><span style="font-family: courier new,monospace;">- Όταν προσπαθώ να το κάνω compile με τον CC_ARM της keil πάλι (πλέον mdk-arm) με εμπέζει και μου λέει </span></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">error: #144: a value of type "const MenuObject_t *" cannot be used to initialize an entity of type "MenuFunc_pt"</span><br style="font-family: courier new,monospace;">
<font style="font-family: courier new,monospace;" face="courier new,monospace">στην γραμμή της αρχικοποίησης του πίνακα με το Menu_Sub</font><span style="font-family: courier new,monospace;">.<br>- Αν δεν χρησιμοποιήσω υπομενού το compile γίνεται κανονικά και το εκτελέσιμο "παίζει" κανονικά μόνο με tasks (ένα layer menu)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">- Αν αλλάξω τη σειρά των member στο union τότε o compiler παραπονιέται ΚΑΙ για:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">error: #144: a value of type "void (*)(void)" cannot be used to initialize an entity of type "MenuObject_pt"</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">"Υποτίθεται" πως ο compiler είναι ANSI C plus μερικά μπλιμπλίκια και δεν έχει διαφορές. Απλά παραπάνω μπιχλιμπίδια.</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Any ideas?</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">Φιλικά</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Χρήστος</span><br style="font-family: courier new,monospace;">