////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: CHello.cs
//
// Note: Simple Singularity test program.
//
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.Io;
namespace Microsoft.Singularity.Applications
{
public class CHello
{
public static int Main(String[] args)
{
Console.WriteLine("Hello World!");
ProtocolTester.UnitTest_LDPC o = new ProtocolTester.UnitTest_LDPC();
o.Run();
return 0;
}
}
}
namespace Microsoft.SPOT
{
///
public abstract class Trace
{
///
[System.Diagnostics.ConditionalAttribute("TINYCLR_TRACE")]
static public void Print( string text )
{
Debug.Print( text );
}
}
///
public abstract class Debug
{
static public void Print( string text )
{
Console.WriteLine( text );
}
static public void DumpBuffer( byte[] buf, bool fCRC, bool fOffset )
{
if(buf == null) return;
int offset = 0;
int len = buf.Length;
while(len > 0)
{
int row = len > 16 ? 16 : len;
int i;
if(fOffset) Console.Write( "{0:X8}:", offset );
for(i=0; i<16; i++)
{
if(i= 0x7F) c = (byte)'.';
Console.Write( "{0}", (char)c );
}
offset += row;
len -= row;
Console.WriteLine();
}
Console.WriteLine();
}
}
public abstract class Math
{
static System.Random s_rnd = new System.Random();
static public int Random( int modulo )
{
return s_rnd.Next( modulo );
}
}
}
namespace Microsoft.SPOT.Hardware
{
public abstract class Radio
{
static public void XorData( byte[]! left, byte[]! right )
{
for(int i=0; i
{
T[]! elements;
int count;
public CreateNonNullArray( int n )
{
this.elements = new T[n];
this.count = 0;
base();
}
public void InitNext( T elem )
{
if(this.count < elements.Length)
{
this.elements[this.count++] = elem;
}
else
{
throw new InvalidOperationException( "Too many elements initialized" );
}
}
public T[]! GetArray()
{
if(count != elements.Length)
{
throw new InvalidOperationException("Not all elements initialized");
}
return this.elements;
}
}
public class LDPC
{
public static T[]![]! ConstructArray( int i, int j )
{
CreateNonNullArray nna = new CreateNonNullArray( i );
for(int k=0; k < i; k++)
{
nna.InitNext( new T[j] );
}
return nna.GetArray();
}
static public byte[]![]! Solve( byte[][] dataPackets, byte[][] eccPackets, int[] eccIndex, int totalEccPackets, int totalDataPackets, int missedDataPackets, int receivedEccPackets, int pktLen )
{
// dataPackets x0 = actual N - k data packets received (blanks in the missing locations)
// eccPackets rhs = actual kp EC packets received
// eccIndex gotec = array contains indices of EC packet received
// totalEccPackets M = total length of EC stream
// totalDataPackets N = total length of data stream
// missedDataPackets kk = number of data packets missed
// receivedEccPackets kp = number of EC packets received
// AA = M * N matrix used to get the EC packets at encoder
if(dataPackets == null) throw new NullReferenceException();
if(eccPackets == null) throw new NullReferenceException();
if(eccIndex == null) throw new NullReferenceException();
int maxMN = (totalEccPackets > totalDataPackets) ? totalEccPackets : totalDataPackets;
bool[] pseudo = new bool[maxMN];
int i;
int j;
int k;
for(i=0; i < maxMN; i += 5) pseudo[i] = true;
for(i=0; i < maxMN; i += 7) pseudo[i] = true;
for(i=0; i < maxMN; i += 13) pseudo[i] = true;
for(i=0; i < maxMN; i += 17) pseudo[i] = true;
for(i=0; i < maxMN; i += 19) pseudo[i] = true;
for(i=0; i < maxMN; i += 33) pseudo[i] = true;
for(i=0; i < maxMN; i += 37) pseudo[i] = true;
//bool[][] A = new bool[receivedEccPackets][];
//for(i=0; i < receivedEccPackets; i++)
//{
// A[i] = new bool[missedDataPackets];
//} // The actual matrix to be inverted (submatrix of AA)
bool[]![]! A = ConstructArray( receivedEccPackets, missedDataPackets );
int[]! miss = new int[missedDataPackets + 1]; // Indices of the missing data packets
int c = 0;
for(i = 0; i < missedDataPackets; i++)
{
while(c < totalDataPackets && dataPackets[c] != null)
{
c++;
}
//Microsoft.SPOT.Debug.Print( "Missing: " + c );
miss[i] = c++;
}
// Get miss array
miss[missedDataPackets] = -1;
for(i=0; i < receivedEccPackets; i++)
{
byte[] t = eccPackets[i]; if(t == null) throw new NullReferenceException();
t = (byte[])t.Clone(); if(t == null) throw new NullReferenceException();
eccPackets[i] = t;
// What's the actual system we have to solve
for(j=0; j < missedDataPackets; j++)
{
int idx = eccIndex[i] + miss[j];
//A[i][j] = AA[eccIndex[i]][miss[j]];
A[i][j] = pseudo[ idx < maxMN ? idx : idx - maxMN ];
}
}
for(j = 0; j < totalDataPackets; j++)
{
byte[] dataPacket = dataPackets[j];
if(dataPacket != null)
{
// Packet j is not a missing packet
for(i = 0; i < receivedEccPackets; i++)
{
int idx = eccIndex[i] + j;
if(pseudo[ idx < maxMN ? idx : idx - maxMN ]) /*AA[eccIndex[i]][j]*/
{
//Microsoft.SPOT.Debug.Print( "XOR: eccPackets[" + i + "], dataPackets[" + j + "]" );
byte[] eccPacket = eccPackets[i];
if(eccPacket != null)
{
Microsoft.SPOT.Hardware.Radio.XorData( eccPacket, dataPacket );
}
}
}
}
}
//DumpMatrix( "Beginning:", A, kp, kk );
// Now set up some variables and do the LU decomposition
//byte[][] y = new byte[missedDataPackets+1][]; // Intermediate solution
//byte[][] xhat = new byte[missedDataPackets+1][];
//
//
//for(i=0; i < missedDataPackets+1; i++)
//{
// y [i] = new byte[ pktLen ];
// xhat[i] = new byte[ pktLen ];
//}
byte[]![]! y = ConstructArray( missedDataPackets+1, missedDataPackets+1 );
byte[]![]! xhat = ConstructArray( missedDataPackets+1, missedDataPackets+1 );
int i2;
int j2;
int p;
//DumpMatrix( "Beginning:", A, kp, kk );
for(k = 0; k < missedDataPackets; k++)
{
p = k;
// Find a remaining row with non-zero k-th element
while(A[p][k] == false)
{
p++;
if(p == receivedEccPackets)
{
//Microsoft.SPOT.Debug.Print( "Non-triangular matrix?" );
//return null;
throw new Exception( "Non-triangular matrix?" );
}
}
if(p != k)
{
//Microsoft.SPOT.Debug.Print( "Swap: " + p + " " + k );
// Swap row k and row p
for(j2 = 0; j2 < missedDataPackets; j2++)
{
bool temp = A[k][j2];
A[k][j2] = A[p][j2];
A[p][j2] = temp;
}
byte[] packetTemp = eccPackets[k];
eccPackets[k] = eccPackets[p];
eccPackets[p] = packetTemp;
//DumpMatrix( "After:", A, kp, kk );
}
for(i2 = k + 1; i2 < receivedEccPackets; i2++)
{
if(A[i2][k] == A[k][k])
{
//Microsoft.SPOT.Debug.Print( "Mix rows: " + i2 + " " + k );
for(j2 = k + 1; j2 < missedDataPackets; j2++)
{
A[i2][j2] ^= A[k][j2];
}
//DumpMatrix( "After:", A, kp, kk );
}
}
}
//DumpMatrix( "After:", A, kp, kk );
//////////////////////////////////////////////////////////
// Solve Ly = Pb
for(i2 = 0; i2 < missedDataPackets; i2++)
{
y[i2] = (byte[]!)eccPackets[i2];
for(j2 = 0; j2 < i2; j2++)
{
//y[i2] = (sbyte) (((y[i2] ^ (A[i2][j2] * y[j2])) & 0x000000ff));
if(A[i2][j2])
{
//Microsoft.SPOT.Debug.Print( "XOR: y[" + i2 + "], y[" + j2 + "]" );
Microsoft.SPOT.Hardware.Radio.XorData( y[i2], y[j2] );
}
}
}
// Now solve Ux = y
for(i2 = missedDataPackets - 1; i2 >= 0; i2--)
{
xhat[i2] = y[i2];
for(j2 = i2 + 1; j2 < missedDataPackets; j2++)
{
//xhat[i2] = (sbyte) (((xhat[i2] ^ (A[i2][j2] * xhat[j2])) & 0x000000ff));
if(A[i2][j2])
{
//Microsoft.SPOT.Debug.Print( "XOR: xhat[" + i2 + "], xhat[" + j2 + "]" );
Microsoft.SPOT.Hardware.Radio.XorData( xhat[i2], xhat[j2] );
}
}
}
for(i2 = 0; i2 < missedDataPackets; i2++)
{
// Rogue value to indicate non-invertible
if(A[i2][i2] == false)
{
//return null;
throw new Exception( "Non-invertible matrix?" );
}
}
return xhat;
}
static public byte[][] GenerateEC( byte[][] dataPackets, int totalEccPackets, int totalDataPackets, int pktLen )
{
int maxMN = (totalEccPackets > totalDataPackets) ? totalEccPackets : totalDataPackets;
int i;
int j;
if(dataPackets == null) throw new NullReferenceException();
bool[] pseudo = new bool[maxMN];
for(i=0; i < maxMN; i += 5) pseudo[i] = true;
for(i=0; i < maxMN; i += 7) pseudo[i] = true;
for(i=0; i < maxMN; i += 13) pseudo[i] = true;
for(i=0; i < maxMN; i += 17) pseudo[i] = true;
for(i=0; i < maxMN; i += 19) pseudo[i] = true;
for(i=0; i < maxMN; i += 33) pseudo[i] = true;
for(i=0; i < maxMN; i += 37) pseudo[i] = true;
byte[][] eccPackets = new byte[totalEccPackets][];
for(i=0; i < totalEccPackets; i++)
{
eccPackets[i] = new byte[ pktLen ];
}
for(i=0; i < totalEccPackets; i++)
{
// Generate the EC stream
for(j=0; j < totalDataPackets; j++)
{
//ec[i] = (sbyte) (((ec[i] ^ (AA[i][j] * x[j])) & 0x000000ff));
int idx = i + j;
if(pseudo[ idx < maxMN ? idx : idx - maxMN ]) /*AA[i][j]*/
{
byte[] eccPacket = eccPackets[i];
byte[] dataPacket = dataPackets[j];
if(eccPacket != null && dataPacket != null)
{
Microsoft.SPOT.Hardware.Radio.XorData( eccPacket, dataPacket );
}
}
}
}
return eccPackets;
}
}
}
namespace ProtocolTester
{
public class UnitTest_LDPC
{
// main program written by hpleung
// Procedure:
// 1. Generate Random Data Unit
// 2. Generate Error Correction Unit
// 3. Inject Errors in The Random Data Unit
// 4. Decode
// 5. Make sure after decoding data is fully received
// Run it with run.exe nDataPacket nErrorCorrection nPercentageLoss nIteration
//
public void Run()
{
//for quick correctness verification
Microsoft.SPOT.Debug.Print( "LPDC Test Started" );
// for(int i=0; i<100; i++)
// {
// RunPass( 40, 40, 40, 106 );
// }
// return;
for(int nPacketLength=10; nPacketLength <= 120; nPacketLength = nPacketLength + 10)
{
RunPass( nPacketLength, nPacketLength, 40, 106 );
}
}
public void RunPass( int nDataPacketCount, int nErrorCorrectionCount, int nPercentageLoss, int nPacketSize )
{
byte[][] arrDataPacket = new byte[nDataPacketCount][];
byte[][] arrDataReceived = new byte[nDataPacketCount][];
byte[][] arrErrorCorrectionStream = null;
int nDataLossCount = 0;
int i;
//randomly generate some data
PopulatePacket( arrDataPacket, nPacketSize );
for(i=0; i= nPacketToLossFix)
{
arrDataReceived[i] = arrDataPacket[i];
}
else
{
arrDataReceived[i] = null;
}
}
#else
int nPacketToGet = nDataPacketCount - nPacketToLossFix;
while(nPacketToGet > 0)
{
i = Microsoft.SPOT.Math.Random( nDataPacketCount - 1 );
//Microsoft.SPOT.Debug.Print( "Picked " + i );
if(arrDataReceived[i] == null)
{
arrDataReceived[i] = arrDataPacket[i];
nPacketToGet--;
}
}
#endif
for(i=0; i (nDataLossCount + 5) * 100)
{
nErrorPacketToReceive = (int)((nDataLossCount * 108)/100) ;
}
else
{
nErrorPacketToReceive = nDataLossCount + 5;
}
if(nErrorPacketToReceive > nErrorCorrectionCount)
{
nErrorPacketToReceive = nErrorCorrectionCount;
}
int[]! arrECPacketReceived = new int [nErrorPacketToReceive];
byte[][] arrRHS = new byte[nErrorPacketToReceive][];
// Randomly Pick up Error Packets
for(i=0; i