The goal of this software is to automatically generate C/C++ code which reads and writes GOOSE and Sampled Value packets. Any valid IEC 61850 Substation Configuration Description (SCD) file, describing GOOSE and/or SV communications, can be used as the input. The output code is lightweight and platform-independent, so it can run on a variety of devices, including low-cost microcontrollers. It\'s ideal for rapid-prototyping new protection and control systems that require communications. This mbed project is a simple example of this functionality. Other code: https://github.com/stevenblair/rapid61850 Project homepage: http://personal.strath.ac.uk/steven.m.blair/

Revision:
0:230c10b228ea
Child:
1:9399d44c2b1a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svDecodePacket.c	Fri Oct 07 13:41:08 2011 +0000
@@ -0,0 +1,99 @@
+#include "svDecodeBasic.h"
+#include "ied.h"
+#include "svDecode.h"
+#include "svPacketData.h"
+#include "decodePacket.h"
+#include <stddef.h>
+
+
+void svDecodeASDU(unsigned char *buf, int len, int noASDU) {
+	unsigned char tag;	// assumes only one byte is used
+	int lengthFieldSize;
+	int lengthValue;
+	int offsetForNonSequence;
+	unsigned char *svID = NULL;
+	int svIDLength = 0;
+
+	int i = 0;
+	for (i = 0; i < len;) {
+		tag = (unsigned char) buf[i];
+		lengthFieldSize = getLengthFieldSize((unsigned char) buf[i + 1]);
+		lengthValue = decodeLength((unsigned char *) &buf[i + 1]);
+		offsetForNonSequence = 1 + lengthFieldSize + lengthValue;
+
+		//printf("\ttag: %x, noASDU: %u, lengthFieldSize: %i, lengthValue: %i, offset: %i\n", tag, noASDU, lengthFieldSize, lengthValue, offsetForNonSequence);
+
+		switch (tag) {
+		case 0x80:
+			svID = &buf[i + 1 + lengthFieldSize];
+			svIDLength = lengthValue;
+			break;
+		case 0x81:
+
+			break;
+		case 0x82:
+			// TODO: may be useful to store smpCnt value
+			break;
+		case 0x83:
+
+			break;
+		case 0x84:
+
+			break;
+		case 0x85:
+
+			break;
+		case 0x86:
+
+			break;
+		case 0x87:
+			if (svID != NULL) {
+				svDecodeDataset(&buf[i + 1 + lengthFieldSize], lengthValue, noASDU, svID, svIDLength);
+			}
+			break;
+		default:
+			break;
+		}
+
+		i += offsetForNonSequence;
+	}
+}
+
+void svDecodeAPDU(unsigned char *buf, int len) {
+	unsigned char tag = (unsigned char) buf[0];	// assumes only one byte is used
+	int lengthFieldSize = getLengthFieldSize((unsigned char) buf[1]);
+	int lengthValue = decodeLength((unsigned char *) &buf[1]);
+	int offsetForSequence = 1 + lengthFieldSize;
+	int offsetForNonSequence = 1 + lengthFieldSize + lengthValue;
+	//static unsigned int noASDU = 0;
+	static unsigned int ASDU = 0;
+
+	//printf("tag: %x, noASDU: %u, lengthFieldSize: %i, lengthValue: %i, offset: %i\n", tag, noASDU, lengthFieldSize, lengthValue, offsetForNonSequence);
+
+	switch (tag) {
+	case 0x60:
+		svDecodeAPDU(&buf[offsetForSequence], lengthValue);
+		break;
+	case 0x80:
+		//noASDU = (unsigned int) buf[1 + lengthFieldSize];	// assuming noASDU is < 126
+		ASDU = 0;
+		svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence);
+		break;
+	case 0xA2:
+		svDecodeAPDU(&buf[offsetForSequence], lengthValue);
+		break;
+	case 0x30:
+		svDecodeASDU(&buf[offsetForSequence], lengthValue, ASDU++);
+
+		svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence);
+		break;
+	default:
+		break;
+	}
+}
+
+void svDecode(unsigned char *buf, int len) {
+	unsigned short APDULength = ((buf[21] << 8) | buf[22]) - 8;	// must use length in PDU because total bytes (len) may contain CRC
+
+	svDecodeAPDU(&buf[26], APDULength);	// cuts out frame header (fixed size of 26 bytes before start of APDU)
+}