http://mbed.org/users/okini3939/notebook/melinverter
Dependents: MelInverter_sample
Diff: MelInverter.cpp
- Revision:
- 0:db82bb30177e
- Child:
- 1:5963d2a1c30f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MelInverter.cpp Thu Mar 29 06:13:13 2012 +0000 @@ -0,0 +1,201 @@ +/** + * Mitsubishi Inverter Protocol library for mbed + * Copyright (c) 2012 Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Mitsubishi Inverter Protocol library for mbed + * @note need: http://mbed.org/users/okini3939/libraries/RingBuffer/latest + * FR-E700 + * Pr.79=2, Pr.340=1, Pr.549=0 + * 19200bps, 8bit data, Stop 2bit, Even parity, CR + */ + +#include "dbg.h" +#include "mbed.h" +#include "MelInverter.h" + +MelInverter::MelInverter (PinName p_tx, PinName p_rx) : _mel(p_tx, p_rx), _buf_data(40) { + _mel.baud(19200); + _mel.format(8, Serial::Even, 2); + _mel.attach(this, &MelInverter::isr_mel, Serial::RxIrq); +} + +void MelInverter::isr_mel () { + static int len, mode, sum, s; + static char tmp[20]; + char dat; + + dat = _mel.getc(); + + if (dat == INVCTRL_CR) { + _mel_mode = MELMODE_NONE; + } + + switch (_mel_mode) { + case MELMODE_NONE: + switch (dat) { + case INVCTRL_STX: + // Start of text + DBG("INVCTRL_STX\r\n"); + _mel_mode = MELMODE_STX; + mode = 0; + len = 0; + sum = 0; + s = 0; + _iid = 0; + break; + case INVCTRL_ACK: + // Acknowledge + DBG("INVCTRL_ACK\r\n"); + _mel_mode = MELMODE_ACK; + len = 0; + _iid = 0; + break; + case INVCTRL_NAK: + // Negative acknowledge + DBG("INVCTRL_NAK\r\n"); + _mel_mode = MELMODE_NAK; + len = 0; + _iid = 0; + break; + } + break; + + case MELMODE_STX: + if (mode == 0) { + // device id + tmp[len] = dat; + len ++; + sum += (unsigned char)dat; + if (len >= 2) { + tmp[len] = 0; + _iid = strtol(tmp, NULL, 16); + mode ++; + } + } else + if (mode == 1) { + if (dat == INVCTRL_ETX) { + // End of text + len = 0; + s = 0; + mode ++; + } else { + _buf_data.put(dat); + sum += (unsigned char)dat; + } + } else + if (mode == 2) { + s = (s << 4) + x2i(dat); + len ++; + if (len >= 2) { + if (s == (sum & 0xff)) { + _mel_ok = 1; + _mel_recv = 1; + _res.attach_us(this, &MelInverter::isr_ack, 10000); + } else { + _mel_failure = 1; + _mel_recv = 1; + _res.attach_us(this, &MelInverter::isr_nak, 10000); + DBG("sum error %02x\r\n", sum & 0xff); + } + mode ++; + } + } + break; + + case MELMODE_ACK: + if (len < 2) { + // device id + tmp[len] = dat; + len ++; + if (len >= 2) { + tmp[len] = 0; + _iid = strtol(tmp, NULL, 16); + _mel_ok = 1; + } + } + break; + + case MELMODE_NAK: + if (len < 2) { + // device id + tmp[len] = dat; + len ++; + if (len >= 2) { + tmp[len] = 0; + _iid = strtol(tmp, NULL, 16); + _mel_failure = 1; + } + } + break; + } + +} + +void MelInverter::isr_ack () { + _res.detach(); + _mel.putc(INVCTRL_ACK); + _mel.printf("%02X\r", _iid); + DBG("ACK\r\n"); +} + +void MelInverter::isr_nak () { + _res.detach(); + _mel.putc(INVCTRL_NAK); + _mel.printf("%02X\r", _iid); + DBG("ACK\r\n"); +} + +int MelInverter::send (int iid, MELCMD cmd, char *data) { + int i, sum = 0; + char buf[40]; + + _mel.putc(INVCTRL_ENQ); + sprintf(buf, "%02X%02X%01X", iid, cmd, MELDELAY); + strncat(buf, data, 20); + for (i = 0; i < strlen(buf); i ++) { + _mel.putc(buf[i]); + sum += (unsigned char)buf[i]; + } + _mel.printf("%02X\r", sum & 0xff); + DBG("command: %d %02X %s\r\n", iid, cmd, buf); + while (!_mel_ok && !_mel_failure); + return (_mel_ok == 1); +} + +int MelInverter::recv (int iid, char *buf, int len) { + int r; + + while (iid != _iid && _mel_recv == 0); + + _mel_recv = 0; + r = _buf_data.get(buf, len); + return r; +} + + +int MelInverter::x2i (char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } else + if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else + if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + return 0; +} + +char MelInverter::i2x (int i) { + if (i >= 0 && i <= 9) { + return i + '0'; + } else + if (i >= 10 && i <= 15) { + return i - 10 + 'A'; + } + return 0; +} +