I need to make a push button "toggle": push goes high, next push goes
low, and so on. In effect I need to "store" button presses: the PIC will
be polling for them, but I can't use interrupts and can't guarantee the
polling frequency. The button is a N.O. one, SPST. I also need to
debounce, of course.

I know I can get this with some cross-coupled gates (for debounce) and a
flip flop (divide by two, basically) but I'm hoping there's a simpler
(read: fewer components) way to do this. Are there ICs with this sort of
function? Or some other cool way to pull (push?) this off?

> From: Dave Johnson <spam_OUTdjohnsonTakeThisOuTSIRIUS.COM>
> To: .....PICLISTKILLspam@spam@MITVMA.MIT.EDU
> Subject: [OT] Pushbutton toggle
> Date: Wednesday, October 28, 1998 9:06 AM
>
> Brace yourself for a newbie electronics question:
>
> I need to make a push button "toggle": push goes high, next push goes
> low, and so on. In effect I need to "store" button presses: the PIC will
> be polling for them, but I can't use interrupts and can't guarantee the
> polling frequency. The button is a N.O. one, SPST. I also need to
> debounce, of course.
>
> I know I can get this with some cross-coupled gates (for debounce) and a
> flip flop (divide by two, basically) but I'm hoping there's a simpler
> (read: fewer components) way to do this. Are there ICs with this sort of
> function? Or some other cool way to pull (push?) this off?
>
> Thanks,
>
> Dave Johnson

>Brace yourself for a newbie electronics question:
>
>I need to make a push button "toggle": push goes high, next push goes
>low, and so on. In effect I need to "store" button presses: the PIC will
>be polling for them, but I can't use interrupts and can't guarantee the
>polling frequency. The button is a N.O. one, SPST. I also need to
>debounce, of course.
>
>I know I can get this with some cross-coupled gates (for debounce) and a
>flip flop (divide by two, basically) but I'm hoping there's a simpler
>(read: fewer components) way to do this. Are there ICs with this sort of
>function? Or some other cool way to pull (push?) this off?

Why don't you use the PICMicro for debouncing the button? This will
certainly minimize the number of components you need.

The code that I always use for sensing and debouncing press or release is:

Debounce ; Wait for the Button to be Pressed
btfsc Button ; While Button Pin is High, Wait
goto Debounce

movlw ?? ; Put in a constant for the next loop to
; have a 20 msec delay
Debouce_Loop ; Loop Here while the Button is being polled
btfsc Button ; Low
goto Debounce ; If the Button is High, Loop Back Again
addlw 0x0FF ; Decrement the "w" register (Counter)
btfss STATUS, Z ; If Zero, then 20 msec Delay with Button
goto Debounce_Loop ; has been completed - Button Debounced

In this code, the button is polled for it to go down (this is for "push")
and then it is checked for staying down for 20 msecs. To convert this code
for "release", just change the two "btfsc Button" instructions to "btfss
Button".

This algorithm can also be implemented using interrupts and TMR0 or multiple
buttons can be handled with it.

In the code above, I have assumed that "Button" is a define for the port and
pin:

#define Button PORTn,Pin

You could save the count value and use "decfsz" for the loop, but the method
shown above doesn't require any "Temp" variables.

>Would a pushbutton toggle switch be too easy? Digi-key sells them.
Too easy :-) Actually, the button I need to use is fixed by the design
(it's a teensy surface mount button, sized precisely for the enclosure,
etc.) so I can't change that, unfortunately. I need a circuit element to
debounce and toggle.

>Why don't you use the PICMicro for debouncing the button? This will
>certainly minimize the number of components you need.
Only because I can't: the PIC will be VERY busy doing other things while
the user is pushing buttons. As I said in the first note, I can't use
interrupts (they're already all used up for other things), so I really do
need to "externally" store the buttons presses for later polling when the
PIC has time.

Thanks for the suggestion, though! And BTW your book was ENORMOUSLY
helpful...

At 08:06 1998-10-28 -0800, you wrote:
>Brace yourself for a newbie electronics question:
>
>I need to make a push button "toggle": push goes high, next push goes
>low, and so on. In effect I need to "store" button presses: the PIC will
>be polling for them, but I can't use interrupts and can't guarantee the
>polling frequency. The button is a N.O. one, SPST. I also need to
>debounce, of course.
>
>I know I can get this with some cross-coupled gates (for debounce) and a
>flip flop (divide by two, basically) but I'm hoping there's a simpler
>(read: fewer components) way to do this. Are there ICs with this sort of
>function? Or some other cool way to pull (push?) this off?
>
>Thanks,
>
>Dave Johnson
>

YES
Just two inverters, two R, and a C !
(preferrably CMOS inverters, 4069 or 74HC04 etc)

Connect the inverters in series, with the second output to PIC input, and
through a 1k-10k resistor back to the first inverter input.
* Thus we made a bistable latch, which we can set as we want by short pulses *

Connect a resistor R2 from the connection between the inverters to C1, a
10n to 1µF cap, other cap end to GND. R2= approx 5 x R1
* Thus the cap will hold the opposite state of output (=currently the input) *

Connect the pushbutton between that cap and first inverter input.
Push, and the opposite state will be induced.
* Got it ? * :)

By higher R2 and C1 values we can set the minimum accepted time between
button pushes.
* This superseeds "debounce" function. *

(hope I am not wrong here...)

Extra 1
If the button is located outside encapsulation:
Add a RCR "pi" filter between button and inverter input.
Both R= R1/10, C = C1/10 This will take care of both EMI and some ESD.
For higher ESD protection add a Zener over this C.

Extra 2
Add a 220 ohm R directly in series with the second inverter output.
Thus, by making the PIC pin an output, the PIC can set the state as desired!
(useful to guarantee the right power up state!)
If the inverter is 4069 (etc) is possible even withput the R (CMOS are weak).

Extra 3
Indication by a LED through an R preferrably connected from the connection
between inverters (because of "Extra 2")
For the inverters to cope, use HC type, (or AC types for high current), or
make a driver from parallelling unused gates.

Extra 4
If R1 = 10 x R2, and inverters (at least the first) are schmidt trigger
(40106 or HC14) the cirquit will oscillate when pressing button, then stop
high or low when button released.
(Sure somebody might find it useful for something...?)

Tip:
There is a logic buffer (forgot its number) containing four buffers with
both inverting and noninvering output on each gate. = one gate per toggle
cirquit, four per IC.

Theory of operation: The Schmitt trigger in the first case biased by
the two 220k resistors to ¸Vcc, and the positive feedback in the second,
hold the current state. The capacitor holds the "debounced" version of
the opposite state, and transfers it to the Schmitt trigger when the
button is pressed.

Resistor values are chosen so that positive feedback exceeds the
negative so it is stable while the button is pressed. Increasing the
positive feedback resistors to greater than 3M ohm would cause automatic
cycling at about 1Hz whilst the button is pressed.

But you *really* wanted the software solution, didn't you?

> In effect I need to "store" button presses: the PIC will be polling
> for them, but I can't use interrupts and can't guarantee the polling
> frequency.

You need to store a bit variable for the current state and a counter
which are polled with the following code at a frequency somewhere in the
vicinity of 1kHz. You need to look at your code and resolve your
apparent inability to guess the polling frequency. Most PIC
applications involve timing and there are ways of doing this, I can't
accept that you are entirely unable to determine how fast your main
code loops.

I described the right one in my previous posting but was too lazy to make
ASCII art
-this is nice drawn :)

For the left one: Yes i have had it working too, but it is sensible to
glitches as V/2 is close to V/3 and 2V/3. Especially as the scmidt trigger
input is the wire that goes to pusbutton, and might catch much EMI.
Another problem is that the schmidt-trigger levels are not guaranteed very
preceisely at all by the manufacturers, and i wouild not be surprised if
some schmidt-trigger inverters in real life would have one level at around
V/2...
The design is neat, but I would not ship that design to customer.
Also, often the extra inverter in the right solution is cheaper than the
saved resistor, compared to the left solution.

Substitute the inverter in the left solution with a 555 timer ckt and the
trig levels will be guaranteed. (Still it is more EMI sensitive than right
solution though)
in= 2&6; out = 3; 1=GND; Vdd=8; use pin 7 and resistor to drive a LED. Pin
4 to system reset (low) or tie to Vdd.

>> I need to make a push button "toggle": push goes high, next push goes
>> low, and so on.
>
> Well, we will all tell you how to do it in software, so I might just
>mention the hardware solutions - use a single gate from a 74HC14 or
>two gates which do not then *need* to be Schmidt.
<snip>

Thanks for that, it *like* it, but it still requires as many or more
components than the cross-coupled gates and flip flop. Is there any
disadvantage to the latter approach I should know about? Is one or the
other more power hungry (this is a battery powered device). Seems like
"pure" digital cmos might use less power, yes?

