00001 #include "mbed.h"
00002 #include "font.h"
00003 #include "arial_8pt.h"
00004 #include "ini.h"
00005 #include <ctype.h>
00006
00007
00008 #define ROWS 16
00009 #define COLUMNS 64
00010
00011 typedef enum
00012 {
00013 kOrange = 0,
00014 kGreen = 1,
00015 kRed = 2,
00016 kBlack = 3
00017 }
00018 color_t;
00019
00020 typedef struct
00021 {
00022 unsigned char pixel[COLUMNS];
00023 }
00024 row_t;
00025
00026 typedef struct
00027 {
00028 int rows;
00029 int columns;
00030 row_t row[ROWS];
00031 }
00032 matrix_t;
00033
00034 matrix_t Panel;
00035
00036 DigitalOut led1(LED1);
00037 DigitalOut led2(LED2);
00038 DigitalOut led3(LED3);
00039 DigitalOut led4(LED4);
00040
00041 DigitalOut Enable(p5);
00042 DigitalOut Clock(p15);
00043 DigitalOut Latch(p14);
00044 DigitalOut R1(p6);
00045 DigitalOut R2(p7);
00046 DigitalOut G1(p12);
00047 DigitalOut G2(p13);
00048 BusOut Row(p8,p9,p10,p11);
00049
00050 DigitalIn Switch(p20);
00051
00052 #define PANEL_ON Enable = 0
00053 #define PANEL_OFF Enable = 1
00054 #define CLOCK_DATA Clock=0; Clock=1
00055 #define LATCH_DATA Latch=0; Latch=1
00056
00057 Serial PC(USBTX,USBRX);
00058 LocalFileSystem local("local");
00059 const char *ini_file = "/local/pages.ini";
00060
00061 #define MAX_LINES (4)
00062 #define MAX_LINE_LENGTH (128)
00063 #define MAX_PAGES (7)
00064 #define SCROLL_GAP (24)
00065
00066
00067 typedef struct
00068 {
00069 char str[MAX_LINE_LENGTH];
00070 color_t color;
00071 int x;
00072 int y;
00073 int scroll;
00074 int strlen_pixels;
00075 }
00076 line_t;
00077
00078 typedef struct
00079 {
00080 line_t line[MAX_LINES];
00081 int hide;
00082 }
00083 page_entry_t;
00084
00085 page_entry_t pages[MAX_PAGES];
00086
00087
00088 struct
00089 {
00090 float scroll_speed;
00091 float brightness;
00092 }
00093 app_data;
00094
00095
00096 void led_sweep();
00097 void panel_load(unsigned char *p_pixel, int nr_of_pixels);
00098 void panel_refresh_row(int nr, row_t *p_pixel_data, int nr_of_pixels);
00099 void panel_refresh(matrix_t *p_panel);
00100 void panel_init(matrix_t& panel, int rows, int columns);
00101 void panel_fill_row(row_t *p_row, unsigned char value, int count);
00102 void panel_fill_matrix(matrix_t& panel, unsigned char value);
00103 void put_pixel(matrix_t& panel, unsigned int x, unsigned int y, color_t color);
00104 int put_char_xy(matrix_t& panel, char ch, unsigned int x, unsigned int y, const FONT_INFO *p_font, color_t color);
00105 int put_string_xy(matrix_t& panel, char *p_str, unsigned int x, unsigned int y, const FONT_INFO *p_font, color_t color);
00106 int measure_string(char *p_str, const FONT_INFO *p_font);
00107 void clear_display(void);
00108 int is_valid_char(char ch);
00109 color_t str_to_color(const char *p_str);
00110 int ini_file_handler(void* user, const char* section, const char* name, const char* value);
00111 void page_pre_init(void);
00112 void page_post_init(const FONT_INFO *p_font);
00113 int page_next(int page);
00114 int page_show(matrix_t& panel, int p);
00115
00116
00117 void led_sweep()
00118 {
00119 led1 = 0;
00120 led2 = 0;
00121 led3 = 0;
00122 led4 = 0;
00123 led1 = 1;
00124 wait(0.05);
00125 led1 = 0;
00126 led2 = 1;
00127 wait(0.05);
00128 led2 = 0;
00129 led3 = 1;
00130 wait(0.05);
00131 led3 = 0;
00132 led4 = 1;
00133 wait(0.05);
00134 led4 = 0;
00135 }
00136
00137
00138
00139
00140 void panel_load(unsigned char *p_pixel, int nr_of_pixels)
00141 {
00142 int i;
00143 for (i=0; i<nr_of_pixels; i++)
00144 {
00145 unsigned char pixel = p_pixel[i];
00146 R1 = pixel & 0x01;
00147 pixel >>= 1;
00148 G1 = pixel & 0x01;
00149 pixel >>= 1;
00150 R2 = pixel & 0x01;
00151 pixel >>= 1;
00152 G2 = pixel & 0x01;
00153 CLOCK_DATA;
00154 }
00155 LATCH_DATA;
00156 }
00157
00158
00159 void panel_refresh_row(int nr, row_t *p_pixel_data, int nr_of_pixels)
00160 {
00161 Row = nr;
00162 panel_load(p_pixel_data->pixel,nr_of_pixels);
00163 PANEL_ON;
00164 wait(app_data.brightness);
00165 PANEL_OFF;
00166 }
00167
00168
00169 void panel_refresh(matrix_t *p_panel)
00170 {
00171 int i;
00172 for (i=0; i<p_panel->rows; i++)
00173 {
00174 panel_refresh_row(i,&p_panel->row[i],p_panel->columns);
00175 }
00176 }
00177
00178
00179 void panel_init(matrix_t& panel, int rows, int columns)
00180 {
00181 CLOCK_DATA;
00182 LATCH_DATA;
00183 panel.rows = rows;
00184 panel.columns = columns;
00185 panel_fill_matrix(panel,kBlack);
00186 }
00187
00188
00189 void panel_fill_row(row_t *p_row, unsigned char value, int count)
00190 {
00191 int i;
00192 for (i=0; i<count; i++)
00193 {
00194 p_row->pixel[i] = value;
00195 }
00196 }
00197
00198
00199 void panel_fill_matrix(matrix_t& panel, unsigned char value)
00200 {
00201 int i;
00202 for (i=0; i<panel.rows; i++)
00203 {
00204
00205 panel_fill_row(&panel.row[i],(value<<2)+value,panel.columns);
00206 }
00207 }
00208
00209
00210 void put_pixel(matrix_t& panel, unsigned int x, unsigned int y, color_t color)
00211 {
00212 unsigned char mask;
00213 unsigned char c;
00214
00215 if (x<panel.columns && y<2*panel.rows)
00216 {
00217 mask = 0x03;
00218 c = color;
00219 if (y>=panel.rows)
00220 {
00221
00222 y -= panel.rows;
00223 c <<= 2;
00224 mask <<= 2;
00225 }
00226 c |= ~mask;
00227 panel.row[y].pixel[x] |= mask;
00228 panel.row[y].pixel[x] &= c;
00229 }
00230 }
00231
00232
00233 int put_char_xy(matrix_t& panel, char ch, unsigned int x, unsigned int y, const FONT_INFO *p_font, color_t color)
00234 {
00235 int i, h, w;
00236 if (p_font!=NULL)
00237 {
00238 i = ch - p_font->start_char;
00239 int width = p_font->p_character_descriptor[i].width;
00240 int second_byte = 0;
00241 if (width>8)
00242 {
00243
00244 second_byte = width - 8;
00245 width = 8;
00246 }
00247 int offset = p_font->p_character_descriptor[i].offset;
00248 const uint8_t *p_char = p_font->p_character_bitmaps + offset;
00249 uint8_t mask;
00250 for (h=0; h<p_font->height; h++)
00251 {
00252
00253 mask = 0x80;
00254 for (w=0; w<width; w++)
00255 {
00256 if ((*p_char&mask)!=0) put_pixel(panel,x+w,y+h,color);
00257 mask >>= 1;
00258 }
00259 if (second_byte>0)
00260 {
00261
00262 p_char += 1;
00263 mask = 0x80;
00264 for (w=0; w<second_byte; w++)
00265 {
00266 if ((*p_char&mask)!=0) put_pixel(panel,x+w+8,y+h,color);
00267 mask >>= 1;
00268 }
00269 }
00270 p_char += 1;
00271 }
00272 return p_font->p_character_descriptor[i].width;
00273 }
00274 return 0;
00275 }
00276
00277
00278 int put_string_xy(matrix_t& panel, char *p_str, unsigned int x, unsigned int y, const FONT_INFO *p_font, color_t color)
00279 {
00280 int _x = 0;
00281 while (*p_str!=0)
00282 {
00283 _x += put_char_xy(panel,*p_str,x+_x,y,p_font,color);
00284 _x += 1;
00285 p_str += 1;
00286 }
00287 return _x>0? _x-1 : 0;
00288 }
00289
00290
00291
00292 int measure_string(char *p_str, const FONT_INFO *p_font)
00293 {
00294 int i;
00295 int strlen_pixels = 0;
00296 if (p_font!=NULL)
00297 {
00298 while (*p_str!=0)
00299 {
00300 i = *p_str - p_font->start_char;
00301 strlen_pixels += p_font->p_character_descriptor[i].width;
00302 strlen_pixels += 1;
00303 p_str += 1;
00304 }
00305 }
00306 return strlen_pixels;
00307 }
00308
00309
00310 void clear_display(void)
00311 {
00312 panel_fill_matrix(Panel,kBlack);
00313 }
00314
00315
00316 int is_valid_char(char ch)
00317 {
00318 return (ch>=' ' && ch<='~');
00319 }
00320
00321 #define IS_SECTION(a) if (strcmp(p_section,(a))==0)
00322 #define IS_NAME(a) if (strcmp(p_name,(a))==0)
00323 #define IS_VALUE(a) if (strcmp(p_value,(a))==0)
00324
00325 color_t str_to_color(const char *p_str)
00326 {
00327 color_t color = kGreen;
00328 if (strcmp(p_str,"green")==0) color = kGreen;
00329 else if (strcmp(p_str,"orange")==0) color = kOrange;
00330 else if (strcmp(p_str,"red")==0) color = kRed;
00331 else if (strcmp(p_str,"black")==0) color = kBlack;
00332 return color;
00333 }
00334
00335
00336 int ini_file_handler(void *p_user, const char *p_section, const char *p_name, const char *p_value)
00337 {
00338
00339
00340 int p = 0;
00341
00342 IS_SECTION("global")
00343 {
00344 IS_NAME("brightness") app_data.brightness = atof(p_value)/10000.0;
00345 else IS_NAME("speed") app_data.scroll_speed = atof(p_value)/1000.0;
00346 }
00347 else IS_SECTION("page1") p = 0;
00348 else IS_SECTION("page2") p = 1;
00349 else IS_SECTION("page3") p = 2;
00350 else IS_SECTION("page4") p = 3;
00351 else IS_SECTION("page5") p = 4;
00352 else IS_SECTION("page6") p = 5;
00353 else IS_SECTION("page7") p = 6;
00354
00355 IS_NAME("hide") pages[p].hide = atoi(p_value);
00356 else IS_NAME("text1") strcpy(pages[p].line[0].str,p_value);
00357 else IS_NAME("text2") strcpy(pages[p].line[1].str,p_value);
00358 else IS_NAME("text3") strcpy(pages[p].line[2].str,p_value);
00359 else IS_NAME("text4") strcpy(pages[p].line[3].str,p_value);
00360 else IS_NAME("color1") pages[p].line[0].color = str_to_color(p_value);
00361 else IS_NAME("color2") pages[p].line[1].color = str_to_color(p_value);
00362 else IS_NAME("color3") pages[p].line[2].color = str_to_color(p_value);
00363 else IS_NAME("color4") pages[p].line[3].color = str_to_color(p_value);
00364 else IS_NAME("x1") pages[p].line[0].x = atoi(p_value);
00365 else IS_NAME("x2") pages[p].line[1].x = atoi(p_value);
00366 else IS_NAME("x3") pages[p].line[2].x = atoi(p_value);
00367 else IS_NAME("x4") pages[p].line[3].x = atoi(p_value);
00368 else IS_NAME("y1") pages[p].line[0].y = atoi(p_value);
00369 else IS_NAME("y2") pages[p].line[1].y = atoi(p_value);
00370 else IS_NAME("y3") pages[p].line[2].y = atoi(p_value);
00371 else IS_NAME("y4") pages[p].line[3].y = atoi(p_value);
00372 else IS_NAME("scroll1") pages[p].line[0].scroll = atoi(p_value);
00373 else IS_NAME("scroll2") pages[p].line[1].scroll = atoi(p_value);
00374 else IS_NAME("scroll3") pages[p].line[2].scroll = atoi(p_value);
00375 else IS_NAME("scroll4") pages[p].line[3].scroll = atoi(p_value);
00376
00377
00378 return 1;
00379 }
00380
00381
00382 void page_pre_init(void)
00383 {
00384 int i, j;
00385 int y;
00386
00387 memset(&pages,0,sizeof(pages));
00388 for (j=0; j<MAX_PAGES; j++)
00389 {
00390 y = 0;
00391 for (i=0; i<MAX_LINES; i++)
00392 {
00393
00394 pages[j].line[i].color = kBlack;
00395 pages[j].line[i].y = y;
00396 y += 8;
00397 }
00398 }
00399 }
00400
00401
00402 void page_post_init(const FONT_INFO *p_font)
00403 {
00404 int i, j;
00405 for (j=0; j<MAX_PAGES; j++)
00406 {
00407 for (i=0; i<MAX_LINES; i++)
00408 {
00409
00410 pages[j].line[i].strlen_pixels = measure_string(pages[j].line[i].str,p_font);
00411 }
00412 }
00413 }
00414
00415
00416 int page_next(int page)
00417 {
00418 page += 1;
00419 if (page<0) page = MAX_PAGES - 1;
00420 else if (page>=MAX_PAGES) page = 0;
00421 return page;
00422 }
00423
00424
00425 int page_show(matrix_t& panel, int p)
00426 {
00427 int i;
00428 clear_display();
00429
00430 if (pages[p].hide==0)
00431 {
00432 for (i=0; i<MAX_LINES; i++)
00433 {
00434 int x = pages[p].line[i].x;
00435
00436 put_string_xy(panel,pages[p].line[i].str,x,pages[p].line[i].y,&arial_8pt_font_info,pages[p].line[i].color);
00437
00438 if (pages[p].line[i].scroll!=0)
00439 {
00440
00441
00442 if (pages[p].line[i].scroll<0)
00443 {
00444
00445 x += (pages[p].line[i].strlen_pixels + SCROLL_GAP);
00446
00447 if (pages[p].line[i].x+pages[p].line[i].strlen_pixels<0) pages[p].line[i].x = x;
00448 }
00449 else if (pages[p].line[i].scroll>0)
00450 {
00451
00452 x -= (pages[p].line[i].strlen_pixels + SCROLL_GAP);
00453
00454 if (pages[p].line[i].x>=COLUMNS) pages[p].line[i].x = x;
00455 }
00456 put_string_xy(panel,pages[p].line[i].str,x,pages[p].line[i].y,&arial_8pt_font_info,pages[p].line[i].color);
00457
00458
00459 pages[p].line[i].x += pages[p].line[i].scroll;
00460 }
00461 }
00462 }
00463 else p = page_next(p);
00464
00465 return p;
00466 }
00467
00468
00469 int main()
00470 {
00471 int page = 0;
00472 int debounce = 0;
00473 const FONT_INFO *p_font = &arial_8pt_font_info;
00474
00475 PC.printf("\nmbed LED panel experiments\n");
00476 led_sweep();
00477
00478 led1 = 0;
00479 led2 = 0;
00480 led3 = 0;
00481 led4 = 0;
00482
00483
00484 app_data.brightness = 0.0005;
00485 app_data.scroll_speed = 0.001;
00486
00487
00488 PANEL_OFF;
00489 panel_init(Panel,ROWS,COLUMNS);
00490
00491
00492 page_pre_init();
00493 int error = false;
00494 error = ini_parse(ini_file,ini_file_handler,0);
00495 page_post_init(p_font);
00496
00497
00498
00499 while (1)
00500 {
00501 if (error==true)
00502 {
00503 put_string_xy(Panel,"file not found",0,0,p_font,kRed);
00504 }
00505 else
00506 {
00507 page = page_show(Panel,page);
00508 }
00509
00510
00511 if (Switch==1)
00512 {
00513 if (debounce<10) debounce += 1;
00514 else if (debounce==10)
00515 {
00516 debounce += 1;
00517 page = page_next(page);
00518 clear_display();
00519 }
00520 }
00521 else debounce = 0;
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 panel_refresh(&Panel);
00541 wait(app_data.scroll_speed);
00542 }
00543 }