PDA

View Full Version : Splitting up bytes question



ERMEGM
- 7th October 2012, 05:44
Hello all,

Not sure how to word this, but I’ll do my best. When writing a number to eeprom (such as the number 15), does it get stored in the 8 bits as 00001111? If so, can you break up the low and high bytes to enter two values of numbers ranging from 0-15?

What I’m trying to do is record into eeprom two variables. Either of these numbers can have a value ranging from 0-15. As an example, I’d like to tell the chip to write 4 to the low byte side and write 5 to the high byte side. Doing so, the 8 bits would look like 01010100 (0101 for the number 5 and 0100 for the number 4). The data stored can then be read back by reading the low side, placing that value into one variable, and reading the high side and placing that value into a second variable.

I’d like to store two sets of values per memory location to double my space. Is this possible?

Thanks,
Tony

rmteo
- 7th October 2012, 06:33
Use hexadecimal notation??

For your example, store 54 hex at the byte location.

Charlie
- 7th October 2012, 12:10
PBP does not have tools to make working with nibbles easier, but you can certainly do it yourself by shifting right and left.

Dave
- 7th October 2012, 14:33
ERMEGM,

nibble1 var byte
nibble2 var byte
both var byte

nibble1 = 7
nibble2 = 10

'to store the 2 nibbles:
both = ((nibble1 & $0F) << 4)
both = both | (nibble2 & $0F)
'both now = $7A

'to retrieve the nibbles
nibble1 = both >> 4
nibble2 = (both & $0F)

ERMEGM
- 8th October 2012, 05:19
Use hexadecimal notation??

For your example, store 54 hex at the byte location.

In my example, it would work until you get to 11 on the first number and say 2 on the second number. How would it store with 112? It could mean 11 and 2 or 1 and 12.


PBP does not have tools to make working with nibbles easier, but you can certainly do it yourself by shifting right and left.

Getting back to my first question, if I use the code: WRITE 15, does it get stored as 1111 or 15? Just trying to see if I have to use if..then commands to translate the bits to numbers and vice-versa. The numbers will be used by the gosub command, so if 112 get's stored it must mean 11 and 2 and not 1 and 12.

Dave,

I will have to look into yours. Half of it makes sense, but I'm trying to interpret what the commands actually mean. Once I understand that, the rest will be easy.

I guess I need the above question answered first, and then I can try to implement the above suggestions by having a clearer understanding.

Thanks,
Tony

rmteo
- 8th October 2012, 06:25
With hexadecimal notation, 11 is B so the byte value to store is B2. Simple isn't it?

HenrikOlsson
- 8th October 2012, 06:30
Hi Tony,
Each location or adress in the EEPROM is a byte, a byte is 8 bits. If you do WRITE 0, 15 you will write the value 15 to adress 0 of the EEPROM. If you read the value back into a variable the variable will contain the value 15, if you decide to "print" the value in binary you'll get 00001111, if you decide to print it in hex you'll get E - it's all the same just different ways for us humans to express it.

If I understand your example with the numbers 11 and 2 correct you want 11 to be stored in the high nibble and 2 in the low nibble, resulting in the full byte containing 10110010, if we express that number in decimal form it's 178. One way to go from your two numbers into a single byte could be:

FullByte = Number_1 * 16 + Number_2
See, 11*16+2=178.
(Multiplying by 16 can be replaced with four left-shifts so FullByte = (Number_1 << 4) + Number_2 which is kind of what Dave is doing.)

To get the value back into your two discrete variables you can do something like

Number_1 = FullByte >> 4 ' This will take the FullByte and shift it four steps to the left, the low nibble will be "pushed" out
Number_2 = FullByte & %00001111 ' This will mask the high nibble.

/Henrik.

Charlie
- 8th October 2012, 10:42
All the answers to the original question are correct - thanks Henrik for spelling out the details better than the rest or us - you just have to choose the one that suits your style of thinking best!

To expand on my shift right and left, you would first write the high nibble, then shift left 4 times, then write the low nibble.
To recover you would shift right 4 times to get the high nibble, and to get the low nibble, shift left 4 times, then shift right 4 times. (Clear as mud?)
Basically, make the bits you don't want fall off the closest end, then make sure the ones you want are in the low nibble position.

Some other compilers have tools for directly accessing nibbles, but the need is pretty rare.

ERMEGM
- 9th October 2012, 00:12
Hi Tony,
Each location or adress in the EEPROM is a byte, a byte is 8 bits. If you do WRITE 0, 15 you will write the value 15 to adress 0 of the EEPROM. If you read the value back into a variable the variable will contain the value 15, if you decide to "print" the value in binary you'll get 00001111, if you decide to print it in hex you'll get E - it's all the same just different ways for us humans to express it.

If I understand your example with the numbers 11 and 2 correct you want 11 to be stored in the high nibble and 2 in the low nibble, resulting in the full byte containing 10110010, if we express that number in decimal form it's 178. One way to go from your two numbers into a single byte could be:

FullByte = Number_1 * 16 + Number_2
See, 11*16+2=178.
(Multiplying by 16 can be replaced with four left-shifts so FullByte = (Number_1 << 4) + Number_2 which is kind of what Dave is doing.)

To get the value back into your two discrete variables you can do something like

Number_1 = FullByte >> 4 ' This will take the FullByte and shift it four steps to the left, the low nibble will be "pushed" out
Number_2 = FullByte & %00001111 ' This will mask the high nibble.

/Henrik.
Hi Henrik,

Thanks for the reply and explanation. What I'm trying to do is store two separate values. Each value can be incremented separately, that's why I need to be able to store digits separately, so they can't be misread. What I am seeking to do is store both values in one byte of eeprom. I am starting to understand how to shift them in and out, what I would like clarification on is when you say they are pushed out, does the value still stay in that byte of eeprom, or are the values shifted out like a shift register? I need to be able to go back to reference those numbers again and a again. If they are "shifted out" then they are gone, right?

It's easy to understand when you know the answer. This is my first time working with shifting, so I'm kind of curious how creative I can be to use these features. I am just trying to make the best use of space I can in eeprom.

The best analogy I can think of when trying to explain what I'm doing is like when working with a chart. You have so many blank entries on a page (eeprom available bytes). When you go to write your pairs of number in the blank spaces, if you enter one number on one blank line and the second on line two, you fill up the sheet twice as fast.

If you squeeze both numbers in on one line, you double the amount of data you can store, however you have to make some kind of separator to make sure the numbers are not merged together. We would normally put a space or a dash or slash when we write it, but for the pic we shift. This is what I've gathered so far from the replies. Does that sound about right?

Thanks for all the input guys.

Tony

rmteo
- 9th October 2012, 01:45
Hexadecimal (http://en.wikipedia.org/wiki/Hexadecimal)

rmteo
- 9th October 2012, 02:35
What is a Nybble? (http://en.wikipedia.org/wiki/Nybble)

HenrikOlsson
- 9th October 2012, 06:35
Hi Tony,
Once the value is written to EEPROM the only thing that will change that value is if you do another WRITE to the same location or erase the EEPROM. When you're going to get the value from the EEPROM you'll need to read the full BYTE into a variable and then split it

READ 0, FullByte ' Get value from EEPROM and put it in FullByte
Number_1 = FullByte >> 4
Number_2 = FullByte %00001111
The second line will not alter FullByte in any way, basically it'll take a copy of it, shift to the right four times and put the result in Number_1, leaving FullByte in its original state. Again, note that you aren't doing these operations directly on the EEPROM.

Lets take the example with 11 and 2 which resulted in the value 178 being stored in EEPROM. When you read the EEPROM you'll get the value 178 into the variable FullByte. Then we take the value 178 (10110010 in binary) and shift that to the right four times, pushing out the lower four bits, filling up the top four bits with zeros, the result is stored as Number_1 (00001011, which is 11 in decimal). Then we go back to the original value (178) again and mask off the four high bits so they not end up in Number_2 which will then contain 00000010, which is 2 in decimal. Both the EEPROM and FullByte still contains the original value (178).

Now you can manipulate either one of the values and the piece them back together as shown earlier. Obviously you need to do another WRITE to actually save the new value in EEPROM because again, you can't manipulate the values directly "in" the EEPROM.

Another way of thinking of this, which is what the other guys here are saying is use hex notation. Remember now that the actual numbers does not change in any way, it's just how WE express them. 178 in decimal is B2 in hex right? B in hex is 11 in decimal and 2 in hex is 2 in decimal. It doesn't change anything, it's just another way of looking at it.

If "all" you're doing is increasing or decreasing the individual numbers then you could do that directly on the full byte instead of splitting them and then putting them back together. If Number_1 (the value stored in the high four bits) should be increased then you add 16 to value. If the Number_2 (the value stored in the low four bits) should be increased you add 1. Let's do that:

Read 0, FullByte ' Get original value from EEPROM
FullByte = FullByte + 17
WRITE 0, FullByte
Now, the first we get the value 178 from EEPROM, then we add 17 resulting in 195 which in hex is C3. C in hex is 12 in decimal (one more than 11) and 3 in hex is 3 in decimal (one more than 2).

/Henrik.

ERMEGM
- 11th October 2012, 04:13
Number_1 = FullByte >> 4

I get that this means to take the value of Fullbyte, shift it to the right 4 times and place the value in Number_1.

Number_2 = FullByte %00001111

But what does this mean? Is there suppose to be an & between Fullbyte & %00001111? If so, then I completely understand.

Why couldn't you do:
Number_1 = FullByte & %11110000 with the first one? Less words the other way?

Thanks,
Tony

HenrikOlsson
- 11th October 2012, 06:10
Hi,
Yes, it should of course be Number_2 = FullByte & %00001111, typo on my behalf, sorry about that.

If you do Number_1 = FullByte & %11110000 you'll mask off the lower four bits (make them zeros) and assign the result to Number_1. In this case, when FullByte is 178 (10110010), you'd end up with 10110000 which 176 and not 11 which is what you're looking for.

/Henrik.

ERMEGM
- 12th October 2012, 00:17
So, with the shift (>>4), you'd go from 11110101 to 00001111 (for 15). But with & %11110000, you'd get 11110000 for Number_1.

I thought %11110000 meant it would discard bits 0-3 and just enter 1111 into the Number_1 value. Apparently that's not the case.

Tony

HenrikOlsson
- 12th October 2012, 06:23
Hi Tony,
Yes, the & operator is bitwise AND.

As input it takes two numbers, it then compares them bit by bit. Think of it like having running each bit in both numbers to a two-input AND-gate, (8 gates, one for each bit) the output of each gate is wired into the result variable. Just as with a real AND-gate both inputs (the same bit in the two numbers) have to set in order for the output (the bit in the result) to be set.

Result = %10101010 & %11111111
Here Result be a copy of the first number because all bits in the second number is set. Any bit which is SET in both numbers will be set in the result.

Result = %10101010 & %0000000
Here Result will be all zeros because the second number is all zeros.

Result = %10101010 & %11110000
Here Result will be %10100000 be because only the four bits of the second number are set.

Result = %10101010 & %00111100
Here Result will be 00101000 because, well I suppose you get it by now ;-)

/Henrik.

ERMEGM
- 13th October 2012, 15:39
Makes total sense. Thank you so much guys for your help. While the book is helpful, it doesn't always break things down on a lower level for all people to understand. That's why these boards are so helpful, you can always find someone able to better present the information. Thanks again.

Tony