> But you *really* wanted the software solution, didn't you?
I was convinced there wasn't one (for this particular application): The
problem is that there are many possible "modes" of operation, and some of
them have very busy, longish loop times (lots of forking off to do other
things), while others are mostly waiting around for something to happen.
Additionally, in one of the modes this same button will need to generate
an interrupt to wake the PIC from sleep: polling obviously won't work
there (sorry I forgot to mention that 'til now). So it seemed to me that
a hardware debounce and "store" was the best, most straightforward
solution. But I'm open to suggestions.

By the way, I fully expect that in some modes I may miss the occasional
press, if the user is pushing the button like crazy and I'm polling
infrequently. And that's OK.

Dave Johnson wrote:
> I was convinced there wasn't one (for this particular application): The
> problem is that there are many possible "modes" of operation, and some of
> them have very busy, longish loop times (lots of forking off to do other
> things), while others are mostly waiting around for something to happen.
> Additionally, in one of the modes this same button will need to generate
> an interrupt to wake the PIC from sleep: polling obviously won't work
> there (sorry I forgot to mention that 'til now). So it seemed to me that
> a hardware debounce and "store" was the best, most straightforward
> solution. But I'm open to suggestions.
>
> By the way, I fully expect that in some modes I may miss the occasional
> press, if the user is pushing the button like crazy and I'm polling
> infrequently. And that's OK.

Try Scott's debounce technique (using vertical counters) to debounce
your buttons. It is single pass (no looping) and can be placed in the
timer interrupt or can be called once in a while.

If you're willing to miss an occasional keypress, you could use something
like a 555 (or a simple r/c/transistor scheme) to debounce/stretch each
keypress until you are "almost certain" to be able to detect it in some
outer loop, and then do the toggle function in software.

Frustrating that no one makes a dual schmidt trigger in a 6 pin dip, eh?

> If you're willing to miss an occasional keypress, you could use something
> like a 555 (or a simple r/c/transistor scheme) to debounce/stretch each
> keypress until you are "almost certain" to be able to detect it in some
> outer loop, and then do the toggle function in software.
>
> Frustrating that no one makes a dual schmidt trigger in a 6 pin dip, eh?

Being of the simple persuasion myself, why not simply charge a
small capacitor when you push this switch. This will hold for quite a
while on an input pin impedance and wait for your pic to poll. When
it has polled make the pin an output and empty the capacitor ready
for the next push (can this be done with the pic?). Failing that, use
a diode to a discharge pin. If you have a few buttons, use a few
diodes, discharge them all with one pin after you have polled them
all.
Simple, I know but should work unless you are waiting tens of seconds
for software to loop round.

> Brace yourself for a newbie electronics question:
>
> I need to make a push button "toggle": push goes high, next push goes
> low, and so on. In effect I need to "store" button presses: the PIC will
> be polling for them, but I can't use interrupts and can't guarantee the
> polling frequency. The button is a N.O. one, SPST. I also need to
> debounce, of course.
>
> Dave Johnson
>
>

I think that if you want this to work reliably in software you need
at least a very very very basic real time executive - this can be as
simple as a constant period timer interrupt incrementing a register
which you can use to measure passage of time OR have the interrupt
routine do the timing.
{{Expert criticism flame shields up: Yes I know this doesn't describe
an RTE per se, but functionally that's what is achieved. ECFSDown}}.
If the timer is already in use (presuming the PIC you are using only
has one) you may be able to do both tasks with the same timer
interrupt or using the timer without interrupt. If you are not using
the timer at all you will find that this is by far the easiest way of
getting "real time" results. In most cases it will be possible to
"share" the timer as above. The penalty may be interrupting very fast
to get a fast enough timer tick to be useful to all tasks - this
results in a significant loss of processing power for non-interrupt
tasks. (eg a 9600 baud software synchronous serial receive MAY need 4
x 9600 ~ 40,000 interrupts per second = 25uS per interrupt (actually
26.04 :-) ) . You wouldn't want to do that with a 4MHz PIC if you
could at all help it.

Try a D-type flip-flop (the 74HC74A has 2 in a 16 pin DIL). If you connect
the /Q output to the D input, then every time you pulse the clock with your
pushbutton the Q output is toggled. The only other component needed is the
10k pull-up resistor on the connection between the pushbutton and the
74HC74A clock input. You would also need to give normal consideration to
all the unused inputs, connecting them to Vdd or Vss as appropriate.

> Thanks for that, it *like* it, but it still requires as many or more
> components than the cross-coupled gates and flip flop.

I count two gates, two resistors and a capacitor. That sounds a lot
*less* than cross-coupled gates, flip-flop, two resistors and a
capacitor. By definition, you *must* have the bias resistor for the PB,
and you need an R and C for debounce. Unless of course you use a SPDT
button which you have already overruled - in which case you would need
two resistors but not the capacitor. I find unacceptable the cross-
connected gates with the SPDT buttton grounding alternate arms without
the resistors, so I can't see you save on resistors that way either.

> Is there any disadvantage to the latter approach I should know about?
> Is one or the other more power hungry (this is a battery powered
> device). Seems like "pure" digital cmos might use less power, yes?

I'm not sure whether by "latter" you mean my right-hand circuit, or
your cross-coupled-gates etc. proposition? I agree with Morgan, my
right-hand circuit is much preferable as it has a far wider noise
threshold (Vcc/2) and draws *no* current at rest. Since (Schmitt)
inverters come in sixes, you might as well use two.

Both circuits however have a limitation that I do my utmost to avoid;
a switch with both "signal" leads as against one grounded. Having one
lead grounded is a great protection against induced impulses causing
spurious operation or damage.

>> But you *really* wanted the software solution, didn't you?
> I was convinced there wasn't one (for this particular application):

But it sounds like you are working on it already. It has the
tremendous advantage that the button is SPST (N/O), grounded and uses
only a bias resistor. Keep your finger off the button and it uses no
current either.

My code was of course very rough-and-ready but in fact debounce
intervals and even auto-repeat rates are immensely flexible so even if
they vary from one mode to another, I am sure you can integrate it
(perhaps more as macros than a subroutine, unless of course code space
is short).
--
Cheers,
Paul B.

> Try a D-type flip-flop (the 74HC74A has 2 in a 16 pin DIL). If you
> connect the /Q output to the D input, then every time you pulse the
> clock with your pushbutton the Q output is toggled. The only other
> component needed is the 10k pull-up resistor on the connection between
> the pushbutton and the 74HC74A clock input.

Brian, I«m not sure you understand the significance of contact bounce.
When you actuate a switch, the contacts do *not* just make and hold, but
make, break again and re-make quite a number of times at a frequency
generally in the audible range.

While the average light bulb will not respond to this rapid switching,
a logic chip such as the 74HC74A you mention will obediently respond to
*every* such make and break (or indeed any sequence of them up to a
frequency of 40MHz!). Insead of detecting a keypress, it registers a
dozen!

Ignoring only the first within a "settling" period of some ten to
fifty milliseconds is an art or procedure called "de-bouncing" and the
real subject of this thread. If you haven«t had this experience, grab
your breadboard, a 74HC74A, sundry resistors, LED and a garden-variety
switch (push-button or microswitch) and see what a circus it is.
--
Cheers,
Paul B.

>At 05:11 1998-10-29 +1000, Paul Webster wrote:
>>Dave Johnson wrote:
>>
>>> I need to make a push button "toggle": push goes high, next push goes
>>> low, and so on.
>>
>> Well, we will all tell you how to do it in software, so I might just
>>mention the hardware solutions - use a single gate from a 74HC14 or
>>two gates which do not then *need* to be Schmidt.
>>
>> 2M2 ohm 2M2 ohm
>> *------/\/\/------* *---/\/\/------*
>> | | | |
>> | ___ PB |\ | | ___ PB |\ | |\
>> +--o o-----+-| o--+----O out +--o o---+-| o-+-| o-+-O out
>> | | |/ | | |/ |/ |
>> | | 1/6 74HC14 | | 74HC14 |
>> --- 0.47µF | --- 0.47µF| |
>> --- | --- | |
>> | 220k ohm | 220k ohm | | 100k ohm |
>> +--/\/\/---+---/\/\/---Vcc | *--/\/\/----*
>> | gnd
>> gnd
>-snip-
>
>Two soles sharing the same thought :)
>
>I described the right one in my previous posting but was too lazy to make
>ASCII art
>-this is nice drawn :)
>
>For the left one: Yes i have had it working too, but it is sensible to
>glitches as V/2 is close to V/3 and 2V/3. Especially as the scmidt trigger
>input is the wire that goes to pusbutton, and might catch much EMI.
>Another problem is that the schmidt-trigger levels are not guaranteed very
>preceisely at all by the manufacturers, and i wouild not be surprised if
>some schmidt-trigger inverters in real life would have one level at around
>V/2...
>The design is neat, but I would not ship that design to customer.
>Also, often the extra inverter in the right solution is cheaper than the
>saved resistor, compared to the left solution.
>
>Substitute the inverter in the left solution with a 555 timer ckt and the
>trig levels will be guaranteed. (Still it is more EMI sensitive than right
>solution though)
>in= 2&6; out = 3; 1=GND; Vdd=8; use pin 7 and resistor to drive a LED. Pin
>4 to system reset (low) or tie to Vdd.
>
>
>The right one is the right one (what a language...) to use ;)
>
>/Morgan
> Morgan Olsson ph +46(0)414 70741
> MORGANS REGLERTEKNIK fax +46(0)414 70331
> H€LLEKS (in A-Z letters: "HALLEKAS")
> SE-277 35 KIVIK, SWEDEN KILLspammrtKILLspaminame.com
>___________________________________________________________
>

>
> Dave Johnson wrote:
> > I was convinced there wasn't one (for this particular application): The
> > problem is that there are many possible "modes" of operation, and some of
> > them have very busy, longish loop times (lots of forking off to do other
> > infrequently. And that's OK.

>
> Try Scott's debounce technique (using vertical counters) to debounce
> your buttons. It is single pass (no looping) and can be placed in the
> timer interrupt or can be called once in a while.
>
> To toggle the state of the button, just do a xor on the last reading.
>
> Ex:
> movf switch,w ;assume 1 = on
> xorwf toggle_state

>> Thanks for that, it *like* it, but it still requires as many or more
>> components than the cross-coupled gates and flip flop.
>
> I count two gates, two resistors and a capacitor. That sounds a lot
>*less* than cross-coupled gates, flip-flop, two resistors and a
>capacitor.
Ah, you are so very right. I was ignoring the resistors (silly me) and
also failed to acknowledge the fact that the cross-coupled gate thing is
for SPDT. I stand corrected. That two inverter circuit is looking better
and better...

>>> But you *really* wanted the software solution, didn't you?
>> I was convinced there wasn't one (for this particular application):
>
> But it sounds like you are working on it already. It has the
>tremendous advantage that the button is SPST (N/O), grounded and uses
>only a bias resistor. Keep your finger off the button and it uses no
>current either.
I'm certainly considering it, and hoping I can do it. One question,
though: if I want this same button to wake the PIC from sleep (in one
mode), doesn't that preclude a software solution? Or am I missing
something (highly likely!).

I really haven't explored the dark deep mysteries of sleep and external
interrupts yet, but it won't be long now...I really need to get away from
the breadboard and write some code and see how long the longest loop will
be (at this point the code is still mostly on paper, and still a little
vague).

Russel McMahon wrote:
>I think that if you want this to work reliably in software you need
>at least a very very very basic real time executive - this can be as
>simple as a constant period timer interrupt incrementing a register
>which you can use to measure passage of time OR have the interrupt
>routine do the timing.
>{{Expert criticism flame shields up: Yes I know this doesn't describe
>an RTE per se, but functionally that's what is achieved. ECFSDown}}.
>If the timer is already in use (presuming the PIC you are using only
>has one) you may be able to do both tasks with the same timer
>interrupt or using the timer without interrupt.
This is on a 16F84 at 10 MHz, and TMR0 is used for serial receive at
19.2K. (Serial transmit is software loop timed: this way transmits can be
"interrupted" by receives. What do you call this? 3/4 duplex? :-). Most
of the time the timer is set to external clock, preloaded with 0xFF,
waiting for a start bit on RA4 to roll it over and generate an interrupt,
signifying a character coming in. And during a character receive the
timer is of course very busy generating interrupts like crazy. So I'd
rather leave the timer alone, if I can. I will, however, ponder the state
diagram for the device and see if there are cases where button presses
are concurrent with potential receives: if not, then maybe I can get the
timer doing double duty. But I don't think I want to try to "interleave"
timer functions.

Many thanks to all: I have to say that this list has one of the best
signal to noise ratios I've seen. Little did I know my simple question
would generate so many responses! I think I have enough info to make it
work now, either in software or with the double-inverter circuit. The
only remaining question in my mind is whether a pure software solution
will work in the "wake up the PIC" case: maybe for that debouncing isn't
so necessary? time to hit the data sheets...

|I was convinced there wasn't one (for this particular application): The
|problem is that there are many possible "modes" of operation, and some of
|them have very busy, longish loop times (lots of forking off to do other
|things), while others are mostly waiting around for something to happen.
|Additionally, in one of the modes this same button will need to generate
|an interrupt to wake the PIC from sleep: polling obviously won't work
|there (sorry I forgot to mention that 'til now). So it seemed to me that
|a hardware debounce and "store" was the best, most straightforward
|solution. But I'm open to suggestions.

One possibility may be to have the button drive the clock
of a "D" flip-flop whose D and Q inputs are both tied to
PIC port pins. Every time the software noticed a state
change on the signal from the latch, it would write the
opposite signal out to D (after some minimum delay). This
would have the 'feature' that once the button was pushed,
no futher button presses would have any effect until the
PIC acknowleged the first one (whether this is a good or
bad thing would depend upon the application).

As an alternative, the Q' -> D latch idea someone else had
offered wouldn't be bad if there were an RC delay between
Q' and D. This method would have the advantage that one
side of the switch could be at VDD or ground; I don't know
how the current consumption of edge-triggered latches com-
pares with that of inverters, though.

> I'm certainly considering it, and hoping I can do it. One question,
> though: if I want this same button to wake the PIC from sleep (in one
> mode), doesn't that preclude a software solution?

I don't see a problem. You are presumably going to put the button on
RB0 to generate an interrupt - it escapes me at the moment whether it
should pull high or low or whatever, but for wakeup, debouncing is
irrelevant; the first event is sufficient.

You may have to look into the initial conditions of the debounce
routine to deal with the finger still being on the button after the PIC
is woken and running.

>> I think that if you want this to work reliably in software you need
>> at least a very very very basic real time executive - this can be as
>> simple as a constant period timer interrupt incrementing a register
>> which you can use to measure passage of time OR have the interrupt
>> routine do the timing.

My point was that for the purpose of debouncing buttons, the timer
("tick") period does not have to be particularly constant.
--
Cheers,
Paul B.

>I need to make a push button "toggle": push goes high, next push goes
>low, and so on. In effect I need to "store" button presses: the PIC will
>be polling for them, but I can't use interrupts and can't guarantee the
>polling frequency. The button is a N.O. one, SPST. I also need to
>debounce, of course.
>

You may want to go to my site and have a look at the ELM411 (or at
least grab a data sheet). This chip is based on the 12C508, so needs no
external components to interface to three push-buttons simultaneously. Only
one output provides the latch function that you need, while the other two
are simple inverters. All three have ~25ms debounce on pickup and dropout.
(I've seen inexpensive pushbuttons bounce for as much as 15ms).
If you'd prefer two make your own, I'd still say the '508 is the
way to go. It has it's own internal oscillator, and pullups on three of the
6 I/Os. Runs on almost no power, and has plenty of code space for what you
want to do.

>Try a D-type flip-flop (the 74HC74A has 2 in a 16 pin DIL). If you connect
>the /Q output to the D input, then every time you pulse the clock with your
>pushbutton the Q output is toggled. The only other component needed is the
>10k pull-up resistor on the connection between the pushbutton and the
>74HC74A clock input. You would also need to give normal consideration to
>all the unused inputs, connecting them to Vdd or Vss as appropriate.

Sorry Brian, but I wish you would try this before suggesting it as a viable
solution. This would make a nice RANDOM toggle but will NOT give a reliable
alternate action toggle.

But why, you might ask? Its because the pushbutton switch has lots and lots
of contact bounce. Each bounce looks exactly like another pushbutton press
and toggles the output.

This CAN be made to work - it requires that the pushbutton be a SPDT switch.
One section of the '74 is configured as a set-reset FF using the set and
clear inputs. The output of that stage feeds the clock input of the other
FF in the '74. But some of the previous suggestions are easier to implement.

I've been on holiday but did I see a whole thread about software implementation
of a toggle action switch? I was
fiddling with the same idea for a remote volume control.

What I came up with works OK on MPLAB\MPSIM - toggles ON\OFF & tests for Volume
up/down
for 4 volume levels, controlled by bits 0,1 operating an attenuator. Yeah, I
know, it ain't pretty but it's a
first attempt and it seems to work, more or less.

I'm using the motorola MC145026 Tx\MC145027 Rx to take care of debounce with
minimal component count - it
can decode a 4x4 pad but I'm only using 4 keys. It gives a clean "valid
transmission" pulse whenever it provides
updated data. The PIC is a 16C54.

Trouble is, when loud\soft gets to the end of the count, it rolls over to max\mi
n
volume. Must put a lockout on the count
as I want one button on the transmitter to step up to max then hold, the other t
o
step down to min, then hold.

Bet this has been done lots of times! Other ideas\approaches would be most
welcome.