Why would I want to toggle an input pin?

Go To Last Post
29 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The data sheet says I can:

Quote:
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a port.
Why on Earth would I ever want to toggle an input? Does anyone do this and if so why and if not why is it a feature worth mentioning in the data sheet? Maybe I'm miss reading this and this is an alternate way to change an output pin, but why would I want to do that. Oh wait, is this how I'd toggle an output pin without knowing its state and not wanting to use the xor bitwise operator. I'm confused.

Smiley

Last Edited: Sat. Aug 27, 2011 - 10:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I'm reading the datasheet correctly, writing a 1 to the PINxn register engages the internal pull-up resistor on that particular pin if DDRxn is set to make that pin an input.

So... if the pin is configured as an output, writing a 1 to the PIN register will toggle the pin - while if the pin is an input, writing a 1 will engage the pull-up.

(Of course... I COULD be wrong. :) )

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do this quite often and find it very useful in bit banging code etc. The PINx just became a writable SFR instead of being read only - this allowed to add the toggle feature without wasting a tight SFR address space with a dedicated toggle SFR.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What d.sht. is that for ? I've seen code here that uses it to as a way to toggle an output pin. I GUESS it's smaller code-wise than using the C operator to do it, for 1 bit toggling anyway.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

RocketMan_Len wrote:

(Of course... I COULD be wrong. :) )
Of course you ARE wrong.

The pullup is turned on by writing a 1 to the PORTx bit while the port is configured as INPUT.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Why on Earth would I ever want to toggle an input?

Quote:

I've seen code here that uses it to as a way to toggle an output pin.

What is exactly what the datasheet says. No, Smiley, it says >>nothing<< about toggling an input.
Quote:

I GUESS it's smaller code-wise than using the C operator to do it, for 1 bit toggling anyway.

Indeed it is smaller. (What does a C operator have to do with it, anyway?!?) More importantly, it allows the toggling operation to be atomic. There is no other atomic way to toggle the state of an AVR output pin with "straight" code.

https://www.avrfreaks.net/index.p...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
What does a C operator have to do with it, anyway?!?
Plenty .
PORTB ^= (1<<OUTPUT); // C operator used to tog. a bit.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

PORTB ^= (1<<OUTPUT); // C operator to tog. a bit.

So, I repeat:
Quote:

What does a C operator have to do with it, anyway?!?

Yes, C has a + operator and the AVR instruction set has an ADD. How are the two of them directly related?

The same goes here: What does writing to PINx have to do with the C ^ operator?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm, well I should've said "...than using the PORTx way to do it.", since using ^ would happen using PORTx or PINx.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Set an output then clear an output is 2 instructions. Toggle the output is 1 instruction. Makes tight loops faster. Guys like Igor use this to bitbang fast stuff like usb.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could toggle to trigger an external ISR. Not sure why.

It all starts with a mental vision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
Set an output then clear an output is 2 instructions.
It's at least 4 instructions - read PORTx to one register, write a bit mask to another register, XOR the two registers, and write back to the PORTx. Plus another two instructions to disable and re-enable interrupts to avoid the RMW side effects.

P.S. KitCarlson, please do not say gibberish.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
... Guys like Igor use this to bitbang fast stuff like usb.
Okay, now that makes sense for a use case.

I think I need to reread that section of the data sheet though as I'm still not 100% about this. It is difficult to explain to folks how to do something when you aren't completely sure why they would do it.

And more realistic use cases?

[edit]
No, wait, that doesn't make sense. Oh, crap I'm going to bed and rethink this tomorrow if my brain returns to my skull.
[/edit]

Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

And more realistic use cases?


Let's just put it this way: It is common to have an instruction set with set/clear/toggle. AVR's did not have the toggle feature in early generations. Atmel added it in later generations thucs completing the set of normal port bit operations.

Why? Why cares. There has been a LOT of talk here about ARM vs. AVR. All the ARMs I've looked at have set/clear/toggle.

Mostly I find I use it as a debugging toggle on a spare pin/LED. so not that bit a deal, but if using the conventional way be very careful if the port is manipulated i9n an ISR and the mainline.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Quote:
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.

Why on Earth would I ever want to toggle an input?

Read it again. You aren't toggling the input you are toggling the output.

You are writing a logic one to PINxn which doesn't seem to make sense since this is where you would normally read the input levels. This unusual operation then causes the output at the corresponding PORTxn pin to toggle.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, this is making sense now. Toggling the output uses a seemingly nonsense operation of setting the PINx bit when that pin is in the output mode - in the same way that setting the pullup resistor uses the also seemingly nonsense operation of setting a bit in PORTx when that pin is in the input mode. I've always used the bitwise operator to toggle bits, but I guess this makes sense if I want to optimize the operation. A bit weird way to toggle a bit, but I get it now.

Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Toggling the output uses a seemingly nonsense operation of setting the PINx bit when that pin is in the output mode
It saves implementing a whole new register and was a combination of DDR/PORT/PIN that didn't already have a defined function.

In Xmega you have DIR (DDR), DIRSET, DIRCLR, DIRTGL, OUT (PORT), OUTSET, OUTCLR, OUTTGL, IN (PIN). So they seem to have gone completely over-board to cover all bases ;-) (in case it's not clear *SET sets bits, *CLR clears bits and *TGL toggles bits)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

+1 for toggling LEDs (Lee was first) if I don't care about off or on, but about some change in state.

I tend to post off-topic replies when I've noticed some interesting detail.
Feel free to stop me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Set an output then clear an output is 2 instructions. Toggle the output is 1 instruction.

and
Quote:
It's at least 4 instructions

Being more realistic - toggling is atomic, while the "set of four" is not, you need to add:

in temp,SREG
cli
"set of four"
out SREG,temp

if used in main in many cases.

If you consider IO registers as additional low functionality working registers, then:

    - set(or add 2^n)
    - clear(or sub 2^n)
    - toggle(good for if(bool) )
are fast and small to use.

What is more(rather off topic in PINx subject), read/write to IOs is twice as fast as push/pop so slow pushpopping on ISR entry/return can be cut in half with those IOs, IMHO more suitable for that task.

Bit/nibble low IO locations are good for static variables(with toggling and sbis as if()) while byte IOs (like GPIORs, TCNT, OCR etc) are good for ISR pushpopping.

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KitCarlson wrote:
You could toggle to trigger an external ISR. Not sure why.

I see using this as a way to emulate a "trap" instruction that is sorely missing on the AVRs.

As to why:
I have a backburner project that will use this.
My use is to use it on INT0 to grab control of the processor so that it can then talk to low level code that eventually talks to GDB for
source level debugging using only a serial interface rather than the current method of depending on DW or JTAG.

I've got all the pieces together to do it,
just haven't finished it up.

Down in the bowls of the GDB interface it currently uses the Break instruction.
If that is instead changed to use the single instruction that simulates this high level trap (requires a custom build of GDB), you can leave the guts of the low level GDB code alone.

Anyway, debugging is already possible without this "trap" instruction but you need to have a way to trap into the low level AVR "gdbmon" code for "code" breakpoints.
("code" breakpoints being breakpoints that modify the code/flash with the "trap" instruction).
"code" breakpoints can be done in s/w only without modifying the flash. i.e. "soft" breakpoints.
It requires enabling a hard interrupt that is set but never cleared
while "looking" for the desired breakpoints.
The ISR looks at the PC to see if a desired breakpoint has been reached, if not, it leaves the ISR but does not clear the pending interrupt source. It works but
then the AVR does not run anywhere near full speed.
Having a single instruction that can "trap" into the low level debugger code is key to making real-time breakpoints happen.

The optimum method is to use "soft" breakpoints that monitor the PC in ISR while single stepping but then use the "code" breakpoints to allow the code to run full speed up the desired code breakpoint.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If that is instead changed to use the single instruction that simulates this high level trap (requires a custom build of GDB), you can leave the guts of the low level GDB code alone.

To generate the INT0 you have to do an OUT or something? If that's the case then why not just an RCALL to the trap code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The optimum method is to use "soft" breakpoints that monitor the PC in ISR

You want to implement a monitor (software) which is under control of (GDB+serial port) and allows break on specific PC value?
What about JTAG?

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What about JTAG?

An AVR model that's only supported by the closed firmware of the recent Atmel debuggers perhaps?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MBedder wrote:
RocketMan_Len wrote:

(Of course... I COULD be wrong. :) )
Of course you ARE wrong.

The pullup is turned on by writing a 1 to the PORTx bit while the port is configured as INPUT.

Not entirely wrong. Writing a one to to PINxn toggles the value of PORTxn independent of the value of DDRxn. So, if PINxn is configured as an input (PORTxn is 0), writing a one to PINxn will toggle the state of the pullup (provided PUD is not set). At least, that's what I get looking the General Digital I/O figure in the data sheet. Of course . . . I could be wrong.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

If that is instead changed to use the single instruction that simulates this high level trap (requires a custom build of GDB), you can leave the guts of the low level GDB code alone.

To generate the INT0 you have to do an OUT or something? If that's the case then why not just an RCALL to the trap code?

RCALL is not good enough. It only gets you +/- 2k
that will not work in the general case.
I need something is only a single word instruction *AND* can block all interrupts.

The goal is to provide source level debugging for something like an Arduino board where the only h/w interface you know you have available is a serial port.

I'll post a new thread with full details when I finally have it fully up and working.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MBedder wrote:
RocketMan_Len wrote:

(Of course... I COULD be wrong. :) )
Of course you ARE wrong..

Yup - I misread the datasheet. My bad... :oops:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
And more realistic use cases?

The Arduino bootloader (512 bytes) manages to save a couple of bytes by blinking the activity LED with this structure. No saved state or registers required.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

RCALL is not good enough. It only gets you +/- 2k

So use CALL?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

RCALL is not good enough. It only gets you +/- 2k

So use CALL?

It isn't a single word plus it won't mask interrupts.
Again, my use is quite special in that it is grabbing complete control of the CPU. You can modify the low level GDB stuff to make it work with a multi word sequence, but a single word sequence will make things easier.

--- bill