/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Created on 27.04.2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package tal; import joprt.RtThread; import util.Dbg; import util.Serial; import com.jopdesign.sys.Const; import com.jopdesign.sys.Native; /** * @author martin * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class Modbus extends RtThread { private Serial ser; private int[] outReg; final static int MAX_LEN = 256; private int[] msg; private int len; private StringBuffer str; public static final int ILLEGAL_FUNCTION = 1; public static final int ILLEGAL_ADDRESS = 2; public static final int ILLEGAL_VALUE = 3; /** * @param prio * @param us */ public Modbus(int prio, int us, Serial serial, int[] or) { super(prio, us); ser = serial; msg = new int[MAX_LEN]; str = new StringBuffer(100); len = 0; outReg = or; } public void run() { for (;;) { readMsg(); if (len != 0) { processMsg(); if (len!=0) sendMsg(); } } } /** * */ private void processMsg() { int devAddr = msg[0]; int cmd = msg[1]; switch (cmd) { case 1: readCoils(); break; case 2: readInputDiscrete(); break; case 3: readMultipleRegisters(); break; case 4: readInputRegister(); break; case 5: writeSingleCoil(); break; case 6: writeSingleRegister(); break; case 15: writeMultipleCoils(); break; case 16: writeMultipleRegisters(); break; case 20: readFileRecord(); break; case 21: writeFileRecord(); break; case 22: maskWriteRegister(); break; case 23: readWriteMultipleRegisters(); break; case 43: readDeviceIdentification(); break; default: msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } } /** * */ private void readCoils() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void readInputDiscrete() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void readMultipleRegisters() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } static int abc; /** * */ private void readInputRegister() { int addr = (msg[2]<<8) + msg[3]; int cnt = (msg[4]<<8) + msg[5]; if (cnt<1 || cnt>5) { msg[1] |= 128; msg[2] = ILLEGAL_VALUE; len = 3; return; } if (addr+cnt>5) { msg[1] |= 128; msg[2] = ILLEGAL_ADDRESS; len = 3; return; } msg[2] = cnt*2; for (int i=0; i<cnt; ++i) { int idx = addr+i; int val = 0; if (idx==0) { val = Native.rd(Const.IO_IN); } else if (idx==1) { val = Native.rd(Const.IO_ADC1); } else if (idx==2) { val = Native.rd(Const.IO_ADC2); } else if (idx==3) { val = Native.rd(Const.IO_ADC3); } else if (idx==4) { val = abc++; } msg[3+(i<<1)] = val>>8; msg[4+(i<<1)] = val; } len = 3+(cnt<<1); } /** * */ private void writeSingleCoil() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void writeSingleRegister() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void writeMultipleCoils() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void writeMultipleRegisters() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void readFileRecord() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void writeFileRecord() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void maskWriteRegister() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void readWriteMultipleRegisters() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void readDeviceIdentification() { // TODO Auto-generated method stub msg[1] |= 128; msg[2] = ILLEGAL_FUNCTION; len = 3; } /** * */ private void sendMsg() { int i; str.setLength(0); str.append(':'); int sum = 0; for (i=0; i<len; ++i) { int val = msg[i]; sum += val; str.append(int2hex(val>>4)); str.append(int2hex(val)); } sum = -sum; str.append(int2hex(sum>>4)); str.append(int2hex(sum)); str.append("\r\n"); len = 0; int slen = str.length(); i = 0; Dbg.wr('<'); for (;;) { int j = ser.txFreeCnt(); for (int k=0; k<j; ++k) { ser.wr(str.charAt(i)); Dbg.wr(str.charAt(i)); ++i; if (i==slen) return; } waitForNextPeriod(); } } /** * @return */ private void readMsg() { int val, cnt; str.setLength(0); waitForStart(); for (;;) { waitForNextPeriod(); cnt = ser.rxCnt(); if (cnt==0) continue; val = 0; for (int i = cnt; i>0; --i) { val = ser.rd(); str.append((char) val); if (val=='\n') break; } if (val=='\n') break; } Dbg.wr('>'); Dbg.wr(str); len = convertMsg(); } /** * @return */ private int convertMsg() { int i; int mlen = str.length()-2; // minimum function code and checksum if (mlen<4) return 0; // parity check and mask, when using 7 bits int sum = 0; for (i=0; i<mlen; i+=2) { int val = Param.readHexByte(str, i); sum += val; msg[i>>1] = val; } sum &= 0xff; if (sum!=0) { Dbg.wr("wrong checksum\n"); return 0; } return (mlen-2)>>1; } /** * @return */ private void waitForStart() { int cnt; for (;;) { waitForNextPeriod(); cnt = ser.rxCnt(); if (cnt==0) continue; for (int i = cnt; i>0; --i) { if (ser.rd()==':') return; } } } /** * @param i * @return */ private char int2hex(int i) { i &= 0x0f; if (i<10) { return (char) ('0'+i); } else { return (char) ('A'+i-10); } } }