I am trying to validate checksums from a device and they give me the below C code for checksum validation, however I cannot convert this code to java and get it to produce the same checksum as the messages. Note this is the entire source code given in document and i have tried several of the example codes online and none of them work for me. Thanks.
const unsigned short NET_CRC_TABLE[256] =
{ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129,
0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5,
0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528,
0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4,
0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF,
0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33,
0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87,
0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A,
0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA,
0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025,
0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589,
0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424,
0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2,
0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8,
0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37,
0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B,
0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F,
0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 };
unsigned short NET_CRC_Calc(unsigned char * pData, unsigned short Count)
{ /* calculate serial CRC (<--CCITT) without changing data */
unsigned char Index;
unsigned short Crc=0;
while (Count--) {
Index = HBYTE_16(Crc);
HBYTE_16(Crc) = LBYTE_16(Crc);
LBYTE_16(Crc) = *pData++;
Crc = (unsigned short)(Crc ^ NET_CRC_TABLE[Index]);
}
return Crc;
}
I have no idea what the definitions for HByte and LByte are (which is why I didn't post code initially). They are nowhere in the protocool document, so i assumed they were methods in the C library. Basically outside of the table my code is this:
int NET_CRC_Calc(int[] pData, int count) {
int index;
int crc = 0;
for(;count > 0; count--) {
index = crc >> 8;
//TODO: Find out Hbyte method
//LBYTE_16(crc) = pData[count]; ???
crc = (int)(crc ^ NET_CRC_TABLE[index]);
}
return crc;
}
If you would like to test your algorithm before posting (trust i will test anything for you!!), below is the string and expected output.
String command = "<Ver>1</Ver><DtTm></DtTm><Type>3</Type>";
Expected Output: 0x12AA
First of all, make sure you make the NET_CRC_TABLE of type int[]. You can copy the initializer, though.
Next is the pData argument, which is unsigned charin C, and should therefore be a byte array in Java. If you have bytes, make sure that you read unsigned values from the array, by doing
(pData[index] & 0xff)
Then the loop looks like this:
int ptr = 0;
while (count-- > 0) {
index = (crc >> 8) & 0xff;
crc = ((crc & 0xff) << 8) | (pData[ptr++] & 0xff);
crc = crc ^ NET_CRC_TABLE[index];
}
(I have taken liberty to rename the variables to lowercase, as usual in java. Using uppercase variable and method names is frowned upon in the Java world.)
=== EDIT ===
In the case that the whole array must be processed, it makes no sense to pass the count argument at all. Java knows the size of its arrays, unlike C.
So, drop the count parameter and change the loop condition like:
while (ptr < pData.length) {
Based on Ingo's answer, here is a complete solution:
boolean isValidCrc16(int[] crcTable, int crcCode, byte[] toValidate) {
int ptr = 0;
int index;
int computedCrcCode = 0;
boolean isValid;
while (ptr < toValidate.length) {
index = (computedCrcCode >> 8) & 0xff;
computedCrcCode = ((computedCrcCode & 0xff) << 8) | (toValidate[ptr++] & 0xff);
computedCrcCode = computedCrcCode ^ crcTable[index];
}
return computedCrcCode == crcCode;
}
Related
Still new to android and java but learning more each day :)
This question refers to
Ok, the error refers to
expression failed to parse:
error: <user expression 27>:1:1: 'bl' has unknown type; cast it to its declared type to use it
bl
^~
and
expression failed to parse:
error: <user expression 28>:1:1: 'uxtb' has unknown type; cast it to its declared type to use it
uxtb.w
^~~~
I call (will want a short ) result = getCheckSum(A, B); from my java code.
The method in my C++ code is
//---------------------------------------------------------------------------
unsigned short ekmCheckCRC16(const unsigned char *dat, unsigned short len)
{
unsigned short crc = 0xffff;
while (len--)
{
crc = (crc >> 8 ) ^ ekmCrcLut[(crc ^ *dat++) & 0xff];
}
crc = (crc << 8 ) | (crc >> 8);
crc &= 0x7f7f;
return crc;
}
//---------------------------------------------------------------------------
// Implementation of the native method getCheckSum()
extern "C"
JNIEXPORT unsigned short JNICALL
Java_com_(...)_getCheckSum(JNIEnv *env, jobject thiz, jstring a) {
const char * aCStr = env->GetStringUTFChars(a, NULL);
if(NULL == aCStr)
return NULL;
unsigned short crc = ekmCheckCRC16(reinterpret_cast<const unsigned char *>(aCStr), strlen(aCStr));
return crc;
}
This code is experimental showing the actual code I want to run ekmCheckCRC16( ... ), its purpose is to learn how to return a value back to the java module.
The error message seems to be clear 'unknown' type cast, so question is, how should I be returning the value of aCStr?
Thanks in advance.
Solved my problem, was simple error of not changing one important detail before executing call i was looking for a return type of short but had String in native declaration.
I had
private native String getCheckSum(String a);
it should have been
`private native short getCheckSum(String a);`
My call was / is
short result = getCheckSum(A);
Worked fine after correcting my mistake.
for those interested my c++ code
#include <jni.h> // JNI header provided by JDK
#include "ekmCheckSum.h"
#include <iostream> // C++ standard IO header
using namespace std;
//---------------------------------------------------------------------------
void ekmCheckSum() {
}
static const unsigned short ekmCrcLut[256] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
//---------------------------------------------------------------------------
unsigned short ekmCheckCRC16(const unsigned char *dat, unsigned short len)
{
unsigned short crc = 0xffff;
while (len--)
{
crc = (crc >> 8 ) ^ ekmCrcLut[(crc ^ *dat++) & 0xff];
}
crc = (crc << 8 ) | (crc >> 8);
crc &= 0x7f7f;
return crc;
}
//---------------------------------------------------------------------------
// Implementation of the native method getCheckSum()
extern "C"
JNIEXPORT unsigned short JNICALL
Java_com_[project name]_ekmV4Fields_getCheckSum(JNIEnv *env, jobject thiz, jstring a) {
const char * aCStr = env->GetStringUTFChars(a, NULL);
if(NULL == aCStr)
return NULL;
unsigned short crc = ekmCheckCRC16(reinterpret_cast<const unsigned char *>(aCStr), strlen(aCStr));
return crc;
}
my .h file contains
#ifndef PROJECT_NAME_EKMCHECKSUM_H
#define PROJECT_NAME_EKMCHECKSUM_H
class ekmCheckSum
{
private:
public:
ekmCheckSum();
unsigned short ekmCheckCRC16(const unsigned char *dat, unsigned short len);
};
#endif //PROJECT_NAME_EKMCHECKSUM_H
my java file includes
static {System.loadLibrary("ekmCheckSum");}
private native short getCheckSum(String a);
public void SetEkmFieldValueStrings(String A, String B)
{
/* if length of A is less than 250 chars, read is no good, discard
* NOTE: both Strings A and B will need to be validated for checksum
* TODO check A & B if checksum is correct
* */
boolean _aOk = false, _bOk=false;
short result = getCheckSum(A);
...
...
I wrote a small app that pings a remote server by sending ICMP packets using sockets (Android's Os package). I tested it on the API 28 emulator and it worked, but it does not work on API 22 (Android 5.1 Lollipop). I tested it on the VD as well as on my smartphone (same old API) with the same negative result
android.system.ErrnoException: sendto failed: EINVAL (Invalid argument)
I debugged the app on different API versions and the only difference I noticed that ByteBuffer.wrap() produces ByteArrayBuffer instance on API 22 and HeapArrayBuffer instance on newer versions. The payload itself seems to be the same.
Here is the code sample (simplified). Also, there is a test application available: https://github.com/alexeysirenko/android-sockets-icmp-ping-test
You could try to launch it on the different emulators (API 22 and >22) and see the difference
private val timeoutMs = 5000
private val delayMs = 500L
private val ECHO_PORT = 80
private val POLLIN = (if (OsConstants.POLLIN == 0) 1 else OsConstants.POLLIN).toShort()
fun ping(host: String): Unit {
val inetAddress: InetAddress = InetAddress.getByName(host)
if (inetAddress is Inet6Address) throw Exception("IPv6 implementation omitted for simplicity")
val proto = OsConstants.IPPROTO_ICMP
val inet = OsConstants.AF_INET
val type = PacketBuilder.TYPE_ICMP_V4
val socketFileDescriptor = Os.socket(inet, OsConstants.SOCK_DGRAM, proto)
if (!socketFileDescriptor.valid()) throw Exception("Socket descriptor is invalid")
var sequenceNumber: Short = 0
for (i in 0..2) {
sequenceNumber++
val echoPacketBuilder =
PacketBuilder(type, "foobarbazquok".toByteArray())
.withSequenceNumber(sequenceNumber)
val buffer = echoPacketBuilder.build()
/**
* This is the command that throws an exception
*/
val bytesSent = Os.sendto(socketFileDescriptor, buffer,0, buffer.size, 0, inetAddress, ECHO_PORT)
// Response processing code omitted
}
}
class PacketBuilder(val type: Byte, val payload: ByteArray, val sequenceNumber: Short = 0, val identifier: Short = 0xDBB) {
private val MAX_PAYLOAD = 65507
private val CODE: Byte = 0
init {
if (payload.size > MAX_PAYLOAD) throw Exception("Payload limited to $MAX_PAYLOAD")
}
fun build(): ByteArray {
val buffer = ByteArray(8 + payload.size)
val byteBuffer = ByteBuffer.wrap(buffer)
byteBuffer.put(type)
byteBuffer.put(CODE)
val checkPos = byteBuffer.position()
byteBuffer.position(checkPos + 2)
byteBuffer.putShort(identifier)
byteBuffer.putShort(sequenceNumber)
byteBuffer.put(payload)
byteBuffer.putShort(checkPos, checksum(buffer))
byteBuffer.flip()
return buffer
}
fun withSequenceNumber(sequenceNumber: Short): PacketBuilder {
return PacketBuilder(type, payload, sequenceNumber, identifier)
}
/**
* RFC 1071 checksum
*/
private fun checksum(data: ByteArray): Short {
var sum = 0
// High bytes (even indices)
for (i in 0 until data.size step 2) {
sum += data[i].and(0xFF.toByte()).toInt() shl 8
sum = (sum and 0xFFFF) + (sum shr 16)
}
// Low bytes (odd indices)
for (i in 1 until data.size step 2) {
sum += data[i] and 0xFF.toByte()
sum = (sum and 0xFFFF) + (sum shr 16)
}
sum = (sum and 0xFFFF) + (sum shr 16)
return (sum xor 0xFFFF).toShort()
}
companion object {
val TYPE_ICMP_V4: Byte = 8
}
}
If my code is incorrect then I'd expect the same error on all platforms, but as I said it does work on all APIs newer than 22 and I do not know exactly what causes this issue
I have the below code which I am trying to convert to Java.
WORD ComputeCRC16(BYTE *data, DWORD data_length)
{
BYTE *ptr;
BYTEWORD retval;
/* Initialize the CRC */
retval.w = 0xFFFF;
/* Iterate through the data */
for (ptr=data; ptr<data+data_length; ptr++)
{
// retval.w = IterateCRC16(ptr, retval);
retval.w = retval.b.hi ^ (ccittrev_tbl[retval.b.lo ^ *ptr]);
}
/* Finalize the CRC */
retval.w = ~retval.w;
/* Done. */
return retval.w;
}
What does the below line mean?
retval.w = retval.b.hi ^ (ccittrev_tbl[retval.b.lo ^ *ptr]);
retval should be an int if i convert to Java right? If then how can it have a memeber called "w" ? Please advice how I can convert the above line to Java?
I'm editing the question to post this part I had missed.
typedef union
{
WORD w;
struct
{
BYTE lo,
hi;
} b;
} BYTEWORD;
Edited after suggestions :
static int calculate_crc(byte[] data) {
int retval_w = 0x0000;
int ccittrev_tbl[] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
for (byte b : data) {
retval_w = ((retval_w>>8)&0xff) ^ (ccittrev_tbl[(retval_w&0xff) ^ b]);
}
}
According to code I guess the BYTEWORD is a union of unsigned short and structure of two bytes, so the author could easily access high and low byte of this short, i.e.:
typedef union BYTEWORD
{
short w;
struct {
char lo, hi;
} b;
} BYTEWORD;
As java doesn't support unions (and as mentioned in discussion, there are endian flaws with the above), you will have to use >>, | and & operators to access to high and low 8 bits of the short:
short retval_w = -1;
...
retval_w = ((retval_w>>8)&0xff) ^ (ccittrev_tbl[(retval_w&0xff) ^ (data[i]&0xff)]);
The ^ is a binary operator which means Exclusive OR (XOR).
I keep getting the following in the serial monitor over and over:
AcX = -1 | AcY = -1 | AcZ = -1 | Tmp = 36.53 | GyX = -1 | GyY = -1 | GyZ = -1
I am using the following code that I got off http://playground.arduino.cc/Main/MPU-6050#sketch:
// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop(){
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //equation for temperature in degrees C from datasheet
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
delay(333);
}
This is the wiring I am using: http://jamesmpoe.com/roboticswiki/images/4/45/MPU6050-Arduino-Uno-Connections.jpg
I do not know what is wrong.
Thank you for your help.
First of all, I'd set the clock to the X gyroscope oscillator instead of the internal oscillator (as it is suggested on the MPU6050 datasheet), hence
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(1); // set to one to turn on the Xgyro oscillator
Wire.endTransmission(true);
In my project, however, I wrote a lot more initializations... I suggest you to
Write some functions to write/read bit(s), byte(s) and word(s) on the I2C interface, because you'll need them
Write functions to get and set the important parts of the registers in the MPU6050
Write more complex functions.
Examples:
// I2C interface
bool i2c_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data)
{
Wire.beginTransmission(devAddr);
Wire.write((uint8_t) regAddr); // send address
for (uint8_t i = 0; i < length; i++)
{
Wire.write((uint8_t) data[i]);
}
return (Wire.endTransmission() == 0);
}
// Simple function
int16_t mpu6050_getAccelerationX() {
i2c_readBytes(MPU6050_ADDRESS, MPU6050_RA_ACCEL_XOUT_H, 2, rwBuffer);
return (((int16_t)rwBuffer[0]) << 8) | rwBuffer[1];
}
// Complex function
void mpu6050_initialize()
{
mpu6050_reset();
delay(100);
mpu6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
mpu6050_setSleepEnabled(false);
mpu6050_setWakeCycleEnabled(false);
mpu6050_switchSPIEnabled(false);
mpu6050_setI2CMasterModeEnabled(false);
mpu6050_setFIFOEnabled(false);
delay(100);
mpu6050_setRate(7); // 1kHz scan freq
mpu6050_setDLPFMode(MPU6050_DLPF_BW_256);
mpu6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
mpu6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
mpu6050_setInterruptMode(MPU6050_INTMODE_ACTIVEHIGH);
mpu6050_setInterruptDrive(MPU6050_INTDRV_PUSHPULL);
mpu6050_setInterruptLatch(MPU6050_INTLATCH_WAITCLEAR);
mpu6050_setInterruptLatchClear(MPU6050_INTCLEAR_ANYREAD);
mpu6050_setFSyncInterruptEnabled(0);
mpu6050_setI2CBypassEnabled(0);
mpu6050_setClockOutputEnabled(0);
mpu6050_setIntEnabled(MPU6050_INTERRUPT_MASK_DATA_RDY_BIT); // Interrupt when data ready
}
A useful resource is the MPU6050 registers map (you can find it here).
It was a soldering error.
It works perfectly with the code above.
I would like to compute the CRC-16 checksum of a byte array, with 0xA001 polynomial. But I don't really know how to do it in Java, and how the given polynomial is used. Is it some kind of special value (0xA001)? Can you point me to a library that can compute the checksum for me, or point me to some useful resources?
Thanks in advance,
M.
It appears you want the CRC-16-IBM polynomial, x16 + x15 + x2 + 1, reversed (0xA001). A Java implementation of CRC-16 using the CRC-16-CCITT polynomial, x16 + x12 + x5 + 1, may be found here; a corresponding unit test is here. These should get you started in the right direction.
String keeps chars in unicode, so a a little correction on this Princeton implementation would be:
public class CRC16 {
private static final int[] table = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
public static String calcularCRC16(String trama) {
char[] chars = trama.toCharArray();
int crc = 0x0000;
for (char c : chars) {
crc = (crc >>> 8) ^ table[(crc ^ c & 0x00ff) & 0xff];
}
return Integer.toHexString(crc);
}
}
The change consists on working with chars, not bytes, and c & 0x00ff to keep only the relevant data.
A good test can be found on:
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
Your referred implementation is CRC16_ARC.