An mbed implementation of IEC 61850-9-2LE Sample Values. Creating using the rapid61850 library, available at: https://github.com/stevenblair/rapid61850.

Dependencies:   mbed

An mbed implementation of IEC 61850-9-2LE Sample Values. Creating using the rapid61850 library, available at: https://github.com/stevenblair/rapid61850.

Committer:
sblair
Date:
Tue Oct 02 21:31:05 2012 +0000
Revision:
0:f09b7bb8bcce
converted library to folder

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sblair 0:f09b7bb8bcce 1 /**
sblair 0:f09b7bb8bcce 2 * Rapid-prototyping protection schemes with IEC 61850
sblair 0:f09b7bb8bcce 3 *
sblair 0:f09b7bb8bcce 4 * Copyright (c) 2012 Steven Blair
sblair 0:f09b7bb8bcce 5 *
sblair 0:f09b7bb8bcce 6 * This program is free software; you can redistribute it and/or
sblair 0:f09b7bb8bcce 7 * modify it under the terms of the GNU General Public License
sblair 0:f09b7bb8bcce 8 * as published by the Free Software Foundation; either version 2
sblair 0:f09b7bb8bcce 9 * of the License, or (at your option) any later version.
sblair 0:f09b7bb8bcce 10
sblair 0:f09b7bb8bcce 11 * This program is distributed in the hope that it will be useful,
sblair 0:f09b7bb8bcce 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sblair 0:f09b7bb8bcce 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
sblair 0:f09b7bb8bcce 14 * GNU General Public License for more details.
sblair 0:f09b7bb8bcce 15
sblair 0:f09b7bb8bcce 16 * You should have received a copy of the GNU General Public License
sblair 0:f09b7bb8bcce 17 * along with this program; if not, write to the Free Software
sblair 0:f09b7bb8bcce 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
sblair 0:f09b7bb8bcce 19 */
sblair 0:f09b7bb8bcce 20
sblair 0:f09b7bb8bcce 21 #include "svDecodeBasic.h"
sblair 0:f09b7bb8bcce 22 #include "ied.h"
sblair 0:f09b7bb8bcce 23 #include "svDecode.h"
sblair 0:f09b7bb8bcce 24 #include "svPacketData.h"
sblair 0:f09b7bb8bcce 25 #include "decodePacket.h"
sblair 0:f09b7bb8bcce 26 #include "gseDecodeBasic.h"
sblair 0:f09b7bb8bcce 27 #include <stddef.h>
sblair 0:f09b7bb8bcce 28
sblair 0:f09b7bb8bcce 29
sblair 0:f09b7bb8bcce 30 void svDecodeASDU(unsigned char *buf, int len, int noASDU) {
sblair 0:f09b7bb8bcce 31 unsigned char tag; // assumes only one byte is used
sblair 0:f09b7bb8bcce 32 int lengthFieldSize;
sblair 0:f09b7bb8bcce 33 int lengthValue;
sblair 0:f09b7bb8bcce 34 int offsetForNonSequence;
sblair 0:f09b7bb8bcce 35 unsigned char *svID = NULL;
sblair 0:f09b7bb8bcce 36 int svIDLength = 0;
sblair 0:f09b7bb8bcce 37 CTYPE_INT16U smpCnt = 0;
sblair 0:f09b7bb8bcce 38
sblair 0:f09b7bb8bcce 39 int i = 0;
sblair 0:f09b7bb8bcce 40 for (i = 0; i < len;) {
sblair 0:f09b7bb8bcce 41 tag = (unsigned char) buf[i];
sblair 0:f09b7bb8bcce 42 lengthFieldSize = getLengthFieldSize((unsigned char) buf[i + 1]);
sblair 0:f09b7bb8bcce 43 lengthValue = decodeLength((unsigned char *) &buf[i + 1]);
sblair 0:f09b7bb8bcce 44 offsetForNonSequence = 1 + lengthFieldSize + lengthValue;
sblair 0:f09b7bb8bcce 45
sblair 0:f09b7bb8bcce 46 //printf("\ttag: %x, noASDU: %u, lengthFieldSize: %i, lengthValue: %i, offset: %i\n", tag, noASDU, lengthFieldSize, lengthValue, offsetForNonSequence);
sblair 0:f09b7bb8bcce 47
sblair 0:f09b7bb8bcce 48 switch (tag) {
sblair 0:f09b7bb8bcce 49 case SV_TAG_SVID:
sblair 0:f09b7bb8bcce 50 svID = &buf[i + 1 + lengthFieldSize];
sblair 0:f09b7bb8bcce 51 svIDLength = lengthValue;
sblair 0:f09b7bb8bcce 52 break;
sblair 0:f09b7bb8bcce 53 case SV_TAG_DATSET:
sblair 0:f09b7bb8bcce 54
sblair 0:f09b7bb8bcce 55 break;
sblair 0:f09b7bb8bcce 56 case SV_TAG_SMPCNT:
sblair 0:f09b7bb8bcce 57 ber_decode_integer(&buf[i + 1 + lengthFieldSize], lengthValue, &smpCnt, SV_GET_LENGTH_INT16U);
sblair 0:f09b7bb8bcce 58 break;
sblair 0:f09b7bb8bcce 59 case SV_TAG_CONFREV:
sblair 0:f09b7bb8bcce 60
sblair 0:f09b7bb8bcce 61 break;
sblair 0:f09b7bb8bcce 62 case SV_TAG_REFRTM:
sblair 0:f09b7bb8bcce 63
sblair 0:f09b7bb8bcce 64 break;
sblair 0:f09b7bb8bcce 65 case SV_TAG_SMPSYNCH:
sblair 0:f09b7bb8bcce 66
sblair 0:f09b7bb8bcce 67 break;
sblair 0:f09b7bb8bcce 68 case SV_TAG_SMPRATE:
sblair 0:f09b7bb8bcce 69
sblair 0:f09b7bb8bcce 70 break;
sblair 0:f09b7bb8bcce 71 case SV_TAG_SEQUENCEOFDATA:
sblair 0:f09b7bb8bcce 72 if (svID != NULL) {
sblair 0:f09b7bb8bcce 73 svDecodeDataset(&buf[i + 1 + lengthFieldSize], lengthValue, noASDU, svID, svIDLength, smpCnt);
sblair 0:f09b7bb8bcce 74 }
sblair 0:f09b7bb8bcce 75 break;
sblair 0:f09b7bb8bcce 76 default:
sblair 0:f09b7bb8bcce 77 break;
sblair 0:f09b7bb8bcce 78 }
sblair 0:f09b7bb8bcce 79
sblair 0:f09b7bb8bcce 80 i += offsetForNonSequence;
sblair 0:f09b7bb8bcce 81 }
sblair 0:f09b7bb8bcce 82 }
sblair 0:f09b7bb8bcce 83
sblair 0:f09b7bb8bcce 84 void svDecodeAPDU(unsigned char *buf, int len, unsigned int ASDU, unsigned int totalASDUs) {
sblair 0:f09b7bb8bcce 85 unsigned char tag = (unsigned char) buf[0]; // assumes only one byte is used
sblair 0:f09b7bb8bcce 86 int lengthFieldSize = getLengthFieldSize((unsigned char) buf[1]);
sblair 0:f09b7bb8bcce 87 int lengthValue = decodeLength((unsigned char *) &buf[1]);
sblair 0:f09b7bb8bcce 88 int offsetForSequence = 1 + lengthFieldSize;
sblair 0:f09b7bb8bcce 89 int offsetForNonSequence = 1 + lengthFieldSize + lengthValue;
sblair 0:f09b7bb8bcce 90 unsigned int noASDU = 0;
sblair 0:f09b7bb8bcce 91 //static unsigned int ASDU = 0;
sblair 0:f09b7bb8bcce 92
sblair 0:f09b7bb8bcce 93 //printf("tag: %x, ASDU: %u, totalASDUs: %u, lengthFieldSize: %i, lengthValue: %i, offset: %i\n", tag, ASDU, totalASDUs, lengthFieldSize, lengthValue, offsetForNonSequence);
sblair 0:f09b7bb8bcce 94
sblair 0:f09b7bb8bcce 95 switch (tag) {
sblair 0:f09b7bb8bcce 96 case SV_TAG_SAVPDU:
sblair 0:f09b7bb8bcce 97 svDecodeAPDU(&buf[offsetForSequence], lengthValue, ASDU, totalASDUs);
sblair 0:f09b7bb8bcce 98 break;
sblair 0:f09b7bb8bcce 99 case SV_TAG_NOASDU:
sblair 0:f09b7bb8bcce 100 noASDU = (unsigned int) buf[1 + lengthFieldSize]; // assuming noASDU is < 126
sblair 0:f09b7bb8bcce 101 //ASDU = 0;
sblair 0:f09b7bb8bcce 102 svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence, ASDU, noASDU);
sblair 0:f09b7bb8bcce 103 break;
sblair 0:f09b7bb8bcce 104 case SV_TAG_SEQUENCEOFASDU:
sblair 0:f09b7bb8bcce 105 svDecodeAPDU(&buf[offsetForSequence], lengthValue, ASDU, totalASDUs);
sblair 0:f09b7bb8bcce 106 break;
sblair 0:f09b7bb8bcce 107 case SV_TAG_ASDU:
sblair 0:f09b7bb8bcce 108 svDecodeASDU(&buf[offsetForSequence], lengthValue, ASDU);
sblair 0:f09b7bb8bcce 109 ASDU++;
sblair 0:f09b7bb8bcce 110
sblair 0:f09b7bb8bcce 111 // process any more ASDUs, until max number
sblair 0:f09b7bb8bcce 112 if (ASDU < totalASDUs) {
sblair 0:f09b7bb8bcce 113 svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence, ASDU, totalASDUs);
sblair 0:f09b7bb8bcce 114 }
sblair 0:f09b7bb8bcce 115 break;
sblair 0:f09b7bb8bcce 116 default:
sblair 0:f09b7bb8bcce 117 break;
sblair 0:f09b7bb8bcce 118 }
sblair 0:f09b7bb8bcce 119 }
sblair 0:f09b7bb8bcce 120
sblair 0:f09b7bb8bcce 121 void svDecode(unsigned char *buf, int len) {
sblair 0:f09b7bb8bcce 122 int offset = 16; // start of 'length' field in payload
sblair 0:f09b7bb8bcce 123
sblair 0:f09b7bb8bcce 124 // check for VLAN tag
sblair 0:f09b7bb8bcce 125 if (buf[12] == 0x81 && buf[13] == 0x00) {
sblair 0:f09b7bb8bcce 126 offset = 20;
sblair 0:f09b7bb8bcce 127 }
sblair 0:f09b7bb8bcce 128
sblair 0:f09b7bb8bcce 129 unsigned short APDULength = ((buf[offset] << 8) | buf[offset + 1]) - 8; // must use length in PDU because total bytes (len) may contain CRC
sblair 0:f09b7bb8bcce 130
sblair 0:f09b7bb8bcce 131 svDecodeAPDU(&buf[offset + 6], APDULength, 0, 0); // cuts out frame header
sblair 0:f09b7bb8bcce 132 }