bit banging example

jims

Senior Member
I'm trying to understand "bit banging". If a FORUM member has a simple example of code for "Bit Banging"; please post it here so that I can try to educate myself about this method of communicating using Picaxe. Also; maybe give a brief explanation about when/why this method is used. Thank you, Jims
 

hippy

Technical Support
Staff member
Bit-banging or bit-bashing is simply a way to set outputs in a particular order to meet the requirements of whatever is receiving that signal. The main thing about it is that each step along the way is done under program control rather than relying upon hardware assistance to do that.

For example, if a one bit latch latched an input (INP) as an output (OUT) with a positive going clock pulse (CLK) its timing diagram as found in its datasheet might look something like ...

Code:
        _________
INP ___|         |___ _________________
       :   __    :       :   __    :  
CLK ___:__|  |___:___ ___:__|  |___:___
       :  :  :   :       :  :  :   :
       :  :  :  _:___ ___:__:__:_  :
OUT ___:__:__:_| :       :  :  : |_:___
       :  :  :   :       :  :  :   :   
        Ts Tp Th          Ts Tp Th
Ts (Setup Time), Tp (Pulse Time) and Th (Hold time) will often be specified, but are probably quite small in most cases so can usually be ignored when used with a PICAXE; the time to get to executing the next PICAXE command is usually longer than the time required but not always. We will assume here those times are 1ms, 2ms and 3ms respectively.

So to clock out a bit ...

Set INP high or low
Pause Ts (1ms)
Set CLK high
Pause Tp (2ms)
Set CLK low
Pause Th (3ms )
Set INP low

Converting that to PICAXE code ...

If b0 = 0 Then : Low INP : Else : High INP : End If
Pause 1
High CLK
Pause 2
Low CLK
Pause 3
Low INP

That's bit-banging done. In most cases it will usually be a longer sequence and possibly multiple data lines needing to be set before performing some clocking action. Sometimes there might not be any actual clocking action and only the times between high and low which is important.

The only other thing to bear in mind is how things should be when the program starts. In this case CLK should be set low when the program first starts ( in order to have it rise to do the clocking ) and it may be necessary to add a pull-down resistor on the CLK line to cater for the pin initially being an input for a short while before the PICAXE program runs.

Normally it's nice to have things how a timing digram shows them when entering a sequence and leaving them as shown once done but that's not an absolute. It can help when debugging with a scope or analyser though. In the above example INP doesn't need to be set low at the end because it's set high or low as required before CLK is made high.

As noted earlier, setup, pulse and hold times are usually much shorter than we need worry about so pauses aren't usually required. For a real one bit latch the command sequence could probably be reduced to ...

If b0 = 0 Then : Low INP : Else : High INP : End If
High CLK
Low CLK
Low INP

That "High CLK" then "Low CLK" could also be reduced to a single "PulsOut CLK" with an appropriate time period ...

If b0 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
Low INP

And, as noted, we don't actually have to do that final "Low INP", leaving just ...

If b0 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1

That outputs a single bit but if we wanted to sequentially output a set of 8 bits, the byte in b0 sent MSB first, such as to a serial to parallel 74HC595 buffer, we can simply repeat that 8 times ...

If bit7 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit6 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit5 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit4 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit3 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit2 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit1 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
If bit0 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1

That's fast but long-winded. If we can tolerate something slower but less memory used, and don't mind losing the original contents of b0 or using an extra b1 variable ...

For b1 = 0 To 7
If bit7 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
b0 = b0 * 2
Next

It might be necessary to output some latching signal (LE) to tell the thing you are controlling it's done so that might need an extra HIGH then LOW or PULSOUT at the end, and there might be a Chip Select (CS) which has to be asserted during the whole thing, so a complete byte write to a 595-style latch could be ...

High CS
For b1 = 0 To 7
If bit7 = 0 Then : Low INP : Else : High INP : End If
PulsOut CLK,1
b0 = b0 * 2
Next
PulsOut LE,1
Low CS

What that would generate, as shown on a logic analyser or scope, is something like ...

Code:
        ________________________________
CS  ___|                                |___
           _______________________
INP ______|D7|D6|D5|D4|D3|D2|D1|D0|_________
     
CLK ________|__|__|__|__|__|__|__|__________

LE  _________________________________|______
Sometimes CS or other signals are inverted, so the HIGH's and LOW's may need swapping as appropriate with signals initialised to the default inactive levels at the start of the program.
 
Last edited:

jims

Senior Member
Thank you, Hippy for this comprehensive explanation of "Bit Banging". I can see that I'm not ready to tackle it yet. Am thankful that someone has put together a set of commands that let me communicate with common serial devices without all of this "Bit Banging". Jims
 

hippy

Technical Support
Staff member
I can see that I'm not ready to tackle it yet.
I am sure you are and you have done it without realising it; every time you turn a LED on or off, and especially if you have flashed a LED a number of times to indicate something or written a traffic light sequencing program. Just in those cases it's done at a slow rate.

UK traffic light sequencing ...

Code:
   __________             _____
R            |___________|
        _____       _____
A  ____|     |_____|     |_____
              _____
G  __________|     |___________
US traffic light sequencing ...

Code:
   ____             _____
R      |___________|
              _____
A  __________|     |_____
        _____
G  ____|     |___________
 
Last edited:

tony_g

Senior Member
jims i can honestly say its not as bad as you would think, i have finally got my first attempt at bit banging working to the point of giving me data i expect to see.

initially i had a few issues due to not completely understanding how to do it with software but after some help and suggestions and a bit of perseverance i have it working now and am finishing up my code to use.

i had initially avoided bit banging for so long as i found it intimidating but now im glad i finally decided to dive in as it allows the use of many different things with the picaxe, especially if you only have "M2" chips like i do.

a logic analyzer definately helps as well.


tony
 

premelec

Senior Member
hi jims - for me the main problem was figuring out - from data sheet - just what sequence the external device needed. Then when I determined my device [8 bit 8 channel DAC from TI] required 12 bits shifted in to set a channel. I would calculate those bits and put them in b0 and b1 and then execute a pinout# = bit12.... pulsout clkpin... pinout# = bit11... pulsout clkpin.... down to pinout# = bit0 pulsout.. clkpin . The code can be compacted using for/next but the 12 bit shiftout time got longer dong that. Anyhow it's not too bad once you understand what has to be done... persist!
 
Top