Wed, 21 Sep 2016 20:09:21 +0200
[SSD1322] add a copy_to_lcd method that accepts an area
#include "hp34comm.h" #include "mbed.h" #include "CircularBuffer.h" /***** HP 34970A communication class ***/ #define HP_SERIAL_TX PC_7 // serial6 RX #define HP_SERIAL_RX PA_1 // serial4 RX #ifdef DEBUG DigitalOut inrx(PC_0); DigitalOut intx(PC_1); DigitalOut ack(PC_3); DigitalOut staterx(PC_2); DigitalOut statetx(PH_1); #endif HPSerial::HPSerial(): ncmd(0), serial_tx(NC, HP_SERIAL_TX), serial_rx(NC, HP_SERIAL_RX) { //pc.printf("HPSerial init\n"); for(uint8_t i=0; i<MAX_ERRS; i++) errs[i] = 0; reset(); serial_tx.baud(187500); serial_tx.attach(this, &HPSerial::txIrq, Serial::RxIrq); //sic! serial_rx.baud(187500); serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq); } bool HPSerial::cmd_available(void) { return !cmdbuf.empty(); } bool HPSerial::pop(CMD& cmd) { return cmdbuf.pop(cmd); } bool HPSerial::cmd_buf_full(void) { return cmdbuf.full(); } unsigned int HPSerial::nerrors(uint8_t errorno) { return errs[errorno]; } void HPSerial::reset(uint8_t errorno) { timeouter.detach(); head = 0; tx_state = Idle; setstatedbg(); tx_cmd = 0xFF; tx_ack = false; tx_len = 0xFF; memset(buf, 0, BUF_SIZE); if (errorno != 0xFF){ errs[errorno]++; } } void HPSerial::handleAck(uint8_t val) { if ((tx_state == Rx) & (tx_cmd == 0xFF) & (tx_ack == false) & (val == 0x66)) { // special case: keypad does not acknwledge and takes precedence // on the "bus" tx_state = Tx; setstatedbg(); } else if (tx_ack == true) reset(0); else if (tx_cmd == 0xFF) // still at the beginning of a packet, expect 0x99 as ack if (val == 0x99) { tx_ack = true; #ifdef DEBUG ack = 1; wait_us(2); ack = 0; #endif } else reset(1); else // expect 0x00 as ack if (val == 0x00) { tx_ack = true; #ifdef DEBUG ack = 1; wait_us(2); ack = 0; wait_us(2); ack = 1; wait_us(2); ack = 0; #endif } else reset(2); } void HPSerial::pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) { CMD val; uint8_t i; val.id = ncmd++; val.direction = direction; val.cmd = cmd; val.size = size; for(i=0; i<size; i++) val.value[i] = payload[i]; val.value[i] = 0x00; cmdbuf.push(val); } void HPSerial::handleChar(uint8_t val) { if (tx_ack == false) reset(3); else // remaining of the state machine if (tx_cmd == 0xFF) { // begin of transmission, expect a cmd tx_cmd = val; tx_ack = false; if (tx_state == Rx) tx_len = 0xFF; else tx_len = 0x00; // no payload: tx_cmd is the key stroke } else if (tx_len == 0xFF) { // got a cmd, expect a payload size tx_len = val; tx_ack = false; } else if (tx_len > 0) { // a payload char buf[head++] = val; tx_len--; tx_ack = false; } else { // end of payload, manage sent content uint8_t cur_state = tx_state; pushCmd(tx_state, tx_cmd, head, buf); switch(val) { case 0x66: // a new transmisson reset(); tx_state = cur_state; setstatedbg(); break; case 0x55: reset(); break; default: reset(6); break; } } } void HPSerial::setstatedbg(void) { /* if (tx_state == Rx) staterx = 1; else staterx = 0; if (tx_state == Tx) statetx = 1; else statetx = 0; */ } void HPSerial::rxIrq(void) { uint8_t val; if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey #ifdef DEBUG inrx=1; #endif val = serial_rx.getc(); timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset if (tx_state == Idle) if (val == 0x66) { // no transmission in progress, expect a start of transmission tx_state = Rx; tx_ack = false; setstatedbg(); } else reset(4); else if (tx_state == Tx) // manage the acks handleAck(val); else handleChar(val); #ifdef DEBUG inrx=0; #endif } } void HPSerial::txIrq(void) { uint8_t val; if(serial_tx.readable()) { // no reason why we would end here without this condition, but hey #ifdef DEBUG intx=1; #endif val = serial_tx.getc(); timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset if (tx_state == Idle) if (val == 0x66) { // no transmission in progress, expect a start of transmission tx_state = Tx; tx_ack = false; setstatedbg(); } else reset(5); else if (tx_state == Rx) // manage the acks handleAck(val); else handleChar(val); } #ifdef DEBUG intx=0; #endif } void HPSerial::timeout(void) { if (tx_state != Idle) { reset(7); } }