Output A Word as Serial Bits

EPAIII

Member
I am searching the past posts for a way to output a Word variable as a series of bits on one pin. I came across this post from 2007 that seems to be doing that, but I have a question about how it works. First the quote:

Hippy, on 10/25/2005 said;
"I haven't tested it, but the fastest way to clock 8 bits out msb first ( removing the FOR-NEXT overhead ), could be to put it in "b0 ( MSB of w0 ) and set b0 (LSB of w0 ) to $FF. As w0=w0*2 operates the LSB is eventually cleared ...
"
"- b1 = $A5 ' Data to send
"- b0 = $FF
"-
"- BitLoop:
"- pinX = bit15
"- w0 = w0*2
"- IF b0 <> 0 THEN BitLoop
"
"To shift 16 bits out, w0 and another word variable can be used ...
"
"- w0 = $A593 ' Data to send
"- w1 = $FFFF
"-
"- BitLoop:
"- pinX = bit15
"- w0 = w0*2
"- w1 = w1*2
"- IF w1 <> 0 THEN BitLoop
"
"No PULSOUT's shown in the above. The code can be modified to do lsb first by some simple changes. It should also be possible "to send an arbitrary number of bits by selecting the right bitX variable and setting the $FF/$FFFF to have some zero bits."

I am interested in the first version for a Word sized output. I can understand it up to the last line, "IF b0 <> 0 THEN BitLoop". It is obviously testing the bo Word, which I would assume would become zero when the last or eighth bit has been sent. But just how is that being done? What are &lt and &gt? And how do they work in the IF ... THEN statement?

From the rest of the conversation, at that time, this method was apparently suggested to avoid using a FOR ... NEXT loop which seems to be the obvious way to do this. Just loop through the lines of code eight times for each bit in the Word. Is a FOR ... NEXT loop particularly slow or does it consume a lot of memory? Why would I want to avoid it? Or is this completely obsolete? Is there a better suggestion now? I would want a routing that is first fast and then as compact in terms of memory usage as possible.
 

hippy

Ex-Staff (retired)
&lt; and &gt; are old code tags from the previous forum representing the less than and greater than symbols ( "<" and ">" ) respectively, so -

IF w1 &lt;&gt; 0 THEN BitLoop

Should actually be read as -

IF w1 <> 0 THEN BitLoop

The way it works is that w1 will only become zero once its initial $FFFF has been shifted out, which would have taken 16 shifts. So repeat until w1 is not zero is the same as repeating for 16 shifts. Each multiply by 2 is a shift left by one bit.

I am not sure of the context for this code but I suspect FOR-NEXT was recommended against because as it would be slower than what was given and the aim was to produce the fastest code. Fastest code would be to completely unroll the loop but from the date of that post I would guess that was from a time when PICAXE chips did not have such large memories as they do now.
 

AllyCat

Senior Member
Hi,

Yes, that thread may be "obsolete" now, because PICaxes now have much more program memory and greater speed.

Also, AFAIK you can't use "method 1" for a word, because it works by using one of the bytes as a "marker", so you can't write "random" data into it.

It depends exactly what you want to do (and with what). X2 chips have shift instructions (and a faster maximum clock) that permit significantly faster operations. With M2s, it's faster to shift out the High Bit First because multiplication by 2 (or addition is even faster) is quicker than division by 2.

No, FOR loops are not particularly slow or memory intensive and often the exact instructions used are not too important anyway, because the Program Editor may generate the same interpreter code. But generally the best advice is to Keep It Simple with IF/GOTOs because that is probably what will be interpreted anyway.

We can probably explain more detailed techniques when it's clear what you actually need to do.

Cheers, Alan.
 

westaust55

Moderator
Knowing which PICAXE chip you are using can help you receive optimal answers.
For the X1 and X2 parts see the SHIFTOUT command as an option.
This is around 4 times faster than bit-bashed code with FOR...NEXT loops.

With an M or M2 part you need to use the code specifically provided in the PICAXE manuals under the SHIFTOUT command.
For 16 bits you just send 2 consecutive bytes or when using the bit-bashed code the entire word in one FOR...NEXT loop.

When using the X1 and X2 parts the math functions << and >> are available which will be faster then multiply and divide to shift left or right.
 

EPAIII

Member
< and > are old code tags from the previous forum representing the less than and greater than symbols ( "<" and ">" ) respectively, so -

IF w1 <> 0 THEN BitLoop

Should actually be read as -

IF w1 <> 0 THEN BitLoop

The way it works is that w1 will only become zero once its initial $FFFF has been shifted out, which would have taken 16 shifts. So repeat until w1 is not zero is the same as repeating for 16 shifts. Each multiply by 2 is a shift left by one bit.

I am not sure of the context for this code but I suspect FOR-NEXT was recommended against because as it would be slower than what was given and the aim was to produce the fastest code. Fastest code would be to completely unroll the loop but from the date of that post I would guess that was from a time when PICAXE chips did not have such large memories as they do now.
Hippy, thanks for the fast reply. I did eventually figure it out after doing a search of the Commands manual and finding neither of those terms anywhere in it. Then the light lit.

What am I doing? I am trying to create an efficient subroutine send the data to a digital circuit of my own design. It will use a serial in/parallel out register to receive the data. I want to do this as fast as possible, with as little code as possible, and I would like it to work on as many PICAXE chips as possible with little or no changes. I am presently working with an 08M2 but will test it on a 18M2 and perhaps some others as well. I do not want to be encumbered with the necessities of RS-232 or I2C if possible. I just want to bang it out. I can tolerate a second line for the clock. Oh, this will be one way communication, no return messages or data.

Please pardon me, in my original post I confused Word with Byte. I am doing an 8 bit byte, not a word, at one time.

I foolishly skipped over the Spiout command when I saw that it did all 8 bits. I missed the clock feature. So, it probably will work. I will try it.

Thanks to all for the prompt and thoughtful suggestions.

If you don't mind, I have one more question about this. Is there a way to use Symbols to define the pins used in this command at the head of the code? I have been experimenting with this and the older code and I keep getting syntax errors.

Symbol SData = C.0 Rem At top of code
.....
SData = bit 15 Rem In the data send loop
 

Rick100

Senior Member
If you don't mind, I have one more question about this. Is there a way to use Symbols to define the pins used in this command at the head of the code? I have been experimenting with this and the older code and I keep getting syntax errors.

Symbol SData = C.0 Rem At top of code
.....
SData = bit 15 Rem In the data send loop
Change to:
Code:
Symbol SData = pinC.0 Rem At top of code
.....
SData = bit15 Rem In the data send loop
Put pin in front of C.0 and you had a space between bit and 15.

Good luck,
Rick
 
Top