# HG changeset patch # User David Douard # Date 1548708609 -3600 # Node ID daf26b0838998d7dd8e2d55d979af02d0d8fd4d8 # Parent 2f51221af82d1ad39e30ad1841912f6cf60aecd6 Add the serialdata tool to read and decode serial data from the hp34970 using the dslogic. diff -r 2f51221af82d -r daf26b083899 serialdata/34970-long-session.sr Binary file serialdata/34970-long-session.sr has changed diff -r 2f51221af82d -r daf26b083899 serialdata/34970.rd Binary file serialdata/34970.rd has changed diff -r 2f51221af82d -r daf26b083899 serialdata/read-ds --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialdata/read-ds Mon Jan 28 21:50:09 2019 +0100 @@ -0,0 +1,1 @@ +sigrok-cli -d dreamsourcelab-dslogic --config samplerate=1000000 --samples=100000 -t 2=f --channels 1,2,3 -l 4 -P uart:baudrate=187500:parity_type=none:rx=1:tx=3 diff -r 2f51221af82d -r daf26b083899 serialdata/read-ds-continuous --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialdata/read-ds-continuous Mon Jan 28 21:50:09 2019 +0100 @@ -0,0 +1,1 @@ +sigrok-cli -d dreamsourcelab-dslogic -c samplerate=1M:continuous=on --triggers 2=f --channels 1,2,3 -l 4 -P uart:baudrate=187500:parity_type=none:rx=1:tx=3 --continuous diff -r 2f51221af82d -r daf26b083899 serialdata/read-sr --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialdata/read-sr Mon Jan 28 21:50:09 2019 +0100 @@ -0,0 +1,1 @@ +sigrok-cli -i 34970-long-session.sr -P uart:baudrate=187500:parity_type=none:rx=RX:tx=TX -l 4 2>/dev/null | python3 uart_filter.py diff -r 2f51221af82d -r daf26b083899 serialdata/sr-info.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialdata/sr-info.py Mon Jan 28 21:50:09 2019 +0100 @@ -0,0 +1,27 @@ +import zipfile +import configparser + + +def extract_metadata(fname): + cfg = configparser.ConfigParser() + with zipfile.ZipFile(fname) as zf: + mdata = zf.open('metadata').read() + cfg.read_string(mdata.decode()) + return cfg + + +def print_metadata(mdata): + for kv in mdata['global'].items(): + print('%s: %s' % kv) + for device, cfg in mdata.items(): + if device in ('global', 'DEFAULT'): + continue + print('%s:' % device) + for kv in cfg.items(): + print(' %s: %s' % kv) + + +if __name__ == '__main__': + import sys + for fn in sys.argv[1:]: + print_metadata(extract_metadata(fn)) diff -r 2f51221af82d -r daf26b083899 serialdata/uart_filter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialdata/uart_filter.py Mon Jan 28 21:50:09 2019 +0100 @@ -0,0 +1,279 @@ +import sys +import re +import click + +F = 1e6 + +reg = re.compile(r'^(?P\d+)-(?P\d+) .*: (?Prx|tx)-data: "(?P..)"$') # noqa + + +class ProtocolError(Exception): + pass + +class ProtocolReset(Exception): + pass + +pkts = [] + + +class Packet: + def __init__(self, frame, rxtx, value): + self.frame = frame + self.rxtx = rxtx + self.value = value + + @property + def timestamp(self): + return self.frame / F * 1000 + + @property + def relts(self): + return self.timestamp - pkts[0].timestamp + + def __str__(self): + return '[%06.2f] %s: %02X' % (self.timestamp, self.rxtx, self.value) + + +def read_line(seq): + for line in seq: + m = reg.match(line) + if m: + frame = int(m.group('fr1')) + v = int(m.group('value'), base=16) + rxtx = m.group('rxtx') + pkt = Packet(frame, rxtx, v) + pkts.append(pkt) + yield pkt + + +def read_input(stream=None): + if stream is None: + stream = sys.stdin + for line in stream: + yield line + + +def print_input(): + t0 = None + for pkt in read_line(read_input()): + c = chr(pkt.value) if 32 <= pkt.value <= 127 else '' + if t0 is None: + t0 = pkt.timestamp + cnxdir = 'CPU-->DP' if pkt.rxtx == 'rx' else 'CPU<--DP' + print('[%s] %06.1f: %02X # %s' % ( + cnxdir, (pkt.timestamp-t0), pkt.value, c)) + + +def flipdir(rxtx): + return 'rx' if rxtx == 'tx' else 'tx' + + +def check_rxtx(cur, pkt): + if cur.rxtx == pkt.rxtx: + raise ProtocolError('Expected %s transmission %02X %02X' % + (flipdir(cur.rxtx), cur.value, pkt.value)) + + +def check_sot_ack(ack, sot): + check_rxtx(ack, sot) + if ack.value != (0xFF - sot.value): + if ack.value == 0x66: + raise ProtocolReset() + raise ProtocolError('Expected ACK value %02X, got %02X' % + (0xFF - sot.value, ack.value)) + + +def wait_for_sot(seq, sot_pkt=None): + if sot_pkt is None: + for sot_pkt in seq: + if sot_pkt.value not in SOT_VALUES: + print('Unexpected value %s: %02X' % + (sot_pkt.rxtx, sot_pkt.value)) + else: + break + for ack_pkt in seq: + try: + check_sot_ack(sot_pkt, ack_pkt) + # print('New packet %s' % sot_pkt) + return sot_pkt, ack_pkt + except ProtocolReset: + # print('reset') + sot_pkt = ack_pkt + raise StopIteration() + + +SOT_VALUES = [0x33, 0x66] + + +def recv_packet(seq): + sot_pkt = None + while True: + sot_pkt, ack_pkt = wait_for_sot(seq, sot_pkt) + payload = [] + recv_char = None + may_stop = False + + cur_pkt = ack_pkt + for pkt in seq: + if pkt.value == 0x66: + sot_pkt = pkt + break + + check_rxtx(pkt, cur_pkt) + if recv_char is None: + if pkt.rxtx != sot_pkt.rxtx: + raise ProtocolError() + recv_char = pkt.value + cur_pkt = pkt + if may_stop: + if recv_char == 0x55: + cur_pkt = None + sot_pkt = None + break + else: + if pkt.rxtx == sot_pkt.rxtx: + raise ProtocolError() + if pkt.value == 0x00: + payload.append(recv_char) + if check_payload(sot_pkt, payload): + may_stop = True + yield (sot_pkt, payload) + else: + may_stop = False + elif pkt.value != 0xFF: + # if FF, ignore the char (ie. its a NACK, so resend) + raise ProtocolError('Not really but hey %02X [%02X] %s' % + (pkt.value, recv_char, payload)) + recv_char = None + cur_pkt = pkt + else: + break + + +def check_payload(sot, payload): + if sot.rxtx == 'tx': + if sot.value == 0x33: + return len(payload) == 2 + else: + return len(payload) == 1 + else: + if len(payload) > 1: + return len(payload) == (payload[1]+2) + return False + + +KEYCODES = { + 0x00: 'View', + 0x01: 'Mon', + 0x02: 'Sto/Rcl', + 0x03: 'Scan', + 0x04: 'Alarm', + 0x05: 'Mx+B', + 0x06: 'Measure', + 0x07: 'Interval', + 0x08: 'Card Reset', + 0x09: 'Close', + 0x0A: 'Open', + 0x0B: 'Read', + 0x0C: 'Shift', + 0x0D: 'Write', + 0x0E: 'Left', + 0x0F: 'Right', + 0x10: 'Advanced', + 0x11: 'Step', + 0x80: 'Knob right', + 0x81: 'Knob left', + } + + +FLAGS = [ + ['', 'Mx+B', 'Ch. frame', 'Channel', 'LO', 'Alarm', 'HI', 'Al. frame'], + ['2', '4', '3', '1', '4W', 'OC', '', 'AVG'], + ['MAX', 'MIN', 'LAST', 'MEM', '', 'ONCE', 'EXT', 'ERROR'], + ['REMOTE', 'ADRS', '*', 'VIEW', 'MON', 'SCAN', 'CONFIG', ''] +] + + +def flag(payload): + flags = [] + for flg, byte in zip(FLAGS, payload[2:]): + for i in range(8): + if byte & 2**i: + flags.append(flg[i]) + return ','.join(flags) + + +def flag_by_num(num): + for b in FLAGS: + for f in b: + if num == 0: + return f + num -= 1 + +CMDS = { + 0x00: ('DISPLAY ', lambda pl: ''.join(chr(x) for x in pl[2:])), + 0x0C: ('CHANNEL ', lambda pl: ''.join(chr(x) for x in pl[2:])), + 0x0A: ('FLAGS ', flag), + 0x01: ('UNSHIFT ', None), + 0x86: ('SHUTDOWN', None), + 0x0D: ('CHAR LO ', lambda pl: str(pl[2])), + 0x08: ('FLAG LO ', lambda pl: flag_by_num(pl[2])), + 0x09: ('FLAG HI ', lambda pl: flag_by_num(pl[2])), + 0x02: ('RST? ', None), + } + + +def parse_packet(sot, payload): + if sot.value == 0x33: + return 'INIT KEY=%s' % KEYCODES.get(payload[1], 'None') + if sot.rxtx == 'tx': + kc = payload[0] + if kc in (0x80, 0x81): + return 'KNOB\t\t%s' % click.style(KEYCODES.get(kc), fg='magenta') + if kc & 0x40: + kc = kc & 0xBF + event = 'RELEASED' + else: + event = 'PRESSED ' + return 'KEY %s\t%s' % (click.style(event, fg='green'), + click.style(KEYCODES.get(kc), fg='cyan')) + lbl, dspfunc = CMDS[payload[0]] + if dspfunc: + lbl += '\t%s' % click.style(dspfunc(payload), fg='green') + return lbl + + +@click.command() +@click.option('-p', '--packets/--no-packets', default=False) +def main(packets): + if packets: + try: + for sot, payload in recv_packet(read_line(read_input())): + cnxdir = 'CPU=>DP' if sot.rxtx == 'rx' else 'CPU<-DP' + print('[%s]: %02X=[%s]' % + (cnxdir, sot.value, + ','.join('%02x' % x for x in payload))) + except: + print('\n'.join(str(x) for x in pkts[-10:])) + raise + else: + try: + t0 = None + for sot, payload in recv_packet(read_line(read_input())): + cnxdir = '>>>' if sot.rxtx == 'rx' else '<<<' + if t0 is None: + t0 = sot.timestamp + click.secho('%08.0f ' % sot.relts, + fg='yellow', nl=False) + click.secho('[+%04.2f] ' % ((sot.timestamp - t0)/1000.), + fg='blue', nl=False) + click.secho(cnxdir + ' ', fg='red', nl=False) + click.secho(parse_packet(sot, payload), fg='white') + t0 = sot.timestamp + except: + print('\n'.join(str(x) for x in pkts[-10:])) + raise + + +if __name__ == '__main__': + main() diff -r 2f51221af82d -r daf26b083899 src/main.cpp --- a/src/main.cpp Wed Nov 07 20:00:52 2018 +0100 +++ b/src/main.cpp Mon Jan 28 21:50:09 2019 +0100 @@ -188,12 +188,9 @@ static DSP table[] = { - { 0x00, 0xF, 0x0, 0, 0, 0x01, MAX_BUFF, 245, Mono19x27}, // main display - { 0x0C, 0xF, 0x0,204, 38, 0x01, 3, 45, Mono15x22}, // channels display - // { 0x01, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8}, - // { 0x02, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8}, - { 0x0A, 0xF, 0x0, 0, 57, 0x08, 4, 0, Terminal6x8}, // flags + bits - // { 0xFF, 0xF, 0x0, 0, 0, 0x80, MAX_BUFF, 0, Terminal6x8}, + { 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 @@ -228,9 +225,9 @@ typedef struct _FLAG { uint8_t flag; - uint16_t zone; uint8_t x; uint8_t y; + bool reverse; const char* msg; const unsigned char* icon; } FLAG; @@ -246,53 +243,47 @@ static const FLAG flags[] = { - // flag, zone, x0, y0, msg, icon + // flag, zone, x0, y0, reverse, msg, icon // right-side icons area - { 0x00, 0x02, 0, 0, NULL, icon_alarm}, // F1.0 - { 0x01, 0x02, 0, 11, NULL, icon_curve}, // F1.1 - //{ 0x14, 0x02, 0, 0, "4W"}, // F2.4 - //{ 0x15, 0x02, 0, 8, "OC"}, // F2.5 + { 0x00, 246, 0, false, NULL, icon_alarm}, // F1.0 + { 0x01, 246, 11, false, NULL, icon_curve}, // F1.1 // F1.2 == Channel frame - { 0x03, 0x04, 1, 2, "Channel"}, // F1.3 - // F1.7 == Alarm frame + { 0x03, 197, 27, false, "Channel"}, // F1.3 + // F1.7 == Alarm frame + - // col 1 - { 0x34, 0x10, 0, 0, "MON"}, // F4.4 - { 0x33, 0x10, 0, 8, "VIEW"}, // F4.3 - { 0x35, 0x10, 0, 16, "SCAN"}, // F4.5 + { 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 - //col 2 - { 0x32, 0x20, 0, 0, "*"}, // F4.2 - { 0x36, 0x20, 0, 8, "CONFIG"}, // F4.6 - { 0x27, 0x20, 0, 16, "ERROR"}, // F3.7 + { 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 - // col 3 - { 0x41, 0x040, 0, 0, "ADRS"}, // F4.1 - { 0x40, 0x040, 0, 8, "RMT"}, // F4.0 + { 0x26, 140, 52, false, "EXT"}, // F3.6 + { 0x25, 164, 52, false, "ONCE"}, // F3.5 - // col 4 - { 0x26, 0x080, 0, 0, "EXT"}, // F3.6 - { 0x25, 0x080, 0, 8, "ONCE"}, // F3.5 - - { 0x23, 0x080, 0, 16, "MEM"}, // F3.3 + { 0x23, 104, 28+16, false, "MEM"}, // F3.3 // col 5 - { 0x14, 0x100, 0, 0, "4W"}, // F2.4 - { 0x15, 0x100, 0, 8, "OC"}, // F2.5 - { 0x22, 0x100, 0, 16, "LAST"}, // F3.2 - { 0x21, 0x100, 0, 16, "MIN"}, // F3.1 - { 0x20, 0x100, 0, 16, "MAX"}, // F3.0 - { 0x17, 0x100, 0, 16, "AVG"}, // F2.7 + { 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, 0x08, 0, 0, "Alarm"}, // F1.5 - { 0x06, 0x08, 0, 10, "H"}, // F1.6 - { 0x13, 0x08, 6, 10, "1"}, // F2.3 - { 0x10, 0x08, 12, 10, "2"}, // F2.0 - { 0x12, 0x08, 18, 10, "3"}, // F2.2 - { 0x11, 0x08, 24, 10, "4"}, // F2.1 - { 0x04, 0x08, 30, 10, "L"}, // F1.4 + { 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 }; @@ -300,7 +291,7 @@ { // flag, x0, y0, x1, y1 { 0x001, 0, 0, 245, 27}, // main display area { 0x002, 246, 0, 255, 27}, // right notif area - { 0x004, 203, 28, 255, 54}, // channels display 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 @@ -313,8 +304,8 @@ static const FRAME frames[] = { - { 0x02, 203, 35, 255, 54}, // F1.2 - channel frame - { 0x07, 160, 28, 202, 54}, // F1.7 - alarm frame + { 0x02, 194, 30, 243, 53}, // F1.2 - channel frame + { 0x07, 151, 30, 192, 46}, // F1.7 - alarm frame }; @@ -405,11 +396,8 @@ 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"); - //dsp.set_orientation(3); + printf(" configure DSP\r\n"); - // myLCD.set_font((unsigned char*) Terminal6x8); - // myLCD.claim(stdout); // send stdout to the LCD display - // myLCD.claim(stderr); // send stderr to the LCD display dsp->background(Black); // set background to black dsp->foreground(0xF); dsp->cls(); @@ -452,7 +440,6 @@ void end_splashscreen(void) { printf("End of splash screen CB\r\n"); - //dsp->cls(); splashscreen = false; } @@ -507,7 +494,8 @@ } } -void show(uint8_t cmd, const char *intxt, uint8_t nchar=0) { +void show(uint8_t cmd, const char *intxt, uint8_t nchar=0) +{ uint8_t i, len; uint16_t bgcolor, fgcolor; char *oldv; @@ -520,143 +508,140 @@ } else { - txt = (char *)malloc(strlen(intxt)+1); - strcpy(txt, intxt); - txtp = txt; + txt = (char *)malloc(strlen(intxt)+1); + strcpy(txt, intxt); + txtp = txt; + + pulse(1, true); + + len = MAX_BUFF; - pulse(1, true); + for (i=0; ibackground(bgcolor); + dsp->foreground(fgcolor); + dsp->set_font((unsigned char*) table[i].font); + oldv = table[i].buffer; - len = MAX_BUFF; + dsp->locate(table[i].x0, table[i].y0); - for (i=0; ibackground(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 (table[i].fmt & 0x01 ) - { - if (strncmp(oldv, txt, table[i].maxsize) != 0) - { - // ascii - 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 (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); jprintf(" "); + } + */ + if (table[i].fmt & 0x08 ) // flag indicators + { + // flags + for (uint8_t j=0; jforeground(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; jprintf(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); jprintf(" "); - } - */ - if (table[i].fmt & 0x08 ) - { - // flags - for (uint8_t j=0; jforeground(fgcolor); - else - dsp->foreground(bgcolor); - - /* - for (uint8_t l=0; - l<(sizeof(frames)/sizeof(frames[0])); ++l) { - if (frames[l].flag & ((j<<4) + k)) - dsp->fillrect(frames[l].x0, frames[l].y0, - frames[l].x1, frames[l].y1, - fgcolor/8); - else - dsp->fillrect(frames[l].x0, frames[l].y0, - frames[l].x1, frames[l].y1, - bgcolor); - - } - */ - - for (uint8_t l=0; - l<(sizeof(flags)/sizeof(flags[0])); ++l) - { - if (flags[l].flag == ((j<<4) + k)) { - for (uint8_t m=0; m<(sizeof(zones)/sizeof(zones[0])); m++) - { - if (flags[l].zone == zones[m].flag) { - if (flags[l].msg != NULL) - { // a string - dsp->locate(flags[l].x + zones[m].x0, - flags[l].y + zones[m].y0); - 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 + zones[m].x0, - flags[l].y + zones[m].y0); - } - must_refresh |= zones[m].flag; - break; - } - } - break; - } - } - } - } - } - } - - for(uint8_t j=0; jcopy_to_lcd(); - pulse(1, false); + free(txt); + //dsp->copy_to_lcd(); + pulse(1, false); } }