📄 display.c
字号:
#include <string.h>#include "printf.h"#include "as31glue.h"#include "parse.h" // for event codes#include "stricmp.h"#include "sta013.h"#include "main.h"#include "rand.h"#include "playlist.h"#include "treedir.h"#include "display.h"/***************************************************************//** **//** Variables **//** **//***************************************************************/#define DISPLAY_WIDTH 24#define DISPLAYBUF_MAX 250// Which screen is (or should be) displayedtypedef enum { MAINSCREEN, AUDIOSCREEN, TREEDIRSCREEN, EPARAMSCREEN, SCREEN_MAX = 3} screen_t;static screen_t current_screen;// Which control on that screen is selectedstatic unsigned char current_control;// Storage for the displayed filenamestatic xdata unsigned char filebuf[DISPLAYBUF_MAX];static xdata unsigned char filebuf_len;static xdata unsigned char filebuf_changed;// Storage for the displayed directory or playlist namestatic xdata unsigned char dirbuf[DISPLAYBUF_MAX];static xdata unsigned char dirbuf_len;static xdata unsigned char dirbuf_changed;// Storage for the id3 tag infostatic xdata char id3_title[DISPLAY_WIDTH+1];static xdata char id3_artist[DISPLAY_WIDTH+1];static xdata char id3_album[DISPLAY_WIDTH+1];static xdata unsigned char id3_title_changed;static xdata unsigned char id3_artist_changed;static xdata unsigned char id3_album_changed;// Set to force all controls to redrawstatic bit force_redraw;// Location and font to use for drawingstatic unsigned char draw_at_x, draw_at_y, draw_font;// Storage of the ID3 tag to displayxdata struct id3_tag_struct id3_tag;// miscstatic unsigned int addr7_backup;static code char lcd_set_xy_cmd[]="\\[\\B";static code char lcd_set_font_cmd[]="\\C";static code char lcd_set_end_cmd[]="\\]\r\n";// on-screen descriptions for play modesstatic code struct { code char *short_name; code char *desc_line1; code char *desc_line2; code char *desc_line3;} play_mode_description[] = { //123456789012 12345678901234567890 12345678901234567890 12345678901234567890 {"DirInOrder ","Play only this", "directory, in", "sequence"}, {"DirRandom ","Play only this", "directory, in", "random order"}, {"AllInOrder ","Play all files in", "sequence", ""}, {"RandomPlylst","Play each dir in", "sequence, choose new","directories randomly"}, {"RandomSelect","Play all files in", "sequence, but select","randomly on keypress"}, {"AllRandom ","Play all files in", "randomized order", ""}};/***************************************************************//** **//** Function Prototypes **//** **//***************************************************************/// Only static defs belong here... functions callable from other files// should be defined in display.h.static void lcd_begin_draw(void);static void lcd_end_draw(void);#pragma CALLEE-SAVES lcd_begin_draw,lcd_end_drawstatic void call_nonreentrant_function(void (*p)(void), unsigned char parm);static code struct screen_config_struct * cfg_of_current_control(void);static void lcd_do_user_action(code struct screen_config_struct *cfg, event_t event);#pragma CALLEE-SAVES print_string;static void print_string(xdata char *str);#pragma CALLEE-SAVES underscore_to_space;static unsigned char underscore_to_space(xdata char *str);/***************************************************************//** **//** Screens Configuration **//** **//***************************************************************/// definition of the tables belowstruct screen_config_struct { unsigned char x; unsigned char y; void (*redraw_routine) (void) reentrant; unsigned char next_up; unsigned char next_down; unsigned char next_left; unsigned char next_right; void (*inc_routine) (unsigned char) reentrant; unsigned char inc_param; void (*dec_routine) (unsigned char) reentrant; unsigned char dec_param;};// These tables configure which controls will appear on each screen, where// they appear, what order they are selected using the navigation keys// and what happens when the user attempts to modify with INC/DEC.static code struct screen_config_struct main_screen_config[] = {// X Y how_to_redraw up dn lf rt inc handler inc param dec handler dec param {0, 7, redraw_vol, 4, 1, 4, 1, action_vol_up, 0, action_vol_down, 0}, {0, 0, redraw_play, 0, 3, 0, 2, put_back_event, E_PLAY_PAUSE, put_back_event, E_PLAY_PAUSE}, {6, 0, redraw_mode, 0, 3, 1, 3, play_mode_next, 0, play_mode_prev, 0}, {0, 1, redraw_file, 1, 4, 1, 4, put_back_event, E_PLAY_PAUSE, put_back_event, E_PLAY_PAUSE}, {0, 2, redraw_dir, 3, 0, 3, 0, put_back_event, E_PLAY_PAUSE, put_back_event, E_PLAY_PAUSE}, {0, 3, redraw_id3_1, 0, 0, 0, 0, no_action, 0, no_action, 0}, {0, 4, redraw_id3_2, 0, 0, 0, 0, no_action, 0, no_action, 0}, {0, 5, redraw_id3_3, 0, 0, 0, 0, no_action, 0, no_action, 0}, {0, 6, redraw_bitrate, 0, 0, 0, 0, no_action, 0, no_action, 0}, {10,6, redraw_sfreq, 0, 0, 0, 0, no_action, 0, no_action, 0}, {18,6, redraw_stereo, 0, 0, 0, 0, no_action, 0, no_action, 0}, {19,0, redraw_time, 0, 0, 0, 0, no_action, 0, no_action, 0}};static code struct screen_config_struct audio_screen_config[] = {// X Y how_to_redraw up dn lf rt inc handler inc param dec handler dec param {0, 7, redraw_vol, 5, 1, 5, 1, action_vol_up, 0, action_vol_down, 0}, {0, 0, redraw_play, 0, 3, 0, 2, put_back_event, E_PLAY_PAUSE, put_back_event, E_PLAY_PAUSE}, {6, 0, redraw_mode, 0, 3, 1, 3, play_mode_next, 0, play_mode_prev, 0}, {0, 1, redraw_treble, 1, 4, 1, 4, sta013_tone_up, PARAM_TREBLE, sta013_tone_down, PARAM_TREBLE}, {0, 3, redraw_bass, 3, 5, 3, 5, sta013_tone_up, PARAM_BASS, sta013_tone_down, PARAM_BASS}, {0, 5, redraw_balance, 4, 0, 4, 0, sta013_tone_up, PARAM_BALANCE, sta013_tone_down, PARAM_BALANCE}, {19,0, redraw_time, 0, 0, 0, 0, no_action, 0, no_action, 0}};/***************************************************************//** **//** Redraw Handlers For Individual On-screen Controls **//** **//***************************************************************/// These redraw handlers actually do all the work of drawing the// on-screen controls. Each one should store the on-screen data// in a static variables and immediately return if the live data// has not changed, unless the force_redraw bit is set.//// Before drawing, lcd_begin_draw() should be called to set up// the X,Y coordinates and proper font, and lcd_end_draw() should// be called after all drawing to take care of cleanup.static voidredraw_vol(void){ unsigned char attn; static unsigned char prev_attn=255; attn = param_value[PARAM_ATTN] - STA013_PARAM_CENTRE + tone_attn; if (attn == prev_attn && !force_redraw) return; prev_attn = attn; if (attn > 99) attn = 99; lcd_begin_draw(); print("Vol:\\C "); if (attn) { printf("-%2d dB", attn); } else { print(" 0 dB"); } lcd_end_draw();}static voidredraw_play(void){ static unsigned char prev_playing=255; if (playing == prev_playing && !force_redraw) return; prev_playing = playing; lcd_begin_draw(); if (playing) { print("Play "); } else { print("Pause"); } lcd_end_draw();}static voidredraw_mode(void){ static unsigned char prev_play_mode=255; if (play_mode == prev_play_mode && !force_redraw) return; prev_play_mode = play_mode; lcd_begin_draw(); print(play_mode_description[play_mode].short_name); // TODO: also check for a flash param to disable this balloon description if (draw_font == 1) { print("\\K2!0\\K2\"0\\C \r\n+----/ \\\\-------+"); // TODO: change printf to left justify strings within field width printf("\r\n| %20s |", play_mode_description[play_mode].desc_line1); printf("\r\n| %20s |", play_mode_description[play_mode].desc_line2); printf("\r\n| %20s |", play_mode_description[play_mode].desc_line3); print( "\r\n+----------------------+\r\n"); } lcd_end_draw();}/* * \[\B !\C \K1! \K3!1bonnie raitt - i cant make you love me\K3!0\K2!0\] **/static voidredraw_scrollable_line(xdata char *str, unsigned char len){ lcd_begin_draw(); if (len <= DISPLAY_WIDTH) { // disable scrolling print("\\K2"); print_char(draw_at_y+0x20); print_char('0'); // print string normally lcd_print_string(str); } else { // set scrolling font (is this necessary? ...because lcd_begin_draw set it) print("\\K1"); print_char(draw_at_y+0x20); print_char(draw_font+0x20); // begin scrolling buffer fill print("\\K3"); print_char(draw_at_y+0x20); print_char('1'); // send full string to LCD's scroll buffer lcd_print_string(str); print(" "); // end scrolling buffer fill print("\\K3"); print_char(draw_at_y+0x20); print_char('0'); // enable automatic horz scrolling by LCD print("\\K2"); print_char(draw_at_y+0x20); print_char('1'); } lcd_end_draw();}static voidredraw_file(void){ if (!filebuf_changed && !force_redraw) return; redraw_scrollable_line(filebuf, filebuf_len); filebuf_changed = 0;}static voidredraw_dir(void){ if (!dirbuf_changed && !force_redraw) return; redraw_scrollable_line(dirbuf, dirbuf_len); dirbuf_changed = 0;}static voidredraw_id3_1(void){ if (!id3_title_changed && !force_redraw) return; lcd_begin_draw(); lcd_print_string_width(id3_title, 24); id3_title_changed = 0; lcd_end_draw();}static voidredraw_id3_2(void){ if (!id3_artist_changed && !force_redraw) return; lcd_begin_draw(); lcd_print_string_width(id3_artist, 24); id3_artist_changed = 0; lcd_end_draw();}static voidredraw_id3_3(void){ if (!id3_album_changed && !force_redraw) return; lcd_begin_draw(); lcd_print_string_width(id3_album, 24); id3_album_changed = 0; lcd_end_draw();}unsigned intget_elapsed_seconds(void){ return (unsigned long)((GetFrameCount() - songStartFrameCount) * (unsigned long)playback.ms_per_frame) / (unsigned long)1000;}static voidredraw_time(void){ static unsigned int prevsec = 0xffff; unsigned int sec; //print_char('t'); sec = get_elapsed_seconds(); if (sec == prevsec && !force_redraw) return; prevsec = sec; lcd_begin_draw(); printf("%2d:%02d", sec / 60, sec % 60); lcd_end_draw();}static voidredraw_bitrate(void){ static unsigned int prev_bitrate=0xFFFF; if (!playback.mode_known) { lcd_begin_draw(); print(" kbps"); prev_bitrate=0xFFFF; lcd_end_draw(); return; } if (prev_bitrate == playback.bitrate && !force_redraw) return; prev_bitrate = playback.bitrate; lcd_begin_draw(); printf("%3d kbps", prev_bitrate); lcd_end_draw();}static voidredraw_sfreq(void){ static unsigned char prev_freq=0xFF; if (!playback.mode_known) { lcd_begin_draw(); print(" kHz"); prev_freq=0xFF; lcd_end_draw(); return; } if (prev_freq == playback.freq && !force_redraw) return; prev_freq = playback.freq; lcd_begin_draw(); printf("%2d kHz", prev_freq); lcd_end_draw();}static voidredraw_stereo(void){ static char prev_stereo=0; if (!playback.mode_known) { lcd_begin_draw(); print(" "); prev_stereo=0; lcd_end_draw(); return; } if (prev_stereo == playback.mode[0] && !force_redraw) return; prev_stereo = playback.mode[0]; lcd_begin_draw(); printf("%s", playback.mode); lcd_end_draw();}static voiddraw_bar(unsigned char param){ signed char i, position; position = param + STA013_MAX_TONE - STA013_PARAM_CENTRE - 2; if (position < 0) position = 0; if (position > 21) position = 21; print_char('['); for (i=0; i<position; i++) { print_char((i == 10) ? 'o' : '-'); } print_char('*'); for (i=position+1; i<=21; i++) { print_char((i == 10) ? 'o' : '-'); } print_char(']');}static voidredraw_treble(void){ static unsigned char prev_treble=255; if (prev_treble == param_value[PARAM_TREBLE] && !force_redraw) return; prev_treble = param_value[PARAM_TREBLE]; printf("Treble = %d\n", prev_treble); lcd_begin_draw(); print("Treble\r\n"); draw_bar(prev_treble); lcd_end_draw();}static voidredraw_bass(void){ static unsigned char prev_bass=255; if (prev_bass == param_value[PARAM_BASS] && !force_redraw) return; prev_bass = param_value[PARAM_BASS]; lcd_begin_draw(); print("Bass\r\n"); draw_bar(prev_bass); lcd_end_draw();}static voidredraw_balance(void){ static unsigned char prev_balance=255; if (prev_balance == param_value[PARAM_BALANCE] && !force_redraw) return; prev_balance = param_value[PARAM_BALANCE]; lcd_begin_draw(); print("Balance\r\n"); draw_bar(prev_balance); lcd_end_draw();}static voidno_action(void) { }/***************************************************************//** **//** Redraw Code (call these functions to redraw) **//** **//***************************************************************/// These routines take care of redrawing the screens, by calling// the individual redraw routine above, according to the config// table.// redraw all on-screen controls that need updatingvoidlcd_redraw_screen(void){ unsigned char num=0, i=0; code struct screen_config_struct *cfg; if (current_screen == TREEDIRSCREEN) { if (force_redraw) { force_redraw = 0; treedir_display(); } return; } if (current_screen == EPARAMSCREEN) { if (force_redraw) { force_redraw = 0; eparam_display(); } return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -