PDA

View Full Version : A Bit manipulation brain teaser for you :)



dw_picbasic
- 2nd February 2007, 12:57
Hey Gang, let me know if you have "done that - got my T-shirt" and know the answer to this one.

I have 4 (8 bit) bytes being sent to me in a serial string.

Byte_1 is to be multiplied by 16777216
Byte_2 is to be multiplied by 65536
Byte_3 is to be multiplied by 256
Byte_4 is to be multiplied by 1

These are all then added to be converted into their decimal equivalent.
I can do this in a PC no problemo
But how do do it in a PIC where your greatest mathmatic result is limited to <= 65535?
I have played around with sum divisions by 1000, and seem to almost get there until I have to deal with adding Byte_4s value to the result.

Interested in your suggestions

sayzer
- 2nd February 2007, 13:32
Write a flip flop code for a PIC to flash couple of colorful LEDs.
Stick that PIC on your PC motherboard; connect to the +5V of PC power supply.

AND pretend as if the PIC were doing the math for you :) :D


--------------------------

dw_picbasic
- 2nd February 2007, 17:26
Cool!..... Yes,
Then I could write a book and title it "Picing up the PC" :)

mister_e
- 2nd February 2007, 17:46
But how do do it in a PIC where your greatest mathmatic result is limited to <= 65535?

Well, you place those limitation yourself. You could still use 2 Words... some basic maths around that. But will this worth if you could do most of the job on your PC side? It's up to you.

HenrikOlsson
- 2nd February 2007, 17:53
Hi,
I don't want to pretend I know the answer but may have an idea....
What do you intend to with the value once (if) you have it?

/Henrik Olsson.

Melanie
- 2nd February 2007, 19:05
I have 4 (8 bit) bytes being sent to me in a serial string.

Byte_1 is to be multiplied by 16777216
Byte_2 is to be multiplied by 65536
Byte_3 is to be multiplied by 256
Byte_4 is to be multiplied by 1

Not exactly a Brain Teaser - more a trick question.

Byte_1 is the MSB of a 32-bit variable, Byte_4 is the LSB of your 32-bit variable... no maths needed... so what you're really asking for is a routine to output a 32-bit (four byte) variable in human readable decimal...

dw_picbasic
- 5th February 2007, 01:52
Hi Melanie,
I thought I posted this the other day, but perhaps the system kicked me out for not posting fast enough.

The 4 bytes represent a value from 0 - 30,000.000
So fortunatly for me, the highest Byte will only be a 1 or 0.
The numbers represent radio frequency.
I have a radio that is sending me the 4 bytes to indicate what its current frequency is.
I have a number of frequency windows to play in.
I split each one of these windows up into 8 slices.
The frequency value then gets matched to one of these slices.
I use this info to control a remote antenna tuner box I made last winter.
I would bet you call this one simple.
But its over my head :)
Thanks
Duane

sayzer
- 5th February 2007, 06:54
...
The 4 bytes represent a value from 0 - 30,000.000


Can you split 30,000 from .000?

If you can, then you can put 30,000 into a word variable, and the remaining three zeros (.000) can get into another word variable (in theory).

If of course this is only for display purposes!


-------------------

mister_e
- 5th February 2007, 07:14
how the data is sent? Did you tried to attach your radio directly to a PC? Maybe he just send you ASCII string or HEX value?

in fact it could make sense... let's assume it send you 4 Bytes...
30,000.000

dw_picbasic
- 5th February 2007, 17:03
Yes, the device is setup to talk to a PC.
The PC queries the device for its set frequency, and the device returns the 4 bytes.

I know I should push the 4 bytes into 2 seperate 16 bit words.
Then I need to figure out what the decimal part is for:

Millions
Thousands
Hundreds

This seem pretty straight forward for a 1 byte word, but no so easy for me to get my head around doing it for 2 bytes, due to the carry effect.

mister_e
- 5th February 2007, 18:01
if you have a LCD, you can do a simple test



HSERIN [ByteA, ByteB, ByteC, ByteD]
LCDOUT $FE,1, HEX2 ByteA, HEX2 ByteB, HEX2 ByteC, HEX2 ByteD


What's happen using that?

Any model or link to your radio?

dw_picbasic
- 7th February 2007, 19:23
I think I got it !!!

I created a program using VB which simulates the PICSs math processing.
I realized that.
1. Even though there are 32 bits sent all together, only 26 of them are used.
Since the devices highest achievable number is 30,000,000.

2. The 5 highest bits with their corresponding multipliers directly effect the 1,000,000s place.

3. The 16 highest bits with their corresponding multipliers directly efffect the 1,000s place.

4. 18 of the bits directly effect the 100s place

So what I do is create 3 bytes.
Symbol MHZ = B5 (8 bit word)
Symbol KHZ = W3 (16 bit word)
Symbol Hz = W4 (16 bit word)

Then I go down through the 26 bits 3 times.
The first run down looks at each bit and applies that bits MHZ multiplier adding these values to MHZ

The second run looks at each bit and applies that bits KHZ multiplier adding these values to KHZ
Any time KHZ goes > 999, I do the appropriate carry to MHZ

The third run looks at each bit and applies that bits HZ multiplier adding these to the HZ value
Any time HZ goes > 999, I do the appropriate carry up through KHZ and MHZ.

Now all I have to do is transfere this code into PBC.
I hope to get that done tonight.
** this is where a simulator program comes in real handy!! ** :)

My next step on this project is to slice some specific frequency windows into numbered slices so that the pic can control a second device based on a reading falling within a specific slice.

I love this stuff!!!!

cagdask
- 26th February 2007, 16:55
multiplication by two is same as shifting left once in binary base. ( as multiplication by 10 is same as shifting left once in base 10). so multiplication by
16777216 = 2^24 = shifting 24 bits left.
65536 = 2^16 = shifting 16 bits
256 = 2 ^8 = shifting 8 bits
1 = 2^0 = no shift.

and division is shift right...

dw_picbasic
- 28th February 2007, 04:59
Hi CagDask,
Thanks for the post.
I ended up using a combination of PBC and assembler.
I put bit multipliers into eeprom and read them based on a bit test for each of the 15 bits. All values greater than 999 go into W2 and all above that into W3. I'm reading the serial data in at 57.6K also with an assembly routine and 20Mhz crystal.

Here is one of the routines.( W2 collecting Mhz & Khz ) from byte 3. (the one that is has 65536 as its multiplier). I played around with simple division, but I kept loosing remainder values and with them resolution, so this seemed pretty easy. Its basic double precision addition in assembly, with each bit multiplier value being read from eeprom. W3 >= 1000 carrys into W2 and I'm getting really good resolution.



B0 = 0 'start of eeprom
B15 = B12 'take copy of byte 3 into B15
W2_B12:
B1 = B0 + 1
Read B0,B2
Read B1,B3
IF B2 = 0 AND B3 = 0 Then exit_W2_b12

asm
btfss 47,7 ;ram 47 = B15 ;if the bit is high add its multiplier
GoTo NO_W2_B12
movf 34,w ;ram 34 = B2 which now has LSB from eeprom
addwf 36,f ;add this value to ram 36 = W2.LSB
btfsc 3,0 ;check status register carry bit
incf 37,f ;if carry occured, increment ram 37 which is W2.MSB
movf 35,w ;ram 35 = B3 which now has MSB from eeprom
addwf 37,f ;add MSB to W2
NO_W2_B12
rlf 47,f ;rotate B15 left one bit

ENDASM
B0 = B0 + 2
GoTo W2_B12

exit_W2_b12: