So I've been playing with an ATtiny45, and it occurs to me that I could probably brute force PWM by prescaling a timer to sysclock/64, then running ISR code that manually switches the outputs on or off depending on global variables set elsewhere in code or via IO. At max sysclock speed of 20MHz I oughta get decent resolution, and I'll get to use all my IO pins as PWMs instead of the two the chip provides, so the big question is...why not? Other than using up a lot of sysclock cycles, I don't really see disadvantages...could someone give me some?
The three disadvantages are Power Consumption, tying up a Timer, and interrupting other code. If you don't care about low power modes, and have no need for the timer, and have no critical code that can't withstand a few clock cycles to service the interrupt, there is no disadvantage. Some projects are fairly simple, and don't take up a tenth of the power of the microcontroller, so don't let anyone tell you you are doing it wrong by taking advantage of the timers like that. Software PWM is fine if it fits your needs.
I've just recently been playing with a lot of PWM switching power supply stuff, and you're right, there are perfectly valid reasons to "bit bang" pulse width modulated signals. But one of the chief failings of this method is when you need immediate feedback control of the generated duty cycle.
Even with a 20 MHz onboard clock, the cycle time is 50 nanoseconds. Computationally, you would have to acquire the signal being monitored, subtract it from the reference level, and then resume generation of the duty cycle. This will create "jitter" where the duty cycle is inconsistent. Using an onboard DAC isn't out of the question, but it eats up cycles. To trim down on this, you could add an external DAC, but then you have committed maybe 8 or 12 pins from the microcontroller to the external DAC for a quick reading (depending on how much resolution you want). Then you have to worry about additional signal propagation delay through switching components.
If what you want is rapid feedback control, it's hard to beat an independent duty cycle IC. The delay of the on board error amplifier is so small that you're more worried about the gain changing at high frequencies. Signal propagation through switching is still the same risk, of course, and has to be designed around.
It is also worth pointing out that a lot of PWM IC packages have shutdown features and dead time control inputs that can do really nifty things when coupled with a microcontroller, all on an 8 or 16 pin package.
It's pretty much up to you to decide if the bit bang method can support your needs. You can actually get the frequency up pretty high if you use a lower prescaler. The duty cycle you get will show quantization error, but that may not even be a big deal depending on what you're doing and how high you take the resolution; but then again, higher resolution comes at the cost of lower frequency. If you don't require instant feedback control, and your application can handle some jitter, then bit-banging may be the way to go.
The point of having hardware devices on the chip is to free up the processor for other tasks. If you use PWM hardware then you can simultaneously do other microcontroller tasks.
Now I think you've picked up on this bit because you are asking about using an ISR instead of running a for/while loop brute force counter but again it is the same answer. If we don't change the width of the pulse why would we want to interrupt our other tasks unnecessarily?
You can easily do what you say - I've done it a few times. It's more useful if you want to change your PWM at predictable times; you can do this by counting the number of PWM cycles, and you'd need a timer to do that anyway.
However, there is a tradeoff between the resolution of the PWM / # of outputs vs the amount of free processor time. You will reach a point where you don't have enough free CPU to make it work.
I recommend hooking a scope up to a free pin, and then setting that pin high at the beginning of the ISR and low at the end. This will let you see the proportion of the time your routine is using.
Software PWM does not have to very CPU intensive if done in a right way, like using Binary Code Modulation. With this nice and simple technique you can have a lot of SoftPWM channels without a big CPU overhead.
Personally I've found the timer PWMs are faster and consistent (in full 256 range, if you don't need such resolution, software["brute-force"] can be faster) , and when I've needed more than 2 I tried soft PWMing alongside the hard PWMs and it wan't very smooth so I opted to do all PWM in software and it turned out great.
The only thing is when doing and intermediary calculations/processing/interrupts that take a bit of time, the soft PWM stalls and can be very noticeable.