PDA

View Full Version : Bit stuffing problem!



atomski
- 31st October 2004, 19:37
Hello everyone,

I've been banging my head with this for the past 2 days
and it's time to ask you guys and gals for advice. Here's
the code:


Start:
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
IF Pulse < 290 THEN Start

Get_Data:
FOR i = 0 to 6
FOR w = 0 TO 5
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
If Pulse > 80 and Pulse < 120 THEN Rx_Bit = 0
IF Pulse > 180 AND Pulse < 220 Then Rx_Bit = 1
Rx_Byte = Rx_Byte << 1
Rx_Byte.0 = Rx_bit
NEXT w
Rx_Data[i] = Rx_Byte
NEXT i
i = 0
w = 0
GOSUB Send_Data
GOTO Start

END

Now, when I send this to hyperterminal all bits are shifted
one place to the left. I understand that I operate with
8 bits per Byte and receive only 6 bits (LSB) but I can't
figure out why my 6 bits get placed between Rx_Byte.7
and Rx_Byte.0. I'd like it to be right justified. can someone
help? Thanks!

YZ7REA Vladimir

mister_e
- 1st November 2004, 04:33
What about your Rx_byte define. Is he declare as WORD. Case not .byte0 will not work. what do you really need to do with your code?

atomski
- 1st November 2004, 07:22
Sorry, abt that my bad ;) Here are the defines:

DEFINE OSC 20
Rx_Data Var Byte[7]
Rx_Byte Var Byte
Rx_Bit Var Bit
Pulse Var Word
I Var Byte
w Var Byte

... and it's not .byte7 and .byte0 it's byte.bit7 and byte.bit0

BTW I found a typo in my snippet:

Rx_Byte = Rx_Byte << 1
Rx_Byte.0 = Rx_bit

the actual code is:

Rx_Byte.0 = Rx_bit
Rx_Byte = Rx_Byte << 1


I'm trying to receive 7 bytes of data, each containing 6 bits
(bit.7 and bit6 are not used). Data received per w loop looks
like this: 01001000 = $48 but I've sent 00100100 = $24. So,
you see all bits are shifted one place to the left towards MSB.
What am I doing wrong here?

YZ7REA Vladimir

mister_e
- 1st November 2004, 13:24
Since i'm not really sure again of what you're trying to do with the PULSIN statement, try this and post reply.




DEFINE OSC 20
Rx_Data Var Byte[7]
Rx_Byte Var Byte
Rx_Bit Var Bit
Pulse Var Word
I Var Byte
w Var Byte


Start:
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
IF Pulse < 290 THEN Start

Get_Data:
FOR i = 0 to 6
FOR w = 0 TO 5
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
If (Pulse > 80) and (Pulse < 128) THEN Rx_Bit = 0
IF (Pulse >= 128) AND (Pulse < 220) Then Rx_Bit = 1
Rx_byte = pulse
Rx_Byte = Rx_Byte << 1
Rx_byte = Rx_Byte & $FE
Rx_Byte.0 = Rx_bit
NEXT w

Rx_Data[i] = Rx_Byte
NEXT i
GOSUB Send_Data
GOTO Start


Maybe i'm totaly dumb but in case this is not solve the problem, tell me exactly, like a children, what you want to do. In case of X pulse..... in case of pulse.....

regards

atomski
- 1st November 2004, 13:49
I use PULSIN statement to measure pulse width of the
incomming data, see post:

http://www.picbasic.co.uk/forum/showthread.php?s=&threadid=695

...similar to SONY remote codes. I measure only low pulses
as all high pulses are the same (200us as per post), so I just
assume they're there :)

I then have to reconstruct data bytes bit-by-bit as you can
see above. I know I'm doing something wrong with shifting
bits to the right, but I can't figure out what.

YZ7REA Vladimir

mister_e
- 1st November 2004, 14:09
did you try my above lines of code?

atomski
- 1st November 2004, 14:29
Steve,

nope, not yet. I'm at work and my project is waiting for me
back at home. However, I don't see (and forgive me if it's
stupid of me) what purpose the folowing statement serves

Rx_byte = pulse

I don't need to copy the value from pulse to Rx_Byte. That's
why I have the folowing statement(s) in place:

IF (Pulse > 80) AND (Pulse < 128) THEN Rx_Bit = 0
IF (Pulse >= 128) AND (Pulse < 220) THEN Rx_Bit = 1

... to determin which bit I just received and stuff it to
Rx_Byte.0, shift it and repeat the proces until I get all 6
bits per byte (.7 and .6 are not used). I do this for all 7 bytes
and voila, I've decoded the message sent by the encoder.
The only problem is placing the all the bits in the right
place. I hope it's clear now... TNX!

PS would you care to explain how exactly you mask the
bits with Rx_byte = Rx_Byte & $FE ? I'm not sure I follow...

YZ7REA Vladimir

Archilochus
- 1st November 2004, 14:33
Hi Vladimir,
I'm a beginner - so might have got this wrong.....

It looks like you'll want to NOT shift left on the first loop through.

Consider if your first received bit is a '1', followed by five '0's received.

Before loop: Rx_Byte = 0000 0000

After first pass through loop Rx_Byte = 0000 0010
when you want it to = 0000 0001

After all six passes through loop, Rx_Byte = 0100 0000
when you wanted Rx_Byte = 0010 0000

You could try adding in something like this...

IF W THEN
Rx_Byte = Rx_Byte << 1
EndIF

Will only shift if W is above 0 (not onh first pass through loop).

Dwayne
- 1st November 2004, 14:52
Hello Atomski,

a>>
Rx_Byte = Rx_Byte << 1
Rx_Byte.0 = Rx_bit
<<


Switch these two statements around...

Rx_Byte.0 = Rx_bit
Rx_Byte = Rx_Byte << 1

LIke the above...

And you will be ok.

Dwayne

atomski
- 1st November 2004, 17:19
Dwayne,

I did. But I still get %01001000 instead of %00100100.
Is there a way to mask my Rx_Byte variable with $FF i.e.
%11111111 and find only zeroes returned by Rx_Bit and
fill them in in the right places? Or should I just use one
extra statement Rx_Byte = Rx_Byte >> 1 at the end of
my w loop? This seems to be the easier way out, but it
looks dumb. Any suggestions?

YZ7REA Vladimir

Dwayne
- 1st November 2004, 19:15
Hello Atomski,

A>>I did. But I still get %01001000 instead of %00100100.
Is there a way to mask my Rx_Byte variable with $FF i.e.
%11111111 and find only zeroes returned by Rx_Bit and
fill them in in the right places? Or should I just use one
extra statement Rx_Byte = Rx_Byte >> 1 at the end of
my w loop? This seems to be the easier way out, but it
looks dumb. Any suggestions?<<

If it works, it works <g>. You are messin with 6 instead of 8 bits... Thus yes... you can shift over two places. Just put a comment by it, and say "Shifty Personality problem".

there are other ways to handle it, but...<g>



to right justify, you can do two shifty's and the Begining (before reading code).

Since I do not know what you are trying to accomplish, I do not know how to fully answer your question.

Steve (Mister_e) had some good looking code for you too.

Another way to accomplish without that extra shift, is to do the following:
PsuedoCode:

RxByte=FF
for Loop=1 to 6
Pulse=Portxyz
RxByte.2=Pulse
RxByte=RxByte<<1
next Loop;

Now if you want to shift to the right
RxByte=RxByte>>2

Archilochus
- 1st November 2004, 20:42
In looking at it again, it actually seems like leaving the following typo from the original snippet should do just fine...

Rx_Byte = Rx_Byte << 1
Rx_Byte.0 = Rx_bit


Here's what I'm thinking...

x = don't know/don't care.

Say we're shifting in the 6 data bits 111111

Rx_Byte = xxxx xxxx before loop begins...

First pass through a 'W' loop, a '0' will be shifted into Rx_Byte, so Rx_Byte will = xxxx xxx0
Then Rx_Byte.0 will be set to Rx_Bit (1, our first data bit in), and Rx_Byte will = xxxx xxx1


On the second 'W' loop, a '0' gets shifted into Rx_Byte, and Rx_Byte = xxxx xx10
Then Rx_Byte.0 is set to the second data bit in, and now Rx_Byte = xxxx xx11

And so on through the remaining four 'W' loops.

On the last 'W' loop, a '0' gets shifted into Rx_Byte, and Rx_Byte = xx11 1110
Then Rx_Byte.0 is set to the sixth data bit in, and now Rx_Byte = xx11 1111


Step by step through a simplified version...


FOR w = 0 TO 5 ;six loops to get data bits

PULSIN Rx_Pin, 0, Pulse ;get pulse length value

If Pulse > 80 and Pulse < 120 THEN Rx_Bit = 0 ;set or clear Rx_Bit as needed

IF Pulse > 180 AND Pulse < 220 Then Rx_Bit = 1

Rx_Byte = Rx_Byte << 1 ;shift a zero into Rx_Byte bit 0

Rx_Byte.0 = Rx_bit ;place new 'Rx_Bit' value into Rx_Byte bit 0

NEXT w

At the end of each 'W' loop, Rx_Byte.0 will = the new Rx_Bit, rather than shifting the new Rx_Bit over to Rx_Byte.1
The first "Rx_Byte = Rx_Byte << 1" command just shifts in a placeholder '0', which ends up in the unused position Rx_Byte.6

Now I'm wondering what happens to Rx_bit if Pulse = 120 to 180 ???
Or if Pulse is less than 80 or more than 220 ???

Bruce
- 1st November 2004, 21:44
Try this;



Start:
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
IF Pulse < 290 THEN Start

Get_Data:
FOR i = 0 to 6 ' 7 bytes
FOR w = 0 TO 5 ' 6 bits
PULSIN Rx_Pin, 0, Pulse
IF Pulse > 80 and Pulse < 120 THEN Rx_Byte.0[w] = 0
IF Pulse > 180 AND Pulse < 220 Then Rx_Byte.0[w] = 1
NEXT w
Rx_Data[i] = Rx_Byte & %00111111 ' Mask upper 2-bits
NEXT i
i = 0
w = 0
GOSUB Send_Data
GOTO Start


This sets or clear bits 0-5 in Rx_Byte as indexed by w. No shifting required.

Rx_Byte.0[w] is the same as Rx_Byte.bit.w where w holds the bit index # to set or clear. I.E. from bits 0 to 5 in Rx_Byte.

Rx_Data[i] = Rx_Byte & %00111111 masks the upper two bits from Rx_Byte leaving these two bit positions clear.

If you need to work from bit 5 to bit 0, then change FOR w = 0 TO 5 to --> FOR w = 5 TO 0 STEP - 1.

atomski
- 2nd November 2004, 08:27
Guys,

thanks for all the ideas, I was thinking more or less along
these lines, but I wasn't sure what would be the best thing
to do. I actually got it to work by doing this:

Start:
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
IF Pulse < 290 THEN Start

Get_Data:
FOR i = 0 to 6
FOR w = 0 TO 5
Pulse = 0
PULSIN Rx_Pin, 0, Pulse
If Pulse > 80 and Pulse < 120 THEN Rx_Bit = 0
IF Pulse > 180 AND Pulse < 220 Then Rx_Bit = 1
Rx_Byte.0 = Rx_bit
Rx_Byte = Rx_Byte << 1
NEXT w
Rx_Data[i] = Rx_Byte >> 1 ' SIMPLE BUT EFFECTIVE
NEXT i
i = 0
w = 0
GOSUB Checksum ' Put a pinholder here, hehehe!
GOSUB Send_Data
GOTO Start

END

Now it works like a charm, but I'll give it a go with your
idea Bruce cuz it lookes slicker hehehe. BTW Archilochus,
I'll add a couple of IF THEN or CASE statements to make
sure shorter or longer pulses are discarted.

And now something completely different ;)

If you take a look at the code above you'll see that I
decided to implement checksum to my routine and since
I'm messin' 'round with 6-bits like Dwayne said, I ran into
another problem. Spent whole afternoon trying to solve it
but no dice.

I've opened another thread regarding this, so if any of you
still have any patience left for trying to crack this one, this
is the place to look:

http://www.picbasic.co.uk/forum/showthread.php?s=&threadid=833

Thanks to everyone who helped me out with this one.

--
Sincerest regards,

YZ7REA Vladimir M Skrbic
4N7ATV Repeater Administrator
YU7GHZ Radio Club President