leveledit.c

Go to the documentation of this file.
00001 
00039 #include "leveledit.h"
00040 
00041 #include "cfg/cfg_gfx.h"
00042 #include <cfg/macros.h> /* MAX() */
00043 
00044 #include <drv/kbd.h>
00045 #include <drv/timer.h>
00046 
00047 #include <gui/levelbar.h>
00048 
00049 #include <cpu/pgm.h>
00050 
00051 #include <gfx/text.h>
00052 #include <gfx/font.h>
00053 
00054 #if CONFIG_MENU_MENUBAR
00055 #include <gui/menubar.h>
00056 #endif
00057 
00058 #include <drv/lcd_gfx.h>
00059 
00060 #warning FIXME: Revise me!
00061 
00062 #define LBAR_HEIGHT 16
00063 
00067 void level_edit(struct LevelEdit *lev)
00068 {
00069 #if CONFIG_MENU_MENUBAR
00070     /* Labels for menubars */
00071     enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 };
00072     const_iptr_t labels[] =
00073     {
00074         (const_iptr_t)LABEL_BACK,
00075         (const_iptr_t)LABEL_MINUS,
00076         (const_iptr_t)LABEL_PLUS,
00077         (const_iptr_t)LABEL_EMPTY
00078     };
00079     struct MenuBar mb;
00080 #endif /* CONFIG_MENU_MENUBAR */
00081 
00082     struct LevelBar bar1, bar2;
00083     keymask_t keys, old_rpt_mask;
00084     int step, rep_step;
00085 
00086     rep_step = MAX(lev->step, ((lev->max - lev->min) / 200));
00087     step = lev->step;
00088 
00089     // Allow keys repetition.
00090     old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
00091 
00092     text_clear(lev->bitmap);
00093     //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE);
00094     text_puts(lev->title, lev->bitmap);
00095     //text_style(0, STYLEF_UNDERLINE);
00096 
00097     if (lev->type & LEVELEDIT_DOUBLE)
00098     {
00099         int chn = 0;  /* edit both channels */
00100 
00101         /* Levelbars init */
00102         lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
00103                 lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23);
00104         lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL,
00105                 lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23);
00106 
00107         #if CONFIG_MENU_MENUBAR
00108             labels[3] = (const_iptr_t)ch_labels[chn];
00109             mbar_init(&mb, lev->bitmap, labels, countof(labels));
00110             mbar_draw(&mb);
00111         #endif /* CONFIG_MENU_MENUBAR */
00112 
00113         /* Input loop for double level setting */
00114         for (;;)
00115         {
00116             #if CONFIG_LEVELEDIT_TIMEOUT != 0
00117                 ticks_t idle_timeout = timer_clock();
00118             #endif
00119             do
00120             {
00121                 if (lev->display_hook)
00122                     lev->display_hook(lev);
00123                 else
00124                 {
00125                     text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit);
00126                     PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val);
00127                     PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val);
00128 
00129                     lbar_setLevel(&bar1, *lev->ch1_val);
00130                     lbar_setLevel(&bar2, *lev->ch2_val);
00131                     lbar_draw(&bar1);
00132                     lbar_draw(&bar2);
00133                 }
00134 
00135                 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00136                     if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT))
00137                     {
00138                         /* Accept input implicitly */
00139                         keys = K_OK;
00140                         break;
00141                     }
00142                 #endif
00143             }
00144             while (!(keys = kbd_peek()));
00145 
00146             if (keys & K_CANCEL)
00147                 break;
00148 
00149             if (keys & K_OK)
00150             {
00151                 chn = (chn + 1) % 3;
00152 
00153                 #if CONFIG_MENU_MENUBAR
00154                     labels[3] = (const_iptr_t)ch_labels[chn];
00155                     mbar_draw(&mb);
00156                 #endif /* CONFIG_MENU_MENUBAR */
00157             }
00158 
00159             /* Increment step to achieve greater accelerations on larger values */
00160             if (keys & K_REPEAT)
00161                 step = MIN(rep_step, step + 1);
00162             else
00163                 step = lev->step;
00164 
00165             if (keys & (K_UP | K_DOWN))
00166             {
00167                 if (keys & K_UP)
00168                 {
00169                     /* If changing both channels (chn == 0), don't change
00170                      * level if one of two is at min or max */
00171                     if (chn != 0 ||
00172                             (*lev->ch1_val + step <= lev->max
00173                              && *lev->ch2_val + step <= lev->max))
00174                     {
00175                         /* If chn == 0 change both channels */
00176                         if (chn != 2)
00177                         {
00178                             *lev->ch1_val += step;
00179                             if (*lev->ch1_val > lev->max)
00180                                 *lev->ch1_val = lev->max;
00181                         }
00182                         if (chn != 1)
00183                         {
00184                             *lev->ch2_val += step;
00185                             if (*lev->ch2_val > lev->max)
00186                                 *lev->ch2_val = lev->max;
00187                         }
00188                     }
00189                 }
00190                 else
00191                 {
00192                     if (chn != 0 ||
00193                             (*lev->ch1_val - step >= lev->min
00194                              && *lev->ch2_val - step >= lev->min))
00195                     {
00196                         if (chn != 2)
00197                         {
00198                             *lev->ch1_val -= step;
00199                             if (*lev->ch1_val < lev->min)
00200                                 *lev->ch1_val = lev->min;
00201                         }
00202                         if (chn != 1)
00203                         {
00204                             *lev->ch2_val -= step;
00205                             if (*lev->ch2_val < lev->min)
00206                                 *lev->ch2_val = lev->min;
00207                         }
00208                     }
00209                 }
00210 
00211                 if (lev->set_hook)
00212                     lev->set_hook();
00213             }
00214         } // end for(;;)
00215     }
00216     else
00217     {
00218         const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
00219 
00220 /*
00221         const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit),
00222                         PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit));
00223 
00224         const coord_t barlen = lev->bitmap->width - 6 - textw;
00225 */
00226         const coord_t barlen = lev->bitmap->width;
00227         const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height;
00228         lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
00229               lev->min, lev->max, *lev->ch1_val,
00230               0, barvtop, barlen,  barvtop + LBAR_HEIGHT);
00231 
00232         #if CONFIG_MENU_MENUBAR
00233             mbar_init(&mb, lev->bitmap, labels, countof(labels));
00234             mbar_draw(&mb);
00235         #endif /* CONFIG_MENU_MENUBAR */
00236 
00237         /* Input loop for single level setting */
00238         for (;;)
00239         {
00240             #if CONFIG_LEVELEDIT_TIMEOUT != 0
00241                 ticks_t idle_timeout = timer_clock();
00242             #endif
00243             do
00244             {
00245                 if (lev->display_hook)
00246                     lev->display_hook(lev);
00247                 else
00248                 {
00249                     if (lev->type != LEVELEDIT_NOBAR)
00250                     {
00251                         lbar_setLevel(&bar1, *lev->ch1_val);
00252                         lbar_draw(&bar1);
00253                     }
00254                     PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height,
00255                         TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit);
00256                 }
00257 
00258                 #if CONFIG_LEVELEDIT_TIMEOUT != 0
00259                     if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT)
00260                     {
00261                         /* Accept input implicitly */
00262                         keys = K_CANCEL;
00263                         break;
00264                     }
00265                 #endif
00266 
00267             }
00268             while (!(keys = kbd_peek()));
00269 
00270             if (keys & K_CANCEL)
00271                 break;
00272 
00273             /* Increment step to achieve greater accelerations on larger values */
00274             if (keys & K_REPEAT)
00275                 step = MIN(rep_step, step + 1);
00276             else
00277                 step = lev->step;
00278 
00279             if (keys & K_UP)
00280             {
00281                 *lev->ch1_val += step;
00282                 if (*lev->ch1_val > lev->max)
00283                     *lev->ch1_val = lev->max;
00284             }
00285 
00286             if (keys & K_DOWN)
00287             {
00288                 *lev->ch1_val -= step;
00289                 if (*lev->ch1_val < lev->min)
00290                     *lev->ch1_val = lev->min;
00291             }
00292 
00293             if (lev->set_hook)
00294                 lev->set_hook();
00295         }
00296     }
00297 
00298     kbd_setRepeatMask(old_rpt_mask);
00299 }
00300 
00305 void level_init(struct LevelEdit *lev,
00306         int type,
00307         struct Bitmap *bmp, const char *title, const char *unit,
00308         int min, int max, int step,
00309         int *ch1_val, int *ch2_val,
00310         level_set_callback *set_hook, display_callback *display_hook)
00311 {
00312     lev->type   = type;
00313     lev->bitmap = bmp;
00314     lev->title  = title;
00315     lev->unit   = unit;
00316     lev->min    = min;
00317     lev->max    = max;
00318     lev->step   = step;
00319 
00320     lev->ch1_val = ch1_val;
00321     lev->ch2_val = ch2_val;
00322     lev->set_hook     = set_hook;
00323     lev->display_hook = display_hook;
00324 }