iOS:CRC in obj c - objective-c

i am new to iOS i need to create data packet by using CRC algorithm for the below commands
int comm[6];
comm[0]=0x01;
comm[1]=6;
comm[2]=0x70;
comm[3]=0x00;
comm[4]=0xFFFF;
comm[5]=0xFFFF;
i had a java code which as same thing developing in android
byte[] getCRC(byte[] bytes)
{
byte[] result = new byte[2];
try
{
short crc = (short) 0xFFFF;
for (int j = 0; j < bytes.length; j++)
{
byte c = bytes[j];
for (int i = 7; i >= 0; i--)
{
boolean c15 = ((crc >> 15 & 1) == 1)
boolean bit = ((c >> (7 - i) & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
{
crc ^= 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
}
}
}
int crc2 = crc - 0xffff0000;
result[0] = (byte) (crc2 % 256);
result[1] = (byte) (crc2 / 256);
return result;
}
catch(Exception ex)
{
result = null;
return result;
}
}
Input for getCRC() method: The data packet for which CRC is to be calculated.
Output of getCRC() method: CRC for the packet.
The same thing i need to do in obj c please help if any sample code available also.

Objective-C also incorporates C, so the contents of your method will look almost the same as in Java. All that is needed is to pass your data into and out of the method, in this example using NSData:
- (NSData *)bytesCRCResult:(NSData *)dataBytes
{
unsigned char *result = (unsigned char *)malloc(2);
unsigned char *bytes = (unsigned char *)[dataBytes bytes]; // returns readonly pointer to the byte stream
uint16_t crc = (short) 0xFFFF;
for (int j = 0; j < dataBytes.length; j++)
{
unsigned char c = bytes[j];
for (int i = 7; i >= 0; i--)
{
bool c15 = ((crc >> 15 & 1) == 1);
bool bit = ((c >> (7 - i) & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
{
crc ^= 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
}
}
}
uint16_t crc2 = crc - 0xffff0000;
result[0] = (unsigned char) (crc2 % 256);
result[1] = (unsigned char) (crc2 / 256);
NSData *resultsToData = [NSData dataWithBytes:result length:2];
free(result);
return resultsToData;
}
NSData can be read as raw bytes using the [NSData bytes] method call, and has a range of useful properties and methods.
For the boolean value, you have a few options:
"bool" seems to be the ISO C/C++ standard type
"Boolean" is defined as "typedef unsigned char"
"boolean_t" is defined as "typedef unsigned int" or "typedef int", depending on 64-bit compilation apparently
"BOOL", the Objective-C bool, which is defined as "typedef signed char", according to http://nshipster.com/bool/ and might therefore not behave as expected.
"uint8_t" can be substituted for "unsigned char", for clarity.
Please note: The above code compiles without warning or complaint, but wasn't tested with actual data.

Related

How to return generated array from c function to objective-c

Need to generated some random 10 byte length string in c function and call the function from objective-c. So, I'm creating a pointer to uint8_t and passing it to C function. The function generates random bytes and assigns them to *randomString. However, after returning from function to objective-c randomValue pointer points to NULL.
Here's my random function in C:
void randomString(uint8_t *randomString)
{
randomString = malloc(10);
char randomByte;
char i;
for (i = 0; i < 10; i++) {
srand((unsigned)time(NULL));
randomByte = (rand() % 255 ) + 1;
*randomString = randomByte;
randomString++;
}
}
Here's objective-c part:
uint8_t *randomValue = NULL;
randomString(randomValue); //randomValue points to 0x000000
NSString *randomString = [[NSString alloc] initWithBytes:randomValue length:10 encoding:NSASCIIStringEncoding];
NSLog(#"Random string: %#", randomString);
A more natural semantic, like malloc() itself would be:
uint8_t * randomString()
{
uint8_t *randomString = malloc(10);
srand((unsigned)time(NULL));
for (unsigned i = 0; i < 10; i++)
randomString[i] = (rand() % 254) + 1;
return randomString;
}
Pointers are passed by value, so randomValue will remain NULL after the call of randomString. You need to pass a pointer to a pointer in order to make it work:
void randomString(uint8_t **randomString) {
*randomString = malloc(10);
// ... the rest of your code goes here, with an extra level of indirection
}
uint8_t *randomValue = NULL;
randomString(&randomValue);
You probably should be using uint8_t **randomeValue instead of uint8_t *.

De-interleave and interleave buffer with vDSP_ctoz() and vDSP_ztoz()?

How do I de-interleave the float *newAudio into float *channel1 and float* channel2 and interleave it back into newAudio?
Novocaine *audioManager = [Novocaine audioManager];
__block float *channel1;
__block float *channel2;
[audioManager setInputBlock:^(float *newAudio, UInt32 numSamples, UInt32 numChannels) {
// Audio comes in interleaved, so,
// if numChannels = 2, newAudio[0] is channel 1, newAudio[1] is channel 2, newAudio[2] is channel 1, etc.
// Deinterleave with vDSP_ctoz()/vDSP_ztoz(); and fill channel1 and channel2
// ... processing on channel1 & channel2
// Interleave channel1 and channel2 with vDSP_ctoz()/vDSP_ztoz(); to newAudio
}];
What would these two lines of code look like? I don't understand the syntax of ctoz/ztoz.
What I do in Novocaine's accessory classes, like the Ringbuffer, for de-interleaving:
float zero = 0.0;
vDSP_vsadd(data, numChannels, &zero, leftSampleData, 1, numFrames);
vDSP_vsadd(data+1, numChannels, &zero, rightSampleData, 1, numFrames);
for interleaving:
float zero = 0.0;
vDSP_vsadd(leftSampleData, 1, &zero, data, numChannels, numFrames);
vDSP_vsadd(rightSampleData, 1, &zero, data+1, numChannels, numFrames);
The more general way to do things is to have an array of arrays, like
int maxNumChannels = 2;
int maxNumFrames = 1024;
float **arrays = (float **)calloc(maxNumChannels, sizeof(float *));
for (int i=0; i < maxNumChannels; ++i) {
arrays[i] = (float *)calloc(maxNumFrames, sizeof(float));
}
[[Novocaine audioManager] setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
float zero = 0.0;
for (int iChannel = 0; iChannel < numChannels; ++iChannel) {
vDSP_vsadd(data, numChannels, &zero, arrays[iChannel], 1, numFrames);
}
}];
which is what I use internally a lot in the RingBuffer accessory classes for Novocaine. I timed the speed of vDSP_vsadd versus memcpy, and (very, very surprisingly), there's no speed difference.
Of course, you can always just use a ring buffer, and save yourself the hassle
#import "RingBuffer.h"
int maxNumFrames = 4096
int maxNumChannels = 2
RingBuffer *ringBuffer = new RingBuffer(maxNumFrames, maxNumChannels)
[[Novocaine audioManager] setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels);
}];
[[Novocaine audioManager] setOuputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {
ringBuffer->FetchInterleavedData(data, numFrames, numChannels);
}];
Hope that helps.
Here is an example:
#include <Accelerate/Accelerate.h>
int main(int argc, const char * argv[])
{
// Bogus interleaved stereo data
float stereoInput [1024];
for(int i = 0; i < 1024; ++i)
stereoInput[i] = (float)i;
// Buffers to hold the deinterleaved data
float leftSampleData [1024 / 2];
float rightSampleData [1024 / 2];
DSPSplitComplex output = {
.realp = leftSampleData,
.imagp = rightSampleData
};
// Split the data. The left (even) samples will end up in leftSampleData, and the right (odd) will end up in rightSampleData
vDSP_ctoz((const DSPComplex *)stereoInput, 2, &output, 1, 1024 / 2);
// Print the result for verification
for(int i = 0; i < 512; ++i)
printf("%d: %f + %f\n", i, leftSampleData[i], rightSampleData[i]);
return 0;
}
sbooth answers how to de-interleave using vDSP_ctoz. Here's the complementary operation, namely interleaving using vDSP_ztoc.
#include <stdio.h>
#include <Accelerate/Accelerate.h>
int main(int argc, const char * argv[])
{
const int NUM_FRAMES = 16;
const int NUM_CHANNELS = 2;
// Buffers for left/right channels
float xL[NUM_FRAMES];
float xR[NUM_FRAMES];
// Initialize with some identifiable data
for (int i = 0; i < NUM_FRAMES; i++)
{
xL[i] = 2*i; // Even
xR[i] = 2*i+1; // Odd
}
// Buffer for interleaved data
float stereo[NUM_CHANNELS*NUM_FRAMES];
vDSP_vclr(stereo, 1, NUM_CHANNELS*NUM_FRAMES);
// Interleave - take separate left & right buffers, and combine into
// single buffer alternating left/right/left/right, etc.
DSPSplitComplex x = {xL, xR};
vDSP_ztoc(&x, 1, (DSPComplex*)stereo, 2, NUM_FRAMES);
// Print the result for verification. Should give output like
// i: L, R
// 0: 0.00, 1.00
// 1: 2.00, 3.00
// etc...
printf(" i: L, R\n");
for (int i = 0; i < NUM_FRAMES; i++)
{
printf("%2d: %5.2f, %5.2f\n", i, stereo[2*i], stereo[2*i+1]);
}
return 0;
}

What's wrong with my CRC-12 implementation?

This is what I have so far, but it doesn't seem to match http://zorc.breitbandkatze.de/crc.html all the time.
short crcTable[256];
for (int i = 0; i < 256; i++) {
int crc = (i << 4);
for (int j = 0; j < 8; j++) {
crc = (crc << 1) ^ ((crc & 0x800) ? 0x80F : 0);
}
crcTable[i] = crc & 0xFFF;
}
NSString *theString = #"blah";
unsigned char *string = (unsigned char *)[theString UTF8String];
int length = [theString length];
unsigned short crc = 0;
for (int i = 0; i < length; i++) {
crc = crcTable[(crc ^ string[i]) & 255] ^ (crc >> 8);
}
NSLog(#"%X", crc);
One of our implementations is incorrect, I'm assuming it's mine. But I have no idea what's wrong, or really how to go about working out what's wrong. Any help'd be much appreciated.
Alec
1 Replace
crc = crcTable[(crc ^ string[i]) & 255] ^ (crc >> 8);
by
crc = crcTable[(crc >> 4) ^ string[i]] ^ (crc << 8);
2 Do mirror the 8 bits of each of the message's bytes before using them to calculate the crc value.
3 Finally mirror the 12 bits of the final crc.
As an alternative to the last mod you could also just do a crc & 0xfff and tell the breitbandkatze to 'reverse data bytes'.
You will want to double check, but it appears you are building your table with big-endian code and calculating your CRC with little-endian code.
Try replacing this:
crc = crcTable[(crc ^ string[i]) & 255] ^ (crc >> 8);
with this:
crc = crc ^ (string[i] << 4);
crc = (crcTable[(crc >> 4) & 0xFF] ^ (crc << 4)) & 0xFFF;
-Jesse

Converting int to bytes and switching endian efficiently

I have to do some int -> byte conversion and switch to big endian for some MIDI data I'm writing. Right now, I'm doing it like:
int tempo = 500000;
char* a = (char*)&tempo;
//reverse it
inverse(a, 3);
[myMutableData appendBytes:a length:3];
and the inverse function:
void inverse(char inver_a[],int j)
{
int i,temp;
j--;
for(i=0;i<(j/2);i++)
{
temp=inver_a[i];
inver_a[i]=inver_a[j];
inver_a[j]=temp;
j--;
}
}
It works, but it's not real clean, and I don't like that I'm having to specify 3 both times (since I have the luxury of knowing how many bytes it will end up).
Is there a more convenient way I should be approaching this?
Use the Core Foundation byte swapping functions.
int32_t unswapped = 0x12345678;
int32_t swapped = CFSwapInt32HostToBig(unswapped);
char* a = (char*) &swapped;
[myMutableData appendBytes:a length:sizeof(int32_t)];
This should do the trick:
/*
Quick swap of Endian.
*/
#include <stdio.h>
int main(){
unsigned int number = 0x04030201;
char *p1, *p2;
int i;
p1 = (char *) &number;
p2 = (p1 + 3);
for (i=0; i<2; i++){
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return 0;
}
You can pack it into a function in whatever way you want to use it. The bitwise swap should compile into some pretty neat assembly :)
Hope it helps :)
int tempo = 500000;
//reverse it
inverse(&tempo);
[myMutableData appendBytes:(char*)tempo length:sizeof(tempo)];
and the inverse function:
void inverse(int *value)
{
char inver_a = (char*)value;
int j = sizeof(*value); //or u can put 2
int i,temp;
// commenting this j--;
for(i=0;i<(j/2);i++)
{
temp=inver_a[i];
inver_a[i]=inver_a[j];
inver_a[j]=temp;
j--;
}
}

Convert Bytes to short or integer

I do have the following code that read in from a socket:
Int8 buffer[102400];
UInt8 *buffer_p = buffer;;
int bytesRead;
bytesRead = CFReadStreamRead(stream, buffer, 102400);
The message i am expecting begin with short(2 bytes) short(2 bytes) integer(4 bytes).
I am not sure how to convert them to the corresponding types.
I tried the following:
uint16_t zero16 = NTOHS(buffer_p);
buffer_p += sizeof(uint16_t);
uint16_t msg_id16 = NTOHS(buffer_p);
buffer_p += sizeof(uint16_t);
uint32_t length32 = NTOHL(buffer_p);
buffer_p += sizeof(uint32_t);
or
NSMutableData *data = [NSMutableData dataWithBytes:buffer length:bytesRead];
NSRange firstshort = {0,2};
NSRange secondshort = {2,2};
NSRange intrange = {4,4};
short zero;
[data getBytes:&zero range:firstshort];
short msgid;
[data getBytes:&msgid range:secondshort];
int length;
[data getBytes:&length range:intrange];
But non is working. Thanks in advance.
You may want to look at OSByteOrder.h. This defines a bunch of macros that can be used to read various integer types or to do byte-swapping. Specifically, you could do something like
uint16_t zero16 = OSReadBigInt16(buffer_p, 0);
uint16_t msg_id16 = OSReadBigInt16(buffer_p, 2);
uint32_t length32 = OSReadBigInt32(buffer_p, 4);