I need to communicate with Arduino from PC.
I have C# code. I send 87 bytes to the Arduino.
C# Code
byte[] MyBuffer = new byte[87];
// I initialize buffer with bytes(0-255) details are not important.
serialport1.Write(MyBuffer, 0, 87);
Arduino part is the most important. Because I am going to split these bytes to 5 different arrays.
byte FirstBlock[16];
byte SecondBlock[16];
byte ThirdBlock[16];
byte FourthBlock[16];
byte FifthBlock[16];
byte ReceivedBuffer[87];
int counter = 0
bool SYNC = false;
void loop(){
if(Serial.available())
CropBytes();
if(SYNC == true){
SplitBytes();
DoSomeStaffWithBlocks();
SYNC = false;
} } //End Loop
void CropBytes(){
while(Serial.available()){
byte ReceivedByte = Serial.read();
ReceivedBuffer[counter] = ReceivedByte;
// byte 35 means my byte transfer is over for ReceivedBuffer[86]
if(counter == 86 && ReceivedBuffer[counter] == 35){
SYNC = true;
counter = 0;
}
else{
counter = counter + 1;
}
}
}
void SplitBytes(){
for (int i = 5; i < 21; i++)
{
FirstBlock[i - 5] = ReceivedBuffer[i];
}
for (int i = 21; i < 37; i++)
{
SecondBlock[i - 21] = ReceivedBuffer[i];
}
for (int i = 37; i < 53; i++)
{
ThirdBlock[i - 37] = ReceivedBuffer[i];
}
for (int i = 53; i < 69; i++)
{
FourthBlock[i - 53] = ReceivedBuffer[i];
}
for (int i = 69; i < 85; i++)
{
FifthBlock[i - 69] = ReceivedBuffer[i];
}
}
The problem - FirstBlock[], SecondBlock[], ThirdBlock[] received successfully no problem. But after ThirdBlock, FourthBlock(after 11th byte) and FifthBlock(all bytes) arrays don't initialize successfully.
I don't know where is the problem.
Related
I have to calculate the spectrum values of an audio.
I used aForge's FFT in Sources/Math/FourierTransform.cs and I used an example of sampling with 16 samples as used in this video to check the results with excel (I tested the results in a spreadsheet like in the video).
FFT:
public enum Direction
{
Forward = 1,
Backward = -1
};
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[,][] complexRotation = new Complex[maxBits, 2][];
static void Main(string[] args)
{
var Data = new Complex[16];
Data[0] = new Complex(0, 0);
Data[1] = new Complex((float)0.998027, 0);
Data[2] = new Complex((float)0.125333, 0);
Data[3] = new Complex((float)-0.98229, 0);
Data[4] = new Complex((float)-0.24869, 0);
Data[5] = new Complex((float)0.951057, 0);
Data[6] = new Complex((float)0.368125, 0);
Data[7] = new Complex((float)-0.90483, 0);
Data[8] = new Complex((float)-0.48175, 0);
Data[9] = new Complex((float)0.844328, 0);
Data[10] = new Complex((float)0.587785, 0);
Data[11] = new Complex((float)-0.77051, 0);
Data[12] = new Complex((float)-0.68455, 0);
Data[13] = new Complex((float)0.684547, 0);
Data[14] = new Complex((float)0.770513, 0);
Data[15] = new Complex((float)-0.58779, 0);
FFT(Data, Direction.Forward);
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Re.ToString());
}
Console.ReadLine();
}
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
int m = Tools.Log2(n);
// reorder data first
ReorderData(data);
// compute FFT
int tn = 1, tm;
for (int k = 1; k <= m; k++)
{
Complex[] rotation = GetComplexRotation(k, direction);
tm = tn;
tn <<= 1;
for (int i = 0; i < tm; i++)
{
Complex t = rotation[i];
for (int even = i; even < n; even += tn)
{
int odd = even + tm;
Complex ce = data[even];
Complex co = data[odd];
double tr = co.Re * t.Re - co.Im * t.Im;
double ti = co.Re * t.Im + co.Im * t.Re;
data[even].Re += tr;
data[even].Im += ti;
data[odd].Re = ce.Re - tr;
data[odd].Im = ce.Im - ti;
}
}
}
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
}
private static int[] GetReversedBits(int numberOfBits)
{
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
// check if the array is already calculated
if (reversedBits[numberOfBits - 1] == null)
{
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
// calculate the array
for (int i = 0; i < n; i++)
{
int oldBits = i;
int newBits = 0;
for (int j = 0; j < numberOfBits; j++)
{
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
}
rBits[i] = newBits;
}
reversedBits[numberOfBits - 1] = rBits;
}
return reversedBits[numberOfBits - 1];
}
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
{
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
// check if the array is already calculated
if (complexRotation[numberOfBits - 1, directionIndex] == null)
{
int n = 1 << (numberOfBits - 1);
double uR = 1.0;
double uI = 0.0;
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
double t;
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
{
rotation[i] = new Complex(uR, uI);
t = uR * wI + uI * wR;
uR = uR * wR - uI * wI;
uI = t;
}
complexRotation[numberOfBits - 1, directionIndex] = rotation;
}
return complexRotation[numberOfBits - 1, directionIndex];
}
// Reorder data for FFT using
private static void ReorderData(Complex[] data)
{
int len = data.Length;
// check data length
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException("Incorrect data length.");
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
{
int s = rBits[i];
if (s > i)
{
Complex t = data[i];
data[i] = data[s];
data[s] = t;
}
}
}
These are the results after the transformation:
Output FFT results: Excel FFT results:
0,0418315622955561 0,669305
0,0533257974328085 0,716163407
0,137615673627316 0,908647001
0,114642731070279 1,673453043
0,234673940537634 7,474988602
0,0811255020953362 0,880988382
0,138088891589122 0,406276784
0,0623766891658306 0,248854492
0,0272978749126196 0,204227
0,0124250144575261 0,248854492
0,053787064184711 0,406276784
0,00783331226557493 0,880988382
0,0884368745610118 7,474988602
0,0155431246384978 1,673453043
0,0301093757152557 0,908647001
0 0,716163407
The results are not at all similar. Where is it wrong?
Is the implementation of complex (Data) wrong or is the FFT method wrong or other?
Thanks in advance!
First, the resulting FFT is a complex function in general. You're only displaying the real parts in your code but the thing you're comparing to is displaying the magnitudes, so of course they're going to be different: you're comparing apples to oranges.
When you use magnitudes and compare apples to apples, you should get this:
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Magnitude.ToString());
}
...
0.0418315622955561
0.0447602132472683
0.0567904388057513
0.104590813761862
0.46718679147454
0.0550617784710375
0.025392294285886
0.0155534081359397
0.0127641875296831
0.0155534081359397
0.025392294285886
0.0550617784710375
0.46718679147454
0.104590813761862
0.0567904388057513
0.0447602132472683
That looks a little better -- it has the same symmetry property as the Excel output and there appear to be peaks in the same locations.
It almost looks like the scale is off. If I divide each element by the corresponding element from the Excel output, I get:
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
So your results are pretty much correct, just off by a scaling factor.
You're dividing everything by n in the last step of your FFT:
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
This is conventionally done for the inverse transform, not the forward transform.
In summary, changing the output from Data[a].Re to Data[a].Magnitude and changing the condition at the end of FFT from if (direction == Direction.Forward) to if (direction == Direction.Backward), I get this output:
0.669304996728897
0.716163411956293
0.908647020892022
1.67345302018979
7.47498866359264
0.880988455536601
0.406276708574176
0.248854530175035
0.20422700047493
0.248854530175035
0.406276708574176
0.880988455536601
7.47498866359264
1.67345302018979
0.908647020892022
0.716163411956293
which matches the Excel output.
I'm trying to send many ints to my "masterArduino".
Because the SerialPort object only send strings. I've tried many things including:
Creating a string from ints (didn't work because the size of the string.length is dynamic).
Then I tried to convert these ints to chars, this because all values are between 0-255, then put the char into a string and send it.
This sort of works. However, I think there is no value for 0 in char world. So the data is not right. But there must be a better way?
void sendInfo() {
for (var i = 0; i < peltiers.Length; i++) {
char tempHot = (char) peltiers[i].GetComponent<Peltier>().hot;
char charTemp = (char) peltiers[i].GetComponent<Peltier>().temp;
peltierInfo += tempHot.ToString();
peltierInfo += charTemp.ToString();
}
sp.WriteLine(peltierInfo);
Debug.Log(peltierInfo);
sp.BaseStream.Flush();
peltierInfo = "";
}
Any help would be greatly appreciated! Thanks!
Arduino Code:
void loop() {
int serialIndex = 0;
int i2cIndex = 0;
while (0 < Serial.available()) { // loop through all the received bytes
char bufferByte = 0;
bufferByte = Serial.read();
serialBuffer[serialIndex] = (byte) bufferByte; // put current index byte in array
serialIndex ++; // add index.
if (serialIndex%12==0 && serialIndex != 0) {
sendBytes(0);
}
}
//sendBytes(0);
delay(50);
}
void sendBytes(int slave) {
byte i2cBuffer[12];
int bufferIndex = slave * 12;
for (int i = 0; i < 12; i++) {
i2cBuffer[i] = serialBuffer[i + bufferIndex];
}
Wire.beginTransmission(slave+1);
Wire.write(i2cBuffer, 12);
Wire.endTransmission();
}
To be able to send any integers, first encode them into a string, separate them by something (e.g the '\0' char) and then decode the string.
void sendInfo() {
...
peltierInfo += peltiers[i].GetComponent<Peltier>().hot.ToString();
peltierInfo += '\0';
peltierInfo += peltiers[i].GetComponent<Peltier>().temp.ToString();
peltierInfo += '\0';
...
}
void loop() {
int serialIndex = 0;
int i2cIndex = 0;
// set to how many digits there can be in an incoming number plus 1
int maxNumberLen = 20;
char buffer[20];
// position at which we now put a char that makes up our number
char* currentCharPtr = buffer;
while (0 < Serial.available()) { // loop through all the received bytes
char bufferByte = 0;
bufferByte = Serial.read();
*currentCharPtr = bufferByte;
// move pointer forward
currentCharPtr ++;
// end of a number in string
if (bufferByte == '\0') {
printf("Got number %s\n", buffer);
// atoi parses string to int
serialBuffer[serialIndex] = atoi(buffer);
serialIndex ++;
if(serialIndex%12==0 && serialIndex != 0){
sendBytes(0);
}
// fill buffer with zeros after we found a number
memset(buffer, 0, 20);
currentCharPtr = buffer;
}
}
//sendBytes(0);
delay(50);
}
Thanks for the reply, your answer was exactly how i got it working. I just did it slightly different and didn't had the time to upload this post. What way is better, or is it just a matter of taste?
Unity
void sendInfo()
{
for (int i = 0; i < peltiers.Length; i++)
{
peltierInfo += ",";
peltierInfo += peltiers[i].GetComponent<Peltier>().hot.ToString();
peltierInfo += ",";
peltierInfo += peltiers[i].GetComponent<Peltier>().temp.ToString("D3");
}
//Debug.Log(peltierInfo);
sp.WriteLine(peltierInfo);
sp.BaseStream.Flush();
peltierInfo = "";
}
Arduino
void loop() {
int serialIndex = 0;
if(Serial.available() > 0){
while (0 < Serial.available()) { // loop through all the received bytes
String bufferString;
uint8_t bufferInt;
bufferString = Serial.readStringUntil(',');
bufferInt = bufferString.toInt();
serialBuffer[serialIndex] = bufferInt; // put current index byte in array
serialIndex ++; // add index.
}
sendBytes(0);
}
delay(50);
}
thanks for the help!
I have a byte array and wish to find the "occurrences" of some bytes.
For example 00 69 73 6F 6D in a very large byte array (> 50/100 Megabytes)
OR
even better a reverse operation: Searching the most common pattern without knowing it the code should be able to read and find it from the file.
You can use the Boyer-Moore algorithm to efficiently search for a sequence of bytes in an array of bytes.
Here's a C# version I converted from the Java version from the Wikipedia entry on Boyer-Moore.
public sealed class BoyerMoore
{
readonly byte[] needle;
readonly int[] charTable;
readonly int[] offsetTable;
public BoyerMoore(byte[] needle)
{
this.needle = needle;
this.charTable = makeByteTable(needle);
this.offsetTable = makeOffsetTable(needle);
}
public IEnumerable<int> Search(byte[] haystack)
{
if (needle.Length == 0)
yield break;
for (int i = needle.Length - 1; i < haystack.Length;)
{
int j;
for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j)
{
if (j != 0)
continue;
yield return i;
i += needle.Length - 1;
break;
}
i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]);
}
}
static int[] makeByteTable(byte[] needle)
{
const int ALPHABET_SIZE = 256;
int[] table = new int[ALPHABET_SIZE];
for (int i = 0; i < table.Length; ++i)
table[i] = needle.Length;
for (int i = 0; i < needle.Length - 1; ++i)
table[needle[i]] = needle.Length - 1 - i;
return table;
}
static int[] makeOffsetTable(byte[] needle)
{
int[] table = new int[needle.Length];
int lastPrefixPosition = needle.Length;
for (int i = needle.Length - 1; i >= 0; --i)
{
if (isPrefix(needle, i + 1))
lastPrefixPosition = i + 1;
table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1;
}
for (int i = 0; i < needle.Length - 1; ++i)
{
int slen = suffixLength(needle, i);
table[slen] = needle.Length - 1 - i + slen;
}
return table;
}
static bool isPrefix(byte[] needle, int p)
{
for (int i = p, j = 0; i < needle.Length; ++i, ++j)
if (needle[i] != needle[j])
return false;
return true;
}
static int suffixLength(byte[] needle, int p)
{
int len = 0;
for (int i = p, j = needle.Length - 1; i >= 0 && needle[i] == needle[j]; --i, --j)
++len;
return len;
}
}
Here's some console app test code for it:
public static void Main()
{
byte[] haystack = new byte[10000];
byte[] needle = { 0x00, 0x69, 0x73, 0x6F, 0x6D };
// Put a few copies of the needle into the haystack.
for (int i = 1000; i <= 9000; i += 1000)
Array.Copy(needle, 0, haystack, i, needle.Length);
var searcher = new BoyerMoore(needle);
foreach (int index in searcher.Search(haystack))
Console.WriteLine(index);
}
Note how the Search() method returns the indices of all the locations of the start of needle inside haystack.
If you just wanted the count, you could just do:
int count = new BoyerMoore(needle).Search(haystack).Count();
For your second question: I assume you are asking about finding the longest repeated sequence of bytes?
That's a much more complicated - and very different - question. If you want an answer for that, you should ask a separate question for it, but you should read the Wikipedia entry on the "longest repeated substring problem".
I got the Biostation T2 from Suprema, they provided a wrapped Dll made with C#, they also provide example using: VB6, VB.net, C++ and C#.Most of the documentation is in C++ and am having a hard time trying to convert that logic to C#.I am unable to enroll a user using the below functions in the pastie.Mainly cause am not sure if the logic in C# and C++ matches up.
See the C++ code for enrolling user and my C# attempt pastie
I get error attempted to read or write protected memory as captured here
Here ia a link of the sdk samples they provide sdk samples in vc,c#,C++
We have no way of compiling and testing your code with what you have shown us. That being said, comparing the c++ and c# side by side, I see the following inconsistencies:
The c++ has the following code:
unsigned char* templateBuf = (unsigned char*)malloc( userHeader.numOfFinger * 2 * BS_TEMPLATE_SIZE );
int bufPos = 0;
for( int i = 0; i < userHeader.numOfFinger * 2; i++ )
{
result = BS_ScanTemplate( handle, templateBuf + bufPos );
bufPos += BS_TEMPLATE_SIZE;
}
This code calls BS_ScanTemplate multiple times and stores the results sequentially in a byte array. Your code does the following:
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE];
int bufPos = 0;
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE * bufPos];
result = BSSDK.BS_ScanTemplate(m_Handle, templateBuf);
bufPos += BS_TEMPLATE_SIZE;
}
Rather than storing the results of BS_ScanTemplate sequentially, this code throws away the results from each preceding call by reallocating the array. Perhaps you want something like:
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BS_TEMPLATE_SIZE];
for (int i = 0, bufPos = 0; i < userHdr.numOfFinger * 2; i++)
{
byte[] singleBuf = new byte[BS_TEMPLATE_SIZE];
result = BSSDK.BS_ScanTemplate(m_Handle, singleBuf);
Array.Copy(singleBuf, 0, templateBuf, bufPos, singleBuf.Length);
bufPos += singleBuf.Length;
}
The c++ code does
for( int i = 0; i < userHeader.numOfFinger; i++ )
{
userHeader.duress[i] = 0; // no duress finger
}
The c# code does:
userHdr.duressMask = 0; // no duress finger
This is completely different.
The c++ code does:
for( int i = 0; i < userHeader.numOfFinger * 2; i++ )
{
if( i % 2 == 0 )
{
userHeader.fingerChecksum[i/2] = 0;
}
unsigned char* templateData = templateBuf + i * BS_TEMPLATE_SIZE;
for( int j = 0; j < BS_TEMPLATE_SIZE; j++ )
{
userHeader.fingerChecksum[i/2] += templateData[j];
}
}
The c# code does:
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
byte[] templateData = templateBuf;
for (int j = 0; j < 2000 - 1; j++)
{
userHdr.checksum[i / 2] += templateData[j];
}
}
As you can see the c++ code loops twice as many times as the c# code. The c# code probably should be:
for (int i = 0; i < userHdr.numOfFinger; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
for (int j = 0; j < BS_TEMPLATE_SIZE; j++)
{
userHdr.checksum[i / 2] += templateBuf[i * BS_TEMPLATE_SIZE + j];
}
}
You don't show the c++ call to BS_EnrollUserBioStation2 in your pastie so it can't be compared with the c# call.
userHdr.checksum = new ushort[] { 0 }; looks wrong. Shouldn't it be something like userHdr.checksum = new ushort[userHdr.numOfFinger];
Thus I'd suggest the following:
Update BSUserHdrEx as follows:
public const int BS_MAX_NAME_LEN = 32;
public const int BS_MAX_PASSWORD_LEN = 16;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct BSUserHdrEx
{
public static BSUserHdrEx CreateDefaultBSUserHdrEx()
{
var userHdr = new BSUserHdrEx();
userHdr.name = new byte[BSSDK.BS_MAX_NAME_LEN + 1];
userHdr.department = new byte[BSSDK.BS_MAX_NAME_LEN + 1];
userHdr.password = new byte[BSSDK.BS_MAX_PASSWORD_LEN];
userHdr.checksum = new ushort[5];
return userHdr;
}
public uint ID;
public ushort reserved1;
public ushort adminLevel;
public ushort securityLevel;
public ushort statusMask; // internally used by BioStation
public uint accessGroupMask;
//char name[BS_MAX_NAME_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_NAME_LEN + 1)]
public byte[] name;
//char department[BS_MAX_NAME_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_NAME_LEN + 1)]
public byte[] department;
// char password[BS_MAX_PASSWORD_LEN + 1];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = BSSDK.BS_MAX_PASSWORD_LEN + 1)]
public byte[] password;
public ushort numOfFinger;
public ushort duressMask;
//public ushort checksum[5];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public ushort[] checksum;
public ushort authMode;
public ushort authLimitCount; // 0 for no limit
public ushort reserved;
public ushort timedAntiPassback; // in minutes. 0 for no limit
public uint cardID; // 0 for not used
public bool bypassCard;
public bool disabled;
public uint expireDateTime;
public uint customID; //card Custom ID
public int version; // card Info Version
public uint startDateTime;
};
Update btngetUserInfo_Click as follows:
private void btngetUserInfo_Click(object sender, EventArgs e)
{
int result;
BSSDK.BSUserHdrEx userHdr = BSSDK.BSUserHdrEx.CreateDefaultBSUserHdrEx();
userHdr.ID = 2; // 0 cannot be assigned as a user ID
userHdr.startDateTime = 0; // no check for start date
userHdr.expireDateTime = 0; // no check for expiry date
userHdr.adminLevel = BSSDK.BS_USER_NORMAL;
userHdr.securityLevel = BSSDK.BS_USER_SECURITY_DEFAULT;
userHdr.authMode = BSSDK.BS_AUTH_MODE_DISABLED; // use the authentication mode of the device
userHdr.accessGroupMask = 0xffff0201; // a member of Group 1 and Group 2;
Encoding.UTF8.GetBytes("Madman").CopyTo(userHdr.name, 0);
Encoding.UTF8.GetBytes("INC").CopyTo(userHdr.department, 0);
Encoding.UTF8.GetBytes("").CopyTo(userHdr.password, 0);
userHdr.password = Encoding.UTF8.GetBytes(""); // no password is enrolled. Password should be longer than 4 bytes.
userHdr.numOfFinger = 2;
byte[] templateBuf = new byte[userHdr.numOfFinger * 2 * BSSDK.BS_TEMPLATE_SIZE];
for (int i = 0, bufPos = 0; i < userHdr.numOfFinger * 2; i++)
{
byte[] singleBuf = new byte[BSSDK.BS_TEMPLATE_SIZE];
result = BSSDK.BS_ScanTemplate(m_Handle, singleBuf);
Array.Copy(singleBuf, 0, templateBuf, bufPos, singleBuf.Length);
bufPos += singleBuf.Length;
}
userHdr.duressMask = 0; // no duress finger
for (int i = 0; i < userHdr.numOfFinger * 2; i++)
{
if (i % 2 == 0)
{
userHdr.checksum[i / 2] = 0;
}
// byte[] templateData = templateBuf;
for (int j = 0; j < BSSDK.BS_TEMPLATE_SIZE; j++)
{
userHdr.checksum[i / 2] += templateBuf[i * BSSDK.BS_TEMPLATE_SIZE + j];
}
}
// enroll the user
result = BSSDK.BS_EnrollUserBioStation2(m_Handle, ref userHdr, templateBuf);
if (result == (int)BSSDK.BS_RET_CODE.BS_SUCCESS)
{
MessageBox.Show("user " + userHdr.name.ToString() + " enrolled");
}
update
The struct you are marshalling is BSUserHdrEx. BS_EnrollUserBioStation2 does not take this as an argument. BS_EnrollUserBioStation2 takes a BS2UserHdr as an argument (source: Page 158 of "BioStar SDK Manual V1.8.pdf".) BSUserHdrEx is an argument to BS_EnrollUserEx. (Page 129).
BS_EnrollUserEx "Enrolls a user to BioStation. Maximum 5 fingers can be enrolled per user."
BS_EnrollUserBioStation2 "Enrolls a user to BioStation T2. Maximum 10 fingers per user."
Either you need to switch to the former function, or use the latter data structure.
I'm trying to convert this MATLAB function into c#
but my results are not as expected.
MATLAB:
function check=CRC8(xa);
% xa is array of bits to be transmitted (column vector)
% Generates 8-bit CRC check with g(x) = x^8 + x^2 +x + 1
xae = [xa;0;0;0;0;0;0;0;0]; % Append 8 zeros to array containing bit-stream
g8x = [1;0;0;0;0;0;1;1;1] ; % Generator polynomial
xsa=xae(1:9);
for i=1:length(xa)
if xsa(1) = = g8x(1), xsa = xor(xsa,g8x); end;
xsa(1:8)=xsa(2:9);
if i<length(xa) xsa(9)=xae(i+9); end;
end;
check = xsa(1:8); % 8 bit CRC column vector
return;
C#
public static int[] checkCRC8(int[] xa)
{
int[] g8x = { 1, 0, 0, 0, 0, 0, 1, 1, 1 };
int[] xae = new int[xa.Length + 8];
xa.CopyTo(xae, 0);
//add zeros
for (int i = xa.Length; i < xae.Length; i++)
{
xae[i] = 0;
}
int[] xsa = new int[8];
for (int i = 0; i < 8; i++)
{
xsa[i] = xae[i];
}
for (int i = 0; i < xa.Length; i++)
{
if (xsa[0] == g8x[0])
{
//xor xsa with g8x
for (int j = 0; j < xsa.Length; j++)
{
xsa[j] = xsa[j] ^ g8x[j];
}
}
//shift array elements left
for (int j = 0; j < xsa.Length - 1; j++)
{
xsa[j] = xsa[j + 1];
}
if (i < xa.Length)
{
xsa[xsa.Length - 1] = xae[i + 8];
}
}
return xsa;
}
}
The matlab ranges like in xsa = xae(1:9) are inclusive, so xsa should have nine elements instead of eight. Also, since your i is already zero based, I think the last if should compare against xa.Length-1 and use the array element at i+9 instead of i+8:
if (i < xa.Length - 1)
{
xsa[xsa.Length - 1] = xae[i + 9];
}