How to read 19bits out of 3 bytes in Swift? - swift

I have a Data object with 20 bytes that I'm getting from a BLE device.
This is an example when I po the data in the CBCharacteristic:
▿ 20 bytes
- count : 20
▿ pointer : 0x0000000282889ab0
- pointerValue : 10779925168
▿ bytes : 20 elements
- 0 : 16
- 1 : 0
- 2 : 0
- 3 : 21
- 4 : 0
- 5 : 0
- 6 : 20
- 7 : 3
- 8 : 87
- 9 : 154
- 10 : 3
- 11 : 88
- 12 : 204
- 13 : 20
- 14 : 255
- 15 : 197
- 16 : 7
- 17 : 159
- 18 : 56
- 19 : 122
Now I have instructions that tell me that on Byte 1,2,3 there is the signal that I'm looking for as 19 bits (0-524288)
So how can I get that signal value?
I would appreciate reading material on how to get this on my own if necessary. I don't have a proper CS background and I'm lost on how/where to even look for this.
Thank you
EDIT (in response to #Sweeper):
These are instructions for Byte 0
General state / configuration. Contains following bits:
7 (highest) – Error state, reads 0 normally and 1 if any error in hardware side
6 – button pressed (’1’ – button is pressed, ’0’ – button is not pressed)
5 – USB connected (’1’ – USB is connected, ’0’ – USB is not connected)
4 – Charging/charged (’1’ – Charging, ’0’ – not charging)
3 – Gain of channel A. 2 gains (0 is slower, 1 is higher)
2 – Gain of channel B. 2 gains (0 is slower, 1 is higher)
1 – Gain of channel C. 2 gains (0 is slower, 1 is higher)
0 – Gain of channel D. 2 gains (0 is slower, 1 is higher)
And by doing this I can get the expected data for the first byte:
guard let data = characteristic.value else { return }
guard data.count == 20 else { return }
let val = [UInt8](data)
let general:UInt8 = val[0]
let error = general >> 7 & 1
let buttonPressed = general >> 6 & 1
let usbConnected = general >> 5 & 1
let charging = general >> 4 & 1
let gainChannelA = general >> 3 & 1
let gainChannelB = general >> 2 & 1
let gainChannelC = general >> 1 & 1
let gainChannelD = general >> 0 & 1
Does this help in knowing the endianness of the protocol?

Since the data comes from multiple bytes, the answer depends on the endianness implied by the protocol. These 19 bits use two full bytes and three bits in a third byte.
If these three bytes are stored in unsigned 8-bit variables a, b, and c, the value would be either
Int(a) << 11 + Int(b) << 3 + Int(c) & 0x07
or
Int(c) << 11 + Int(b) << 3 + Int(a) & 0x07
values for a b and c would come either from bytes 1, 2, and 3 or bytes 3, 2, 1, depending on the order specified in the protocol.
Note: Expression x & 0x07 means "three lower bits", because 0x07 hex is 00000111 in binary.

Related

Why Int8.max &+ Int8.max equals to "-2"?

Following Swift Standard Library documentation, &+ discards any bits that overflow the fixed width of the integer type. I just did not get why adding two maximum values, 8-bit signed integer can hold results in -2:
/// Two max Int8 values (127 each, 8-bit group)
let x6 = Int8.max
let x7 = Int8.max
/// Prints `1 1 1 1 1 1 1`
String(Int8.max, radix: 2)
/// Here we get `-2` in decimal system
let x8 = x6 &+ x7
/// Prints `-1 0`
String(x8, radix: 2)
If we break down the binary calculation we will get this:
1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1
-----------------------------
1 1 1 1 1 1 1 0
Which is -126, as the leftmost bit is a negative sign.
Why does Swift discards any bits except the rightmost two (1 and 0). Did I miss some overflow rules? I've read some pieces of knowledge in the web, but did not get closed to cracking this one.
Swift (and every other programming language I know) uses 2's complement to represent signed integers, rather than sign-and-magnitude as you seem to assume.
In the 2's complement representation, the leftmost 1 does not represent "a negative sign". You can think of it as representing -128, so the Int8 value of -2 would be represented as 1111 1110 (-128 + 64 + 32 + 16 + 8 + 4 + 2).
OTOH, -126 would be represented as 1000 0010 (-128 + 2).

Hashtable open addressing handling probing cycles

I have been investigating various collision resolution techniques for hashtables implemented via open addressing. However, all the collision resolution methods I have investigated so far (linear probing, quadratic probing, double hashing) have the pitfall that there exists a probing sequence that produces a cycle whose length is less than the size of the table. This becomes problematic when you're trying to insert an element with the open addressing scheme because there are free buckets to insert an entry but they might not be reachable if they're not part of the cycle.
For example, if we're using linear probing on a table of size 12 with the linear function: H(k, i) = (h(k) + 4*i) mod 12 then a cycle would occur if a particular key hashes to 8 and all the slots 0, 4, and 8 are already filled:
H(k, 0) = 8 + 0 mod 12 = 8
H(k, 1) = 8 + 4 mod 12 = 0
H(k, 2) = 8 + 8 mod 12 = 4
H(k, 3) = 8 + 12 mod 12 = 8
H(k, 4) = 8 + 16 mod 12 = 0
H(k, 5) = 8 + 20 mod 12 = 4
H(k, 6) = 8 + 24 mod 12 = 8
...
Similar cycles can also be found with quadratic and double hashing if the probing sequence is bad, so my question then is how are cycles handled? Or do we always pick hash functions/special table sizes which do not permit cycles which are too short?

soft viterbi decoder not working properly

I have been working on viterbi decoder in matlab2009 on simple 1/2 rate convolutional encoder.
Here is my code
trel = poly2trellis(3,[7 5]);
msg = [ 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1 ];
code = convenc(msg,trel);
% Traceback Length
tblen = 5;
ucode = real(awgn(1-2*code,tblen,'measured'));
dcd = vitdec(ucode,trel,tblen,'cont','unquant');
According to this input code
i am getting the code = 00 11 10 00 01 10 01 11 11 10 00 10 11 00 11
which is correct
but talking about the dcd which is output after viterbi decoder is coming incorrect
i.e 000000101110010. which is far different from my msg input.
guide me where i am going incorrect
The decoded output depends on the type of opmode Input you selected.
In case of cont, there is a delay in the output equal to tblen number of symbols whereas there are 'term' and trunc modes as well.
You can compare the initial msg(1,end-tblen) symbols with dcd(1,tblen+1:end). They are same!
You may check vitdec at Matlab help.

Hex Twos Complement Arithmetic

I'm trying to do the following problem:
E8B2035D
-FB60528D
----------
In which, the integers represented are hex representations of 32-bit two's compliment binary numbers. What is the best approach to solve this problem, and detect overflow?
Subtraction becomes addition when you use two's complement. So I would take the complement of the second number, then add them:
As you know, the two's complement of a number starts out by turning every 1 into 0 and vice versa (handy rule of thumb: do 15 - number, so F -> 0, E -> 1, D -> 2, etc):
FB60528D --> 049FAD72
Then add one to the number (in this case, 2 + 1 = 3, and there is no carry):
049FAD73 -- the two's complement of FB60528D
Now we add the numbers, using conventional rules of addition:
E8B2035D
049FAD73 +
----------
D + 3 = 10 : write 0, carry 1
1 + 5 + 7 : write D, carry 0
3 + D = 10 : write 0, carry 1
1 + 0 + A : write B, carry 0
2 + F : write 1, carry 1
1 + B + 9 : write 5, carry 1
1 + 8 + 4 : write D, carry 0
E + 0 : write E
The final result (still in two's complement) is
ED51B0D0
You would detect overflow if the last calculation resulted in a carry (a number > F).

Overflow/underflow in unsigned numbers

So, if you have a carry out of 1 on addition with unsigned numbers, you have overflowed, and if you have a carry out of 0 with subtraction, you have underflowed. Does this work in every case, though?
If you do 5-0:
0101
-0000
=
0101
+(1111 + 1)
=
0101
+0000
= 0101... there is a carry out of zero here, instead of 1. How does one account for this case? Is there a different way to do it?
(using MIPS architecture, or anything else)
---Edit
Thanks Amadan. I understand that part, though. My problem is just that zero seems to be a special case. It does not seem to follow what normal numbers do: in my example above, there is no carry out of 1.
I'm doing circuit design working with an ALU at the moment and trying to implement the overflow detection, when this one case came up that doesn't follow what the others do.
We are assuming that with subtraction, the second operand is preinverted (twos complement) before going into the ALU (then added to the first operand). So, whenever the "invert_b" for subtraction is set to 1, b is inverted and we assume that the case we are checking for is subtraction, which should have a carry out of 1.
I believe the msbit carry out bit on its own covers unsigned and for signed you look to see if the carry in to the msbit and the carry out differ.
5-0 does not overflow because the result fits in the number of bits available. The same way that 15-1 does not overflow a 4 bit system for signed numbers
5 - 0 = 0101 + 1111 + 1
1
0101
+1111
=====
11111
0101
+1111
=====
0101
so 5 - 0 certainly carries out a 1, since this is a subtract that is not an overflow
15 - 1 = 1111 + ~1 with the carry in set
1
1111
1110
====
11111
1111
1110
====
1110
a subtract with a 1 out is not an unsigned overflow as you stated
Likewise -1 - 1 = 1111 + ~1 with the carry in bit set
11111
1111
1110
====
1110
the carry in to the last bit is a 1 the carry out is a 1 they match, no signed overflow.
8 + 8 = 1000 + 1000 with the carry in clear
0
1000
+1000
=====
10000
1000
+1000
=====
0000
unsigned overflow.
hmmm 4 + 4
0
0100
+0100
=====
01000
0100
+0100
=====
1000
unsigned add the carry out is 0 this is not an unsigned overflow. but this is a signed overflow because the carry in to the msbit and carry out differ. +4 + +4 = +8, in a 4 bit signed system you cannot represent +8, so the signed overflow is accurate.
No matter how many bits the weird numbers are all zeros and a one and the rest zeros, 0 and 8 or -8 for a 4 bit system.
Make a chart either with 2, 3, or 4 bit numbers all combinations and manually look through all of them to see that they make sense. whatever you find will scale no matter how many bits wide, a 100 bit adder works like a 10 bit adder...
add C V unsigned signed
00 + 00 = 000 0 0 0 + 0 = 0 0 + 0 = 0
00 + 01 = 001 0 0 0 + 1 = 1 0 + 1 = 1
00 + 10 = 010 0 0 0 + 2 = 2 0 + -2 = -2
00 + 11 = 011 0 0 0 + 3 = 3 0 + -1 = -1
01 + 00 = 001 0 0 1 + 0 = 1 1 + 0 = 1
01 + 01 = 010 0 1 1 + 1 = 2 1 + 1 = 2 signed cannot represent a +2
01 + 10 = 011 0 0 1 + 2 = 3 1 + -2 = -1
01 + 11 = 100 1 0 1 + 3 = 4 1 + -1 = 0 unsigned cannot represent +4
10 + 00 = 010 0 0 2 + 0 = 2 -2 + 0 = -2
10 + 01 = 011 0 0 2 + 1 = 3 -2 + 1 = -1
10 + 10 = 100 1 1 2 + 2 = 4 -2 + -2 = -4 neither +4 nor -4 will fit in 2 bits
10 + 11 = 101 1 1 2 + 3 = 5 -2 + -1 = -3 neither +4 nor -3 will fit in 2 bits
11 + 00 = 011 0 0 3 + 0 = 3 -1 + 0 = -1
11 + 01 = 100 1 0 3 + 1 = 4 -1 + 1 = -2 +4 does not fit in 2 bits
11 + 10 = 101 1 1 3 + 2 = 5 -1 + -2 = -3 neither +5 nor -3 fit in 2 bits
11 + 11 = 110 1 0 3 + 3 = 6 -1 + -1 = -2 6 does not fit in 2 bits
sub
00 - 00 = 100 0 0
00 - 01 = 011 1 0 0 - 1 = -1 -1 does not fit in an unsigned result
00 - 10 = 010 1 1 0 - 2 = -2 0 - -2 = +2
00 - 11 = 001 1 0 0 - 3 = -3
01 - 00 = 101 0 0
01 - 01 = 100 0 0
01 - 10 = 011 1 1 1 - 2 = -1 1 - -2 = 3
01 - 11 = 010 1 1 1 - 3 = -2 1 - -1 = 2
10 - 00 = 110 0 0
10 - 01 = 101 0 1 -2 - 1 = -3
10 - 10 = 100 0 0
10 - 11 = 011 1 0 2 - 3 = -1
11 - 00 = 111 0 0
11 - 01 = 110 0 0
11 - 10 = 101 0 0
11 - 11 = 100 0 0
The code that generated the above
printf("add\n");
for(ra=0;ra<4;ra++)
{
for(rb=0;rb<4;rb++)
{
rd=(ra&1)+(rb&1);
rc=ra+rb;
rd=(rd>>1)&1;
re=(rc>>2)&1;
if(re) c=1; else c=0;
if(rd!=re) v=1; else v=0;
if(ra&2) printf("1"); else printf("0");
if(ra&1) printf("1"); else printf("0");
printf(" + ");
if(rb&2) printf("1"); else printf("0");
if(rb&1) printf("1"); else printf("0");
printf(" = ");
if(rc&4) printf("1"); else printf("0");
if(rc&2) printf("1"); else printf("0");
if(rc&1) printf("1"); else printf("0");
printf(" %u %u\n",c,v);
}
}
printf("sub\n");
for(ra=0;ra<4;ra++)
{
for(rb=0;rb<4;rb++)
{
rd=(ra&1)+((~rb)&1)+1;
rc=ra+((~rb)&3)+1;
rd=(rd>>1)&1;
re=(rc>>2)&1;
if(re) c=0; else c=1;
if(rd!=re) v=1; else v=0;
if(ra&2) printf("1"); else printf("0");
if(ra&1) printf("1"); else printf("0");
printf(" - ");
if(rb&2) printf("1"); else printf("0");
if(rb&1) printf("1"); else printf("0");
printf(" = ");
if(rc&4) printf("1"); else printf("0");
if(rc&2) printf("1"); else printf("0");
if(rc&1) printf("1"); else printf("0");
printf(" %u %u\n",c,v);
}
}
Now your question was talking about unsigned numbers yes? so you may not care about the V bit nor the right half, the signed half.
Here is some HDL/RTL for a small 16 bit processor I implemented:
case 4b0000:
{
//0000 add rd,rs
op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
op_res = op_a + op_b;
reg[1].value[CBIT] <= op_res[16];
reg[1].value[NBIT] <= op_res[15];
if(op_res[16;0] == 16h0000)
{
reg[1].value[ZBIT] <= 1b1;
}
else
{
reg[1].value[ZBIT] <= 1b0;
}
if((op_a[15] == op_b[15]) && (op_res[15] != op_b[15] ) )
{
reg[1].value[VBIT] <= 1b1;
}
else
{
reg[1].value[VBIT] <= 1b0;
}
reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
case 4b0001:
{
//0001 sub rd,rs
op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
op_res = op_a - op_b;
reg[1].value[CBIT] <= (~op_res[16]);
reg[1].value[NBIT] <= op_res[15];
if(op_res[16;0] == 16h0000)
{
reg[1].value[ZBIT] <= 1b1;
}
else
{
reg[1].value[ZBIT] <= 1b0;
}
if((op_a[15] != op_b[15]) && (op_res[15] == op_b[15] ) )
{
reg[1].value[VBIT] <= 1b1;
}
else
{
reg[1].value[VBIT] <= 1b0;
}
reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
I have/had seen the msbit thing for signed overflow in other logic and couldnt find a case where it didnt match the carry in vs carry out method when trying every possible combination in a head to head analysis.
If I went overboard with the answer I dont mind clipping it off at the beginning where it shows that 5 - 0 has a 1 as a carry out of 1, which for a subtract is not an overflow. The long answer because it can be hard to wrap your head around signed vs unsigned and how the adder works in logic in general. The adder does not know or care about signed or unsigned, it does care about add vs subtract, with subtract you invert the second operand, invert the carry in to the lsbit and the carry out of the msbit (think about add, add with carry, sub and sub with carry). The signed vs unsigned takes care if itself (the beauty of twos complement). Reducing the above to an unsigned only discussion makes it more than half as simple as the signed overflow is not (as) obvious (as unsigned overflow) to the casual observer.
I sure hope I cut and pasted the debugged HDL , will get a lot of responses/corrections if I didnt...I spent a few days convincing myself of all of the above and comparing to the results of other processors I had access to, etc. Hopefully this saves you a few days.
Not an expert, but the whole statement on subtraction seems wrong.
You can implement subtraction in two basic ways: directly as subtraction, or as addition of two's complement.
If you go with two's complement addition, then it is as you say: carry of 1 is underflow.
5 - 6
= 0101 - 0110
= 0101 + (1001 + 1)
= 0101 + 1010
= (0)1111, carry 0 = underflow
If you subtract directly, then 1 carry is underflow:
0101 - 0110:
0 to 1 is 1
1 to (1)0 is 1, carry 1
1 + 1 to (1)1 is 1, carry 1
0 + 1 to (1)0 is 1, carry 1 = underflow
There may be other equivalent ways of designing overflow detection units for adders, but the most common is Cin XOR Cout. For example, see the end of lecture 4 http://cs.nyu.edu/~gottlieb/courses/2007-08-fall/arch/class-notes.html
It simply checks if the numbers being added (if something is inverted for 2's complement or not doesn't matter, we look at these values afterwards) carry in to the last digit's calculation but not into the digit beyond the supported bit-size, or the opposite.
This makes sense because if they carry in and not out the result must be negative (since the MSB must be 1) but the operands must be positive (since if they were negative there would be carry out). This is the definition of overflow, since two positives cannot sum to a negative.
This is a signed model however, I'm not sure if that's what you're looking for since you mentioned unsigned. If that's the case, then you're right, the simple addition model has overflow when carry out is 1 (this is equivalent to the above if you consider the addition to have an extra 0 for each operands' MSB, then the carry out will always be 0 and there's overflow iff the carry in is 1. The carry in in this case is the carry out in our model).
Subtraction results in underflow if the value is negative. We can again derive an equivalence if we consider the positive operand to have an appended MSB of 0 and the negative operand one of 1 (sign extension). Then we are negative when the MSB of the result is 1. This happens iff the carry out in our original model (the carry in in the new model) is 0, since only then will the MSB of the result in the new model remain 1.
You example is no exception: 0101 + 1111 + 1 = 0101 with a carry out of 1, and therefore no underflow, since the result is positive.