On Fri, 2005-10-07 at 17:52 +1000, Timothy Smith wrote: > the timer stuff is still a little confusing, all the abreviations > are unintuitive.
You mean the bit names? They come straight from Atmel's datasheet. Usually, with a bit of phantasy, you could guess what they mean. /* tmr1 is 10-bit PWM */ TCCR1A = _BV (PWM10) | _BV (PWM11) | _BV (XCOM11); Timer/counter 1's control register A gets bits PWM10 and PWM11 set plus bit XCOM11. The comment on top basically explains the effect of these. ;-) What makes it confusing here (sorry, I don't see a better way) is that each and every AVR has some variations of how the bits are named. The #ifdef spaghetti on top then maps the names for one AVR to the names of another one if needed. So you need to make sure to get the right datasheet to interpret the above. :-( As that particular code is already a bit aged, it has once been written for the AT90S2313, so for all newer AVRs, bit names are mapped to the old ones. For similar reasons, that XCOM11 is rather an alias for COM1A1, see a few lines above in that file. So with PWM10, PWM11, and COM1A1, you'll find the explanation on pages 32 (table 9) and 34 (table 12) of the AT90S2313 datasheet. PWM10+PWM11 enable a 10-bit PWM mode (iow, the counter counts from 0 to 1023 and then back to 0). COM1A1 without COM1A0 in PWM mode says the respective output compare pin will be cleared on compare match (i.e. when the counter reaches the value of the OCR1A register) when counting up, and set again when getting below that value while counting down. Thus, a large value in OCR1A (remember the largest possible value is 1023, due to it being a 10-bit counter here) means the OC1A pin will get a wide high portion of its output pulse, so the LED will be bright. /* tmr1 running on full MCU clock */ TCCR1B = _BV (CS10); Timer/counter 1's control register B is explained on page 32. The comment says it all, the above starts the timer at full CPU clock. Thus, the frequency of the PWM itself is F_CPU / 2046 (see table 11). /* set PWM value to 0 */ OCR = 0; Should be clear. OCR (output compare register) is actually OCR1A here (see the #ifdefs). This will start the PWM with a LED that's turned off, as there's never a condition where OC1 would get high. /* enable OC1 and PB2 as output */ DDROC = _BV (OC1); This enables the data direction register for the output compare match pin, to set that pin as an output. As different AVRs have the OC1 register at different pins even on different ports, this again needs to be #ifdefed. For the AT90S2313, OC1 is physical pin PB3, so DDROC will actually be DDRB (data direction register for port B). > eg. i was told on this list that _BV() is discouraged, .. No, _BV() is not discouraged, only the previous BV() was (as it has a rather high probability to be a valid name within the application itself so it could cause collisions). _BV() is nothing more but shifting a 1-bit left by the count given as parameter, so if you prefer you can always write (1 << OC1) etc. yourself. This bit shifting is frequently needed on the AVR, as the datasheet lists all bits not as bit masks but as bit numbers. This is probably due to these bit numbers also being needed for the SBI, SBIS, CBI, and CBIS assembly instructions, and as the header files defining the IO bits (i.e. <avr/io.h> in our case) are also meant to be used in assembly source files, but C's bit manipulation always requires bit masks, we need to shift around... -- cheers, J"org .-.-. --... ...-- -.. . DL8DTL http://www.sax.de/~joerg/ NIC: JW11-RIPE Never trust an operating system you don't have sources for. ;-) _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list