Pin change interrupts are usually not a good way to detect button actions. This is because mechanical buttons bounce, and you will get lots of meaningless interrupts, and then you still have to do debouncing anyway.
A better way is to have a periodic interrupt, like every 1 ms (1 kHz rate). That's a long time on most processors, so the fraction of time spent in the interrupt will be small. Simply sample the button state every interrupt. Declare a new button state if you have seen the new state 50 ms in a row. 50 ms is longer than most buttons bounce, but is still short enough so that humans won't notice or care about the lag.
Note that this way you can also handle multiple buttons in the same periodic 1 ms interrupt. All you need is one counter for each button.
More on debounce time:
Occasionally, as in this case, someone says 50 ms is too long a debounce time. This is not true for ordinary buttons pressed by humans. It might be a issue perhaps in very timing-critical applications like a stopwatch, but so far I haven't run into one. I did test on this in the early 1980s, and lots of other people have too.
It is true that typical pushbutton bounce time is around 10 ms, with just about all settling by 25 ms. The limiting factor on debounce time is human perception. 50 ms is a bit shorter than where people start to notice a delay when they aren't looking for it. Even then, it takes a much longer time for it to be annoying. It can be possible in some cases for a human to detect a difference between 50 ms and 0 ms delay if they are specifically looking for it, but that is quite different from pushing a button and seeing something happen and not thinking about the delay.
50 ms is therefore a good debounce time because the delay is below the perception limit in ordinary applications, way below the annoyance limit, and well above the bounce time of most switches. I have found switches that did bounce for nearly that long, so you might as well push to the perception limit since there is nothing to loose.
I have done many products with firmware-debounced buttons using 50 ms debounce time. Not once did a customer mention even noticing a delay. They all accepted the buttons as working fine without issue.
Until I checked the ATtiny45 datasheet today I was convinced that you can't program the AVR after programming RSTDSBL in Fuse High Byte. But then I stumbled over this note under Table 6-7 Start-up Times for Internal Calibrated RC Oscillator Clock"
Note: 1. If the RSTDISBL fuse is programmed, this start-up time will be increased to 14CK + 4 ms to ensure programming mode can be entered.
Now it doesn't mention what programming mode is refered to, either High Voltage or SPI. So if your programmer supports it, you may be able to enter the programming mode within 4ms after power up, instead of using the "\$\overline{\text{RESET}}\$-line protocol" (don't know the proper name for it). You should even be able to verify this without programming the RSTDISBL fuse, and just by programming Start Up Times (SUT[1:0] in Fuse Low Byte) for the internal RC osscillator.
Chapter 20 on page 147 and onwards explains various modes for programming of the devices, but fails to mention the RSTDISBL fuse. Seems you need trial-and-error to be 100% sure ...
I personally use Arduino to ISP program AVR's and I suppose one should be able to hack the ArduinoISP sketch to power up the AVR and start the programming handshake within 4ms after that. But I never tried it myself.
Of course you could reset the fuses for your controller using a high voltage programmer like the AVR Dragon. (Dragon apparently isn't able to power cycle the target device, so Dragon won't support programming without utilizing the \$\overline{\text{RESET}}\$-line). On the other hand, Dragon does support HV programming, which solves your problem either way.
Or you could improvise an HV-programmer to reset the default fuses.
Best Answer
The problem is you have an ISR on the
PCINT1
vector, but the vector for PORTB pin changes isPCINT0
. Uninitialized vectors jump to address 0, so the MCU resets when a pin change interrupt occurs on PORTB.This is an easy mistake to make because
PCINT1
is the designation of pin PB1 for pin change, and also the name of the vector for pin change interrupts on PORTC (thanks Atmel!).You need to change
ISR(PCINT1_vect)
toISR(PCINT0_vect)
.Yes (this is how I found the error in your code). In AVR simulator you can simulate a pin change by clicking on the pin to toggle it, then follow the resulting code execution with 'step into' (F11). View disassembler to step through the machine code one instruction at a time.