Sun, 01 Nov 2020 22:21:19 +0100
Many improvements
- add support for dimm-based selection,
- add support for poweroff (at least power thr display off),
- add support for the initial key pressed during initialization sequence,
- fix a race condition (sending a keycode while receiving a message)
- add support for the shift button
- many code cleanups and improvements
src/def_f446re.h | file | annotate | diff | comparison | revisions | |
src/def_hp34970_fp.h | file | annotate | diff | comparison | revisions | |
src/display.cpp | file | annotate | diff | comparison | revisions | |
src/display.h | file | annotate | diff | comparison | revisions | |
src/hp34comm.cpp | file | annotate | diff | comparison | revisions | |
src/hp34comm.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions |
--- a/src/def_f446re.h Sun Nov 01 22:16:33 2020 +0100 +++ b/src/def_f446re.h Sun Nov 01 22:21:19 2020 +0100 @@ -45,7 +45,7 @@ #define DBGPIN PC_6 #ifdef HAVE_PC -BufferedSerial pc(USBTX, USBRX); +BufferedSerial pc(USBTX, USBRX, 115200); #endif DigitalOut led(LED1); #define HAS_LED
--- a/src/def_hp34970_fp.h Sun Nov 01 22:16:33 2020 +0100 +++ b/src/def_hp34970_fp.h Sun Nov 01 22:21:19 2020 +0100 @@ -33,11 +33,12 @@ #define KP_C2 PC_0 #define KP_C3 PB_4 #define KP_C4 PB_0 -/* + #if defined(HAVE_PC) -#include <USBSerial.h> -USBSerial pc; +//#include <USBSerial.h> +//USBSerial pc; +BufferedSerial pc(PC_10_ALT0, PC_11_ALT0, 115200); // UART_4 +//BufferedSerial pc(PC_10, PC_11, 115200); // UART_4 #endif -*/ #endif
--- a/src/display.cpp Sun Nov 01 22:16:33 2020 +0100 +++ b/src/display.cpp Sun Nov 01 22:21:19 2020 +0100 @@ -23,26 +23,64 @@ set_font((unsigned char*)Terminal6x8); locate(90, 40); this->printf("David Douard"); - locate(0, 52); - this->printf("Clock = %ld ", SystemCoreClock); + copy_to_lcd(); +} - RCC_OscInitTypeDef cfg; - HAL_RCC_GetOscConfig(&cfg); - if (cfg.HSEState == RCC_HSE_BYPASS) - this->printf("HSE:EXT "); - else if (cfg.HSEState == RCC_HSE_ON) - this->printf("HSE:XTAL "); - else - this->printf("HSE:OFF "); - - if (cfg.HSIState == RCC_HSI_ON) - this->printf("HSI:ON "); - else - this->printf("HSI:OFF "); - +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::dimm_char(uint8_t n) +{ + // dimm 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) + static char txt[64]; + 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) { + ::printf("DIMM CHAR %d\n", n); + ::printf("repl '%s'\n", table[i].buffer); + len = strlen(table[i].buffer); + if (n >= len) + break; // nothing to do + strncpy(txt, table[i].buffer, table[i].maxsize); + // look for the actual position of the char in the string (only alphanum) + // XXX very poor implementation... + for (j=0; (j<len)&&(j<=n); j++) + { + c = txt[j]; + if ((c == ',') || (c == '.') || (c == ';') || (c == ':') || (c == ' ')) + n++; + } + // now move the end of the string for char n to steps on the right + // so we can insert our 2 '\t' characters before and after the + // character to dimm + for (j=len; j>n; j--) + { + txt[j+2] = txt[j]; + } + txt[n+2] = '\t'; + txt[n+1] = txt[n]; + txt[n] = '\t'; + txt[len+2] = 0x00; // make sure the string will be terminated + + ::printf("with '%s'\n", txt); + // now display this string + show(0x00, txt, 0); + break; + } + } +} void Display::show(uint8_t cmd, const char *intxt, uint8_t nchar=0) { @@ -52,21 +90,24 @@ char *oldv; // char *txt; char *txtp; - static char txt[256]; + static char txt[64]; if (cmd == 0xFF) // cls { clrbuff(); } + else if (cmd == 0x0D) + { // dimm a character of the main area + dimm_char(intxt[0]); + } else { - //txt = (char *)malloc(strlen(intxt)+1); - strcpy(txt, intxt); - txtp = txt; - 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); @@ -76,45 +117,48 @@ locate(table[i].x0, table[i].y0); - if (table[i].fmt & 0x01) // ASCII text + if (table[i].fmt & FMT_ASCII) // ASCII text { + // check if the string has changed since last time if (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], - bgcolor); + 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; } } - if (cmd == 0x00) // main area - must_refresh |= 0x01; - if (cmd == 0x0C) // channels area - must_refresh |= 0x04; + must_refresh = 1; } } /* - if (table[i].fmt & 0x02 ) { + if (table[i].fmt & FMT_HEX ) { // hex for (uint8_t j=0;; j++) { if (txt[j] == 0x00) @@ -125,52 +169,42 @@ this->printf(" "); } */ - if (table[i].fmt & 0x08 ) // flag indicators + if (table[i].fmt & FMT_FLAGS ) // flag indicators { + uint8_t nbyte; + uint8_t nbit; // flags - for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) + for (uint8_t l=0; l<(sizeof(flags)/sizeof(flags[0])); ++l) { - for (uint8_t k=0; k<8; k++) - { - if (1) - { //(txt[j] & (1 << k) ) != (oldv[j] & (1 << k))) { - for (uint8_t l=0; - l<(sizeof(flags)/sizeof(flags[0])); ++l) - { - if (flags[l].flag == ((j<<4) + k)) { - if (txtp[j] & (1 << k)) - { - foreground(flags[l].reverse ? bgcolor : fgcolor); - background(flags[l].reverse ? fgcolor : bgcolor); - } - else - { - foreground(bgcolor); - background(bgcolor); - } - if (flags[l].msg != NULL) - { // a string - locate(flags[l].x, flags[l].y); - this->printf(flags[l].msg);} - else - { // an icon - Bitmap_s pic = {9, 10, 2, (char*) flags[l].icon}; - Bitmap_BW(pic, flags[l].x, flags[l].y); - } - must_refresh = 1; //|= zones[m].flag; - break; - } - } - } + nbyte = flags[l].flag / 8; + nbit = flags[l].flag % 8; + + if (intxt[nbyte] & (1 << nbit)) + { // draw the flag, possibly reversed fg/bg + foreground(flags[l].reverse ? bgcolor : fgcolor); + background(flags[l].reverse ? fgcolor : bgcolor); + } + else + { // erase the flag + foreground(bgcolor); + background(bgcolor); + } + if (flags[l].msg != NULL) + { // flag is a string + locate(flags[l].x, flags[l].y); + this->printf(flags[l].msg);} + else + { // flag is an icon + Bitmap_s pic = {9, 10, 2, (char*) flags[l].icon}; + Bitmap_BW(pic, flags[l].x, flags[l].y); } } // draw frames (Alarm and Channel) - for (uint8_t l=0; - l<(sizeof(frames)/sizeof(frames[0])); ++l) + for (uint8_t l=0; l<(sizeof(frames)/sizeof(frames[0])); ++l) { uint16_t color; - if (frames[l].flag & txt[0]) // frame flags are on the 1st byte only + if (intxt[0] & (1 << frames[l].flag)) // frame flags are on the 1st byte only color = fgcolor/6; else color = bgcolor; @@ -181,6 +215,7 @@ vline(frames[l].x0, frames[l].y0+1, frames[l].y1-1, color); vline(frames[l].x1, frames[l].y0+1, frames[l].y1-1, color); } + must_refresh = 1; //|= zones[m].flag; } for(uint8_t j=0; j<table[i].maxsize; j++) @@ -194,6 +229,61 @@ } +void Display::set_flag(uint8_t flag, bool show=true) +{ + uint8_t i; + uint8_t bgcolor = 0x00, fgcolor = 0xFF; + + for (uint8_t l=0; l<(sizeof(flags)/sizeof(flags[0])); ++l) + { + if (flag == flags[l].flag) + { + + if (show) + { + foreground(flags[l].reverse ? bgcolor : fgcolor); + background(flags[l].reverse ? fgcolor : bgcolor); + } + else + { + foreground(bgcolor); + background(bgcolor); + } + if (flags[l].msg != NULL) + { // flag is a string + locate(flags[l].x, flags[l].y); + set_font((unsigned char*)Terminal6x8); + this->printf(flags[l].msg);} + else + { // flag is an icon + Bitmap_s pic = {9, 10, 2, (char*) flags[l].icon}; + Bitmap_BW(pic, flags[l].x, flags[l].y); + } + } + } + + // draw frames (Alarm and Channel) + for (uint8_t l=0; l<(sizeof(frames)/sizeof(frames[0])); ++l) + { + if (flag == frames[l].flag) + { + uint16_t color; + if (show) + color = fgcolor/6; + else + color = bgcolor; + hline(frames[l].x0+1, frames[l].x0+3, frames[l].y0, color); + hline(frames[l].x1-3, frames[l].x1-1, frames[l].y0, color); + hline(frames[l].x0+1, frames[l].x1-1, frames[l].y1, color); + + vline(frames[l].x0, frames[l].y0+1, frames[l].y1-1, color); + vline(frames[l].x1, frames[l].y0+1, frames[l].y1-1, color); + } + } + must_refresh = 1; +} + + void Display::test_dsp() { const FRAME *z;
--- a/src/display.h Sun Nov 01 22:16:33 2020 +0100 +++ b/src/display.h Sun Nov 01 22:21:19 2020 +0100 @@ -8,6 +8,15 @@ #include "SSD1322.h" #include "hp34comm.h" +//typedef enum { +#define FMT_ASCII 0x01 +#define FMT_HEX 0x02 +#define FMT_BITS 0x04 +#define FMT_FLAGS 0x08 +#define FMT_IGNORE 0x80 + //} dsp_format_t; + + typedef struct _DSP { uint8_t cmd; @@ -22,11 +31,13 @@ char buffer[MAX_BUFF+1]; } DSP; + + static DSP table[] = -{ - { 0x00, 0xF, 0x0, 0, 0, 0x01, MAX_BUFF, 245, Mono19x27}, // main display - { 0x0C, 0xF, 0x0,196, 34, 0x01, 3, 45, Mono15x22}, // channels display - { 0x0A, 0xF, 0x0, 0, 57, 0x08, 4, 0, Terminal6x8}, // flags + bits +{ // cmd, fg, bg, x0, y0, fmt, maxsize, width, font + { 0x00, 0xF, 0x0, 0, 0, FMT_ASCII, MAX_BUFF, 245, Mono19x27}, // main display + { 0x0C, 0xF, 0x0,196, 34, FMT_ASCII, 3, 45, Mono15x22}, // channels display + { 0x0A, 0xF, 0x0, 0, 57, FMT_FLAGS, 4, 0, Terminal6x8}, // flags + bits }; // 9x10 @@ -79,47 +90,47 @@ static const FLAG flags[] = { - // flag, zone, x0, y0, reverse, msg, icon + // flag, x0, y0, reverse, msg, icon // right-side icons area - { 0x00, 246, 0, false, NULL, icon_alarm}, // F1.0 - { 0x01, 246, 11, false, NULL, icon_curve}, // F1.1 - - // F1.2 == Channel frame - { 0x03, 197, 27, false, "Channel"}, // F1.3 - // F1.7 == Alarm frame + // flag is the bit index in the 4 bytes viewed as a 32bits value + { 0x00, 246, 0, false, NULL, icon_alarm}, // F1.0 01 00 00 00 + { 0x01, 246, 11, false, NULL, icon_curve}, // F1.1 02 00 00 00 + // F1.2 04 00 00 00 - Channel frame + { 0x03, 197, 27, false, "CHANNEL"}, // F1.3 08 00 00 00 + // F1.7 80 00 00 00 - Alarm frame + { 0x1c, 0, 28+8, false, "MON"}, // F4.4 00 00 00 10 + { 0x1b, 0, 28+16, false, "VIEW"}, // F4.3 00 00 00 08 + { 0x1d, 0, 28, true, "SCAN"}, // F4.5 00 00 00 20 + { 0x1e, 0, 28+25, true, "CONFIG"}, // F4.6 00 00 00 40 - { 0x34, 0, 28+8, false, "MON"}, // F4.4 - { 0x33, 0, 28+16, false, "VIEW"}, // F4.3 - { 0x35, 0, 28, true, "SCAN"}, // F4.5 - { 0x36, 0, 28+25, true, "CONFIG"}, // F4.6 + { 0x1a, 40, 52, false, "*"}, // F4.2 00 00 00 04 + { 0x19, 50, 52, false, "ADRS"}, // F4.1 00 00 00 02 + { 0x18, 80, 52, false, "RMT"}, // F4.0 00 00 00 01 + { 0x17, 104, 52, true, "ERROR"}, // F3.7 00 00 80 00 - { 0x32, 40, 52, false, "*"}, // F4.2 - { 0x31, 50, 52, false, "ADRS"}, // F4.1 - { 0x30, 80, 52, false, "RMT"}, // F4.0 - { 0x27, 104, 52, true, "ERROR"}, // F3.7 + { 0x16, 140, 52, false, "EXT"}, // F3.6 00 00 40 00 + { 0x15, 164, 52, false, "ONCE"}, // F3.5 00 00 20 00 - { 0x26, 140, 52, false, "EXT"}, // F3.6 - { 0x25, 164, 52, false, "ONCE"}, // F3.5 - - { 0x23, 104, 28+16, false, "MEM"}, // F3.3 + { 0x13, 104, 28+16, false, "MEM"}, // F3.3 00 00 08 00 // col 5 - { 0x14, 244, 22, false, "4W"}, // F2.4 - { 0x15, 244, 30, false, "OC"}, // F2.5 - { 0x22, 129, 28+16, false, "LAST"}, // F3.2 - { 0x21, 129, 28+16, false, "MIN"}, // F3.1 - { 0x20, 129, 28+16, false, "MAX"}, // F3.0 - { 0x17, 129, 28+16, false, "AVG"}, // F2.7 + { 0x0c, 244, 22, false, "4W"}, // F2.4 00 10 00 00 + { 0x0d, 244, 30, false, "OC"}, // F2.5 00 20 00 00 + { 0x12, 129, 28+16, false, "LAST"}, // F3.2 00 00 04 00 + { 0x11, 129, 28+16, false, "MIN"}, // F3.1 00 00 02 00 + { 0x10, 129, 28+16, false, "MAX"}, // F3.0 00 00 01 00 + { 0x0f, 129, 28+16, false, "AVG"}, // F2.7 00 80 00 00 - { 0x05, 154+0, 17+10, false, "Alarm"}, // F1.5 - { 0x06, 154+0, 17+20, false, "H"}, // F1.6 - { 0x13, 154+6, 17+20, false, "1"}, // F2.3 - { 0x10, 154+12, 17+20, false, "2"}, // F2.0 - { 0x12, 154+18, 17+20, false, "3"}, // F2.2 - { 0x11, 154+24, 17+20, false, "4"}, // F2.1 - { 0x04, 154+30, 17+20, false, "L"}, // F1.4 + { 0x05, 154+0, 17+10, false, "Alarm"}, // F1.5 20 00 00 00 + { 0x06, 154+0, 17+20, false, "H"}, // F1.6 40 00 00 00 + { 0x0b, 154+6, 17+20, false, "1"}, // F2.3 00 08 00 00 + { 0x08, 154+12, 17+20, false, "2"}, // F2.0 00 01 00 00 + { 0x0a, 154+18, 17+20, false, "3"}, // F2.2 00 04 00 00 + { 0x09, 154+24, 17+20, false, "4"}, // F2.1 00 02 00 00 + { 0x04, 154+30, 17+20, false, "L"}, // F1.4 00 10 00 00 + { 0x80, 224, 54, true, "SHIFT"}, // not an actual command, managed by the front panel }; static const FRAME zones[] = @@ -154,7 +165,15 @@ void test_dsp(); void show(uint8_t, const char*, uint8_t); + void dimm_char(uint8_t); void show_splashscreen(); + void show_byescreen(); + void set_flag(uint8_t flag, bool show); + void show_flag(uint8_t flag) {set_flag(flag, true);}; + void hide_flag(uint8_t flag) {set_flag(flag, false);}; + void shift_on() {set_flag(0x80, true);}; + void shift_off() {set_flag(0x80, false);}; + private: uint8_t must_refresh;
--- a/src/hp34comm.cpp Sun Nov 01 22:16:33 2020 +0100 +++ b/src/hp34comm.cpp Sun Nov 01 22:21:19 2020 +0100 @@ -5,31 +5,22 @@ /***** HP 34970A communication class ***/ -#ifdef DEBUG2 - -DigitalOut inrx(D9); - -#endif - -DigitalOut lled(LED3); - #define RXTIMEOUT 50ms #define STARTUPRETRY 0.5 uint8_t startup_seq[] = { 0x33, - 0x02, + 0x02, // 0x02? 0x00, - 0x00, // to be replaced by the actual keycode, if any + 0x00, }; HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { - &HPSerial::do_state_initial, - &HPSerial::do_state_command, - &HPSerial::do_state_payload_size, - &HPSerial::do_state_payload, - &HPSerial::do_state_sending, - &HPSerial::do_state_eot, + &HPSerial::do_state_initial, // STATE_IDLE + &HPSerial::do_state_command, // STATE_COMMAND + &HPSerial::do_state_payload_size, // STATE_PAYLOAD_SIZE + &HPSerial::do_state_payload, // STATE_PAYLOAD + &HPSerial::do_state_sending, // STATE_SENDING }; @@ -39,17 +30,21 @@ cur_gstate(GSTATE_IDLE) { serial.baud(187500); + serial.format(8, BufferedSerial::Even, 1); cur_state = STATE_IDLE; - serial.attach(callback(this, &HPSerial::rxIrq), SerialBase::RxIrq); + serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); } void HPSerial::startup(uint8_t keycode) { + cur_gstate = GSTATE_STARTING; + if (keycode != 0xFF) { - startup_sed[2] = 0xFF; - startup_sed[3] = keycode; + printf("Set startup keycode to %X\n", keycode); + startup_seq[2] = 0xFF; + startup_seq[3] = keycode; } - - cur_gstate = GSTATE_STARTING; + else + startup_seq[2] = 0x00; set_timer(10ms); // launch the startup in 10ms } @@ -65,18 +60,28 @@ tr_data.size = 3; // sizeof(startup_seq); for(uint8_t i=0; i<tr_data.size; i++) tr_data.payload[i] = startup_seq[i]; - cur_state = do_state_sending(); } void HPSerial::sendkey(uint8_t keycode) { - tr_data.size = 2; - tr_data.cmd = 0xFF; - tr_data.pos = 0; - tr_data.payload[0] = 0x66; - tr_data.payload[1] = keycode; - cur_state = do_state_sending(); + if (!sendbuf.full()) + sendbuf.push(keycode); +} + +void HPSerial::send_key_when_idle() { + if (!sendbuf.empty() && cur_gstate == GSTATE_IDLE) + { + uint8_t keycode; + cur_gstate = GSTATE_TX; + sendbuf.pop(keycode); + tr_data.size = 2; + tr_data.cmd = 0xFF; + tr_data.pos = 0; + tr_data.payload[0] = 0x66; + tr_data.payload[1] = keycode; + cur_state = do_state_sending(); + } } bool HPSerial::cmd_available(void) @@ -112,8 +117,8 @@ } void HPSerial::send_ack(uint8_t c) { - serial.write(&c, 1); - set_timer(RXTIMEOUT); // if nothing else happen in the next ms, reset + serial.write(&c, 1); + set_timer(RXTIMEOUT); // if nothing else happen in the next RXTIMEOUT ms, reset } HPSerial::state_t HPSerial::do_state_initial(uint8_t c) @@ -122,7 +127,7 @@ // knwon handcheck values are 0x66 and 0x33 set_timer(RXTIMEOUT); // reset the watchdog switch (c) { - case 0x33: + case 0x33: // XXX? when are we expecting a 0x33 here? send_ack(0xCC); return HPSerial::STATE_PAYLOAD_SIZE; break; @@ -173,9 +178,9 @@ send_ack(0x00); if (tr_data.pos >= tr_data.size) { pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); - return HPSerial::STATE_IDLE; + return STATE_IDLE; } - return HPSerial::STATE_PAYLOAD; + return STATE_PAYLOAD; } HPSerial::state_t HPSerial::do_state_sending(uint8_t c) @@ -184,48 +189,41 @@ if (c == 0xFF) { // resend current char tr_data.pos--; - tr_data.payload[tr_data.pos] += 1; } // TODO: check ACK values (c is the received ack) if (tr_data.pos >= tr_data.size) { - return do_state_eot(); + c = 0x55; + serial.write(&c, 1); // EoT + cur_gstate = GSTATE_IDLE; + set_timer(); // We are IDLE, detach the timeouter + return STATE_IDLE; } - serial.write(&tr_data.payload[tr_data.pos++], 1); - set_timer(RXTIMEOUT); - return HPSerial::STATE_SENDING; -} - -HPSerial::state_t HPSerial::do_state_eot(uint8_t c) -{ - serial.write(&c, 1); // EoT - cur_gstate = GSTATE_IDLE; - set_timer(); // We are IDLE, detach the timeouter - return STATE_IDLE; + else + { + serial.write(&tr_data.payload[tr_data.pos++], 1); + set_timer(RXTIMEOUT); + return STATE_SENDING; + } } HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, - uint8_t c) + uint8_t c) { return (this->*(HPSerial::state_table[cur_state]))(c); }; -void HPSerial::rxIrq(void) { +void HPSerial::rx_irq(void) { uint8_t val; if(serial.readable()) { // no reason why we would end here without // this condition, but hey -#ifdef DEBUG2 - inrx=1; -#endif - //lled = 1; - //val = serial.getc(); + if (cur_gstate == GSTATE_IDLE) + // occurs when the CPU starts a new transmission + // at this point, cur_state should be STATE_IDLE also (TODO add a check?) + cur_gstate = GSTATE_RX; serial.read(&val, 1); cur_state = run_state(cur_state, val); - //lled = 0; -#ifdef DEBUG2 - inrx=0; -#endif } } @@ -234,7 +232,7 @@ set_timer(); // detach the timeouter if (cur_gstate == GSTATE_STARTING) _startup(); - else // reset + else // CPU took too long to reply, reset { cur_gstate = GSTATE_IDLE; cur_state = STATE_IDLE;
--- a/src/hp34comm.h Sun Nov 01 22:16:33 2020 +0100 +++ b/src/hp34comm.h Sun Nov 01 22:21:19 2020 +0100 @@ -32,22 +32,24 @@ void startup(uint8_t keycode=0xFF); void sendkey(uint8_t keycode); + void send_key_when_idle(); private: void pushCmd(uint8_t cmd, uint8_t size, char *payload); - void rxIrq(void); + void rx_irq(void); void timeout(void); void set_timer(Kernel::Clock::duration_u32 v=0ms) { timeouter.detach(); if (v > 0ms) timeouter.attach(callback(this, &HPSerial::timeout), v); - } + }; private: UnbufferedSerial serial; uint8_t buf[BUF_SIZE]; uint8_t head; CircularBuffer<CMD, 32> cmdbuf; + CircularBuffer<uint8_t, 32> sendbuf; unsigned long ncmd; unsigned int errs[MAX_ERRS]; Ticker timeouter; @@ -84,7 +86,6 @@ STATE_PAYLOAD_SIZE, STATE_PAYLOAD, STATE_SENDING, - STATE_EOT, NUM_STATES} state_t; state_t state() {return cur_state;}; @@ -102,7 +103,6 @@ state_t do_state_payload_size(uint8_t c); state_t do_state_payload(uint8_t c); state_t do_state_sending(uint8_t c=0x00); - state_t do_state_eot(uint8_t c=0x55); void send_ack(uint8_t c);
--- a/src/main.cpp Sun Nov 01 22:16:33 2020 +0100 +++ b/src/main.cpp Sun Nov 01 22:21:19 2020 +0100 @@ -23,15 +23,18 @@ Display *dsp; volatile bool splashscreen; HPSerial *hp; -Thread tdsp; -Ticker blinker; +Thread tdsp(osPriorityNormal, OS_STACK_SIZE, nullptr, "DSP"); +Ticker dsp_refresh; Timeout rst_delay; Timeout splashscreen_timer; +Timeout byescreen_timer; InterruptIn rst(HP_RST); QEI qenc(KP_ENC1, KP_ENC2, NC, 16); volatile uint8_t knob; bool shift; // true when kp is shifted, cleared by command 0x01 from Unit +bool must_reset; +bool must_shutdown; typedef enum { KEY_NONE=0, @@ -45,7 +48,6 @@ key_event_t keyevent; } keycode_t; -//volatile keycode_t cur_keycode; #define KEY_BUF_SIZE 10 CircularBuffer<keycode_t, KEY_BUF_SIZE> key_buf; @@ -94,10 +96,14 @@ {0x0A, 0x09, 0x08, 0x02, 0xFF} }; +#define KC_SHIFT 0x0C + void kp_cb(uint8_t row, uint8_t col); void kr_cb(uint8_t row, uint8_t col); Keypad *kpad; +keycode_t last_key = {0, 0, KEY_NONE}; + uint8_t curchar; //uint8_t curcmd; uint8_t nchars; @@ -139,21 +145,17 @@ void qei_cb(int dir); void end_splashscreen(void); -/* - #if defined(HAVE_PC) - FileHandle *mbed::mbed_override_console(int fd) - { - return static_cast<FileHandle*> (&pc); - } - #endif -*/ + +#if defined(HAVE_PC) +FileHandle *mbed::mbed_override_console(int fd) +{ + return static_cast<FileHandle*> (&pc); +} +#endif + void setup() { #if defined(HAVE_PC) -#if defined(TARGET_NUCLEO_F446RE) - pc.set_baud(115200); -#endif - /* #if defined(TARGET_HP34970_FP_F303RD) pc.init(); @@ -163,8 +165,7 @@ #endif printf("\n\nSETUP\n"); - printf(" System Core Clock = %.3f MHZ\r\n", - (float)SystemCoreClock/1000000); + printf(" System Core Clock = %ld MHZ\r\n", SystemCoreClock/1000000); /* #if defined(HAS_LED) @@ -199,9 +200,10 @@ qenc.attach(&qei_cb); printf(" setup Keypad\r\n"); - //cur_keycode.keyevent = KEY_NONE; shift = false; + must_reset = false; + must_shutdown = false; kpad = new Keypad(KP_NROWS, kp_rows, KP_NCOLS, kp_columns); printf(" attach Keypad callbacks\r\n"); kpad->attach(&kp_cb, &kr_cb); @@ -230,15 +232,10 @@ dsp->show_splashscreen(); printf("Starting LCD thread\r\n"); + // does not compile... + // dsp_refresh.attach(callback(dsp, &Display::copy_to_lcd), 50ms); tdsp.start(&refresh_display); - /* - dsp->clrbuff(); - show(0x00, "HH:MM:\tSS\t:mmmm", 15); // main dsp - show(0x0C, "888", 3); // channel dsp - show(0x0A, "\xFF\xFF\xFF\xFF", 4); // all flags - */ - printf("Attaching timers\r\n"); splashscreen = true; splashscreen_timer.attach(callback(&end_splashscreen), 2ms); @@ -254,85 +251,86 @@ splashscreen = false; } +void reset_irq_tmr(void) +{ + must_reset = true; +} + void reset_irq(void) { - rst_delay.attach(callback(&reset), 1ms); + rst_delay.attach(callback(&reset_irq_tmr), 50ms); } void reset(void) { + // this should be called as a result of the HP_RST pin going LO + printf("Reset connection to the main unit\n"); if (DigitalIn(HP_RST).read() == 0) { if (hp == NULL) { printf("setup HP communication handler\r\n"); hp = new HPSerial(HP_TX, HP_RX); } + else { + printf("Connection already initialized\n"); + } printf("!! RST !! (gstate=%d, state=%d)\r\n", hp->gstate(), hp->state()); //printf("Value is ... %X\n", hp->search()); - hp->startup(); + dsp->power_on(); + dsp->cls(); + printf("Initiate startup sequence\n"); + if (last_key.keyevent == KEY_PRESSED) + hp->startup(kp_mapping[last_key.row][last_key.col]); + else + hp->startup(); + } + else + { + printf("HP_RST is not LOW, skipping\n"); } } void refresh_display(void) { - //uint8_t mask=1; - - while(1) { - pulse(0, true); - if (splashscreen == false) { - //Thread::wait(20); // give a bit of time for some more cmds - dsp->copy_to_lcd(); - } + while(1) { //!must_shutdown) { + dsp->copy_to_lcd(); + ThisThread::sleep_for(50ms); + } +} - /* - if (must_refresh & mask) { - for(uint8_t i=0; i<sizeof(zones)/sizeof(zones[0]); i++) - if (zones[i].flag == mask) { - dsp->copy_to_lcd(zones[i].x0/4, (zones[i].x1+3)/4, - zones[i].y0, zones[i].y1); - must_refresh &= ~mask; - break; - } - } - mask = mask << 1; - if (mask == 0) { - mask = 1; - } - */ - pulse(0, false); - - ThisThread::sleep_for(30ms); - } +void shutdown(void) +{ + must_shutdown = true; } void mainloop() { // run over and over keycode_t key = {0, 0, KEY_NONE}; - + uint8_t keycode; // actual sent value to the CPU + HPSerial::CMD cmd; + unsigned int nkeys = 0; unsigned int err[8]; for (uint8_t i=0; i<8; i++) err[i] = 0; - int p, pp; // rot encoder pulse counters - p = 0; - pp = 0; while(1) { - p = qenc.getPulses(); - if (p != pp) - { - dsp->locate(0, 0); - dsp->printf("Pulses = %d ", p); - dsp->copy_to_lcd(); - pp = p; - } + if (must_reset) { + must_reset = false; + reset(); + } + if (must_shutdown) { + //tdsp.join(); + //dsp_refresh.detach(); + must_shutdown = false; + dsp->power_off(); + } if (knob != 0) { if (hp != NULL) { - printf("Sending keycode %X\r\n", knob); + printf("KEY[%d] %s%X\n", nkeys++, knob<0x0F ? "0" : "", knob); hp->sendkey(knob); - printf(" DONE\r\n"); } else { @@ -343,19 +341,28 @@ knob = 0; } - if (!key_buf.empty()) //cur_keycode.keyevent != KEY_NONE) + if (!key_buf.empty()) { key_buf.pop(key); - printf("Keycode %dx%d: %s\r\n", - key.row, key.col, key.keyevent==KEY_PRESSED?"pressed":"released"); + keycode = kp_mapping[key.row][key.col]; + + if ((keycode == KC_SHIFT) && (key.keyevent == KEY_PRESSED)) + { + shift = true; + dsp->shift_on(); + } + if (hp != NULL) { - uint8_t keycode = kp_mapping[key.row][key.col]; + if ((shift) && (keycode != KC_SHIFT)) + { + keycode |= 0x20; // bit 5: key shifted + shift = false; + dsp->shift_off(); + } if (key.keyevent == KEY_RELEASED) keycode |= 0x40; // bit 6: key relased - if (shift) - keycode |= 0x20; // bit 5: key shifted - - hp->sendkey(kp_mapping[key.row][key.col]); + printf("KEY[%d] %s%X\n", nkeys++, keycode<0x0F ? "0" : "", keycode); + hp->sendkey(keycode); } else { @@ -367,13 +374,14 @@ key.keyevent==KEY_PRESSED ? "PRE" : "REL"); dsp->copy_to_lcd(); } - // cur_keycode.keyevent = KEY_NONE; } + // at each loop iteration, send buffered keycodes, if any + if (hp != NULL) + hp->send_key_when_idle(); if ((hp != NULL) && (hp->cmd_available())) { - HPSerial::CMD cmd; if (hp->pop(cmd)) { #if defined(HAS_LED) @@ -381,7 +389,7 @@ #endif for (uint8_t i=0; i<7; i++) if (hp->nerrors(i) > err[i]) { - printf("ERR: %d/%d/%d/%d/%d/%d/%d\r\n", + printf("ERR: %X/%X/%X/%X/%X/%X/%X\n", hp->nerrors(0), hp->nerrors(1), hp->nerrors(2), @@ -395,17 +403,17 @@ for (uint8_t i=0; i<7; i++) err[i] = hp->nerrors(i); - printf("CMD[%d] %02X", (int)cmd.id, cmd.cmd); + printf("CMD[%d] %s%X", (int)cmd.id, cmd.cmd<0x10 ? "0" : "", cmd.cmd); // 0x00: main display // 0x0C: channel display if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C)) - printf(": '%s'\r\n", cmd.value); + printf(": '%s'\n", cmd.value); else { - printf(":"); + printf(": "); for (uint8_t i=0; i<cmd.size; i++) - printf("%02x ", cmd.value[i]); - printf("\r\n"); + printf("%s%X ", cmd.value[i] < 0x10 ? "0" : "", cmd.value[i]); + printf("\n"); } if (cmd.cmd == 0x01) { @@ -413,11 +421,13 @@ if (cmd.value[0] == 0x0E) { // clear the Shift flag shift = false; + dsp->shift_off(); } } else if (cmd.cmd == 0x86) { - // shutdown - // TODO - } else { + // shutdown + dsp->show_byescreen(); + byescreen_timer.attach(callback(&shutdown), 2s); + } else { // display related commands dsp->show(cmd.cmd, cmd.value, cmd.size); } @@ -431,6 +441,7 @@ } } + void qei_cb(int dir) { if(dir == 1) // turn right @@ -441,22 +452,20 @@ void kp_cb(uint8_t row, uint8_t col) { - keycode_t key; - key.row = row; - key.col = col; - key.keyevent = KEY_PRESSED; + last_key.row = row; + last_key.col = col; + last_key.keyevent = KEY_PRESSED; if(!key_buf.full()) - key_buf.push(key); + key_buf.push(last_key); } void kr_cb(uint8_t row, uint8_t col) { - keycode_t key; - key.row = row; - key.col = col; - key.keyevent = KEY_RELEASED; + last_key.row = row; + last_key.col = col; + last_key.keyevent = KEY_RELEASED; if(!key_buf.full()) - key_buf.push(key); + key_buf.push(last_key); } int main()