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.

Files at this revision

API Documentation at this revision

Comitter:
sblair
Date:
Tue Oct 02 21:31:05 2012 +0000
Commit message:
converted library to folder

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
rapid61850/ctypes.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/ctypes.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/datatypes.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/datatypes.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/decodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/decodePacket.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/encodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/encodePacket.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gse.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gse.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseDecode.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseDecode.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseDecodeBasic.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseDecodeBasic.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseDecodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseEncode.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseEncode.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseEncodeBasic.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseEncodeBasic.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/gseEncodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/gsePacketData.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/iec61850.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/iec61850.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/ied.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/ied.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/sv.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/sv.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/svDecode.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svDecode.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/svDecodeBasic.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svDecodeBasic.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/svDecodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svEncode.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svEncode.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/svEncodeBasic.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svEncodeBasic.h Show annotated file Show diff for this revision Revisions of this file
rapid61850/svEncodePacket.c Show annotated file Show diff for this revision Revisions of this file
rapid61850/svPacketData.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r f09b7bb8bcce main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,145 @@
+/**
+ * IEC 61850-9-2LE Sampled Values demonstration
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "mbed.h"
+#include "iec61850.h"
+
+#include <stdio.h>
+
+#define NUMBER_OF_SIGNALS           8
+#define NUMBER_OF_SIGNALS_PHASES    6
+#define NUMBER_OF_SAMPLES           80
+
+#define PI                          3.1415926535897932384626433832795f
+#define TWO_PI                      6.283185307179586476925286766559f
+#define TWO_PI_OVER_THREE           2.0943951023931954923084289221863f
+
+
+CTYPE_INT32 signal[NUMBER_OF_SIGNALS_PHASES][NUMBER_OF_SAMPLES] = {0};
+
+float phi = 0.1 * PI;        // phase angle between voltage and current (rad)
+float freq = 50.0;           // frequency of waveforms (Hz)
+float w = 2.0 * PI * freq;
+float Ts = 250e-6;           // timestep; should equal 1 / (freq * NUMBER_OF_SAMPLES)
+float V = 8981.462390205;    // voltage magnitude; equals 11 kV * sqrt(2) / sqrt(3)
+float Zmag = 15.0;           // impedance magnitude - defines the current magnitude
+float harmonic = 7;          // harmonic number
+float harmonicMagPu = 0.03;  // harmonic magnitude (p.u.); set to zero to ignore
+
+unsigned char buf[1024] = {0};
+int len = 0;
+
+DigitalOut watchdogLED(LED1);
+DigitalOut ethLink(p29);
+DigitalOut ethAct(p30);
+Ethernet eth;
+Ticker sv;
+
+/**
+ *  Pre-calculate all voltage and current samples (only possible if exactly 50 Hz frequency is used).
+ */
+void preCalculate() {
+    int t = 0;
+    for (t = 0; t < NUMBER_OF_SAMPLES; t++) {
+        double theta = w * (((float) t) * Ts);
+        
+        signal[0][t] = (CTYPE_INT32) (V * sin(theta) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor)));
+        signal[1][t] = (CTYPE_INT32) (V * sin(theta - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic - TWO_PI_OVER_THREE) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor));
+        signal[2][t] = (CTYPE_INT32) (V * sin(theta + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.sVC.scaleFactor) + (V * harmonicMagPu * sin(theta * harmonic + TWO_PI_OVER_THREE) / ((float) LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC.scaleFactor));
+        
+        signal[3][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC.scaleFactor);
+        signal[4][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi - TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC.scaleFactor);
+        signal[5][t] = (CTYPE_INT32) ((V / Zmag) * sin(theta - phi + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC.scaleFactor) + ((harmonicMagPu * V / Zmag) * sin(theta * harmonic - phi + TWO_PI_OVER_THREE) / LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC.scaleFactor);
+    }
+}
+
+/**
+ * Transmit the next set of samples.
+ */
+void svSnapshot() {
+    static int t = 0;
+    
+    LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.instMag.i = signal[0][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.instMag.i = signal[1][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.instMag.i = signal[2][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.instMag.i = 0;
+
+    LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.instMag.i = signal[3][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.instMag.i = signal[4][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.instMag.i = signal[5][t];
+    LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.instMag.i = 0;
+
+    len = sv_update_LE_IED_MUnn_MSVCB01(buf);
+    
+    if (len > 0) {
+        ethAct = 1;
+        eth.write((const char *) buf, len);
+        eth.send();
+        ethAct = 0;
+    }
+    
+    if (++t >= NUMBER_OF_SAMPLES) {
+        t = 0;
+    }
+}
+
+/**
+ * Overriding this function sets the MAC address.
+ * Set to the destination MAC of all received SV or GOOSE packets to simplify hardware MAC filtering.
+ */
+extern "C" void mbed_mac_address(char *s) {
+    char mac[6];
+    
+    mac[0] = 0x01;
+    mac[1] = 0x0C;
+    mac[2] = 0xCD;
+    mac[3] = 0x04;
+    mac[4] = 0x00;
+    mac[5] = 0x00;
+
+    memcpy(s, mac, 6);
+}
+
+int main() {
+    initialise_iec61850();   
+     
+    // enable hardware MAC address filtering
+    LPC_EMAC->RxFilterCtrl = 1 << 5;
+    
+    eth.set_link(eth.FullDuplex100);
+    while (!eth.link()) {
+        wait(1);
+    }
+    ethLink = 1;
+    
+    wait(1);
+    
+    preCalculate();
+    
+    sv.attach_us(&svSnapshot, 250);     // create 250 us (for 50 Hz, 80 samples/cycle) periodic timer
+
+    // loop forever, toggling LED
+    while(1) {
+        watchdogLED = 1;
+        wait(0.01);
+        watchdogLED = 0;
+        wait(2);
+    }
+}
diff -r 000000000000 -r f09b7bb8bcce mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479
\ No newline at end of file
diff -r 000000000000 -r f09b7bb8bcce rapid61850/ctypes.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/ctypes.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,207 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ctypes.h"
+#include "gse.h"
+#include "sv.h"
+#if TIMESTAMP_SUPPORTED == 1
+#include <sys\time.h>
+#endif
+
+#define ENDIAN_BUFFER_SIZE        8
+
+unsigned char    LOCAL_MAC_ADDRESS[] = LOCAL_MAC_ADDRESS_VALUE;
+
+int ber_integer_length(void *value, int maxLength) {
+    unsigned char    endian_buf[ENDIAN_BUFFER_SIZE] = {0};
+    netmemcpy(endian_buf, value, maxLength);    // ensure bytes are in big-endian order
+
+    unsigned char *buf = endian_buf;
+    unsigned char *end1 = buf + maxLength - 1;
+    int shift = 0;
+
+    /* Compute the number of superfluous leading bytes */
+    for(; buf < end1; buf++) {
+        /*
+         * If the contents octets of an integer value encoding
+         * consist of more than one octet, then the bits of the
+         * first octet and bit 8 of the second octet:
+         * a) shall not all be ones; and
+         * b) shall not all be zero.
+         */
+        switch(*buf) {
+        case 0x00:
+            if((buf[1] & 0x80) == 0) {
+                continue;
+            }
+            break;
+        case 0xff:
+            if((buf[1] & 0x80)) {
+                continue;
+            }
+            break;
+        }
+        break;
+    }
+
+    shift = buf - endian_buf;
+
+    return maxLength - shift;
+}
+
+int ber_encode_integer_fixed_size(unsigned char *bufDst, void *value, int maxLength) {
+    unsigned char *firstByte = (unsigned char*) value;
+    unsigned char padding = (firstByte[0] & 0x80) ? 0xFF : 0x00;
+
+    bufDst[0] = padding;
+    netmemcpy(&bufDst[1], value, maxLength);
+
+    return maxLength + 1;
+}
+
+int ber_encode_integer(unsigned char *bufDst, void *value, int maxLength) {
+    unsigned char    endian_buf[ENDIAN_BUFFER_SIZE] = {0};
+    netmemcpy(endian_buf, value, maxLength);    // ensure bytes are in big-endian order
+
+    unsigned char *buf = endian_buf;
+    unsigned char *end1 = buf + maxLength - 1;
+    int shift = 0;
+
+    /* Compute the number of superfluous leading bytes */
+    for(; buf < end1; buf++) {
+        /*
+         * If the contents octets of an integer value encoding
+         * consist of more than one octet, then the bits of the
+         * first octet and bit 8 of the second octet:
+         * a) shall not all be ones; and
+         * b) shall not all be zero.
+         */
+        switch(*buf) {
+        case 0x00:
+            if((buf[1] & 0x80) == 0) {
+                continue;
+            }
+            break;
+        case 0xff:
+            if((buf[1] & 0x80)) {
+                continue;
+            }
+            break;
+        }
+        break;
+    }
+
+    shift = buf - endian_buf;
+
+    unsigned char *nb = endian_buf;
+    unsigned char *end;
+
+    maxLength -= shift;    /* New size, minus bad bytes */
+    end = nb + maxLength;
+
+    int i = 0;
+    for(; nb < end; nb++, buf++, i++) {
+        //*nb = *buf;
+        bufDst[i] = *buf;
+    }
+
+    return maxLength;
+}
+
+//#if GOOSE_FIXED_SIZE == 1
+//void ber_decode_integer(unsigned char *buf, int length, void *value, int maxLength) {
+//    ;
+//}
+//#else
+void ber_decode_integer(unsigned char *buf, int length, void *value, int maxLength) {
+    unsigned char    endian_buf[ENDIAN_BUFFER_SIZE] = {0};
+    unsigned char padding = (buf[0] & 0x80) ? 0xFF : 0x00;
+    int i = 0;
+    unsigned char *dest = (unsigned char *) value;
+
+    for (i = maxLength - 1; i >= 0; i--) {
+        if ((i + length) < maxLength) {
+            endian_buf[i] = padding;
+        }
+        else {
+            endian_buf[i] = buf[i - (maxLength - length)];
+        }
+    }
+
+    netmemcpy(dest, endian_buf, maxLength);
+}
+//#endif
+
+//TODO need cast to, for example, (unsigned char *) for calls to reversememcpy()?
+
+// a simple memcpy implementation, that reverses endian-ness
+void reversememcpy(unsigned char *dst, const unsigned char *src, unsigned int len) {
+    while (len--) {
+        *dst++ = src[len];
+    }
+}
+
+void setTimestamp(CTYPE_TIMESTAMP *dest) {
+#if TIMESTAMP_SUPPORTED == 1
+    unsigned char *buf = (unsigned char *) dest;
+    struct timeval tv;
+    CTYPE_INT32U frac = 0;
+
+    gettimeofday(&tv, NULL);
+    frac = (CTYPE_INT32U) ((float) tv.tv_usec * 4294.967296);    // * 2^32 / 1000000;
+
+    netmemcpy(&buf[0], &tv.tv_sec, 4);
+    netmemcpy(&buf[4], &frac, 4);
+
+    buf[7] = 0x18;    // quality: 24 bits of accuracy
+#endif
+}
+
+// if the recommended MAC address ranges are used, this function filters GOOSE and SV packets
+void gse_sv_packet_filter(unsigned char *buf, int len) {
+    if (buf[0] == 0x01 && buf[1] == 0x0C && buf[2] == 0xCD) {
+        if (buf[3] == 0x01) {
+            //GOOSE: 01-0C-CD-01-00-00 to 01-0C-CD-01-01-FF
+            gseDecode(buf, len);
+        }
+        else if (buf[3] == 0x04) {
+            //SV: 01-0C-CD-04-00-00 to 01-0C-CD-04-01-FF
+            svDecode(buf, len);
+        }
+    }
+}
+
+// copies bytes to network format (big-endian)
+void netmemcpy(void *dst, const void *src, unsigned int len) {
+#ifdef LITTLE_ENDIAN
+    reversememcpy((unsigned char *) dst, (const unsigned char *) src, len);
+#else
+    memcpy((unsigned char *) dst, (const unsigned char *) src, len);
+#endif
+}
+
+// copies bytes to host format (little-endian)
+void hostmemcpy(void *dst, const void *src, unsigned int len) {
+#ifdef LITTLE_ENDIAN
+    memcpy((unsigned char *) dst, (const unsigned char *) src, len);
+#else
+    reversememcpy((unsigned char *) dst, (const unsigned char *) src, len);
+#endif
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/ctypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/ctypes.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,177 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef CTYPES_H
+#define CTYPES_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include <string.h>
+
+#ifndef LITTLE_ENDIAN
+    #define LITTLE_ENDIAN            1
+#endif
+#define TIMESTAMP_SUPPORTED        0
+#define GOOSE_FIXED_SIZE        0    // set to 1 to enable fixed-sized GOOSE encoding, which is slightly more efficient to encode.
+#define HIGH_LEVEL_INTERFACE    0    //
+
+#define LOCAL_MAC_ADDRESS_VALUE    {0x01, 0x0C, 0xCD, 0x01, 0x00, 0x02}
+
+// platform-specific data types to conform to SV type sizes (Table 14 in IEC 61850-9-2)
+#define CTYPE_BOOLEAN        unsigned char
+#define CTYPE_INT8            char
+#define CTYPE_INT16            short
+#define CTYPE_INT32            int
+#define CTYPE_INT8U            unsigned char
+#define CTYPE_INT16U        unsigned short
+#define CTYPE_INT32U        unsigned int
+#if GOOSE_FIXED_SIZE == 1
+#define CTYPE_ENUM            CTYPE_INT8
+#else
+#define CTYPE_ENUM            CTYPE_INT32
+#endif
+#define CTYPE_FLOAT32        float
+#define CTYPE_FLOAT64        double
+#define CTYPE_VISSTRING255    char *
+#define CTYPE_DBPOS            int
+#define CTYPE_QUALITY        CTYPE_INT16U
+#define CTYPE_TIMESTAMP        long long
+
+// sampled value dataset type sizes, in bytes
+#define SV_GET_LENGTH_FLOAT32                4
+#define SV_GET_LENGTH_FLOAT64                8
+#define SV_GET_LENGTH_TIMESTAMP                8
+#define SV_GET_LENGTH_INT8                    1
+#define SV_GET_LENGTH_INT16                    2
+#define SV_GET_LENGTH_INT32                    4
+#define SV_GET_LENGTH_INT8U                    1
+#define SV_GET_LENGTH_INT16U                2
+#define SV_GET_LENGTH_INT32U                4
+#define SV_GET_LENGTH_VISSTRING255            35
+#define SV_GET_LENGTH_BOOLEAN                1
+#define SV_GET_LENGTH_ENUM                    4
+#define SV_GET_LENGTH_QUALITY                4
+#define SV_GET_LENGTH_DBPOS                    4
+
+#if GOOSE_FIXED_SIZE == 1
+#define BER_GET_LENGTH_CTYPE_FLOAT32(x)            (SV_GET_LENGTH_FLOAT32 + 1)
+#define BER_GET_LENGTH_CTYPE_FLOAT64(x)            (SV_GET_LENGTH_FLOAT64 + 1)            // fixed-size FLOAT64 not actually specified in -8-1
+#define BER_GET_LENGTH_CTYPE_TIMESTAMP(x)        (SV_GET_LENGTH_TIMESTAMP)
+#define BER_GET_LENGTH_CTYPE_INT8(x)            (2)                                // 8-bit datatypes are encoded in 16 bits!
+#define BER_GET_LENGTH_CTYPE_INT16(x)            (3)
+#define BER_GET_LENGTH_CTYPE_INT32(x)            (5)
+#define BER_GET_LENGTH_CTYPE_INT16U(x)            (3)
+#define BER_GET_LENGTH_CTYPE_INT32U(x)            (5)
+#define BER_GET_LENGTH_CTYPE_VISSTRING255(x)    (SV_GET_LENGTH_VISSTRING255)
+#define BER_GET_LENGTH_CTYPE_BOOLEAN(x)            (SV_GET_LENGTH_BOOLEAN)
+#define BER_GET_LENGTH_CTYPE_ENUM(x)            (2)
+#define BER_GET_LENGTH_CTYPE_QUALITY(x)            (3)
+#define BER_GET_LENGTH_CTYPE_DBPOS(x)            (SV_GET_LENGTH_DBPOS)
+#else
+// BER datatype sizes, which are dependent on the actual data
+#define BER_GET_LENGTH_CTYPE_FLOAT32(x)            (SV_GET_LENGTH_FLOAT32 + 1)        // + 1 byte for number of exponent bits
+#define BER_GET_LENGTH_CTYPE_FLOAT64(x)            (SV_GET_LENGTH_FLOAT64 + 1)        // + 1 byte for number of exponent bits
+#define BER_GET_LENGTH_CTYPE_TIMESTAMP(x)        (SV_GET_LENGTH_TIMESTAMP)
+#define BER_GET_LENGTH_CTYPE_INT8(x)            (ber_integer_length((x), SV_GET_LENGTH_INT8))
+#define BER_GET_LENGTH_CTYPE_INT16(x)            (ber_integer_length((x), SV_GET_LENGTH_INT16))
+#define BER_GET_LENGTH_CTYPE_INT32(x)            (ber_integer_length((x), SV_GET_LENGTH_INT32))
+#define BER_GET_LENGTH_CTYPE_INT16U(x)            (ber_integer_length((x), SV_GET_LENGTH_INT16U))
+#define BER_GET_LENGTH_CTYPE_INT32U(x)            (ber_integer_length((x), SV_GET_LENGTH_INT32U))
+#define BER_GET_LENGTH_CTYPE_VISSTRING255(x)    (SV_GET_LENGTH_VISSTRING255)
+#define BER_GET_LENGTH_CTYPE_BOOLEAN(x)            (SV_GET_LENGTH_BOOLEAN)
+#define BER_GET_LENGTH_CTYPE_ENUM(x)            (ber_integer_length((x), SV_GET_LENGTH_ENUM))
+#define BER_GET_LENGTH_CTYPE_QUALITY(x)            (2 + 1)        // + 1 byte for padding
+#define BER_GET_LENGTH_CTYPE_DBPOS(x)            (SV_GET_LENGTH_DBPOS)
+#endif
+
+#define ASN1_TAG_SEQUENCE                        0x61
+#define ASN1_TAG_ARRAY                            0x81
+#define ASN1_TAG_STRUCTURE                        0x82
+#define ASN1_TAG_BOOLEAN                        0x83
+#define ASN1_TAG_BIT_STRING                        0x84
+#define ASN1_TAG_INTEGER                        0x85
+#define ASN1_TAG_UNSIGNED                        0x86
+#define ASN1_TAG_FLOATING_POINT                    0x87
+#define ASN1_TAG_REAL                            0x88
+#define ASN1_TAG_OCTET_STRING                    0x89
+#define ASN1_TAG_VISIBLE_STRING                    0x8A
+
+#define GSE_TAG_GOCBREF                            0x80
+#define GSE_TAG_TIME_ALLOWED_TO_LIVE            0x81
+#define GSE_TAG_DATSET                            0x82
+#define GSE_TAG_GOID                            0x83
+#define GSE_TAG_T                                0x84
+#define GSE_TAG_STNUM                            0x85
+#define GSE_TAG_SQNUM                            0x86
+#define GSE_TAG_SIMULATION                        0x87
+#define GSE_TAG_CONFREV                            0x88
+#define GSE_TAG_NDSCOM                            0x89
+#define GSE_TAG_NUMDATSETENTRIES                0x8A
+#define GSE_TAG_ALLDATA                            0xAB
+
+#define SV_TAG_SAVPDU                            0x60
+#define SV_TAG_NOASDU                            0x80
+#define SV_TAG_SECURITY                            0x81
+#define SV_TAG_SEQUENCEOFASDU                    0xA2
+#define SV_TAG_ASDU                                0x30
+#define SV_TAG_SVID                                0x80
+#define SV_TAG_DATSET                            0x81
+#define SV_TAG_SMPCNT                            0x82
+#define SV_TAG_CONFREV                            0x83
+#define SV_TAG_REFRTM                            0x84
+#define SV_TAG_SMPSYNCH                            0x85
+#define SV_TAG_SMPRATE                            0x86
+#define SV_TAG_SEQUENCEOFDATA                    0x87
+
+#define QUALITY_UNUSED_BITS                        3        // total_bits (16) - used_bits (13) = 3
+
+int ber_integer_length(void *value, int maxLength);
+int ber_encode_integer(unsigned char *bufDst, void *value, int maxLength);
+int ber_encode_integer_fixed_size(unsigned char *bufDst, void *value, int maxLength);
+void ber_decode_integer(unsigned char *buf, int length, void *value, int maxLength);
+
+void reversememcpy(unsigned char *dst, const unsigned char *src, unsigned int len);
+void netmemcpy(void *dst, const void *src, unsigned int len);
+void hostmemcpy(void *dst, const void *src, unsigned int len);
+
+void setTimestamp(CTYPE_TIMESTAMP *t);
+void gse_sv_packet_filter(unsigned char *buf, int len);
+
+struct UtcTime {
+    unsigned char bytes[8];        // format: ssssssssssssssssssssssssssssssssffffffffffffffffffffffffqqqqqqqq
+};
+
+extern unsigned char LOCAL_MAC_ADDRESS[];
+
+struct ethHeaderData {
+    unsigned char destMACAddress[6];    // stored in big-endian format
+    CTYPE_INT16U APPID;
+    CTYPE_INT16U VLAN_ID;
+    CTYPE_INT16U VLAN_PRIORITY;
+};
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/datatypes.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/datatypes.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,64 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include "ctypes.h"
+#include "datatypes.h"
+#include "ied.h"
+
+
+
+
+
+void init_IEC_61850_9_2LEAV(struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+}
+void init_IEC_61850_9_2LEsVCAmp(struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    IEC_61850_9_2LEsVCAmp->scaleFactor = 0.001;
+    IEC_61850_9_2LEsVCAmp->offset = 0;
+}
+void init_IEC_61850_9_2LEsVCVol(struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    IEC_61850_9_2LEsVCVol->scaleFactor = 0.01;
+    IEC_61850_9_2LEsVCVol->offset = 0;
+}
+void init_IEC_61850_9_2LESAVAmp(struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+}
+void init_IEC_61850_9_2LESAVVol(struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+}
+void init_IEC_61850_9_2LEINC(struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+}
+void init_datatypes() {
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.sVC);
+    init_IEC_61850_9_2LEsVCAmp(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.sVC);
+    init_IEC_61850_9_2LEsVCVol(&LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.sVC);
+}
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/datatypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/datatypes.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,109 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef DATATYPES_H
+#define DATATYPES_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "ctypes.h"
+
+
+// enums
+
+// data attributes
+struct IEC_61850_9_2LEAV {
+    CTYPE_INT32 i;
+};
+struct IEC_61850_9_2LEsVCAmp {
+    CTYPE_FLOAT32 scaleFactor;
+    CTYPE_FLOAT32 offset;
+};
+struct IEC_61850_9_2LEsVCVol {
+    CTYPE_FLOAT32 scaleFactor;
+    CTYPE_FLOAT32 offset;
+};
+
+// data objects
+struct IEC_61850_9_2LESAVAmp {
+    struct IEC_61850_9_2LEAV instMag;
+    CTYPE_QUALITY q;
+    struct IEC_61850_9_2LEsVCAmp sVC;
+};
+struct IEC_61850_9_2LESAVVol {
+    struct IEC_61850_9_2LEAV instMag;
+    CTYPE_QUALITY q;
+    struct IEC_61850_9_2LEsVCVol sVC;
+};
+struct IEC_61850_9_2LEINC {
+    CTYPE_INT32 ctlVal;
+    CTYPE_INT32 stVal;
+    CTYPE_QUALITY q;
+    CTYPE_TIMESTAMP t;
+};
+
+// datasets
+struct LE_IED_MUnn_PhsMeas1 {
+    struct IEC_61850_9_2LEAV MUnn_TCTR_1_Amp_instMag;
+    CTYPE_QUALITY MUnn_TCTR_1_Amp_q;
+    struct IEC_61850_9_2LEAV MUnn_TCTR_2_Amp_instMag;
+    CTYPE_QUALITY MUnn_TCTR_2_Amp_q;
+    struct IEC_61850_9_2LEAV MUnn_TCTR_3_Amp_instMag;
+    CTYPE_QUALITY MUnn_TCTR_3_Amp_q;
+    struct IEC_61850_9_2LEAV MUnn_TCTR_4_Amp_instMag;
+    CTYPE_QUALITY MUnn_TCTR_4_Amp_q;
+    struct IEC_61850_9_2LEAV MUnn_TVTR_1_Vol_instMag;
+    CTYPE_QUALITY MUnn_TVTR_1_Vol_q;
+    struct IEC_61850_9_2LEAV MUnn_TVTR_2_Vol_instMag;
+    CTYPE_QUALITY MUnn_TVTR_2_Vol_q;
+    struct IEC_61850_9_2LEAV MUnn_TVTR_3_Vol_instMag;
+    CTYPE_QUALITY MUnn_TVTR_3_Vol_q;
+    struct IEC_61850_9_2LEAV MUnn_TVTR_4_Vol_instMag;
+    CTYPE_QUALITY MUnn_TVTR_4_Vol_q;
+};
+
+// logical nodes
+struct IEC_61850_9_2LELLN0 {
+    struct IEC_61850_9_2LEINC Mod;
+};
+struct IEC_61850_9_2LETCTR {
+    struct IEC_61850_9_2LESAVAmp Amp;
+    struct {
+        struct LE_IED_MUnn_PhsMeas1 LE_IED_MUnn_PhsMeas1;
+        void (*datasetDecodeDone)(CTYPE_INT16U smpCnt);
+        CTYPE_INT16U smpCnt;
+    } sv_inputs_MSVCB01;
+};
+struct IEC_61850_9_2LETVTR {
+    struct IEC_61850_9_2LESAVVol Vol;
+};
+
+void init_datatypes(void);
+
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/decodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/decodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,52 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "decodePacket.h"
+//#include "svEncodeBasic.h"
+
+
+// returns size of length field, from first byte
+int getLengthFieldSize(unsigned char byte) {
+    if (byte <= 126) {
+        return 1;
+    }
+    else {
+        return 1 + (byte & 0x7F);
+    }
+}
+
+//TODO    check this works for all inputs, e.g., buf[1] = 0xFF
+int decodeLength(unsigned char *buf) {
+    if (buf[0] <= 126) {
+        return buf[0];
+    }
+    else {
+        int bytes = (buf[0] & 0x7F);
+
+        if (bytes == 1) {
+            return buf[1];
+        }
+        else if (bytes == 2) {    // assumes max length of 2^15
+            return ((buf[1] & 0xFF) << 8) | (buf[2] & 0xFF);
+        }
+    }
+
+    return 0;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/decodePacket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/decodePacket.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,35 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef DECODE_PACKET_H
+#define DECODE_PACKET_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+int getLengthFieldSize(unsigned char byte);
+int decodeLength(unsigned char *buf);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/encodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/encodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,54 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "encodePacket.h"
+#include "svEncodeBasic.h"
+
+int getLengthBytes(int len) {
+    if (len <= 126) {
+        return 1;
+    }
+    else if (len <= 255) {
+        return 2;
+    }
+    else {
+        return 3;
+    }
+}
+
+int encodeLength(unsigned char *buf, CTYPE_INT16U len) {
+    if (len <= 126) {
+        buf[0] = (unsigned char) len;
+        return 1;
+    }
+    else if (len <= 255) {
+        buf[0] = (unsigned char) 0x81;            // 0x80 specifies larger than one byte; 0x02 is number of length bytes to follow
+        buf[1] = (unsigned char) len;
+
+        return 2;
+    }
+    else {
+        // assume length is not greater than 2^15
+        buf[0] = (unsigned char) 0x82;            // 0x80 specifies larger than one byte; 0x02 is number of length bytes to follow
+        ENCODE_CTYPE_INT16U(&buf[1], &len);
+
+        return 3;
+    }
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/encodePacket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/encodePacket.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,37 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef ENCODE_PACKET_H
+#define ENCODE_PACKET_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "ctypes.h"
+
+int getLengthBytes(int len);
+int encodeLength(unsigned char *buf, CTYPE_INT16U len);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gse.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gse.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,33 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ied.h"
+#include "gsePacketData.h"
+#include "gseDecode.h"
+#include "gseEncode.h"
+
+
+
+
+
+
+void init_gse() {
+}
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gse.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gse.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,45 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_H
+#define GSE_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "gseEncode.h"
+#include "gseDecode.h"
+#include "gsePacketData.h"
+
+
+
+
+void init_gse(void);
+void gseDecode(unsigned char *buf, int len);
+
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseDecode.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseDecode.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,131 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "gseDecodeBasic.h"
+#include "gse.h"
+#include "ied.h"
+#include "gseDecode.h"
+
+
+
+
+int ber_decode_IEC_61850_9_2LEAV(unsigned char *buf, struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += BER_DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEAV->i);
+    }
+
+    return offset;
+}
+int ber_decode_IEC_61850_9_2LEsVCAmp(unsigned char *buf, struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->scaleFactor);
+        offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->offset);
+    }
+
+    return offset;
+}
+int ber_decode_IEC_61850_9_2LEsVCVol(unsigned char *buf, struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->scaleFactor);
+        offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->offset);
+    }
+
+    return offset;
+}
+int ber_decode_IEC_61850_9_2LESAVAmp(unsigned char *buf, struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVAmp->instMag);
+        offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVAmp->q);
+        offset += ber_decode_IEC_61850_9_2LEsVCAmp(&buf[offset], &IEC_61850_9_2LESAVAmp->sVC);
+    }
+
+    return offset;
+}
+int ber_decode_IEC_61850_9_2LESAVVol(unsigned char *buf, struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVVol->instMag);
+        offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVVol->q);
+        offset += ber_decode_IEC_61850_9_2LEsVCVol(&buf[offset], &IEC_61850_9_2LESAVVol->sVC);
+    }
+
+    return offset;
+}
+int ber_decode_IEC_61850_9_2LEINC(unsigned char *buf, struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+    int offset = 0;
+
+    if (buf[offset++] == 0xA2) {
+        offset += getLengthFieldSize(buf[offset]);
+
+        offset += BER_DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->ctlVal);
+        offset += BER_DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->stVal);
+        offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LEINC->q);
+        offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &IEC_61850_9_2LEINC->t);
+    }
+
+    return offset;
+}
+int ber_decode_LE_IED_MUnn_PhsMeas1(unsigned char *buf, struct LE_IED_MUnn_PhsMeas1 *LE_IED_MUnn_PhsMeas1) {
+    int offset = 0;
+
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_1_Amp_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_1_Amp_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_2_Amp_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_2_Amp_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_3_Amp_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_3_Amp_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_4_Amp_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_4_Amp_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_1_Vol_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_1_Vol_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_2_Vol_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_2_Vol_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_3_Vol_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_3_Vol_q);
+    offset += ber_decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_4_Vol_instMag);
+    offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_4_Vol_q);
+
+    return offset;
+}
+
+void gseDecodeDataset(unsigned char *dataset, CTYPE_INT16U datasetLength, unsigned char *gocbRef, CTYPE_INT16U gocbRefLength, CTYPE_INT32U timeAllowedToLive, CTYPE_TIMESTAMP T, CTYPE_INT32U stNum, CTYPE_INT32U sqNum) {
+
+}
+
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseDecode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseDecode.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,44 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_DECODE_H
+#define GSE_DECODE_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "gsePacketData.h"
+#include "datatypes.h"
+
+
+
+
+int ber_decode_LE_IED_MUnn_PhsMeas1(unsigned char *buf, struct LE_IED_MUnn_PhsMeas1 *LE_IED_MUnn_PhsMeas1);
+
+void gseDecodeDataset(unsigned char *dataset, CTYPE_INT16U datasetLength, unsigned char *gocbRef, CTYPE_INT16U gocbRefLength, CTYPE_INT32U timeAllowedToLive, CTYPE_TIMESTAMP T, CTYPE_INT32U stNum, CTYPE_INT32U sqNum);
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseDecodeBasic.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseDecodeBasic.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,198 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ctypes.h"
+#include "datatypes.h"
+#include "ied.h"
+#include "gseDecodeBasic.h"
+#include <string.h>
+
+// GSE decoding of basic types
+int BER_DECODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == 0x87) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        // check for fixed-length GOOSE. If not, check for 8 bits for exponent
+        if (len == 5 && buf[offset] == 0x08) {
+            netmemcpy(value, &buf[offset + 1], len - 1);
+        }
+        else if (len == 4) {
+            netmemcpy(value, &buf[offset], len);
+        }
+    }
+
+    return offset + len;
+}
+
+int BER_DECODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == 0x87) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        // check for fixed-length GOOSE. If not, check for 11 bits for exponent
+        if (len == 9 && buf[offset] == 0x0B) {
+            netmemcpy(value, &buf[offset + 1], len - 1);
+        }
+        else if (len == 8) {
+            netmemcpy(value, &buf[offset], len);
+        }
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset] == ASN1_TAG_BIT_STRING) {
+        offset++;
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        netmemcpy(value, &buf[offset + 1], len - 1);    // skip over one byte (which contains number of unused bits)
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == 0x89) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        netmemcpy(value, &buf[offset], len);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {    // assuming enum is an int - allows any enum type to be used
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_UNSIGNED) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+#if GOOSE_FIXED_SIZE == 1
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT8);
+#else
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
+#endif
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_INTEGER) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT8);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_INTEGER) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT16);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_INTEGER) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_UNSIGNED) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT16U);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_UNSIGNED) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        ber_decode_integer(&buf[offset], len, value, SV_GET_LENGTH_INT32U);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_VISSTRING255);
+
+    return SV_GET_LENGTH_VISSTRING255;
+}
+int BER_DECODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = 0;
+
+    if (buf[offset++] == ASN1_TAG_BOOLEAN) {
+        len += decodeLength(&buf[offset]);
+        offset += getLengthFieldSize(buf[offset]);
+
+        netmemcpy(value, &buf[offset], len);
+    }
+
+    return offset + len;
+}
+int BER_DECODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_DBPOS);
+
+    return SV_GET_LENGTH_DBPOS;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseDecodeBasic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseDecodeBasic.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,48 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_BER_DECODE_BASIC_H
+#define GSE_BER_DECODE_BASIC_H
+
+#include "datatypes.h"
+#include "decodePacket.h"
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+int BER_DECODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value);
+int BER_DECODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value);
+int BER_DECODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value);
+int BER_DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value);
+int BER_DECODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value);
+int BER_DECODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value);
+int BER_DECODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value);
+int BER_DECODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value);
+int BER_DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value);
+int BER_DECODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value);
+int BER_DECODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value);
+int BER_DECODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseDecodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseDecodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,98 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+
+#include "gseDecodeBasic.h"
+#include "ied.h"
+#include "gseDecode.h"
+#include "gsePacketData.h"
+#include "decodePacket.h"
+#include <stddef.h>
+
+void gseDecodePDU(unsigned char *buf) {
+    unsigned char    tag = 0;
+    CTYPE_INT16U    lengthFieldSize = 0;
+    CTYPE_INT16U    lengthValue = 0;
+    CTYPE_INT16U    offsetForSequence = 0;
+    CTYPE_INT16U    offsetForNonSequence = 0;
+    unsigned char    *gocbRef = NULL;
+    CTYPE_INT16U    gocbRefLength = 0;
+    CTYPE_INT32U    timeAllowedToLive = 0;
+    CTYPE_TIMESTAMP    T = 0;
+    CTYPE_INT32U    sqNum = 0;
+    CTYPE_INT32U    stNum = 0;
+
+    while (1) {
+        tag = (unsigned char) buf[0];    // assumes only one byte is used
+        lengthFieldSize = getLengthFieldSize((unsigned char) buf[1]);
+        lengthValue = decodeLength((unsigned char *) &buf[1]);
+        offsetForSequence = 1 + lengthFieldSize;
+        offsetForNonSequence = 1 + lengthFieldSize + lengthValue;
+
+        switch (tag) {
+        case GSE_TAG_GOCBREF:
+            // save pointer to gocbRef name
+            gocbRef = &buf[offsetForSequence];
+            gocbRefLength = lengthValue;
+
+            buf = &buf[offsetForNonSequence];
+            break;
+        case GSE_TAG_TIME_ALLOWED_TO_LIVE:
+            ber_decode_integer(&buf[offsetForSequence], lengthValue, &timeAllowedToLive, SV_GET_LENGTH_INT32U);
+            buf = &buf[offsetForNonSequence];
+            break;
+        case ASN1_TAG_SEQUENCE:
+            buf = &buf[offsetForSequence];
+            break;
+        case GSE_TAG_DATSET:
+            buf = &buf[offsetForNonSequence];
+            break;
+        case GSE_TAG_T:
+            memcpy(&T, &buf[offsetForSequence], BER_GET_LENGTH_CTYPE_TIMESTAMP(&T));
+            buf = &buf[offsetForNonSequence];
+            break;
+        case GSE_TAG_STNUM:
+            ber_decode_integer(&buf[offsetForSequence], lengthValue, &stNum, SV_GET_LENGTH_INT32U);
+            buf = &buf[offsetForNonSequence];
+            break;
+        case GSE_TAG_SQNUM:
+            ber_decode_integer(&buf[offsetForSequence], lengthValue, &sqNum, SV_GET_LENGTH_INT32U);
+            buf = &buf[offsetForNonSequence];
+            break;
+        case GSE_TAG_ALLDATA:
+            gseDecodeDataset(&buf[offsetForSequence], lengthValue, gocbRef, gocbRefLength, timeAllowedToLive, T, stNum, sqNum);
+            return;
+        default:
+            buf = &buf[offsetForNonSequence];
+            break;
+        }
+    }
+}
+
+void gseDecode(unsigned char *buf, int len) {
+    int offset = 22;
+
+    // check for VLAN tag
+    if (buf[12] == 0x81 && buf[13] == 0x00) {
+        offset = 26;
+    }
+
+    gseDecodePDU(&buf[offset]);    // cuts out frame header
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseEncode.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseEncode.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,231 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "gseEncodeBasic.h"
+#include "ied.h"
+#include "gseEncode.h"
+
+
+
+
+int ber_get_length_IEC_61850_9_2LEAV(struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+    int total = 0;
+    int len = 0;
+
+    len = BER_GET_LENGTH_CTYPE_INT32(&IEC_61850_9_2LEAV->i);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LEAV(unsigned char *buf, struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LEAV(IEC_61850_9_2LEAV));
+
+    offset += BER_ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEAV->i);
+
+    return offset;
+}
+int ber_get_length_IEC_61850_9_2LEsVCAmp(struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    int total = 0;
+    int len = 0;
+
+    len = BER_GET_LENGTH_CTYPE_FLOAT32(&IEC_61850_9_2LEsVCAmp->scaleFactor);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_FLOAT32(&IEC_61850_9_2LEsVCAmp->offset);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LEsVCAmp(unsigned char *buf, struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LEsVCAmp(IEC_61850_9_2LEsVCAmp));
+
+    offset += BER_ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->scaleFactor);
+    offset += BER_ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->offset);
+
+    return offset;
+}
+int ber_get_length_IEC_61850_9_2LEsVCVol(struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    int total = 0;
+    int len = 0;
+
+    len = BER_GET_LENGTH_CTYPE_FLOAT32(&IEC_61850_9_2LEsVCVol->scaleFactor);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_FLOAT32(&IEC_61850_9_2LEsVCVol->offset);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LEsVCVol(unsigned char *buf, struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LEsVCVol(IEC_61850_9_2LEsVCVol));
+
+    offset += BER_ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->scaleFactor);
+    offset += BER_ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->offset);
+
+    return offset;
+}
+int ber_get_length_IEC_61850_9_2LESAVAmp(struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+    int total = 0;
+    int len = 0;
+
+    len = ber_get_length_IEC_61850_9_2LEAV(&IEC_61850_9_2LESAVAmp->instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&IEC_61850_9_2LESAVAmp->q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEsVCAmp(&IEC_61850_9_2LESAVAmp->sVC);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LESAVAmp(unsigned char *buf, struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LESAVAmp(IEC_61850_9_2LESAVAmp));
+
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVAmp->instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVAmp->q);
+    offset += ber_encode_IEC_61850_9_2LEsVCAmp(&buf[offset], &IEC_61850_9_2LESAVAmp->sVC);
+
+    return offset;
+}
+int ber_get_length_IEC_61850_9_2LESAVVol(struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+    int total = 0;
+    int len = 0;
+
+    len = ber_get_length_IEC_61850_9_2LEAV(&IEC_61850_9_2LESAVVol->instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&IEC_61850_9_2LESAVVol->q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEsVCVol(&IEC_61850_9_2LESAVVol->sVC);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LESAVVol(unsigned char *buf, struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LESAVVol(IEC_61850_9_2LESAVVol));
+
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVVol->instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVVol->q);
+    offset += ber_encode_IEC_61850_9_2LEsVCVol(&buf[offset], &IEC_61850_9_2LESAVVol->sVC);
+
+    return offset;
+}
+int ber_get_length_IEC_61850_9_2LEINC(struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+    int total = 0;
+    int len = 0;
+
+    len = BER_GET_LENGTH_CTYPE_INT32(&IEC_61850_9_2LEINC->ctlVal);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_INT32(&IEC_61850_9_2LEINC->stVal);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&IEC_61850_9_2LEINC->q);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_TIMESTAMP(&IEC_61850_9_2LEINC->t);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_IEC_61850_9_2LEINC(unsigned char *buf, struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+    int offset = 0;
+
+    buf[offset++] = 0xA2;
+    offset += encodeLength(&buf[offset], ber_get_length_IEC_61850_9_2LEINC(IEC_61850_9_2LEINC));
+
+    offset += BER_ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->ctlVal);
+    offset += BER_ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->stVal);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LEINC->q);
+    offset += BER_ENCODE_CTYPE_TIMESTAMP(&buf[offset], &IEC_61850_9_2LEINC->t);
+
+    return offset;
+}
+int ber_get_length_LE_IED_MUnn_PhsMeas1() {
+    int total = 0;
+    int len = 0;
+
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.q);
+    total += len + getLengthBytes(len) + 1;
+    len = ber_get_length_IEC_61850_9_2LEAV(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.instMag);
+    total += len + getLengthBytes(len) + 1;
+    len = BER_GET_LENGTH_CTYPE_QUALITY(&LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.q);
+    total += len + getLengthBytes(len) + 1;
+
+    return total;
+}
+int ber_encode_LE_IED_MUnn_PhsMeas1(unsigned char *buf) {
+    int offset = 0;
+
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.q);
+    offset += ber_encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.instMag);
+    offset += BER_ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.q);
+
+    return offset;
+}
+
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseEncode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseEncode.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,44 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_ENCODE_H
+#define GSE_ENCODE_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "gseEncodeBasic.h"
+#include "gsePacketData.h"
+
+
+
+
+int ber_get_length_LE_IED_MUnn_PhsMeas1();
+int ber_encode_LE_IED_MUnn_PhsMeas1(unsigned char *buf);
+int gseEncodePacket(struct gseControl *gseControl, unsigned char *buf);
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseEncodeBasic.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseEncodeBasic.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,196 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_BER_ENCODE_BASIC_C
+#define GSE_BER_ENCODE_BASIC_C
+
+#include "ctypes.h"
+#include "datatypes.h"
+#include "ied.h"
+#include "gseEncodeBasic.h"
+
+// BER encoding of basic types
+int BER_ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT32(value);
+
+    buf[offset++] = ASN1_TAG_FLOATING_POINT;
+    offset += encodeLength(&buf[offset], len);
+
+    buf[offset++] = 0x08;    // bits for exponent
+    netmemcpy(&buf[offset], value, len - 1);
+
+    return offset + len - 1;
+}
+int BER_ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT64(value);
+
+    buf[offset++] = ASN1_TAG_FLOATING_POINT;
+    offset += encodeLength(&buf[offset], len);
+
+    buf[offset++] = 0x0B;    // bits for exponent
+    netmemcpy(&buf[offset], value, len - 1);
+
+    return offset + len - 1;
+}
+
+int BER_ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_QUALITY(value);
+
+    buf[offset++] = ASN1_TAG_BIT_STRING;
+    offset += encodeLength(&buf[offset], len);
+
+    buf[offset++] = QUALITY_UNUSED_BITS;    // number of unused bits
+    netmemcpy(&buf[offset], value, len - 1);
+
+    return offset + len - 1;
+}
+int BER_ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_TIMESTAMP(value);
+
+    buf[offset++] = ASN1_TAG_OCTET_STRING;
+    offset += encodeLength(&buf[offset], len);
+
+    memcpy(&buf[offset], value, len);
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_ENUM(value);
+
+    buf[offset++] = ASN1_TAG_INTEGER;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT8);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);            // assuming enum is an int - allows any enum type to be used
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT8(value);
+
+    buf[offset++] = ASN1_TAG_INTEGER;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT8);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT8);
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16(value);
+
+    buf[offset++] = ASN1_TAG_INTEGER;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT16);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16);
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32(value);
+
+    buf[offset++] = ASN1_TAG_INTEGER;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT32);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32);
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16U(value);
+
+    buf[offset++] = ASN1_TAG_UNSIGNED;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT16U);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16U);
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32U(value);
+
+    buf[offset++] = ASN1_TAG_UNSIGNED;
+    offset += encodeLength(&buf[offset], len);
+
+#if GOOSE_FIXED_SIZE == 1
+    ber_encode_integer_fixed_size(&buf[offset], value, SV_GET_LENGTH_INT32U);
+#else
+    ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);
+#endif
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
+    netmemcpy(buf, value, BER_GET_LENGTH_CTYPE_VISSTRING255(value));
+
+    return BER_GET_LENGTH_CTYPE_VISSTRING255(value);
+}
+int BER_ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_BOOLEAN(value);
+
+    buf[offset++] = ASN1_TAG_BOOLEAN;
+    offset += encodeLength(&buf[offset], len);
+
+    netmemcpy(&buf[offset], value, len);
+
+    return offset + len;
+}
+int BER_ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
+    CTYPE_INT16U offset = 0;
+    CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_DBPOS(value);
+
+    buf[offset++] = 0x85;
+    offset += encodeLength(&buf[offset], len);
+
+    netmemcpy(&buf[offset], value, len);
+
+    return offset + len;
+}
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseEncodeBasic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseEncodeBasic.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,49 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_ENCODE_BASIC_H
+#define GSE_ENCODE_BASIC_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "datatypes.h"
+#include "encodePacket.h"
+
+int BER_ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value);
+int BER_ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value);
+int BER_ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value);
+int BER_ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value);
+int BER_ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value);
+int BER_ENCODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value);
+int BER_ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value);
+int BER_ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value);
+int BER_ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value);
+int BER_ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value);
+int BER_ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value);
+int BER_ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value);
+int BER_ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gseEncodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gseEncodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,187 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "encodePacket.h"
+#include "gsePacketData.h"
+#include "gseEncode.h"
+#include "svEncode.h"
+
+int getGseHeaderLength(struct gseControl *gseControl) {
+    int size = 0;
+    int len = 0;
+
+    size = strlen((const char *) gseControl->gocbRef);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_INT32U(&gseControl->timeAllowedToLive);
+    len += size + getLengthBytes(size) + 1;
+
+    size = strlen((const char *) gseControl->datSet);
+    len += size + getLengthBytes(size) + 1;
+
+    size = strlen((const char *) gseControl->goID);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_TIMESTAMP(&gseControl->t);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_INT32U(&gseControl->stNum);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_INT32U(&gseControl->sqNum);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_BOOLEAN(&gseControl->test);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_INT32U(&gseControl->confRev);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_BOOLEAN(&gseControl->ndsCom);
+    len += size + getLengthBytes(size) + 1;
+
+    size = BER_GET_LENGTH_CTYPE_INT32U(&gseControl->numDatSetEntries);
+    len += size + getLengthBytes(size) + 1;
+
+    size = (gseControl->getDatasetLength)();
+    len += size + getLengthBytes(size) + 1;
+
+    return len;
+}
+
+// creates a GSE packet, including frame header. returns 0 on fail; number of bytes on success
+int gseEncodePacket(struct gseControl *gseControl, unsigned char *buf) {
+    int offset = 0;
+    int size = 0;
+    int ADPULength = getGseHeaderLength(gseControl);
+    int len = ADPULength + 9 + getLengthBytes(ADPULength);    // APDU tag size (1 byte), plus 8 "header" bytes
+
+    //printf("ADPULength: %i, len: %i\n", ADPULength, len);
+
+    // frame header
+    memcpy(&buf[offset], gseControl->ethHeaderData.destMACAddress, 6);    // destination MAC addresses
+    offset += 6;
+    memcpy(&buf[offset], LOCAL_MAC_ADDRESS, 6);                        // source MAC addresses
+    offset += 6;
+
+    buf[offset++] = 0x81;    // TPID
+    buf[offset++] = 0x00;
+
+    netmemcpy(&buf[offset], &gseControl->ethHeaderData.VLAN_ID, 2);    // TCI
+    buf[offset] |= (gseControl->ethHeaderData.VLAN_PRIORITY << 5);
+    offset += 2;
+
+    buf[offset++] = 0x88;    // EtherType
+    buf[offset++] = 0xB8;
+
+    netmemcpy(&buf[offset], &gseControl->ethHeaderData.APPID, 2);    // APPID
+    offset += 2;
+
+    netmemcpy(&buf[offset], &len, 2);    // length
+    offset += 2;
+
+    buf[offset++] = 0x00;    // reserved 1
+    buf[offset++] = 0x00;
+    buf[offset++] = 0x00;    // reserved 2
+    buf[offset++] = 0x00;
+
+    buf[offset++] = ASN1_TAG_SEQUENCE;
+    offset += encodeLength(&buf[offset], ADPULength /*+ getLengthBytes(ADPULength) + 1*/);
+
+    buf[offset++] = GSE_TAG_GOCBREF;
+    size = strlen((const char *) gseControl->gocbRef);
+    buf[offset++] = size;
+    memcpy(&buf[offset], gseControl->gocbRef, size);
+    offset += size;
+
+    buf[offset++] = GSE_TAG_TIME_ALLOWED_TO_LIVE;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_INT32U(&gseControl->timeAllowedToLive));
+#if GOOSE_FIXED_SIZE == 1
+    offset += ber_encode_integer_fixed_size(&buf[offset], &gseControl->timeAllowedToLive, SV_GET_LENGTH_INT32U);
+#else
+    offset += ber_encode_integer(&buf[offset], &gseControl->timeAllowedToLive, SV_GET_LENGTH_INT32U);
+#endif
+
+    buf[offset++] = GSE_TAG_DATSET;
+    size = strlen((const char *) gseControl->datSet);
+    buf[offset++] = size;
+    memcpy(&buf[offset], gseControl->datSet, size);
+    offset += size;
+
+    buf[offset++] = GSE_TAG_GOID;
+    size = strlen((const char *) gseControl->goID);
+    buf[offset++] = size;
+    memcpy(&buf[offset], gseControl->goID, size);
+    offset += size;
+
+    buf[offset++] = GSE_TAG_T;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_TIMESTAMP(&gseControl->t));
+    setTimestamp(&gseControl->t);
+    memcpy(&buf[offset], &gseControl->t, BER_GET_LENGTH_CTYPE_TIMESTAMP(&gseControl->t));
+    offset += BER_GET_LENGTH_CTYPE_TIMESTAMP(&gseControl->t);
+
+    buf[offset++] = GSE_TAG_STNUM;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_INT32U(&gseControl->stNum));
+#if GOOSE_FIXED_SIZE == 1
+    offset += ber_encode_integer_fixed_size(&buf[offset], &gseControl->stNum, SV_GET_LENGTH_INT32U);
+#else
+    offset += ber_encode_integer(&buf[offset], &gseControl->stNum, SV_GET_LENGTH_INT32U);
+#endif
+
+    buf[offset++] = GSE_TAG_SQNUM;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_INT32U(&gseControl->sqNum));
+#if GOOSE_FIXED_SIZE == 1
+    offset += ber_encode_integer_fixed_size(&buf[offset], &gseControl->sqNum, SV_GET_LENGTH_INT32U);
+#else
+    offset += ber_encode_integer(&buf[offset], &gseControl->sqNum, SV_GET_LENGTH_INT32U);
+#endif
+
+    buf[offset++] = GSE_TAG_SIMULATION;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_BOOLEAN(&gseControl->test));
+    offset += ber_encode_integer(&buf[offset], &gseControl->test, SV_GET_LENGTH_BOOLEAN);
+
+    buf[offset++] = GSE_TAG_CONFREV;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_INT32U(&gseControl->confRev));
+#if GOOSE_FIXED_SIZE == 1
+    offset += ber_encode_integer_fixed_size(&buf[offset], &gseControl->confRev, SV_GET_LENGTH_INT32U);
+#else
+    offset += ber_encode_integer(&buf[offset], &gseControl->confRev, SV_GET_LENGTH_INT32U);
+#endif
+
+    buf[offset++] = GSE_TAG_NDSCOM;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_BOOLEAN(&gseControl->ndsCom));
+    offset += ber_encode_integer(&buf[offset], &gseControl->ndsCom, SV_GET_LENGTH_BOOLEAN);
+
+    buf[offset++] = GSE_TAG_NUMDATSETENTRIES;
+    offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_INT32U(&gseControl->numDatSetEntries));
+#if GOOSE_FIXED_SIZE == 1
+    offset += ber_encode_integer_fixed_size(&buf[offset], &gseControl->numDatSetEntries, SV_GET_LENGTH_INT32U);
+#else
+    offset += ber_encode_integer(&buf[offset], &gseControl->numDatSetEntries, SV_GET_LENGTH_INT32U);
+#endif
+
+    buf[offset++] = GSE_TAG_ALLDATA;
+    offset += encodeLength(&buf[offset], (gseControl->getDatasetLength)());
+    offset += (gseControl->encodeDataset)(&buf[offset]);
+
+    // assume network interface, such as WinPcap, generates CRC bytes
+
+    return offset;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/gsePacketData.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/gsePacketData.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,56 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef GSE_PACKET_DATA_H
+#define GSE_PACKET_DATA_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "ctypes.h"
+
+struct gseControl {
+    struct ethHeaderData ethHeaderData;
+    unsigned char *gocbRef;                        // <LDinst>/LLN0$<GSEControl.name> e.g. "C1/LLN0$ItlPositions"
+    CTYPE_INT32U timeAllowedToLive;
+    unsigned char *datSet;                        // <IEDname><LDinst>/LLN0$<DataSet.name> e.g. "E1Q1SB1C1/LLN0$Positions"
+    unsigned char *goID;                        // optional
+    CTYPE_TIMESTAMP t;
+    CTYPE_INT32U stNum;
+    CTYPE_INT32U sqNum;
+    CTYPE_BOOLEAN test;
+    CTYPE_INT32U confRev;
+    CTYPE_BOOLEAN ndsCom;
+    CTYPE_INT32U numDatSetEntries;
+    CTYPE_INT32U minTime;                        // stored in milliseconds
+    CTYPE_INT32U maxTime;                        // stored in milliseconds
+    int (*encodeDataset)(unsigned char *buf);    // function pointer to dataset-specific encoder
+    int (*getDatasetLength)();                    // function pointer to dataset-specific getLength function
+    int (*send)(unsigned char *buf, CTYPE_BOOLEAN statusChange, CTYPE_INT32U timeAllowedToLive);    // function pointer to send GSE packet
+};
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/iec61850.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/iec61850.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,27 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "iec61850.h"
+
+void initialise_iec61850() {
+    init_datatypes();
+    init_sv();
+    init_gse();
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/iec61850.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/iec61850.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,40 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef IEC61850_H
+#define IEC61850_H
+
+//#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+//extern "C" {
+//#endif
+
+
+#include "ied.h"
+#include "sv.h"
+#include "gse.h"
+
+void initialise_iec61850();
+
+
+//#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+//}
+//#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/ied.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/ied.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,30 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ied.h"
+#include "datatypes.h"
+
+
+struct LE_IED_t LE_IED;
+struct LE_IED_RECV_t LE_IED_RECV;
+
+
+
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/ied.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/ied.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,81 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef IED_H
+#define IED_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "datatypes.h"
+#include "sv.h"
+#include "gse.h"
+
+
+struct LE_IED_t {
+    struct {
+        struct {
+            struct {
+                struct IEC_61850_9_2LELLN0 LLN0;
+                struct svControl MSVCB01;
+            } LN0;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_1;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_2;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_3;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_4;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_1;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_2;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_3;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_4;
+        } MUnn;
+    } S1;
+};
+
+struct LE_IED_RECV_t {
+    struct {
+        struct {
+            struct {
+                struct IEC_61850_9_2LELLN0 LLN0;
+            } LN0;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_1;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_2;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_3;
+            struct IEC_61850_9_2LETCTR IEC_61850_9_2LETCTR_4;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_1;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_2;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_3;
+            struct IEC_61850_9_2LETVTR IEC_61850_9_2LETVTR_4;
+        } MUnn;
+    } S1;
+};
+
+
+
+
+extern struct LE_IED_t LE_IED;
+extern struct LE_IED_RECV_t LE_IED_RECV;
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/sv.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/sv.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,83 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ied.h"
+#include "sv.h"
+#include "svPacketData.h"
+#include "svDecode.h"
+#include "svEncode.h"
+
+
+
+
+
+
+// returns 1 if buf contains valid packet data
+int sv_update_LE_IED_MUnn_MSVCB01(unsigned char *buf) {
+    int size = encode_control_LE_IED_MUnn_MSVCB01(LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount].data.data);
+    LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount].data.size = size;
+
+    LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount].smpCnt = LE_IED.S1.MUnn.LN0.MSVCB01.sampleCountMaster;
+    LE_IED.S1.MUnn.LN0.MSVCB01.sampleCountMaster++;
+
+    if (LE_IED.S1.MUnn.LN0.MSVCB01.sampleCountMaster == LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount].smpRate) {
+        LE_IED.S1.MUnn.LN0.MSVCB01.sampleCountMaster = 0;
+    }
+
+    if (++LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount == LE_IED.S1.MUnn.LN0.MSVCB01.noASDU) {
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount = 0;
+        return svEncodePacket(&LE_IED.S1.MUnn.LN0.MSVCB01, buf);
+    }
+
+    return 0;
+}
+
+void init_sv() {
+    int i = 0;
+
+    LE_IED.S1.MUnn.LN0.MSVCB01.noASDU = 1;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[0] = 0x01;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[1] = 0x0C;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[2] = 0xCD;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[3] = 0x04;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[4] = 0x00;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.destMACAddress[5] = 0x01;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.APPID = 0x4000;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.VLAN_ID = 0x123;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ethHeaderData.VLAN_PRIORITY = 0x4;
+    LE_IED.S1.MUnn.LN0.MSVCB01.ASDU = (struct ASDU *) malloc(1 * sizeof(struct ASDU));
+    for (i = 0; i < 1; i++) {
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].svID = (unsigned char *) malloc(11);
+        strncpy((char *) LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].svID, "0000MU0001\0", 11);
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].datset = (unsigned char *) malloc(9);
+        strncpy((char *) LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].datset, "PhsMeas1\0", 9);
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].smpCnt = 0;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].confRev = 1;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].smpSynch = 1;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].showRefrTm = 0;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].showDatset = 0;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].showSmpRate = 0;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].smpRate = 4000;
+        LE_IED.S1.MUnn.LN0.MSVCB01.ASDU[i].data.size = 0;
+    }
+    LE_IED.S1.MUnn.LN0.MSVCB01.ASDUCount = 0;
+    LE_IED.S1.MUnn.LN0.MSVCB01.update = &sv_update_LE_IED_MUnn_MSVCB01;
+}
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/sv.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/sv.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,46 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_H
+#define SV_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "svEncode.h"
+#include "svDecode.h"
+#include "svPacketData.h"
+
+
+
+
+void init_sv();
+int sv_update_LE_IED_MUnn_MSVCB01(unsigned char *buf);
+void svDecode(unsigned char *buf, int len);
+
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svDecode.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svDecode.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,114 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "sv.h"
+#include "svDecodeBasic.h"
+#include "ied.h"
+#include "svDecode.h"
+
+
+
+
+int decode_IEC_61850_9_2LEAV(unsigned char *buf, struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+    int offset = 0;
+
+    offset += DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEAV->i);
+
+    return offset;
+}
+int decode_IEC_61850_9_2LEsVCAmp(unsigned char *buf, struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    int offset = 0;
+
+    offset += DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->scaleFactor);
+    offset += DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->offset);
+
+    return offset;
+}
+int decode_IEC_61850_9_2LEsVCVol(unsigned char *buf, struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    int offset = 0;
+
+    offset += DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->scaleFactor);
+    offset += DECODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->offset);
+
+    return offset;
+}
+int decode_IEC_61850_9_2LESAVAmp(unsigned char *buf, struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+    int offset = 0;
+
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVAmp->instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVAmp->q);
+    offset += decode_IEC_61850_9_2LEsVCAmp(&buf[offset], &IEC_61850_9_2LESAVAmp->sVC);
+
+    return offset;
+}
+int decode_IEC_61850_9_2LESAVVol(unsigned char *buf, struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+    int offset = 0;
+
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVVol->instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVVol->q);
+    offset += decode_IEC_61850_9_2LEsVCVol(&buf[offset], &IEC_61850_9_2LESAVVol->sVC);
+
+    return offset;
+}
+int decode_IEC_61850_9_2LEINC(unsigned char *buf, struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+    int offset = 0;
+
+    offset += DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->ctlVal);
+    offset += DECODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->stVal);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LEINC->q);
+    offset += DECODE_CTYPE_TIMESTAMP(&buf[offset], &IEC_61850_9_2LEINC->t);
+
+    return offset;
+}
+int decode_LE_IED_MUnn_PhsMeas1(unsigned char *buf, CTYPE_INT16U smpCnt, struct LE_IED_MUnn_PhsMeas1 *LE_IED_MUnn_PhsMeas1) {
+    int offset = 0;
+
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_1_Amp_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_1_Amp_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_2_Amp_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_2_Amp_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_3_Amp_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_3_Amp_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_4_Amp_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TCTR_4_Amp_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_1_Vol_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_1_Vol_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_2_Vol_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_2_Vol_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_3_Vol_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_3_Vol_q);
+    offset += decode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_4_Vol_instMag);
+    offset += DECODE_CTYPE_QUALITY(&buf[offset], &LE_IED_MUnn_PhsMeas1->MUnn_TVTR_4_Vol_q);
+
+    return offset;
+}
+
+void svDecodeDataset(unsigned char *dataset, int datasetLength, int ASDU, unsigned char *svID, int svIDLength, CTYPE_INT16U smpCnt) {
+
+    if (svIDLength == 10 && strncmp((const char *) svID, "0000MU0001", svIDLength) == 0) {
+        decode_LE_IED_MUnn_PhsMeas1(dataset, smpCnt, &LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_1.sv_inputs_MSVCB01.LE_IED_MUnn_PhsMeas1);
+        LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_1.sv_inputs_MSVCB01.smpCnt = smpCnt;
+        if (LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_1.sv_inputs_MSVCB01.datasetDecodeDone != NULL) {
+            LE_IED_RECV.S1.MUnn.IEC_61850_9_2LETCTR_1.sv_inputs_MSVCB01.datasetDecodeDone(smpCnt);
+        }
+    }
+}
+
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svDecode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svDecode.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,43 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_DECODE_H
+#define SV_DECODE_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "svPacketData.h"
+
+
+
+
+int decode_LE_IED_MUnn_PhsMeas1(unsigned char *buf, CTYPE_INT16U smpCnt, struct LE_IED_MUnn_PhsMeas1 *LE_IED_MUnn_PhsMeas1);
+
+void svDecodeDataset(unsigned char *dataset, int datasetLength, int ASDU, unsigned char *svID, int svIDLength, CTYPE_INT16U smpCnt);
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svDecodeBasic.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svDecodeBasic.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,92 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ctypes.h"
+#include "datatypes.h"
+#include "ied.h"
+#include "svDecodeBasic.h"
+#include <string.h>
+
+// SV encoding of basic types
+int DECODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_FLOAT32);
+
+    return SV_GET_LENGTH_FLOAT32;
+}
+int DECODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_FLOAT64);
+
+    return SV_GET_LENGTH_FLOAT64;
+}
+int DECODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_QUALITY);
+
+    return SV_GET_LENGTH_QUALITY;
+}
+int DECODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_TIMESTAMP);
+
+    return SV_GET_LENGTH_TIMESTAMP;
+}
+int DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {    // assuming enum is an int - allows any enum type to be used
+    netmemcpy(value, buf, SV_GET_LENGTH_ENUM);
+
+    return SV_GET_LENGTH_ENUM;
+}
+int DECODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_INT8);
+
+    return SV_GET_LENGTH_INT8;
+}
+int DECODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_INT16);
+
+    return SV_GET_LENGTH_INT16;
+}
+int DECODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_INT32);
+
+    return SV_GET_LENGTH_INT32;
+}
+int DECODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_INT16U);
+
+    return SV_GET_LENGTH_INT16U;
+}
+int DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_INT32U);
+
+    return SV_GET_LENGTH_INT32U;
+}
+int DECODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_VISSTRING255);
+
+    return SV_GET_LENGTH_VISSTRING255;
+}
+int DECODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_BOOLEAN);
+
+    return SV_GET_LENGTH_BOOLEAN;
+}
+int DECODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
+    netmemcpy(value, buf, SV_GET_LENGTH_DBPOS);
+
+    return SV_GET_LENGTH_DBPOS;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svDecodeBasic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svDecodeBasic.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,48 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_DECODE_BASIC_H
+#define SV_DECODE_BASIC_H
+
+#include "datatypes.h"
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+int DECODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value);
+int DECODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value);
+int DECODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value);
+int DECODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value);
+int DECODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value);
+int DECODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) ;
+int DECODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value);
+int DECODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value);
+int DECODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value);
+int DECODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value);
+int DECODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value);
+int DECODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value);
+int DECODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svDecodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svDecodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,132 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "svDecodeBasic.h"
+#include "ied.h"
+#include "svDecode.h"
+#include "svPacketData.h"
+#include "decodePacket.h"
+#include "gseDecodeBasic.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;
+    CTYPE_INT16U smpCnt = 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 SV_TAG_SVID:
+                svID = &buf[i + 1 + lengthFieldSize];
+                svIDLength = lengthValue;
+                break;
+            case SV_TAG_DATSET:
+
+                break;
+            case SV_TAG_SMPCNT:
+                ber_decode_integer(&buf[i + 1 + lengthFieldSize], lengthValue, &smpCnt, SV_GET_LENGTH_INT16U);
+                break;
+            case SV_TAG_CONFREV:
+
+                break;
+            case SV_TAG_REFRTM:
+
+                break;
+            case SV_TAG_SMPSYNCH:
+
+                break;
+            case SV_TAG_SMPRATE:
+
+                break;
+            case SV_TAG_SEQUENCEOFDATA:
+                if (svID != NULL) {
+                    svDecodeDataset(&buf[i + 1 + lengthFieldSize], lengthValue, noASDU, svID, svIDLength, smpCnt);
+                }
+                break;
+            default:
+                break;
+        }
+
+        i += offsetForNonSequence;
+    }
+}
+
+void svDecodeAPDU(unsigned char *buf, int len, unsigned int ASDU, unsigned int totalASDUs) {
+    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;
+    unsigned int noASDU = 0;
+    //static unsigned int ASDU = 0;
+
+    //printf("tag: %x, ASDU: %u,  totalASDUs: %u, lengthFieldSize: %i, lengthValue: %i, offset: %i\n", tag, ASDU, totalASDUs, lengthFieldSize, lengthValue, offsetForNonSequence);
+
+    switch (tag) {
+        case SV_TAG_SAVPDU:
+            svDecodeAPDU(&buf[offsetForSequence], lengthValue, ASDU, totalASDUs);
+            break;
+        case SV_TAG_NOASDU:
+            noASDU = (unsigned int) buf[1 + lengthFieldSize];    // assuming noASDU is < 126
+            //ASDU = 0;
+            svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence, ASDU, noASDU);
+            break;
+        case SV_TAG_SEQUENCEOFASDU:
+            svDecodeAPDU(&buf[offsetForSequence], lengthValue, ASDU, totalASDUs);
+            break;
+        case SV_TAG_ASDU:
+            svDecodeASDU(&buf[offsetForSequence], lengthValue, ASDU);
+            ASDU++;
+
+            // process any more ASDUs, until max number
+            if (ASDU < totalASDUs) {
+                svDecodeAPDU(&buf[offsetForNonSequence], len - offsetForNonSequence, ASDU, totalASDUs);
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+void svDecode(unsigned char *buf, int len) {
+    int offset = 16;   // start of 'length' field in payload
+
+    // check for VLAN tag
+    if (buf[12] == 0x81 && buf[13] == 0x00) {
+        offset = 20;
+    }
+
+    unsigned short APDULength = ((buf[offset] << 8) | buf[offset + 1]) - 8;    // must use length in PDU because total bytes (len) may contain CRC
+
+    svDecodeAPDU(&buf[offset + 6], APDULength, 0, 0);    // cuts out frame header
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svEncode.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svEncode.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,105 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "svEncodeBasic.h"
+#include "ied.h"
+#include "svEncode.h"
+
+
+
+
+int encode_IEC_61850_9_2LEAV(unsigned char *buf, struct IEC_61850_9_2LEAV *IEC_61850_9_2LEAV) {
+    int offset = 0;
+
+    offset += ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEAV->i);
+
+    return offset;
+}
+int encode_IEC_61850_9_2LEsVCAmp(unsigned char *buf, struct IEC_61850_9_2LEsVCAmp *IEC_61850_9_2LEsVCAmp) {
+    int offset = 0;
+
+    offset += ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->scaleFactor);
+    offset += ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCAmp->offset);
+
+    return offset;
+}
+int encode_IEC_61850_9_2LEsVCVol(unsigned char *buf, struct IEC_61850_9_2LEsVCVol *IEC_61850_9_2LEsVCVol) {
+    int offset = 0;
+
+    offset += ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->scaleFactor);
+    offset += ENCODE_CTYPE_FLOAT32(&buf[offset], &IEC_61850_9_2LEsVCVol->offset);
+
+    return offset;
+}
+int encode_IEC_61850_9_2LESAVAmp(unsigned char *buf, struct IEC_61850_9_2LESAVAmp *IEC_61850_9_2LESAVAmp) {
+    int offset = 0;
+
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVAmp->instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVAmp->q);
+    offset += encode_IEC_61850_9_2LEsVCAmp(&buf[offset], &IEC_61850_9_2LESAVAmp->sVC);
+
+    return offset;
+}
+int encode_IEC_61850_9_2LESAVVol(unsigned char *buf, struct IEC_61850_9_2LESAVVol *IEC_61850_9_2LESAVVol) {
+    int offset = 0;
+
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &IEC_61850_9_2LESAVVol->instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LESAVVol->q);
+    offset += encode_IEC_61850_9_2LEsVCVol(&buf[offset], &IEC_61850_9_2LESAVVol->sVC);
+
+    return offset;
+}
+int encode_IEC_61850_9_2LEINC(unsigned char *buf, struct IEC_61850_9_2LEINC *IEC_61850_9_2LEINC) {
+    int offset = 0;
+
+    offset += ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->ctlVal);
+    offset += ENCODE_CTYPE_INT32(&buf[offset], &IEC_61850_9_2LEINC->stVal);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &IEC_61850_9_2LEINC->q);
+    offset += ENCODE_CTYPE_TIMESTAMP(&buf[offset], &IEC_61850_9_2LEINC->t);
+
+    return offset;
+}
+int encode_LE_IED_MUnn_PhsMeas1(unsigned char *buf) {
+    int offset = 0;
+
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_1.Amp.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_2.Amp.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_3.Amp.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETCTR_4.Amp.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_1.Vol.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_2.Vol.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_3.Vol.q);
+    offset += encode_IEC_61850_9_2LEAV(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.instMag);
+    offset += ENCODE_CTYPE_QUALITY(&buf[offset], &LE_IED.S1.MUnn.IEC_61850_9_2LETVTR_4.Vol.q);
+
+    return offset;
+}
+int encode_control_LE_IED_MUnn_MSVCB01(unsigned char *buf) {
+    return encode_LE_IED_MUnn_PhsMeas1(buf);
+}
+
+
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svEncode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svEncode.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,45 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ * 
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_ENCODE_H
+#define SV_ENCODE_H
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include "svEncodeBasic.h"
+#include "svPacketData.h"
+
+
+
+
+int encode_LE_IED_MUnn_PhsMeas1(unsigned char *buf);
+int encode_control_LE_IED_MUnn_MSVCB01(unsigned char *buf);
+
+int svEncodePacket(struct svControl *svControl, unsigned char *buf);
+
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svEncodeBasic.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svEncodeBasic.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,91 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "ctypes.h"
+#include "datatypes.h"
+#include "ied.h"
+#include "svEncodeBasic.h"
+
+// SV encoding of basic types
+int ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_FLOAT32);
+
+    return SV_GET_LENGTH_FLOAT32;
+}
+int ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_FLOAT64);
+
+    return SV_GET_LENGTH_FLOAT64;
+}
+int ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
+    netmemcpy(&buf[2], value, 2);            // assumes Quality is stored as 16-bit, but SV encoding is 32-bit
+
+    return SV_GET_LENGTH_QUALITY;
+}
+int ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_TIMESTAMP);
+
+    return SV_GET_LENGTH_TIMESTAMP;
+}
+int ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) {    // assuming enum is an int - allows any enum type to be used
+    netmemcpy(buf, value, SV_GET_LENGTH_ENUM);
+
+    return SV_GET_LENGTH_ENUM;
+}
+int ENCODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_INT8);
+
+    return SV_GET_LENGTH_INT8;
+}
+int ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_INT16);
+
+    return SV_GET_LENGTH_INT16;
+}
+int ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_INT32);
+
+    return SV_GET_LENGTH_INT32;
+}
+int ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_INT16U);
+
+    return SV_GET_LENGTH_INT16U;
+}
+int ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_INT32U);
+
+    return SV_GET_LENGTH_INT32U;
+}
+int ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_VISSTRING255);
+
+    return SV_GET_LENGTH_VISSTRING255;
+}
+int ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_BOOLEAN);
+
+    return SV_GET_LENGTH_BOOLEAN;
+}
+int ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
+    netmemcpy(buf, value, SV_GET_LENGTH_DBPOS);
+
+    return SV_GET_LENGTH_DBPOS;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svEncodeBasic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svEncodeBasic.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,48 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_ENCODE_BASIC_H
+#define SV_ENCODE_BASIC_H
+
+#include "datatypes.h"
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+int ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value);
+int ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value);
+int ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value);
+int ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value);
+int ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value);
+int ENCODE_CTYPE_INT8(unsigned char *buf, CTYPE_INT8 *value);
+int ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value);
+int ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value);
+int ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value);
+int ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value);
+int ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value);
+int ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value);
+int ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svEncodePacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svEncodePacket.c	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,191 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "svPacketData.h"
+#include "svEncode.h"
+#include "gseEncode.h"
+#include "encodePacket.h"
+
+
+int svASDULength(struct svControl *svControl) {
+    int len = 0;
+
+    len += strlen((const char *) svControl->ASDU[0].svID) + 2;
+    //printf("%i, %s\n", strlen(svControl->ASDU[0].svID), svControl->ASDU[0].svID);
+    //len += strlen((const char *) svControl->ASDU[0].datset) + 2;
+
+#if SV_FIXED_SMPCNT_CONFREV_SIZE == 1
+    len += SV_GET_LENGTH_INT16U + 2;    // smpCnt
+    len += SV_GET_LENGTH_INT32U + 2;    // confRev
+#else
+    len += ber_integer_length((&svControl->ASDU[0].smpCnt), SV_GET_LENGTH_INT16U)/*BER_GET_LENGTH_CTYPE_INT16U(&svControl->ASDU[0].smpCnt)*/ + 2;
+    len += ber_integer_length((&svControl->ASDU[0].confRev), SV_GET_LENGTH_INT32U)/*BER_GET_LENGTH_CTYPE_INT32U(&svControl->ASDU[0].confRev)*/ + 2;
+#endif
+    len += SV_GET_LENGTH_BOOLEAN + 2;
+
+
+
+
+    //len += BER_GET_LENGTH_CTYPE_INT16U(&svControl->ASDU[0].smpRate) + 2;
+    len += svControl->ASDU[0].data.size + getLengthBytes(svControl->ASDU[0].data.size);
+    len++;
+
+    return len;
+}
+
+int svSeqLength(struct svControl *svControl) {
+    int len = svASDULength(svControl);
+    len += getLengthBytes(len);
+    len++;
+    len = len * svControl->noASDU;    // assume all ASDUs are the same size
+
+    return len;
+}
+
+int svAPDULength(struct svControl *svControl) {
+    int len = svSeqLength(svControl);
+    len += getLengthBytes(len);
+    len++;
+
+    len += 3;
+
+    return len;
+}
+
+// creates an SV packet, including frame header. returns 0 on fail; number of bytes on success
+int svEncodePacket(struct svControl *svControl, unsigned char *buf) {
+    int offset = 0;
+    int len = svAPDULength(svControl);
+    len += getLengthBytes(len);
+    len += 9;        // savPdu tag size (1 byte), plus 8 "header" bytes
+
+    // frame header
+    memcpy(&buf[offset], svControl->ethHeaderData.destMACAddress, 6);    // destination MAC addresses
+    offset += 6;
+    memcpy(&buf[offset], LOCAL_MAC_ADDRESS, 6);                        // source MAC addresses
+    offset += 6;
+
+#if SV_USE_VLAN == 1
+    buf[offset++] = 0x81;    // TPID
+    buf[offset++] = 0x00;
+
+    netmemcpy(&buf[offset], &svControl->ethHeaderData.VLAN_ID, 2);    // TCI
+    buf[offset] |= (svControl->ethHeaderData.VLAN_PRIORITY << 5);
+    offset += 2;
+#endif
+
+    buf[offset++] = 0x88;    // EtherType
+    buf[offset++] = 0xBA;
+
+    netmemcpy(&buf[offset], &svControl->ethHeaderData.APPID, 2);    // APPID
+    offset += 2;
+
+    netmemcpy(&buf[offset], &len, 2);    // length
+    offset += 2;
+
+    buf[offset++] = 0x00;    // reserved 1
+    buf[offset++] = 0x00;
+    buf[offset++] = 0x00;    // reserved 2
+    buf[offset++] = 0x00;
+
+    buf[offset++] = SV_TAG_SAVPDU;
+    offset += encodeLength(&buf[offset], svAPDULength(svControl));
+
+    buf[offset++] = SV_TAG_NOASDU;
+    offset += encodeLength(&buf[offset], ber_integer_length(&svControl->noASDU, SV_GET_LENGTH_INT16U));
+    offset += ber_encode_integer(&buf[offset], &svControl->noASDU, ber_integer_length(&svControl->noASDU, SV_GET_LENGTH_INT16U));
+
+    buf[offset++] = SV_TAG_SEQUENCEOFASDU;
+    offset += encodeLength(&buf[offset], svSeqLength(svControl));
+
+    int i = 0;
+    int size = 0;
+    for (i = 0; i < svControl->noASDU; i++) {
+        buf[offset++] = SV_TAG_ASDU;
+        offset += encodeLength(&buf[offset], svASDULength(svControl));
+
+        size = strlen((const char *) svControl->ASDU[i].svID);
+        buf[offset++] = SV_TAG_SVID;
+        buf[offset++] = size;
+        memcpy(&buf[offset], svControl->ASDU[i].svID, size);
+        offset += size;
+
+#if SV_OPTIONAL_SUPPORTED == 1
+        if (svControl->ASDU[i].showDatset) {
+            size = strlen(svControl->ASDU[i].datset);
+            buf[offset++] = SV_TAG_DATSET;
+            buf[offset++] = size;
+            memcpy(&buf[offset], svControl->ASDU[i].datset, size);
+            offset += size;
+        }
+#endif
+
+        buf[offset++] = SV_TAG_SMPCNT;
+#if SV_FIXED_SMPCNT_CONFREV_SIZE == 1
+        buf[offset++] = SV_GET_LENGTH_INT16U;
+        netmemcpy(&buf[offset], &svControl->ASDU[i].smpCnt, SV_GET_LENGTH_INT16U);
+        offset += SV_GET_LENGTH_INT16U;
+#else
+        offset += encodeLength(&buf[offset], ber_integer_length(&svControl->ASDU[i].smpCnt, SV_GET_LENGTH_INT16U));
+        offset += ber_encode_integer(&buf[offset], &svControl->ASDU[i].smpCnt, SV_GET_LENGTH_INT16U);
+#endif
+
+        buf[offset++] = SV_TAG_CONFREV;
+#if SV_FIXED_SMPCNT_CONFREV_SIZE == 1
+        buf[offset++] = SV_GET_LENGTH_INT32U;
+        netmemcpy(&buf[offset], &svControl->ASDU[i].confRev, SV_GET_LENGTH_INT32U);
+        offset += SV_GET_LENGTH_INT32U;
+#else
+        offset += encodeLength(&buf[offset], ber_integer_length(&svControl->ASDU[i].confRev, SV_GET_LENGTH_INT32U));
+        offset += ber_encode_integer(&buf[offset], &svControl->ASDU[i].confRev, SV_GET_LENGTH_INT32U);
+#endif
+
+#if SV_OPTIONAL_SUPPORTED == 1
+        if (svControl->ASDU[i].showRefrTm) {
+            buf[offset++] = SV_TAG_REFRTM;
+            offset += encodeLength(&buf[offset], BER_GET_LENGTH_CTYPE_TIMESTAMP(&svControl->ASDU[i].refrTm));
+            setTimestamp(&svControl->ASDU[i].refrTm);
+            memcpy(&buf[offset], &svControl->ASDU[i].refrTm, BER_GET_LENGTH_CTYPE_TIMESTAMP(&svControl->ASDU[i].refrTm));
+            offset += BER_GET_LENGTH_CTYPE_TIMESTAMP(&svControl->ASDU[i].refrTm);
+        }
+#endif
+
+        buf[offset++] = SV_TAG_SMPSYNCH;
+        buf[offset++] = SV_GET_LENGTH_BOOLEAN;
+        offset += ENCODE_CTYPE_BOOLEAN(&buf[offset], &svControl->ASDU[i].smpSynch);
+
+#if SV_OPTIONAL_SUPPORTED == 1
+        if (svControl->ASDU[i].showSmpRate) {
+            buf[offset++] = SV_TAG_SMPRATE;
+            buf[offset++] = SV_GET_LENGTH_INT16U;
+            offset += ENCODE_CTYPE_INT16U(&buf[offset], &svControl->ASDU[i].smpRate);
+        }
+#endif
+
+        buf[offset++] = SV_TAG_SEQUENCEOFDATA;
+        offset += encodeLength(&buf[offset], svControl->ASDU[i].data.size);
+        memcpy(&buf[offset], svControl->ASDU[i].data.data, svControl->ASDU[i].data.size);
+        offset += svControl->ASDU[i].data.size;
+    }
+
+    // assume network interface, such as WinPcap, generates CRC bytes
+
+    return offset;
+}
diff -r 000000000000 -r f09b7bb8bcce rapid61850/svPacketData.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rapid61850/svPacketData.h	Tue Oct 02 21:31:05 2012 +0000
@@ -0,0 +1,61 @@
+/**
+ * Rapid-prototyping protection schemes with IEC 61850
+ *
+ * Copyright (c) 2012 Steven Blair
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SV_PACKET_DATA_H
+#define SV_PACKET_DATA_H
+
+#include <stdlib.h>
+#include <string.h>
+#include "ctypes.h"
+
+#define SV_USE_VLAN                        0    // set to "1" to insert VLAN tag into SV packets
+#define SV_OPTIONAL_SUPPORTED            0    // set to "1" to enable output of optional items in SV packets (Wireshark does not support these)
+#define SV_FIXED_SMPCNT_CONFREV_SIZE    1    // set to "1" to force smpCnt and confRev field to be fixed size, rather than BER encoded
+
+#define SV_MAX_DATASET_SIZE     512//1024
+
+struct ASDU {
+    unsigned char *svID;
+    unsigned char *datset;            // optional
+    CTYPE_INT16U smpCnt;
+    CTYPE_INT32U confRev;
+    //struct UtcTime refrTm;            // optional
+    CTYPE_TIMESTAMP refrTm;            // optional
+    CTYPE_BOOLEAN smpSynch;
+    CTYPE_INT16U smpRate;            // optional
+    int showDatset;
+    int showRefrTm;
+    int showSmpRate;
+    struct data {
+        unsigned char data[SV_MAX_DATASET_SIZE];
+        CTYPE_INT32U size;
+    } data;
+};
+
+struct svControl {
+    struct ethHeaderData ethHeaderData;
+    short noASDU;
+    struct ASDU *ASDU;
+    CTYPE_INT16U ASDUCount;                // stores present ASDU count; transmit a packet when equals "noASDU"
+    CTYPE_INT16U sampleCountMaster;
+    int (*update)(unsigned char *buf);    // function pointer to save next ASDU, and possible send SV packet
+};
+
+#endif