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

Dependents:   MelInverter_sample

MelInverter.cpp

Committer:
okini3939
Date:
2012-03-29
Revision:
0:db82bb30177e
Child:
1:5963d2a1c30f

File content as of revision 0:db82bb30177e:

/**
 * 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;
}