I'm using a map to merge duplicates and sort items in a dll. It's not exposed in the interface of the dll. The simplified code is as follows.
UINT GetInfo(UINT request, LPVOID data)
{
//...
switch (request)
{
case COUNT_RES:
{
CountRes* countRes = (CountRes*)data;
ZeroMemory(countRes, sizeof(CountRes));
try
{
//...
PUINT posValue = (PUINT)buffer;
PUINT posCount = (PUINT)buffer2;
FLOAT value; UINT count;
std::map<FLOAT, UINT, std::greater<FLOAT> > coinMap; //Access violation
countRes->rejected = ntohl(posCount[20]);
for (UCHAR i = 0; i < 20; ++i)
{
value = (FLOAT)ntohl(posValue[i]) / 100;
count = ntohl(posCount[i]);
coinMap[value] += count; //Access violation
countRes->total += value * count;
}
//...
}
//...
}
The GetInfo function is called from an exe. The showed code raises an access violation exception at the declaration line. The call stack is as follows.
_heap_alloc_dbg(unsigned int 0x00000018, int 0x00000001, const char * 0x00000000, int 0x00000000) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 0x00000018, int 0x00000001, int 0x00000001, const char * 0x00000000, int 0x00000000) line 242 + 21 bytes
_nh_malloc(unsigned int 0x00000018, int 0x00000001) line 194 + 19 bytes
operator new(unsigned int 0x00000018) line 24 + 11 bytes
std::_Allocate(int 0x00000018, char * 0x00000000) line 30 + 9 bytes
std::allocator<unsigned int>::_Charalloc(unsigned int 0x00000018) line 62 + 11 bytes
std::_Tree<float,std::pair<float const ,unsigned int>,std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::_Kfn,std::greater<float>,std::allocator<unsigned int> >::_Buynode(...) line 587 + 10 bytes
std::_Tree<float,std::pair<float const ,unsigned int>,std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::_Kfn,std::greater<float>,std::allocator<unsigned int> >::_Init() line 461 + 16 bytes
std::_Tree<float,std::pair<float const ,unsigned int>,std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::_Kfn,std::greater<float>,std::allocator<unsigned int> >::_Tree<float,std::pair<float const ,unsigned int>,std::ma1aad805f(const std::greater<float> & {...}, unsigned char 0x00, const std::allocator<unsigned int> & {...}) line 162 + 67 bytes
std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >(const std::greater<float> & {...}, const std::allocator<unsigned int> & {...}) line 57 + 47 bytes
GetInfo(unsigned int 0xffffffff, void * 0x0012f658) line 331 + 25 bytes
If I declare coinMap out of the try scope, then the exception occurs at the insertion line instead. The call stack is as follows.
std::greater<float>::operator()(const float & 1.00000, const float &) line 80 + 37 bytes
std::_Tree<float,std::pair<float const ,unsigned int>,std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::_Kfn,std::greater<float>,std::allocator<unsigned int> >::insert(const std::pair<float const ,unsigned int> & {...}) line 222 + 37 bytes
std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::insert(const std::pair<float const ,unsigned int> & {...}) line 96 + 45 bytes
std::map<float,unsigned int,std::greater<float>,std::allocator<unsigned int> >::operator[](const float & 1.00000) line 93 + 65 bytes
GetInfo(unsigned int 0xffffffff, void * 0x0012f658) line 337 + 18 bytes
I have no clue how to solve the issue. Please help!
Crash in legal allocation code is 99.99% heap corruption issue.
Comment out all data / countRes references in GetInfo() and see is crash still raising. If yes very likely the problem is outside of code you posted here.
Related
I am trying to follow the example code from XGBoost4J's tutorial, but am running into a check failure in the C++ implementation. The error message is not obvious what's wrong:
ml.dmlc.xgboost4j.java.XGBoostError: [21:28:54] /Users/phcho/tmp/xgboost/src/objective/regression_obj.cu:35: Check failed: info.labels.Shape(0) == info.num_row_ (0 vs. 329) : Invalid shape of labels.
Stack trace:
[bt] (0) 1 libxgboost4j3410071582095733624.dyl 0x000000013ac09a74 dmlc::LogMessageFatal::~LogMessageFatal() + 116
[bt] (1) 2 libxgboost4j3410071582095733624.dyl 0x000000013ad495b9 xgboost::obj::(anonymous namespace)::CheckRegInputs(xgboost::MetaInfo const&, xgboost::HostDeviceVector<float> const&) + 249
[bt] (2) 3 libxgboost4j3410071582095733624.dyl 0x000000013ad4dda8 xgboost::obj::RegLossObj<xgboost::obj::LogisticClassification>::GetGradient(xgboost::HostDeviceVector<float> const&, xgboost::MetaInfo const&, int, xgboost::HostDeviceVector<xgboost::detail::GradientPairInternal<float> >*) + 40
[bt] (3) 4 libxgboost4j3410071582095733624.dyl 0x000000013ace6f04 xgboost::LearnerImpl::UpdateOneIter(int, std::__1::shared_ptr<xgboost::DMatrix>) + 580
[bt] (4) 5 libxgboost4j3410071582095733624.dyl 0x000000013ac14b89 XGBoosterUpdateOneIter + 137
[bt] (5) 6 ??? 0x000000011671978c 0x0 + 4671510412
[bt] (6) 7 ??? 0x0000000116712b28 0x0 + 4671482664
[bt] (7) 8 ??? 0x0000000116712e90 0x0 + 4671483536
[bt] (8) 9 ??? 0x00000001167129ba 0x0 + 4671482298
The code:
List<float[]> rows = new ArrayList<>();
int trainRows = (int) (rows.size() * 0.7);
int testRows = rows.size() - trainRows;
int columnCount = rows.get(0).length;
float[] flatTrainMatrix = new float[trainRows * columnCount];
float[] flatTestMatrix = new float[testRows * columnCount];
for (int i = 0; i < rows.size(); i++) {
if (i < trainRows) {
System.arraycopy(rows.get(i), 0, flatTrainMatrix, i * columnCount, columnCount);
} else {
System.arraycopy(rows.get(i), 0, flatTestMatrix, (i - trainRows) * columnCount, columnCount);
}
}
var params = Map.<String, Object>of("max_depth", 4, "eta", 1.0, "objective", "binary:logistic", "eval_metric", "auc");
try {
DMatrix trainMatrix = new DMatrix(flatTrainMatrix, trainRows, columnCount, -1);
DMatrix testMatrix = new DMatrix(flatTestMatrix, testRows, columnCount, -1);
var booster = XGBoost.train(trainMatrix, params, 1, Map.of("train", trainMatrix, "test", testMatrix), null, null);
booster.saveModel("/tmp/model.bin");
} catch (XGBoostError e) {
throw new RuntimeException(e); // The error message from above is from here.
}
}
I am using the ml.dmlc:xgboost4j_2.12:1.6.1.
The Arduino core is on github as ArduinoCore-mbed
I have had some success storing a camera buffer into Arduino MBED SDRAM, but that was fairly easy as the code was expecting a pointer when working with the camera. See code below:
SDRAMClass mySDRAM;
uint8_t *sdram_frame_buffer;
//uint8_t frame_buffer[320*320];
void setup() {
mySDRAM.begin();
sdram_frame_buffer = (uint8_t *)mySDRAM.malloc(320 * 320 * sizeof(uint8_t));
then in the main loop I did
if (cam.grab(sdram_frame_buffer) == 0){...
Note: I also do some frame alignment on the above code, but it still kind of works fine.
But now I want to store the entire TensorflowMicro c++ array
const unsigned char model_tflite[] = { 0x74, 0x69, 0x74, ...};
unsigned int model_tflite_len = 2640;
//which is later called as an array
model = tflite::GetModel(model_tflite); // name from the tflite converter model.h file
The problem here is that the Portenta has a max array size <= 1MB which is much less than the SDRAM max array size 8MB. What would be best would be to put the data for the Machine Learning model directly into SDRAM without using an array at all. Not sure if there is an easy way to do that.
Anyone have any suggestions?
Here is an example that runs on the Arduino Portenta
// Needed for SDRAM assignment on Arduino Portenta
#include <SDRAM.h>
#define ALIGN_PTR(p,a) ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)
SDRAMClass mySDRAM;
// assign values to a regular array
unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;
// define SDRAM pointer
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned
void setup() {
Serial.begin(115200);
mySDRAM.begin(SDRAM_START_ADDRESS);
// setup SDRAM memory block
sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);
// THE PROBLEM
// How to assign the data directly to the allocated pointer memory
// without having to make an array as well
// The following traditional line works
// sdram_tflite = model_tflite;
// This line doesn't work
// sdram_tflite = {0x54, 0x46, 0x4c, 0x33};
// The following works, but is very clumsy
*(sdram_tflite + 0) = 0x54;
*(sdram_tflite + 1) = 0x46;
*(sdram_tflite + 2) = 0x4c;
*(sdram_tflite + 3) = 0x33;
}
void myShowArray( unsigned char b[], int sizeOfArray ) {
for ( int k = 0 ; k < sizeOfArray ; k++ ){
Serial.println(b[k], HEX);
}
Serial.println();
}
void myShowPointer( unsigned char *b, int sizeOfArray ) {
for ( int k = 0 ; k < sizeOfArray ; k++ ){
Serial.println(*(b + k), HEX);
}
Serial.println();
}
void loop() {
Serial.println("Regular array");
for (int i=0; i < model_tflite_len; i++){
Serial.println(model_tflite[i], HEX);
}
Serial.println();
Serial.println("SDRAM pointer as an array");
for (int i=0; i < model_tflite_len; i++){
Serial.println( *(sdram_tflite + i), HEX );
}
Serial.println();
Serial.println("Regular array passed as an array to the receiving function");
myShowArray(model_tflite, model_tflite_len);
Serial.println("Pointer passed as a pointer to the receiving function");
myShowPointer(sdram_tflite, model_tflite_len);
Serial.println("Pointer passed as an array to the receiving function");
myShowArray(*&sdram_tflite, model_tflite_len);
Serial.println("--------------------");
Serial.println();
delay(4000);
}
with output :
Regular array
54
46
4C
33
SDRAM pointer as an array
54
46
4C
33
Regular array passed as an array to the receiving function
54
46
4C
33
Pointer passed as a pointer to the receiving function
54
46
4C
33
Pointer passed as an array to the receiving function
54
46
4C
33
--------------------
// Needed for SDRAM assignment on Arduino Portenta
#include <SDRAM.h>
#define ALIGN_PTR(p,a) ((p & (a-1)) ?(((uintptr_t)p + a) & ~(uintptr_t)(a-1)) : p)
SDRAMClass mySDRAM;
// assign values to a regular array
unsigned char model_tflite[] = {0x54, 0x46, 0x4c, 0x33};
unsigned int model_tflite_len = 4;
// define SDRAM pointer
unsigned char *sdram_mem;
unsigned char *sdram_tflite; // 32-byte aligned
void setup() {
Serial.begin(115200);
mySDRAM.begin(SDRAM_START_ADDRESS);
// setup SDRAM memory block
sdram_mem = (unsigned char *) SDRAM.malloc(4 + 32 /*alignment*/);
sdram_tflite = (unsigned char *)ALIGN_PTR((uintptr_t)sdram_mem, 32);
// THE PROBLEM
// How to assign the data directly to the allocated pointer memory
// without having to make an array as well
// The following traditional line works
// sdram_tflite = model_tflite;
// This line doesn't work
// sdram_tflite = {0x54, 0x46, 0x4c, 0x33};
// The following works, but is very clumsy
// *(sdram_tflite + 0) = 0x54;
// *(sdram_tflite + 1) = 0x46;
// *(sdram_tflite + 2) = 0x4c;
// *(sdram_tflite + 3) = 0x33;
// Try this
// unsigned char buffer[8];
// memcpy(buffer,"\x20\x38\x00\x00\x0E\x82\x00\x06",8);
// yes this works fine!
memcpy(sdram_tflite, "\x54\x46\x4c\x33", model_tflite_len);
}
void myShowArray( unsigned char b[], int sizeOfArray ) {
for ( int k = 0 ; k < sizeOfArray ; k++ ){
Serial.println(b[k], HEX);
}
Serial.println();
}
void myShowPointer( unsigned char *b, int sizeOfArray ) {
for ( int k = 0 ; k < sizeOfArray ; k++ ){
Serial.println(*(b + k), HEX);
}
Serial.println();
}
void loop() {
Serial.println("Regular array");
for (int i=0; i < model_tflite_len; i++){
Serial.println(model_tflite[i], HEX);
}
Serial.println();
Serial.println("SDRAM pointer as an array");
for (int i=0; i < model_tflite_len; i++){
Serial.println( *(sdram_tflite + i), HEX );
}
Serial.println();
Serial.println("Regular array passed as an array to the receiving function");
myShowArray(model_tflite, model_tflite_len);
Serial.println("Pointer passed as a pointer to the receiving function");
myShowPointer(sdram_tflite, model_tflite_len);
Serial.println("Pointer passed as an array to the receiving function");
// myShowArray(*&sdram_tflite, model_tflite_len);
myShowArray(sdram_tflite, model_tflite_len);
Serial.println("--------------------");
Serial.println();
delay(4000);
}
Please understand that the tone is awkward using a translator
I coded the below code for Arduino Mega Board.
However, the value of buf_i is not increasing in the second while loop.
char buf[] = {0, };
if (Serial3.available()) {
int inByte = Serial3.read();
int nextChar = 0;
if (inByte == 90) { //find Header 1
nextChar = Serial3.read();
if (nextChar == 165) { // find Header 2
int buf_i = 0;
int dataLen = Serial3.read(); // get Message Length
//save data [ char buf[] ] ---> works well!
while (buf_i < dataLen) {
buf[buf_i] = Serial3.read();
buf_i++;
}
buf_i = 0;
//print data to Serial ---> not work (Does not increase buf_i)
while (buf_i < dataLen) {
Serial.print(" ");
Serial.println(buf[buf_i]);
buf_i++;
}
}
}
Serial.write(inByte);
}
and this is Serial Moniter Log
in Serial3 Message
5A A5 06 83 21 00 01 00 11
in Serial Message
enter image description here
Thank you for your help :)
The buffer you created has only one element. If you try to insert more than one, then the behavior is undefined.
char buf[] = {0, };
You must make this buffer large enough for the largest message.
char buf[maximum_data_length] = {0};
I keep receiving these errors when I run the compiler:
Program04.cpp:21:14: error: variable or field âgetDataâ declared void
Program04.cpp:21:14: error: âStudentTypeâ was not declared in this scope
Program04.cpp:21:26: error: expected primary-expression before â]â token
Program04.cpp:21:29: error: expected primary-expression before âintâ
Program04.cpp:23:15: error: variable or field âsortDataâ declared void
Program04.cpp:23:15: error: âStudentTypeâ was not declared in this scope
Program04.cpp:23:27: error: expected primary-expression before â]â token
Program04.cpp:23:30: error: expected primary-expression before âintâ
Program04.cpp:27:22: error: variable or field âcomputeAveragesâ declared void
Program04.cpp:27:22: error: âStudentTypeâ was not declared in this scope
Program04.cpp:27:34: error: expected primary-expression before â]â token
Program04.cpp:27:37: error: expected primary-expression before âintâ
Program04.cpp:29:16: error: variable or field âprintDataâ declared void
Program04.cpp:29:16: error: âStudentTypeâ was not declared in this scope
Program04.cpp:29:28: error: expected primary-expression before â]â token
Program04.cpp:29:31: error: expected primary-expression before âintâ
Program04.cpp: In function âint main()â:
Program04.cpp:34:1: error: âStudentTypeâ was not declared in this scope
Program04.cpp:34:13: error: expected â;â before âstudentsâ
Program04.cpp:37:9: error: âstudentsâ was not declared in this scope
Program04.cpp:37:19: error: ânâ was not declared in this scope
Program04.cpp:37:20: error: âgetDataâ was not declared in this scope
Program04.cpp:38:21: error: âsortDataâ was not declared in this scope
Program04.cpp:39:25: error: âcomputeAveragesâ was not declared in this scope
Program04.cpp:40:19: error: âprintDataâ was not declared in this scope
Program04.cpp: At global scope:
Program04.cpp:45:14: error: variable or field âgetDataâ declared void
Program04.cpp:45:14: error: âStudentTypeâ was not declared in this scope
Program04.cpp:45:38: error: expected primary-expression before âintâ
Everything looks good to me, so i'm obviously not understanding something.
Any suggestions?
PROGRAM FILE
using namespace std;
#include "StudentType.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <climits>
#include <string>
const int MAX_STDS = 20;
void getData(StudentType[], int&);
void sortData(StudentType[], int&);
void getFormat(string&);
void computeAverages(StudentType[], int&);
void printData(StudentType[], int&);
int main () {
StudentType students[MAX_STDS];
StudentType();
getData(students, n);
sortData(students, n);
computeAverages(students);
printData(students);
return 0;
}
void getData(StudentType students[], int n){
ifstream fin;
int grade;
string filename, name;
bool done = false;
cout << "Enter filename: ";
cin >> filename;
fin.open(filename.c_str());
while(true) {
try {
fin.open(filename.c_str());
if(!fin) {
throw(string("Could not open " + filename + "."));
}
break;
}
catch (string s) {
cout << s << endl;
cout << "Enter a different file name: ";
cin >> filename;
}
}
n=0;
while(n<MAX_STDS && getline(fin, name)) {
students[n].setName(getFormat(name));
for(int i = 0; i < NUM_GRDS; ++i) {
fin >> grade;
student[n].setGrade(grade, i);
}
getline(fin, name);
++n;
}
}
void printData(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].printLine();
}
}
void computeAverages(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].computeAverage();
}
}
void sortData(StudentType students[], int n) {
for(int i=0; i<n-1; i++) {
for(int j=0; j < n-1-i; ++j) {
if(students[j].getName() > students[j+1].getName()) {
swap(students[j], students[j+1]);
}
}
}
}
void getFormat(string& name) {
string first;
string middle;
string last;
char n, m;
int size = 0;
n = name.find(' ');
first = name.substr(0, n);
m = name.find(' ', n + 1);
size = name.size();
if (m != string::npos) {
middle = name.substr(n+1, m-(n+1));
last = name.substr(m+1, size - (m+1));
}
else {
middle = "";
last = name.substr(n + 1, size - (n + 1));
}
name = last + ", " + first;
if (middle != "") {
name = (name + ' ') + middle[0];
}
}
HEADER FILE
#ifdef STUDENTTYPE__H
#define STUDENTTYPE__H
#include <string>
#include<iostream>
const int NUM_GRDS = 10;
class StudentType {
public:
StudentType();
void setName(std::string);
void setGrade(int, int);
void computeAverage();
std::string getName() const;
void print(std::ostream& = std::cout) const;
private:
std::string name;
int grades[NUM_GRDS];
float avg;
};
#endif
IMPLEMENTATION FILE
#include "StudentType.h"
#include <iomanip>
StudentType::StudentType(){
name = "";
for(int i =0; i <NUM_GRDS; ++i){
grades[i] = 0;
}
avg = 0.0;
}
void StudentType::setName(std::string newName){
name = newName;
}
void StudentType::setGrade(int grade, int num){
grades[num] = grade;
}
void StudentType::computeAverage(){
float total = 0;
for(int i = 0; i<NUM_GRDS; ++i){
total += grades[i];
}
avg = total/NUM_GRDS;
}
std::string StudentType::getName() const{
return name;
}
void StudentType::printLine(std::ostream& out) const {
out.setf(std::left);
out.setf(std::fixed);
out.setf(std::showpoint);
out << "\n" << setw(25) << "Student" << setw(50) << "Grades" << setw(10) << "Average" << endl;
out << "_____________________________________________________________________________________" << endl;
out << std::left << std::setw(25) << name << std::right << ' ';
for(int i = 0; i < NUM_GRDS; ++i){
out << std::setw(5) << grades[i] << ' ';
}
out << setprecision(2) << std::setw(6) << avg << endl;
}
My output should look like this after the program compiles...
Enter file name: grades.dat
Student Grades Average
________________________________________________________________________________________
Last, First 90 80 70 60 50 40 30 20 10 0 45.00
Last, First 40 40 40 40 40 40 40 40 40 40 40.00
Last, First 54 98 65 32 21 87 54 65 98 32 60.60
Flames, Blood A 9 8 7 6 5 4 3 2 1 0 4.50
Bottoms, Car 32 65 98 87 54 24 56 89 78 68 65.10
Guitars, Dean 10 10 10 10 10 10 10 10 10 10 10.00
Honer, Ruth T 78 56 12 23 45 89 31 64 97 79 57.40
Hot, Zepher R 12 54 87 89 56 32 51 46 97 31 55.50
.
.
.
The input file should have this format and include over 20 students for testing purposes:
g0, g1,...g9 should be 10 grades ranging from 0 to 100
First Middle Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
First Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
Change
#ifdef STUDENTTYPE__H
to
#ifndef STUDENTTYPE__H
then you have proper double-inclusion guard
(quite a common typo I must say)
From taking a sharp look at your files, i spotted 2 main errors:
your include guard in the header file is messed up:
#ifdef STUDENTTYPE__H
#define STUDENTTYPE__H
you probably want:
#ifndef STUDENTTYPE__H
#define STUDENTTYPE__H
Also, in the program file:
void getData(StudentType[], int&);
does not match the implementation
void getData(StudentType students[], int n){
as it should be
void getData(StudentType students[], int& n){
which is also true for the other methods.
Also, i am not sure whether stackoverflow is the correct place for you, as you do not have a specific question but just seem to "debug" all your errors here. Maybe start with some c++ tutorials and try to use the error messages of the compiler to trace down all errors.
I'm using this RFID module for Arduino Ethernet R3 and I need to retrieve from the Software Serial the card (TAG) ID that is written outside the tag.
The module's datasheet says that 14 bytes are sent to the Arduino. The first is the header, the last the footer, the 2 bytes before the footer are the checksum, and the other 10 bytes are the ASCII data that contains the tag ID.
How can I recreate the ID of the card, and control the checksum? For example with a tag that has this ID: 0013530444, the Arduino response is:
I received: 2
I received: 51
I received: 67
I received: 48
I received: 48
I received: 67
I received: 69
I received: 55
I received: 53
I received: 52
I received: 67
I received: 67
I received: 66
I received: 3
But I've no idea how to print on the screen the ID read by the Arduino. How to calculate the checksum?
http://www.seeedstudio.com/wiki/index.php?title=125Khz_RFID_module_-_UART
Can anyone help me?
Here's a walkthrough of how to calculate the checksum.
Take your card number (this is just directly quoted from your text)
I received: 2
I received: 51
I received: 67
I received: 48
I received: 48
I received: 67
I received: 69
I received: 55
I received: 53
I received: 52
I received: 67
I received: 67
I received: 66
I received: 3
This would give you a number that is equivalent to the following:
2 51 67 48 48 67 69 55 53 52 67 67 66 3
The first numer (2) indicates that this is the beginning of a request.
The last number (3) indicates that this is the end of a request.
2 51 67 48 48 67 69 55 53 52 67 67 66 3
For the purposes of calculating the checksum, we are going to remove these two numbers. So your new number is now:
51 67 48 48 67 69 55 53 52 67 67 66
The last two numbers that you have are your checksum. The remaining numbers are your card number. So:
Your card number is:
51 67 48 48 67 69 55 53 52 67
And your checksum is:
67 66
Next you need to convert your Card Number and your Checksum to ASCII values:
Your card number is:
3 C 0 0 C E 7 5 4 C
And your checksum is:
C B
Next, grab each number into pairs:
Your card number is:
3C 00 CE 75 4C
And your checksum is:
CB
Then you need to treat each pair as a HEXIDECIMAL value and do an XOR against them. So basically you need to prove the following:
3C ^ 00 ^ CE ^ 75 ^ 4C == CB
(3C ^ 00) = 3C
3C ^ CE ^ 75 ^ 4C == CB
(3C ^ CE) = F2
F2 ^ 75 ^ 4C == CB
(3C ^ CE) = 87
87 ^ 4C == CB
(87 ^ 4C) = CB
CB == CB
Because CB == CB, this is a valid transaction.
No doubt someone else can come up with a better approach than this, but there should be enough pseudo code here for you to write it yourself.
I found this blog which has an implementation in Arduino, I've adapted it to work in Java and results are good. Since there are a lot of bitwise operations - I used http://www.miniwebtool.com/bitwise-calculator/ to try to understand what's going on. I understand all of it except (val | (tempbyte << 4)), I mean I understand what the statement does, I just struggle to see how that produces the result I want.
void loop () {
byte i = 0;
byte val = 0;
byte code[6];
byte checksum = 0;
byte bytesread = 0;
byte tempbyte = 0;
if(Serial.available() > 0) {
if((val = Serial.read()) == 2) {
// check for header
bytesread = 0;
while (bytesread < 12) {
// read 10 digit code + 2 digit checksum
if( Serial.available() > 0) {
val = Serial.read();
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) {
// if header or stop bytes before the 10 digit reading
break;
// stop reading
}
// Do Ascii/Hex conversion:
if ((val >= '0') && (val <= '9')) {
val = val - '0';
} else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
// Every two hex-digits, add byte to code:
if (bytesread & 1 == 1) {
// make some space for this hex-digit by
// shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (val | (tempbyte << 4));
if (bytesread >> 1 != 5) {
// If we're at the checksum byte,
checksum ^= code[bytesread >> 1];
// Calculate the checksum... (XOR)
};
} else {
tempbyte = val;
// Store the first hex digit first...
};
bytesread++;
// ready to read next digit
}
}
// Output to Serial:
if (bytesread == 12) {
// removed code for clarity
LCD.print("Check:");
LCD.print(code[5], HEX);
LCD.print(code[5] == checksum ? "-passed" : "-error");
}
bytesread = 0;
}
}
}
My Java/Android port is listening over a BluetoothSocket. I'm using the code from BlueTerm as the base, this code goes in the ConnectedThread. Apologies for all silly comments, but I'm still learning Java).
//assume you have checksum as int and code as int array. it will overflow if bytes are used like above example
public void run() {
Log.d(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
Log.d(TAG, "Running");
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
for (int i = 0; i < bytes; i++) {
Log.d(TAG, "Reading: " + i + " of " + bytes + " from input stream");
byte b = buffer[i];
try {
if(bytesread >= 0) {
//just printing ASCII
char printableB = (char) b;
if (b < 32 || b > 126) printableB = ' ';
Log.d(TAG, "'" + Character.toString(printableB) + "' (" + Integer.toString(b) + ")");
if((b == 0x0D)||(b == 0x0A)||(b == 0x03)||(b == 0x02)) {
// if header or stop bytes before the 10 digit reading
Log.e(TAG, i + " Unexpected header while processing character " + Integer.toString(b));
} else {
// Do ASCII/Hex conversion
if ((b >= '0') && (b <= '9')) {
b = (byte) (b - '0');
} else if ((b >= 'A') && (b <= 'F')) {
b = (byte) (10 + b - 'A');
}
if ((bytesread & 1) == 1) {
//if isOdd(bytesread)
// make some space for this hex-digit by shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (b | (tempbyte << 4));
if (bytesread >> 1 != 5) {
// If we're not at the checksum byte,
checksum ^= code[bytesread >> 1];
// Calculate the checksum... (XOR)
}
} else {
// Store the first hex digit first
tempbyte = b;
}
}
bytesread++;
} else if(b == 2) {
bytesread = 0;
Log.d(TAG, "Header found!");
}
if(bytesread == 12) {
String check = (code[5] == checksum ? "-passed" : "-error");
String r = "";
for(int j = 0; j < 5; j++){
r += Integer.toString(code[i]);
}
Log.d(TAG, "Check:" + Integer.toString(code[5]) + check);
init();
} else if(bytesread > 12){
Log.e(TAG, "Too many bytes!");
}
} catch (Exception e) {
Log.e(TAG, i + " Exception while processing character " + Integer.toString(b), e);
}
}
String a = buffer.toString();
a = "";
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
Log.i(TAG, "END mConnectedThread");
}