Mon, 23 Nov 2020 21:55:40 +0100
Small fixes in main
- toggle the shift indicator when the key is pressed while already on
- attempt to fix the restart-while-shuting-down bug
#include "stdio.h" #include <mbed.h> #include <rtos.h> #include "display.h" static DSP table[] = { // cmd, fg, bg, x0, y0, fmt, maxsize, width, font { 0x00, 0xF, 0x0, 0, 0, FMT_ASCII, MAX_BUFF, 255, Mono19x27}, // main display { 0x0C, 0xF, 0x0,194, 38, FMT_ASCII, 3, 45, Mono15x22}, // channels display { 0x0A, 0xF, 0x0, 0, 57, FMT_FLAGS, 4, 0, Terminal6x8}, // flags + bits }; // 9x10 const unsigned char icon_alarm[] __attribute__((aligned (2))) = { 0x1c, 0x0, 0x3e, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0xff, 0x80, 0x10, 0x0 }; const unsigned char icon_curve[] __attribute__((aligned (2))) = { 0x80, 0x0, 0x80, 0x0, 0x80, 0x80, 0x81, 0x0, 0x9e, 0x0, 0xa0, 0x0, 0xc0, 0x0, 0x80, 0x0, 0x80, 0x0, 0xff, 0x80 }; static const flags_map flags = { // id x0 y0 rev. msg icon { 0x00, {246, 27, 0, 0, false, NULL, icon_alarm}}, // F1.0 01 00 00 00 { 0x01, {246, 38, 0, 0, false, NULL, icon_curve}}, // F1.1 02 00 00 00 { 0x02, {192, 32, 240, 60, false, NULL, NULL}}, // F1.2 04 00 00 00 - Channel frame { 0x03, {195, 29, 0, 0, false, "CHANNEL", NULL}}, // F1.3 08 00 00 00 { 0x1c, {0, 38, 0, 0, false, "MON", NULL}}, // F4.4 00 00 00 10 { 0x1b, {0, 47, 0, 0, false, "VIEW", NULL}}, // F4.3 00 00 00 08 { 0x1d, {0, 29, 0, 0, true, "SCAN", NULL}}, // F4.5 00 00 00 20 { 0x1e, {0, 56, 0, 0, true, "CONFIG", NULL}}, // F4.6 00 00 00 40 { 0x1a, {40, 56, 0, 0, false, "*", NULL}}, // F4.2 00 00 00 04 { 0x19, {50, 56, 0, 0, false, "ADRS", NULL}}, // F4.1 00 00 00 02 { 0x18, {80, 56, 0, 0, false, "RMT", NULL}}, // F4.0 00 00 00 01 { 0x17, {104, 56, 0, 0, true, "ERROR", NULL}}, // F3.7 00 00 80 00 { 0x16, {86, 38, 0, 0, false, "EXT", NULL}}, // F3.6 00 00 40 00 { 0x15, {60, 38, 0, 0, false, "ONCE", NULL}}, // F3.5 00 00 20 00 { 0x13, {40, 38, 0, 0, false, "MEM", NULL}}, // F3.3 00 00 08 00 { 0x0c, {244, 47, 0, 0, false, "4W", NULL}}, // F2.4 00 10 00 00 { 0x0d, {244, 56, 0, 0, false, "OC", NULL}}, // F2.5 00 20 00 00 { 0x12, {40, 47, 0, 0, false, "LAST", NULL}}, // F3.2 00 00 04 00 { 0x11, {66, 47, 0, 0, false, "MIN", NULL}}, // F3.1 00 00 02 00 { 0x10, {86, 47, 0, 0, false, "MAX", NULL}}, // F3.0 00 00 01 00 { 0x0f, {106, 47, 0, 0, false, "AVG", NULL}}, // F2.7 00 80 00 00 { 0x05, {152, 29, 0, 0, false, "Alarm", NULL}}, // F1.5 20 00 00 00 { 0x08, {152, 39, 0, 0, false, "H", NULL}}, // F1.6 40 00 00 00 { 0x07, {158, 39, 0, 0, false, "1", NULL}}, // F2.3 00 08 00 00 { 0x06, {164, 39, 0, 0, false, "2", NULL}}, // F2.0 00 01 00 00 { 0x04, {170, 39, 0, 0, false, "3", NULL}}, // F2.2 00 04 00 00 { 0x09, {176, 39, 0, 0, false, "4", NULL}}, // F2.1 00 02 00 00 { 0x0a, {182, 39, 0, 0, false, "L", NULL}}, // F1.4 00 10 00 00 { 0x0b, {149, 32, 190, 50, false, NULL, NULL}}, // F1.7 - alarm frame { 0x0e, {152, 56, 0, 0, true, "SHIFT", NULL}}, // not an actual command, managed by the front panel { 0x14, {0xFF, 0xFF, 0xFF, 0xFF, false, NULL, NULL}}, // not an actual command, for the sake of completeness { 0x1f, {0xFF, 0xFF, 0xFF, 0xFF, false, NULL, NULL}}, // not an actual command, for the sake of completeness }; Display::Display(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const char* name) : SSD1322(Hz, mosi, miso, sclk, CS, reset, DC, name) { must_refresh = 0; for (flags_map::const_iterator it=flags.cbegin(); it!=flags.cend(); ++it) { flags_status[it->first] = false; flags_dim[it->first] = false; } } Display::~Display() { } void Display::show_splashscreen() { locate(30, 10); set_font((unsigned char*)Mono19x27); this->printf("HP34970A"); set_font((unsigned char*)Terminal6x8); locate(90, 40); this->printf("David Douard"); copy_to_lcd(); } void Display::show_byescreen() { cls(); background(0x00); foreground(0xFF); locate(30, 10); set_font((unsigned char*)Mono19x27); this->printf("Bye..."); copy_to_lcd(); } void Display::dim_char(uint8_t n) { // dim the char number of the currently displayed string of the main area; // do this by printing a modifed version of the last displayed string // but only alphanumeric chars should be counted (not the punctuation) char c; uint8_t len, i, j; // for which we need to look for the entry in the table for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { if (table[i].cmd == 0x00) { background(table[i].bgcolor); foreground(table[i].color / 2); // dimmed set_font((unsigned char*) table[i].font); locate(table[i].x0, table[i].y0); len = strlen(table[i].buffer); if (n >= len) break; // nothing to do for (j=0; (j<len); j++) { // advae the location up to the char to dimm c = table[i].buffer[j]; if ((c == ',') || (c == '.') || (c == ';') || (c == ':')) // it's a "zero" width char, skip it n++; if (n == 0) { // found it character(c); break; } // otherwise, just advance the char_x char_width(c, true); n--; } } } } void Display::show(uint8_t cmd, const char *intxt, uint8_t nchar=0) { uint8_t i; // uint8_t len; uint16_t bgcolor, fgcolor; char *oldv; // char *txt; char *txtp; static char txt[64]; if (cmd == 0xFF) // cls { clrbuff(); } else if (cmd == 0x0D) { // dimm a character of the main area dim_char(intxt[0]); } else { pixel_buffer_mutex.lock(); for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { if (table[i].cmd == cmd) { strcpy(txt, intxt); txtp = txt; bgcolor = table[i].bgcolor; fgcolor = table[i].color; background(bgcolor); foreground(fgcolor); set_font((unsigned char*) table[i].font); oldv = table[i].buffer; locate(table[i].x0, table[i].y0); if (table[i].fmt & FMT_ASCII) // ASCII text { // check if the string has changed since last time if (true) //(strncmp(oldv, txt, table[i].maxsize) != 0) { // clear the text area if (table[i].width > 0) fillrect(table[i].x0, table[i].y0, table[i].x0 + table[i].width, table[i].y0 + table[i].font[2] - 1, bgcolor); // draw chars by portions of string separated by \t (highlight) for (uint8_t k=0; ;k++) { if (txtp[k] == 0x00) { // end of string, display it this->printf(txtp); break; } if (txtp[k] == 0x09) { // \t is a special char for 'unselected' display value // first disply the beginning of the string txtp[k] = 0x00; this->printf(txtp); // swap the fg color (dimm/bright) if (fgcolor == table[i].color) fgcolor /= 2; else fgcolor = table[i].color; foreground(fgcolor); // continue on the next with part of the string txtp = &(txtp[k+1]); k = 0; } } must_refresh = 1; } } if (table[i].fmt & FMT_FLAGS ) // flag indicators { uint8_t id; uint8_t c; id = 0; for (uint8_t nc=0; nc<4; nc++) { c = intxt[nc]; for (uint8_t nb=0; nb<8; nb++) { if (c & (0x01 << nb)) set_flag_status(id, true); else set_flag_status(id, false); draw_flag(id); id++; } } } for(uint8_t j=0; j<table[i].maxsize; j++) oldv[j] = txt[j]; break; } } pixel_buffer_mutex.unlock(); } } void Display::set_flag_status(uint8_t flagid, bool show) { flags_status[flagid] = show; } void Display::set_flag_dim(uint8_t flagid, bool dim) { flags_dim[flagid] = dim; } void Display::draw_flag(uint8_t flagid) { uint8_t i; uint8_t bgcolor = 0x00, fgcolor = 0x0F; ::printf(" FLAG %X:", flagid); const FLAG flag = flags.at(flagid); // can't use the [] operator on a const map... if (flag.msg != NULL) ::printf("%s ", flag.msg); else if (flag.icon != NULL) ::printf("ICN "); else if (flag.x0 > 0) ::printf("FR[%dx%d] ", flag.x0, flag.y0); else ::printf(" WTF? "); if (flags_status[flagid]) { if (flags_dim[flagid]) ::printf(" DIM\n"); else ::printf(" ON\n"); } else ::printf(" OFF\n"); if ((flag.msg == NULL) && (flag.icon == NULL) && (flag.x0 == 0xFF) && (flag.y0 == 0xFF)) // noop command return; if (flags_dim[flagid]) fgcolor = fgcolor / 4; else if ((flag.msg == NULL) && (flag.icon == NULL)) fgcolor = fgcolor / 6; // it's a frame if (flags_status[flagid]) { foreground(flag.reverse ? bgcolor : fgcolor); background(flag.reverse ? fgcolor : bgcolor); } else { foreground(bgcolor); background(bgcolor); } if (flag.msg != NULL) { set_font((unsigned char*)Terminal6x8); locate(flag.x0, flag.y0); this->printf(flag.msg); } else if (flag.icon != NULL) { // flag is an icon Bitmap_s pic = {9, 10, 2, (char*) flag.icon}; Bitmap_BW(pic, flag.x0, flag.y0); } else { // draw frames (Alarm and Channel) hline(flag.x0+1, flag.x0+3, flag.y0, foreground()); hline(flag.x1-3, flag.x1-1, flag.y0, foreground()); hline(flag.x0+1, flag.x1-1, flag.y1, foreground()); vline(flag.x0, flag.y0+1, flag.y1-1, foreground()); vline(flag.x1, flag.y0+1, flag.y1-1, foreground()); } must_refresh = 1; }