http://mbed.org/users/okini3939/notebook/melinverter

Dependents:   MelInverter_sample

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;
+}
+