Sun, 25 Oct 2020 17:12:22 +0100
Add a few patterns in hgignore
#include "stdio.h" #include <mbed.h> #include <rtos.h> #include <string> #include "Terminal6x8.h" #include "Mono19x27.h" #include "Mono15x22.h" #include "Arial12x12.h" #include "SSD1322.h" #include "hp34comm.h" #include "QEI.h" #include "Keypad.h" /******************************************************/ /* F446RE */ /******************************************************/ #if defined STM32F446xx // UART // USBTX PA_2 // USBRX PA_3 // display #define DSP_MOSI PB_15 // blue #define DSP_MISO PB_14 // NC #define DSP_SCLK PB_13 // yellow #define DSP_CS PB_12 // green #define DSP_RST PB_5 // green #define DSP_DC PB_4 // red // UART for RX (CPU->DP) #define HP_RX PC_11 // serial3 RX #define HP_TX PC_10 // serial3 TX // RST pin (handle this by hand) #define HP_RST PC_12 // encoder #define KP_ENC1 PC_4 #define KP_ENC2 PC_5 // keypad #define KP_R0 PC_0 // I-6 #define KP_R1 PC_1 // II-5 #define KP_R2 PC_2 // I-5 #define KP_R3 PC_3 // II-4 #define KP_C0 PB_0 // I-4 #define KP_C1 PA_6 // I-2 #define KP_C2 PA_7 // I-3 #define KP_C3 PA_10 // I-1 #define KP_C4 PD_2 // II-1 // misc #define DBGPIN PC_6 #elif defined STM32F303xE // HP34970 replacement PCB #define DSP_MOSI PA_7 #define DSP_MISO PA_6 // NC #define DSP_SCLK PA_5 #define DSP_CS PA_2 #define DSP_RST PA_3 #define DSP_DC PA_4 // UART for RX (CPU->DP) #define HP_RX PC_5 #define HP_TX PC_4 // RST pin (handle this by hand) #define HP_RST PA_15 // encoder #define KP_ENC1 PA_0 #define KP_ENC2 PA_1 // keypad #define KP_R0 PB_5 #define KP_R1 PB_6 #define KP_R2 PB_7 #define KP_R3 PB_8 #define KP_C0 PC_2 #define KP_C1 PC_1 #define KP_C2 PC_0 #define KP_C3 PB_4 #define KP_C4 PB_0 #endif #ifdef HAVE_PC BufferedSerial pc(USBTX, USBRX); #endif SSD1322 *dsp; HPSerial *hp; volatile uint8_t must_refresh; Thread tdsp, tloop; Ticker blinker; Timeout rst_delay; Timeout splashscreen_timer; DigitalOut led(LED1); InterruptIn rst(HP_RST); QEI qenc(KP_ENC1, KP_ENC2, NC, 16); volatile uint8_t knob; volatile bool splashscreen; typedef enum { KEY_NONE=0, KEY_PRESSED, KEY_RELEASED } key_event_t; typedef struct keycode { uint8_t row; uint8_t col; key_event_t keyevent; } keycode_t; volatile keycode_t cur_keycode; PinName kp_rows[] = { KP_R0, KP_R1, KP_R2, KP_R3 }; PinName kp_colums[] = { KP_C0, KP_C1, KP_C2, KP_C3, KP_C4 }; DigitalIn kp_in[] = { KP_R0, KP_R1, KP_R2, KP_R3 }; DigitalOut kp_out[] = { KP_C0, KP_C1, KP_C2, KP_C3, KP_C4 }; uint8_t kp_nrows = sizeof(kp_in)/sizeof(kp_in[0]); uint8_t kp_ncols = sizeof(kp_out)/sizeof(kp_out[0]); void kp_cb(uint8_t row, uint8_t col); void kr_cb(uint8_t row, uint8_t col); Keypad *kpad; uint8_t curchar; //uint8_t curcmd; uint8_t nchars; char buffer[MAX_BUFF+1]; void timeout_h() { led = !led; } typedef struct _DSP { uint8_t cmd; uint8_t color; uint8_t bgcolor; uint8_t x0; uint8_t y0; uint8_t fmt; // 0x01=>ascii, 0x02=>hex, 0x04=>bits, 0x08=>flags, 0x80=>ignore uint8_t maxsize; uint8_t width; const unsigned char* font; 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 }; // 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 }; typedef struct _FLAG { uint8_t flag; uint8_t x; uint8_t y; bool reverse; const char* msg; const unsigned char* icon; } FLAG; typedef struct _FRAME { uint16_t flag; uint8_t x0; uint8_t y0; uint8_t x1; uint8_t y1; } FRAME; static const FLAG flags[] = { // flag, zone, 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 { 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 { 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 { 0x26, 140, 52, false, "EXT"}, // F3.6 { 0x25, 164, 52, false, "ONCE"}, // F3.5 { 0x23, 104, 28+16, false, "MEM"}, // F3.3 // 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 { 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 }; static const FRAME zones[] = { // flag, x0, y0, x1, y1 { 0x001, 0, 0, 245, 27}, // main display area { 0x002, 246, 0, 255, 27}, // right notif area { 0x004, 208, 35, 254, 62}, // channels display area { 0x008, 160, 28, 202, 54}, // alarms area { 0x010, 0, 28, 32, 54}, // flags col1 { 0x020, 33, 28, 70, 54}, // flags col2 { 0x040, 71, 28, 103, 54}, // flags col3 { 0x080, 104, 28, 128, 54}, // flags col4 { 0x100, 129, 28, 159, 54}, // flags col5 // { 0x8000, 0, 55, 255, 63}, // flags bits display area }; static const FRAME frames[] = { { 0x02, 194, 30, 243, 53}, // F1.2 - channel frame { 0x07, 151, 30, 192, 46}, // F1.7 - alarm frame }; #ifdef DEBUG DigitalOut dbgpin(DBGPIN); inline void pulse(uint8_t count=1, bool stayup=false) { dbgpin = 0; wait_us(2); while (count--) { dbgpin = 1; wait_us(2); dbgpin = 0; wait_us(2); } if (stayup) dbgpin = 1; } #else inline void pulse(uint8_t count=1, bool stayup=false) {} #endif // callbacks & thread functions void loop(); void copy_to_lcd(void); void test_dsp(); void reset(void); void reset_irq(void); void qei_cb(int dir); void end_splashscreen(void); void show(uint8_t, const char*, uint8_t); void setup() { #ifdef HAVE_PC pc.set_baud(115200); #endif printf("\n\nSETUP\n"); printf(" System Core Clock = %.3f MHZ\r\n", (float)SystemCoreClock/1000000); //printf("Attaching Led 1: %d\n", LED1); //blinker.attach(callback(timeout_h), 0.5f); hp = NULL; printf("Serial communication pins\r\n"); printf(" USBRX=%d\r\n", USBRX); printf(" USBTX=%d\r\n", USBTX); printf("Setup HP communication pins\r\n"); printf(" HP_RX=%d\r\n", HP_RX); DigitalIn(HP_RX).mode(PullDown); printf(" HP_TX=%d\r\n", HP_TX); DigitalOut(HP_TX).write(1); printf(" HP_RST=%d\r\n", HP_RST); DigitalIn(HP_RST).mode(PullDown); printf(" setup QEI pins\r\n"); printf(" ENC1=%d\r\n", KP_ENC1); DigitalIn(KP_ENC1).mode(PullUp); printf(" ENC2=%d\r\n", KP_ENC2); DigitalIn(KP_ENC2).mode(PullUp); qenc.attach(&qei_cb); printf(" setup Keypad\r\n"); cur_keycode.keyevent = KEY_NONE; uint8_t nrows = sizeof(kp_rows)/sizeof(kp_rows[0]); uint8_t ncols = sizeof(kp_colums)/sizeof(kp_colums[0]); kpad = new Keypad(nrows, kp_in, ncols, kp_out); printf(" attach Keypad callbacks\r\n"); kpad->attach(&kp_cb, &kr_cb); printf(" start Keypad\r\n"); kpad->start(); printf("Setup OLED display\r\n"); // init the LCD printf(" DSP_MOSI=%d\r\n", DSP_MOSI); printf(" DSP_MISO=%d\r\n", DSP_MISO); printf(" DSP_SCLK=%d\r\n", DSP_SCLK); printf(" DSP_CS=%d\r\n", DSP_CS); printf(" DSP_RST=%d\r\n", DSP_RST); printf(" DSP_DC=%d\r\n", DSP_DC); dsp = new SSD1322(20000000, DSP_MOSI, DSP_MISO, DSP_SCLK, DSP_CS, DSP_RST, DSP_DC, "SSD1322"); printf(" configure DSP\r\n"); dsp->background(Black); // set background to black dsp->foreground(0xF); dsp->cls(); //curcmd = 0xFF; curchar = 0; nchars = 0; for (uint8_t i=0; i<sizeof(table)/sizeof(table[0]); ++i) memset(table[i].buffer, 0, MAX_BUFF+1); printf(" display splash screen\r\n"); dsp->locate(30, 10); dsp->set_font((unsigned char*)Mono19x27); dsp->printf("HP34970A"); dsp->set_font((unsigned char*)Terminal6x8); dsp->locate(90, 40); dsp->printf("David Douard"); dsp->copy_to_lcd(); printf("Starting LCD thread\r\n"); tdsp.start(©_to_lcd); printf("Starting Event thread\r\n"); tloop.start(&loop); 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), 2); rst.fall(&reset_irq); printf("SETUP DONE\r\n"); } void end_splashscreen(void) { // print is forbidden here because we are in an ISR context here //printf("End of splash screen CB\r\n"); splashscreen = false; } void reset_irq(void) { rst_delay.attach(callback(&reset), 0.1); } void reset(void) { if (DigitalIn(HP_RST).read() == 0) { if (hp == NULL) { printf("setup HP communication handler\r\n"); hp = new HPSerial(HP_TX, HP_RX); } printf("!! RST !! (gstate=%d, state=%d)\r\n", hp->gstate(), hp->state()); //printf("Value is ... %X\n", hp->search()); hp->startup(); } } void copy_to_lcd(void) { //uint8_t mask=1; while(1) { pulse(0, true); if ((splashscreen == false) && (must_refresh)) { must_refresh = 0; //Thread::wait(20); // give a bit of time for some more cmds dsp->copy_to_lcd(); } /* 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(30); } } void 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[256]; if (cmd == 0xFF) // cls { dsp->clrbuff(); } else { //txt = (char *)malloc(strlen(intxt)+1); strcpy(txt, intxt); txtp = txt; pulse(1, true); // len = MAX_BUFF; for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) { if (table[i].cmd == cmd) { bgcolor = table[i].bgcolor; fgcolor = table[i].color; dsp->background(bgcolor); dsp->foreground(fgcolor); dsp->set_font((unsigned char*) table[i].font); oldv = table[i].buffer; dsp->locate(table[i].x0, table[i].y0); if (table[i].fmt & 0x01) // ASCII text { if (strncmp(oldv, txt, table[i].maxsize) != 0) { if (table[i].width > 0) dsp->fillrect(table[i].x0, table[i].y0, table[i].x0 + table[i].width, table[i].y0 + table[i].font[2], bgcolor); for (uint8_t k=0; ;k++) { if (txtp[k] == 0x00) { dsp->printf(txtp); break; } if (txtp[k] == 0x09) { // \t is a special char for 'unselected' display value txtp[k] = 0x00; dsp->printf(txtp); if (fgcolor == table[i].color) fgcolor /= 2; else fgcolor = table[i].color; dsp->foreground(fgcolor); txtp = &(txtp[k+1]); k = 0; } } if (cmd == 0x00) // main area must_refresh |= 0x01; if (cmd == 0x0C) // channels area must_refresh |= 0x04; } } /* if (table[i].fmt & 0x02 ) { // hex for (uint8_t j=0;; j++) { if (txt[j] == 0x00) break; dsp->printf("%02X ", txt[j]); } for (uint8_t j=3*strlen(txt); j<table[i].maxsize; j++) dsp->printf(" "); } */ if (table[i].fmt & 0x08 ) // flag indicators { // flags for (uint8_t j=0; j<max(nchar, table[i].maxsize) ; j++) { 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)) { dsp->foreground(flags[l].reverse ? bgcolor : fgcolor); dsp->background(flags[l].reverse ? fgcolor : bgcolor); } else { dsp->foreground(bgcolor); dsp->background(bgcolor); } if (flags[l].msg != NULL) { // a string dsp->locate(flags[l].x, flags[l].y); dsp->printf(flags[l].msg);} else { // an icon Bitmap_s pic = {9, 10, 2, (char*) flags[l].icon}; dsp->Bitmap_BW(pic, flags[l].x, flags[l].y); } must_refresh = 1; //|= zones[m].flag; break; } } } } } // draw frames (Alarm and Channel) 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 color = fgcolor/6; else color = bgcolor; dsp->hline(frames[l].x0+1, frames[l].x0+3, frames[l].y0, color); dsp->hline(frames[l].x1-3, frames[l].x1-1, frames[l].y0, color); dsp->hline(frames[l].x0+1, frames[l].x1-1, frames[l].y1, color); dsp->vline(frames[l].x0, frames[l].y0+1, frames[l].y1-1, color); dsp->vline(frames[l].x1, frames[l].y0+1, frames[l].y1-1, color); } } for(uint8_t j=0; j<table[i].maxsize; j++) oldv[j] = txt[j]; break; } } //free(txt); //dsp->copy_to_lcd(); pulse(1, false); } } void test_dsp() { const FRAME *z; printf("TEST DSP\r\n"); dsp->cls(); printf("TEST DSP #2\r\n"); show(0x00, "8g8g8g8g8g8g8", 13); // main dsp show(0x0C, "888", 3); // channel dsp show(0x0A, "\xFF\xFF\xFF\xFF", 4); // all flags dsp->copy_to_lcd(); ThisThread::sleep_for(3); dsp->cls(); printf("TEST DSP #3\r\n"); for (uint8_t i=0; i<(sizeof(zones)/sizeof(zones[0])); i++) { z = &zones[i]; dsp->fillrect(z->x0, z->y0, z->x1, z->y1, 4+i); dsp->locate(z->x0+1, z->y0+1); dsp->printf("%d", i); } /* for (uint8_t i=0; i<(sizeof(zones)/sizeof(zones[0])); i++) { z = &zones[i]; printf("Zone %d [%x]: %d, %d, %d, %d\n", i, z->flag, z->x0, z->y0, z->x1, z->y1); must_refresh = z->flag; wait(1); } printf("Done\n"); wait(2); printf("Copy ALL\n"); dsp->copy_to_lcd(); */ ThisThread::sleep_for(2); dsp->cls(); printf("TEST DSP DONE\r\n"); } void loop() { // run over and over unsigned int err[8]; for (uint8_t i=0; i<8; i++) err[i] = 0; int p, pp; p = 0; pp = 0; while(1) { if (knob != 0) { if (hp != NULL) { printf("Sending keycode %X\r\n", knob); hp->sendkey(knob); printf(" DONE\r\n"); } knob = 0; } if (cur_keycode.keyevent != KEY_NONE) { printf("Keycode %dx%d: %s\r\n", cur_keycode.row, cur_keycode.col, cur_keycode.keyevent==KEY_PRESSED?"pressed":"released"); cur_keycode.keyevent = KEY_NONE; } p = qenc.getPulses(); if (p != pp) { printf("Pulses = %d\r\n", p); pp = p; } if ((hp != NULL) && (hp->cmd_available())) { HPSerial::CMD cmd; if (hp->pop(cmd)) { led = 1; 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", hp->nerrors(0), hp->nerrors(1), hp->nerrors(2), hp->nerrors(3), hp->nerrors(4), hp->nerrors(5), hp->nerrors(6) ); break; } for (uint8_t i=0; i<7; i++) err[i] = hp->nerrors(i); printf("CMD[%d] %02X", (int)cmd.id, cmd.cmd); if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C)) printf(": '%s'\r\n", cmd.value); else { printf(":"); for (uint8_t i=0; i<cmd.size; i++) printf("%02x ", cmd.value[i]); printf("\r\n"); } show(cmd.cmd, cmd.value, cmd.size); led = 0; } } //else ThisThread::sleep_for(1); } } void qei_cb(int dir) { if(dir == 1) // turn right knob = 0x80; else // turn left knob = 0x83; } void kp_cb(uint8_t row, uint8_t col) { cur_keycode.row = row; cur_keycode.col = col; cur_keycode.keyevent = KEY_PRESSED; } void kr_cb(uint8_t row, uint8_t col) { cur_keycode.row = row; cur_keycode.col = col; cur_keycode.keyevent = KEY_RELEASED; } int main() { setup(); printf("Main loop (noop)\r\n"); while(1) { timeout_h(); ThisThread::sleep_for(1); } }