I am trying to display 4 separate digits on my 7 segment display. These numbers are made from a program and Processing receives a number like 9561, and through math, I isolate 9 5 6 1 into individual digits.
since a single digit is 4 bits, I use an integer to sequentially compress the numbers, which in it's full decimal form appears to be 5721. I then send this integer to the Arduino, where I have 2 bytes sequencially running Serial.read();
My issue is that my 7 segment 4 digit display only displays 9500 meaning that x2 is 00 meaning that the 61 get lost in translation.
Even more so, when I speed up time (t) or the time for multiplexing, the 95 will flash over 00 and I confirmed it when I made seg0 and seg1 of the array 0 and 0.
When t = 3 this occurs, but anything higher than say, 8 doesn't have this issue.
I should also mention in my switch() the default case displays a 0.
Processing
void draw()
{
seg[0] = 9;
seg[1] = 5;
seg[2] = 6;
seg[3] = 1;
int x = (seg[pos+3] & 0x000f)<<12|((seg[pos+2]) & 0x000f)<<8|(seg[pos+1] & 0x000f )<<4|((seg[pos] & 0x000f)); //3210
myPort.write(x);
//0123
int disp1 = x;
int disp2 = (x & 0x00f0)>>4;
int disp3 = (x & 0x0f00)>>8;
int disp4 = (x & 0xf000)>>12;
//0123
print(disp1, '\n', disp2, '\n', disp3, '\n', disp4, '\n', '\n');
}
Arduino (Relevant areas, its a lot of code
void digitdisplay(byte x,byte x2)
{
//unsigned char tn = int (num/1000);
//if (tn>10)
//{
// tn = tn - 10;
//}
//
//unsigned char hn = int (num/100)%10;
//unsigned char tenn = int (num/10)%10;
//unsigned char on = int (num%10);
int disp[4];
disp[0] = ( x & 0x0f);
disp[1] = ( x & 0xf0)>>4;
disp[2] = ( x2 & 0x0f);
disp[3] = ( x2 & 0xf0)>>4;
numberselect(disp[0]);
digitselect(1);
delay(t);
numberselect(disp[1]);
digitselect(2);
delay(t);
numberselect(disp[2]);
digitselect(3);
delay(t);
numberselect(disp[3]);
digitselect(4);
delay(t);
}
void loop()
{
int sen = analogRead(A0);
int maxrange = (sen*maxval);
byte x,x2;
if (Serial.available()>2)
{ // If data is available to read,
x=Serial.read();
x2=Serial.read();
}
//shiftlight(maxrange);
digitdisplay(x,x2);
}
Supposing that myPort is an OutputStream, your one invocation of myPort.write(int) writes just one byte, extracted from the lowest-order 8 bits of its argument. The higher-order bits are lost. That's why you're seeing only the 9 and 5.
I cannot explain from the code presented why you display 9500 instead of 9595, but that seems consistent with your claim that at higher update rates you see the 95 alternating with 00. Both lead me to think that some other part of your code is writing zeroes to the serial port.
Java's String representation is UTF-16. That means that each character is represented by 2 bytes. For ASCII-letters one of them is 0x00. This could be the reason why you don't get the 61 out of the stream at the expected position.
You can either skip each second byte on the Arduino or convert the characters to plain ASCII before sending using getBytes(Charset charset) https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html
Related
If I have a char array A, I use it to store hex
A = "0A F5 6D 02" size=11
The binary representation of this char array is:
00001010 11110101 01101101 00000010
I want to ask is there any function can random flip the bit?
That is:
if the parameter is 5
00001010 11110101 01101101 00000010
-->
10001110 11110001 01101001 00100010
it will random choose 5 bit to flip.
I am trying make this hex data to binary data and use bitmask method to achieve my requirement. Then turn it back to hex. I am curious is there any method to do this job more quickly?
Sorry, my question description is not clear enough. In simply, I have some hex data, and I want to simulate bit error in these data. For example, if I have 5 byte hex data:
"FF00FF00FF"
binary representation is
"1111111100000000111111110000000011111111"
If the bit error rate is 10%. Then I want to make these 40 bits have 4 bits error. One extreme random result: error happened in the first 4 bit:
"0000111100000000111111110000000011111111"
First of all, find out which char the bit represents:
param is your bit to flip...
char *byteToWrite = &A[sizeof(A) - (param / 8) - 1];
So that will give you a pointer to the char at that array offset (-1 for 0 array offset vs size)
Then get modulus (or more bit shifting if you're feeling adventurous) to find out which bit in here to flip:
*byteToWrite ^= (1u << param % 8);
So that should result for a param of 5 for the byte at A[10] to have its 5th bit toggled.
store the values of 2^n in an array
generate a random number seed
loop through x times (in this case 5) and go data ^= stored_values[random_num]
Alternatively to storing the 2^n values in an array, you could do some bit shifting to a random power of 2 like:
data ^= (1<<random%7)
Reflecting the first comment, you really could just write out that line 5 times in your function and avoid the overhead of a for loop entirely.
You have 32 bit number. You can treate the bits as parts of hte number and just xor this number with some random 5-bits-on number.
int count_1s(int )
{
int m = 0x55555555;
int r = (foo&m) + ((foo>>>1)&m);
m = 0x33333333;
r = (r&m) + ((r>>>2)&m);
m = 0x0F0F0F0F;
r = (r&m) + ((r>>>4)&m);
m = 0x00FF00FF;
r = (r&m) + ((r>>>8)&m);
m = 0x0000FFFF;
return r = (r&m) + ((r>>>16)&m);
}
void main()
{
char input[] = "0A F5 6D 02";
char data[4] = {};
scanf("%2x %2x %2x %2x", &data[0], &data[1], &data[2], &data[3]);
int *x = reinterpret_cast<int*>(data);
int y = rand();
while(count_1s(y) != 5)
{
y = rand(); // let's have this more random
}
*x ^= y;
printf("%2x %2x %2x %2x" data[0], data[1], data[2], data[3]);
return 0;
}
I see no reason to convert the entire string back and forth from and to hex notation. Just pick a random character out of the hex string, convert this to a digit, change it a bit, convert back to hex character.
In plain C:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main (void)
{
char *hexToDec_lookup = "0123456789ABCDEF";
char hexstr[] = "0A F5 6D 02";
/* 0. make sure we're fairly random */
srand(time(0));
/* 1. loop 5 times .. */
int i;
for (i=0; i<5; i++)
{
/* 2. pick a random hex digit
we know it's one out of 8, grouped per 2 */
int hexdigit = rand() & 7;
hexdigit += (hexdigit>>1);
/* 3. convert the digit to binary */
int hexvalue = hexstr[hexdigit] > '9' ? hexstr[hexdigit] - 'A'+10 : hexstr[hexdigit]-'0';
/* 4. flip a random bit */
hexvalue ^= 1 << (rand() & 3);
/* 5. write it back into position */
hexstr[hexdigit] = hexToDec_lookup[hexvalue];
printf ("[%s]\n", hexstr);
}
return 0;
}
It might even be possible to omit the convert-to-and-from-ASCII steps -- flip a bit in the character string, check if it's still a valid hex digit and if necessary, adjust.
First randomly chose x positions (each position consist of array index and the bit position).
Now if you want to flip ith bit from right for a number n. Find the remainder of n by 2n as :
code:
int divisor = (2,i);
int remainder = n % divisor;
int quotient = n / divisor;
remainder = (remainder == 0) ? 1 : 0; // flip the remainder or the i th bit from right.
n = divisor * quotient + remainder;
Take mod 8 of input(5%8)
Shift 0x80 to right by input value (e.g 5)
XOR this value with (input/8)th element of your character array.
code:
void flip_bit(int bit)
{
Array[bit/8] ^= (0x80>>(bit%8));
}
I have a vector<char> and I want to be able to get an unsigned integer from a range of bits within the vector. E.g.
And I can't seem to be able to write the correct operations to get the desired output. My intended algorithm goes like this:
& the first byte with (0xff >> unused bits in byte on the left)
<< the result left the number of output bytes * number of bits in a byte
| this with the final output
For each subsequent byte:
<< left by the (byte width - index) * bits per byte
| this byte with the final output
| the final byte (not shifted) with the final output
>> the final output by the number of unused bits in the byte on the right
And here is my attempt at coding it, which does not give the correct result:
#include <vector>
#include <iostream>
#include <cstdint>
#include <bitset>
template<class byte_type = char>
class BitValues {
private:
std::vector<byte_type> bytes;
public:
static const auto bits_per_byte = 8;
BitValues(std::vector<byte_type> bytes) : bytes(bytes) {
}
template<class return_type>
return_type get_bits(int start, int end) {
auto byte_start = (start - (start % bits_per_byte)) / bits_per_byte;
auto byte_end = (end - (end % bits_per_byte)) / bits_per_byte;
auto byte_width = byte_end - byte_start;
return_type value = 0;
unsigned char first = bytes[byte_start];
first &= (0xff >> start % 8);
return_type first_wide = first;
first_wide <<= byte_width;
value |= first_wide;
for(auto byte_i = byte_start + 1; byte_i <= byte_end; byte_i++) {
auto byte_offset = (byte_width - byte_i) * bits_per_byte;
unsigned char next_thin = bytes[byte_i];
return_type next_byte = next_thin;
next_byte <<= byte_offset;
value |= next_byte;
}
value >>= (((byte_end + 1) * bits_per_byte) - end) % bits_per_byte;
return value;
}
};
int main() {
BitValues<char> bits(std::vector<char>({'\x78', '\xDA', '\x05', '\x5F', '\x8A', '\xF1', '\x0F', '\xA0'}));
std::cout << bits.get_bits<unsigned>(15, 29) << "\n";
return 0;
}
(In action: http://coliru.stacked-crooked.com/a/261d32875fcf2dc0)
I just can't seem to wrap my head around these bit manipulations, and I find debugging very difficult! If anyone can correct the above code, or help me in any way, it would be much appreciated!
Edit:
My bytes are 8 bits long
The integer to return could be 8,16,32 or 64 bits wside
The integer is stored in big endian
You made two primary mistakes. The first is here:
first_wide <<= byte_width;
You should be shifting by a bit count, not a byte count. Corrected code is:
first_wide <<= byte_width * bits_per_byte;
The second mistake is here:
auto byte_offset = (byte_width - byte_i) * bits_per_byte;
It should be
auto byte_offset = (byte_end - byte_i) * bits_per_byte;
The value in parenthesis needs to be the number of bytes to shift right by, which is also the number of bytes byte_i is away from the end. The value byte_width - byte_i has no semantic meaning (one is a delta, the other is an index)
The rest of the code is fine. Though, this algorithm has two issues with it.
First, when using your result type to accumulate bits, you assume you have room on the left to spare. This isn't the case if there are set bits near the right boundry and the choice of range causes the bits to be shifted out. For example, try running
bits.get_bits<uint16_t>(11, 27);
You'll get the result 42 which corresponds to the bit string 00000000 00101010 The correct result is 53290 with the bit string 11010000 00101010. Notice how the rightmost 4 bits got zeroed out. This is because you start off by overshifting your value variable, causing those four bits to be shifted out of the variable. When shifting back at the end, this results in the bits being zeroed out.
The second problem has to do with the right shift at the end. If the rightmost bit of the value variable happens to be a 1 before the right shift at the end, and the template parameter is a signed type, then the right shift that is done is an 'arithmetic' right shift, which causes bits on the right to be 1-filled, leaving you with an incorrect negative value.
Example, try running:
bits.get_bits<int16_t>(5, 21);
The expected result should be 6976 with the bit string 00011011 01000000, but the current implementation returns -1216 with the bit string 11111011 01000000.
I've put my implementation of this below which builds the bit string from the right to the left, placing bits in their correct positions to start with so that the above two problems are avoided:
template<class ReturnType>
ReturnType get_bits(int start, int end) {
int max_bits = kBitsPerByte * sizeof(ReturnType);
if (end - start > max_bits) {
start = end - max_bits;
}
int inclusive_end = end - 1;
int byte_start = start / kBitsPerByte;
int byte_end = inclusive_end / kBitsPerByte;
// Put in the partial-byte on the right
uint8_t first = bytes_[byte_end];
int bit_offset = (inclusive_end % kBitsPerByte);
first >>= 7 - bit_offset;
bit_offset += 1;
ReturnType ret = 0 | first;
// Add the rest of the bytes
for (int i = byte_end - 1; i >= byte_start; i--) {
ReturnType tmp = (uint8_t) bytes_[i];
tmp <<= bit_offset;
ret |= tmp;
bit_offset += kBitsPerByte;
}
// Mask out the partial byte on the left
int shift_amt = (end - start);
if (shift_amt < max_bits) {
ReturnType mask = (1 << shift_amt) - 1;
ret &= mask;
}
}
There is one thing you certainly missed I think: the way you index the bits in the vector is different from what you have been given in the problem. I.e. with algorithm you outlined, the order of the bits will be like 7 6 5 4 3 2 1 0 | 15 14 13 12 11 10 9 8 | 23 22 21 .... Frankly, I didn't read through your whole algorithm, but this one was missed in the very first step.
Interesting problem. I've done similar, for some systems work.
Your char is 8 bits wide? Or 16? How big is your integer? 32 or 64?
Ignore the vector complexity for a minute.
Think about it as just an array of bits.
How many bits do you have? You have 8*number of chars
You need to calculate a starting char, number of bits to extract, ending char, number of bits there, and number of chars in the middle.
You will need bitwise-and & for the first partial char
you will need bitwise-and & for the last partial char
you will need left-shift << (or right-shift >>), depending upon which order you start from
what is the endian-ness of your Integer?
At some point you will calculate an index into your array that is bitindex/char_bit_width, you gave the value 171 as your bitindex, and 8 as your char_bit_width, so you will end up with these useful values calculated:
171/8 = 23 //location of first byte
171%8 = 3 //bits in first char/byte
8 - 171%8 = 5 //bits in last char/byte
sizeof(integer) = 4
sizeof(integer) + ( (171%8)>0?1:0 ) // how many array positions to examine
Some assembly required...
I have array from serial read, named sensor_buffer. It contains 21 bytes.
gyro_out_X=((sensor_buffer[1]<<8)+sensor_buffer[2]);
gyro_out_Y=((sensor_buffer[3]<<8)+sensor_buffer[4]);
gyro_out_Z=((sensor_buffer[5]<<8)+sensor_buffer[6]);
acc_out_X=((sensor_buffer[7]<<8)+sensor_buffer[8]);
acc_out_Y=((sensor_buffer[9]<<8)+sensor_buffer[10]);
acc_out_Z=((sensor_buffer[11]<<8)+sensor_buffer[12]);
HMC_xo=((sensor_buffer[13]<<8)+sensor_buffer[14]);
HMC_yo=((sensor_buffer[15]<<8)+sensor_buffer[16]);
HMC_zo=((sensor_buffer[17]<<8)+sensor_buffer[18]);
adc_pressure=(((long)sensor_buffer[19]<<16)+(sensor_buffer[20]<<8)+sensor_buffer[21]);
What does this line do:
variable = (array_var<<8) + next_array_var
What effect does it have on the 8 bits?
<<8 ?
UPDATE:
Any example in another language (java, processing)?
Example for processing: (why use H like header?).
/*
* ReceiveBinaryData_P
*
* portIndex must be set to the port connected to the Arduino
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
short portIndex = 1; // select the com port, 0 is the first port
char HEADER = 'H';
int value1, value2; // Data received from the serial port
void setup()
{
size(600, 600);
// Open whatever serial port is connected to Arduino.
String portName = Serial.list()[portIndex];
println(Serial.list());
println(" Connecting to -> " + Serial.list()[portIndex]);
myPort = new Serial(this, portName, 9600);
}
void draw()
{
// read the header and two binary *(16 bit) integers:
if ( myPort.available() >= 5) // If at least 5 bytes are available,
{
if( myPort.read() == HEADER) // is this the header
{
value1 = myPort.read(); // read the least significant byte
value1 = myPort.read() * 256 + value1; // add the most significant byte
value2 = myPort.read(); // read the least significant byte
value2 = myPort.read() * 256 + value2; // add the most significant byte
println("Message received: " + value1 + "," + value2);
}
}
background(255); // Set background to white
fill(0); // set fill to black
// draw rectangle with coordinates based on the integers received from Arduino
rect(0, 0, value1,value2);
}
Your code has the same pattern:
value = (partial_value << 8) | (other_partial_value)
Your array has data stored in 8 bit bytes, but the values are in 16 bit bytes. Each of your data points are two bytes, with the most significant byte stored first in your array. This pattern simply builds the full 16 bit value by shifting the most significant byte 8 bits to the left, then OR'ing the least significant byte into the lower 8 bits.
Its a shift operator. It shifts the bits in you variable to the left by 8. Shift by 1 bit to the left is equivalent to multiplying by two (shifting to the right divides by 2). So essentially <<8 is equivalent to multiplying by 2^8.
See here for a list of C++ operators and what they do:
http://en.wikipedia.org/wiki/C%2B%2B_operators
<< is the left bit-shift operator, the result is the bits from the first operand moved to the left, with 0 bits filling in from the right.
A simple example in pseudocode:
x = 10000101;
x = x << 3;
now x is "00101000"
Study the Bitwise operation article on wikipedia for an introduction.
This is just a bit shift operator. If is basically taking the value and shitfing the bits a places to the left. This is equivalent to multiplying the value by 2^8. The code looks like its reading in 2 bytes of the array and creating a 16 bit integer from each pair.
It seems that sensor_buffer is a matrix of chars.
In order to get your value, e.g. gyro_out_X you have to combine sensor_buffer[1] and sensor_buffer[2],
where
sensor_buffer[1] holds the most significant byte and
sensor_buffer[2] holds the least significant byte
in that case
int gyro_out_X=((sensor_buffer[1]<<8)+sensor_buffer[2]);
combines the two bytes:
if sensor_buffer[1] is 0xFF
and sensor_buffer[2] is 0x10
then gyro_out_X is 0xFF10
It shifts the bits 8 places to the left, eg:
0000000001000100 << 8 = 0100010000000000
0000000001000100 << 1 =
0000000010001000 << 1 =
0000000100010000 << 1 =
0000001000100000 << 1 =
0000010001000000 << 1 =
0000100010000000 << 1 =
0001000100000000 << 1 =
0010001000000000 << 1 =
0100010000000000
How can I create a file that uses 4-bit encoding to represent integers 0-9 separated by a comma ('1111')? for example:
2,34,99 = 0010 1111 0011 0100 1111 1001 1001 => actually becomes without spaces
0010111100110100111110011001 = binary.txt
Therefore 0010111100110100111110011001 is what I see when I view the file ('binary.txt')in WINHEX in binary view but I would see 2,34,99 when view the file (binary.txt) in Notepad.
If not Notepad, is there another decoder that will do '4-bit encoding' or do I have a write a 'decoder program' to view the integers?
How can I do this in C++?
The basic idea of your format (4 bits per decimal digit) is well known and called BCD (Binary Coded Decimal). But I doubt the use of 0xF as an encoding for a coma is something well established and even more supported by notepad.
Writing a program in C++ to do the encoding and decoding would be quite easy. The only difficulty would be that the standard IO use byte as the more basic unit, not bit, so you'd have to group yourself the bits into a byte.
You can decode the files using od -tx1 if you have that (digits will show up as digits, commas will show up as f). You can also use xxd to go both directions; it comes with Vim. Use xxd -r -p to copy hex characters from stdin to a binary file on stdout, and xxd -p to go the other way. You can use sed or tr to change f back and forth to ,.
This is the simplest C++ 4-bit (BCD) encoding algorithm I could come up with - wouldn't call it exactly easy, but no rocket science either. Extracts one digit at a time by dividing and then adds them to the string:
#include <iostream>
int main() {
const unsigned int ints = 3;
unsigned int a[ints] = {2,34,99}; // these are the original ints
unsigned int bytes_per_int = 6;
char * result = new char[bytes_per_int * ints + 1];
// enough space for 11 digits per int plus comma, 8-bit chars
for (int j=0; j < bytes_per_int * ints; ++j)
{
result[j] = 0xFF; // fill with FF
}
result[bytes_per_int*ints] = 0; // null terminated string
unsigned int rpos = bytes_per_int * ints * 2; // result position, start from the end of result
int i = ints; // start from the end of the array too.
while (i != 0) {
--i;
unsigned int b = a[i];
while (b != 0) {
--rpos;
unsigned int digit = b % 10; // take the lowest decimal digit of b
if (rpos & 1) {
// odd rpos means we set the lowest bits of a char
result[(rpos >> 1)] = digit;
}
else {
// even rpos means we set the highest bits of a char
result[(rpos >> 1)] |= (digit << 4);
}
b /= 10; // make the next digit the new lowest digit
}
if (i != 0 || (rpos & 1))
{
// add the comma
--rpos;
if (rpos & 1) {
result[(rpos >> 1)] = 0x0F;
}
else {
result[(rpos >> 1)] |= 0xF0;
}
}
}
std::cout << result;
}
Trimming the bogus data left at the start portion of the result according to rpos will be left as an exercise for the reader.
The subproblem of BCD conversion has also been discussed before: Unsigned Integer to BCD conversion?
If you want a more efficient algorithm, here's a bunch of lecture slides with conversion from 8-bit ints to BCD: http://edda.csie.dyu.edu.tw/course/fpga/Binary2BCD.pdf
I have an array of unsigned chars. Basically I have an array of bits.
I know that the first 16 bits corresponds to an unsigned integer and I retrieve its value using (u16)(*(buffer+ 1) << 8 | *abcBuffer)
Then comes a data type called u30 which is described as follows:
u30 - variable length encoded 30-bit unsigned integer value. The variable encoding for u30 uses one to five bytes, depending on the magnitude of the value encoded. Each byte contributes its low seven bits to the value.If the high (8th) bit of a byte is set then the next byte is also part of the value.
I don't understand this description: it says u30(thirty!) and then it says 1 to 5 bytes? Also I have another data type called s24 - three-byte signed integer value.
How should one read (retrieve their values) such non-typical data types? Any help will be appreciated.
Thanks a lot!
i=0;
val = buf[i]&0x7F;
while (buf[i++]&0x80)
{
val |= (buf[i]&0x7F)<<(i*7);
}
Assuming I understand correctly (always a questionable matter), the following will read the values. It starts at position zero in this example (i would need to be offset by the actual position in the buffer):
unsigned int val;
unsigned char buf[300];
int i;
int shift;
i = 0;
buf[0] = 0x81;
buf[1] = 0x3;
val = 0;
shift = 0;
do
{
val |= (0x7F & buf[i] ) << shift;
shift += 7;
i++;
} while (( buf[i-1] & 0x80 ) && ( i < 5 ));
printf( "Val = %u\n", val );
The encoding format description is somewhat informal perhaps, but should be enough. The idea will be that you read one byte (call it x), you take the lowest 7 bits x & 0x7F and at the same time check if it's highest bit is set. You'll need to write a small loop that merges the 7 bit sequences in a uint variable until the current byte no longer has its highest bit set.
You will have to figure out if you need to merge the new bits at the high end, or the low end of the number (a = (a << 7) | (x & 0x7F)). For that you need one test sequence of which you know what the correct output is.
To read the variable length 30 bit value, you could do something like such:
const char HIGH_BIT = 0x80;
const char DATA_MASK = 0x7F;
const char LAST_MASK = 0x03; // only need 2 bits of last byte
char tmpValue = 0; // tmp holder for value of byte;
int value = 0; holder for the actual value;
char* ptr = buffer; // assume buffer is at the start of the 30 bit number
for(int i = 0; i < 5; i++)
{
if(i == 4)
{
tmpValue = LAST_MASK & *ptr;
}
else
{
tmpValue = DATA_MASK & *ptr;
}
value |= tmpValue << ( 7 * i);
if(!(HIGH_BIT & *ptr))
{
break;
}
if(i != 4)
{
++ptr;
}
}
buff = ptr; // advance the buffer afterwards.
#Mark: your answer was posted while I was typing this, and would work except for the high byte. the value is only 30 bits, so only the first 2 bits of the high byte are used for the value and you are using the full 8 bits of the value.