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

Committer:
sblair
Date:
Fri Oct 07 13:41:08 2011 +0000
Revision:
0:230c10b228ea
Child:
1:9399d44c2b1a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sblair 0:230c10b228ea 1 #ifndef GSE_BER_ENCODE_BASIC_C
sblair 0:230c10b228ea 2 #define GSE_BER_ENCODE_BASIC_C
sblair 0:230c10b228ea 3
sblair 0:230c10b228ea 4 #include "ctypes.h"
sblair 0:230c10b228ea 5 #include "datatypes.h"
sblair 0:230c10b228ea 6 #include "ied.h"
sblair 0:230c10b228ea 7 #include "gseEncodeBasic.h"
sblair 0:230c10b228ea 8
sblair 0:230c10b228ea 9 #include <stdlib.h>
sblair 0:230c10b228ea 10 #include <stdio.h>
sblair 0:230c10b228ea 11
sblair 0:230c10b228ea 12 // BER encoding of basic types
sblair 0:230c10b228ea 13 int BER_ENCODE_CTYPE_FLOAT32(unsigned char *buf, CTYPE_FLOAT32 *value) {
sblair 0:230c10b228ea 14 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 15 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT32(value);
sblair 0:230c10b228ea 16
sblair 0:230c10b228ea 17 buf[offset++] = ASN1_TAG_FLOATING_POINT;
sblair 0:230c10b228ea 18 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 19
sblair 0:230c10b228ea 20 buf[offset++] = 0x08; // bits for exponent
sblair 0:230c10b228ea 21 netmemcpy(&buf[offset], value, len - 1);
sblair 0:230c10b228ea 22
sblair 0:230c10b228ea 23 return offset + len - 1;
sblair 0:230c10b228ea 24 }
sblair 0:230c10b228ea 25 int BER_ENCODE_CTYPE_FLOAT64(unsigned char *buf, CTYPE_FLOAT64 *value) {
sblair 0:230c10b228ea 26 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 27 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_FLOAT64(value);
sblair 0:230c10b228ea 28
sblair 0:230c10b228ea 29 buf[offset++] = ASN1_TAG_FLOATING_POINT;
sblair 0:230c10b228ea 30 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 31
sblair 0:230c10b228ea 32 buf[offset++] = 0x0B; // bits for exponent
sblair 0:230c10b228ea 33 netmemcpy(&buf[offset], value, len - 1);
sblair 0:230c10b228ea 34
sblair 0:230c10b228ea 35 return offset + len - 1;
sblair 0:230c10b228ea 36 }
sblair 0:230c10b228ea 37 int BER_ENCODE_CTYPE_QUALITY(unsigned char *buf, CTYPE_QUALITY *value) {
sblair 0:230c10b228ea 38 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 39 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_QUALITY(value);
sblair 0:230c10b228ea 40
sblair 0:230c10b228ea 41 buf[offset++] = ASN1_TAG_BIT_STRING;
sblair 0:230c10b228ea 42 offset += encodeLength(&buf[offset], len - 1);
sblair 0:230c10b228ea 43
sblair 0:230c10b228ea 44 buf[offset++] = QUALITY_UNUSED_BITS; // number of unused bits
sblair 0:230c10b228ea 45 netmemcpy(&buf[offset], value, len - 1);
sblair 0:230c10b228ea 46
sblair 0:230c10b228ea 47 return offset + len - 1;
sblair 0:230c10b228ea 48 }
sblair 0:230c10b228ea 49 int BER_ENCODE_CTYPE_TIMESTAMP(unsigned char *buf, CTYPE_TIMESTAMP *value) {
sblair 0:230c10b228ea 50 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 51 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_TIMESTAMP(value);
sblair 0:230c10b228ea 52
sblair 0:230c10b228ea 53 buf[offset++] = ASN1_TAG_OCTET_STRING;
sblair 0:230c10b228ea 54 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 55
sblair 0:230c10b228ea 56 memcpy(&buf[offset], value, len); //TODO should be memcpy, because already in big-endian?
sblair 0:230c10b228ea 57
sblair 0:230c10b228ea 58 return offset + len;
sblair 0:230c10b228ea 59 }
sblair 0:230c10b228ea 60 int BER_ENCODE_CTYPE_ENUM(unsigned char *buf, CTYPE_ENUM *value) { // assuming enum is an int - allows any enum type to be used
sblair 0:230c10b228ea 61 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 62 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_ENUM(value);
sblair 0:230c10b228ea 63
sblair 0:230c10b228ea 64 buf[offset++] = ASN1_TAG_INTEGER;
sblair 0:230c10b228ea 65 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 66
sblair 0:230c10b228ea 67 ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);
sblair 0:230c10b228ea 68 //netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 69
sblair 0:230c10b228ea 70 return offset + len;
sblair 0:230c10b228ea 71 }
sblair 0:230c10b228ea 72 int BER_ENCODE_CTYPE_INT16(unsigned char *buf, CTYPE_INT16 *value) {
sblair 0:230c10b228ea 73 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 74 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16(value);
sblair 0:230c10b228ea 75
sblair 0:230c10b228ea 76 buf[offset++] = ASN1_TAG_INTEGER;
sblair 0:230c10b228ea 77 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 78
sblair 0:230c10b228ea 79 ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16);
sblair 0:230c10b228ea 80 //netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 81
sblair 0:230c10b228ea 82 return offset + len;
sblair 0:230c10b228ea 83 }
sblair 0:230c10b228ea 84 int BER_ENCODE_CTYPE_INT32(unsigned char *buf, CTYPE_INT32 *value) {
sblair 0:230c10b228ea 85 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 86 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32(value);
sblair 0:230c10b228ea 87
sblair 0:230c10b228ea 88 buf[offset++] = ASN1_TAG_INTEGER;
sblair 0:230c10b228ea 89 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 90
sblair 0:230c10b228ea 91 printf("INT32 value: %u, len: %i, total: %i\n", *value, len, offset + len);
sblair 0:230c10b228ea 92 fflush(stdout);
sblair 0:230c10b228ea 93 ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32);
sblair 0:230c10b228ea 94 //netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 95
sblair 0:230c10b228ea 96 return offset + len;
sblair 0:230c10b228ea 97 }
sblair 0:230c10b228ea 98 int BER_ENCODE_CTYPE_INT16U(unsigned char *buf, CTYPE_INT16U *value) {
sblair 0:230c10b228ea 99 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 100 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT16U(value);
sblair 0:230c10b228ea 101
sblair 0:230c10b228ea 102 buf[offset++] = ASN1_TAG_UNSIGNED;
sblair 0:230c10b228ea 103 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 104
sblair 0:230c10b228ea 105 printf("INT16U value: %u, len: %i, total: %i\n", *value, len, offset + len);
sblair 0:230c10b228ea 106 fflush(stdout);
sblair 0:230c10b228ea 107 ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT16U);
sblair 0:230c10b228ea 108 //netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 109
sblair 0:230c10b228ea 110 return offset + len;
sblair 0:230c10b228ea 111 }
sblair 0:230c10b228ea 112 int BER_ENCODE_CTYPE_INT32U(unsigned char *buf, CTYPE_INT32U *value) {
sblair 0:230c10b228ea 113 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 114 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_INT32U(value);
sblair 0:230c10b228ea 115
sblair 0:230c10b228ea 116 buf[offset++] = ASN1_TAG_UNSIGNED;
sblair 0:230c10b228ea 117 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 118
sblair 0:230c10b228ea 119 ber_encode_integer(&buf[offset], value, SV_GET_LENGTH_INT32U);
sblair 0:230c10b228ea 120
sblair 0:230c10b228ea 121 printf("INT32U value: %u, len: %i, total: %i\n", *value, len, offset + len);
sblair 0:230c10b228ea 122 fflush(stdout);
sblair 0:230c10b228ea 123 //netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 124
sblair 0:230c10b228ea 125 return offset + len;
sblair 0:230c10b228ea 126 }
sblair 0:230c10b228ea 127 int BER_ENCODE_CTYPE_VISSTRING255(unsigned char *buf, CTYPE_VISSTRING255 *value) {
sblair 0:230c10b228ea 128 netmemcpy(buf, value, BER_GET_LENGTH_CTYPE_VISSTRING255(value));
sblair 0:230c10b228ea 129
sblair 0:230c10b228ea 130 return BER_GET_LENGTH_CTYPE_VISSTRING255(value);
sblair 0:230c10b228ea 131 }
sblair 0:230c10b228ea 132 int BER_ENCODE_CTYPE_BOOLEAN(unsigned char *buf, CTYPE_BOOLEAN *value) {
sblair 0:230c10b228ea 133 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 134 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_BOOLEAN(value);
sblair 0:230c10b228ea 135
sblair 0:230c10b228ea 136 buf[offset++] = ASN1_TAG_BOOLEAN;
sblair 0:230c10b228ea 137 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 138
sblair 0:230c10b228ea 139 netmemcpy(&buf[offset], value, len);
sblair 0:230c10b228ea 140
sblair 0:230c10b228ea 141 return offset + len;
sblair 0:230c10b228ea 142 }
sblair 0:230c10b228ea 143 int BER_ENCODE_CTYPE_DBPOS(unsigned char *buf, CTYPE_DBPOS *value) {
sblair 0:230c10b228ea 144 CTYPE_INT16U offset = 0;
sblair 0:230c10b228ea 145 CTYPE_INT16U len = BER_GET_LENGTH_CTYPE_DBPOS(value);
sblair 0:230c10b228ea 146
sblair 0:230c10b228ea 147 buf[offset++] = 0x85;
sblair 0:230c10b228ea 148 offset += encodeLength(&buf[offset], len);
sblair 0:230c10b228ea 149
sblair 0:230c10b228ea 150 netmemcpy(&buf[offset], value, len); //TODO should be memcpy, because already in big-endian?
sblair 0:230c10b228ea 151
sblair 0:230c10b228ea 152 return offset + len;
sblair 0:230c10b228ea 153 }
sblair 0:230c10b228ea 154
sblair 0:230c10b228ea 155 #endif