On Fri, 9 Aug 2002, Kieren Johnstone wrote: > Surely if TMR0 overflows at 19.5 KHz, by switching a PWM every time I could > get 9.7 KHz, every 256 interrupts I could get about 76 Hz; in the original > post I mentioned 4.9 KHz being the highest note I'd consider.. Kieren, You misunderstood Olin. PWM = Pulse Width Modulation, normally means constant frequency and varying duty-cycle. What Olin said is that the constant frequency for what you proposed is 76 Hz. But now, you seem to be suggesting that you want to generate square waves for your tones! However, let me suggest a slightly different way in which "PWM" can be generated. Suppose you divide time into equal intervals. At each interval you generate a high or a low; i.e. a pulse. Over a period of N pulses, you're average ouput will be: avg = # of high's / total # of time slots So for example, if you had 100 time slots and 10 of these were high pulses (and 90 low ones) then the average would be 10/100 = 1/10. With normal PWM, all of the high pulses are grouped together as one pulse. But from a signal processing point of view, this is not necessary. So for example to get the value 1/10 you could generate these various pulse streams: 10 H, 90 L 5 H, 45 L, 5 H, 45 L, 1 h, 9 L, 1 H, 9 L Or even this would work: 3 H, 20 L, 1 H, 33 L, 5 H, 7L, 1 H, 30 L In other words, over the 100 pulses you want 10 high ones and 90 low ones. If you're driving a motor (or some other big thing that can incur large switching losses), you may want to minimize the switching and so you'd choose the 10/90/10/90 approach which groups the highs together. If you're generating audio, you may wish to *maximize* the carry frequency - preferably beyond the range of human hearing, so that it is easier to filter. Thus you'd choose the 1/9/1/9 approach. To maximize the frequency, all you need to do is implement PWM with phase accumulators. In this case, all you do is repeatedly add your "duty cycle" to the phase accumulator. If the phase accumulator rolls over, you output a "1" if not you output a "0". So for example: unsigned char phase = 0; unsigned char analog = 15; // i.e. 15 out of 256 while (1) { old_phase = phase; phase = phase + analog; if(phase < old_phase) output = 1; else output = 0; } Play with this for different values of "analog" and observe how "output" changes. Once you grasp it then consider this assembly code: movf analog,w ;Get the current analog value addwf phase,f ;Add it to the phase accumulator ; carry get's set if we rollover. rlf output,f ;Lsb contains the "rollover" info What's nice about this is that multiple PWM's can be constructed by just repeating this snippet. The variable "output" is copied to the I/O port at the last stage. For 4 outputs, the last rlf will look like this: rlf output,w andlw 0x0f movwf PORTB With this scheme, the maximum frequency occurs at your 9.6 kHz for an analog value of 1/2 and the minimum frequency is 76 Hz for analog value 1/256 or 255/256. I'd be inclined to write an isochronous loop so that the frequencies are somewhat higher. You'll want to run this through a low pass filter to knock off the edges. Now, note that you don't get something for nothing. It still takes time to achieve the "average" analog value you seek. It also takes time to generate the desired signal. This scheme may help, but at these frequencies you won't ever be competing with Yamaha synthesizers! Scott -- http://www.piclist.com hint: To leave the PICList mailto:piclist-unsubscribe-request@mitvma.mit.edu