Okey doke! Those #defines are a way to make a particular location in memory look like a variable of a particular type. The typedef bitfield that comes above it defines what that variable type is.
The typedef bitfield stuff defines a variable type called bitfield that packs eight one-bit variables into an eight-bit area of memory.
The #defines that come right after that basically say, “Make this place in memory act like it’s a variable of this type.” For _PORTB it’s pointed at the location in memory where PORTB lives. For _PINB it’s where PINB lives. For _DDRB it’s where DDRB lives.
The bitfield typedef is a definition of a record. To get at a value in a record, you give the variable name, then a dot, then the name of the field inside the record you want to get at the value of. In the typedef bitfield statement, each field in the record is called B0, B1, B2, B3, etc. up to B7, each corresponding to a bit inside an 8-bit patch of memory.
So the upshot is to get at the third bit of the PORTB register, you could do:
_PORTB.B3
(I hope that explanation helps…)
How this is nifty is that you can use it like a variable (because it is.) So, for example, if you wanted to toggle a bit in DDRD, you could do:
_DDRD.B3 ^= 1;
Doing that using more conventional notation is a bit more of a pain.
One caveat on all this: I haven’t really played around to see what this compiles to in assembly. So I don’t know if you’re saving a lot in terms of actual assembly calls. It could be a break-even kind of thing. It could be more expensive in terms of clock cycles. I really don’t know.
On the AVR codes, all of that’s in the datasheet for the ATMega48/88/168 from Atmel. When I first got my Baby-O I didn’t take too much of a look at the datasheet. I should’ve! They have all kinds of examples in there, and there are way WAY more ways to use the AVR than anything I’ve found online so far. The datasheet covers it very very well.
The motor_init bit you found is a bug. It looks the same because it really is the same. DOH! This is what happens when you write faster than you test. (Big forehead slap on my end…)
That PWM motor code came from Jim, but the bug comes from me. In any case it uses TIMER1, the 16-bit timer. Since I wanted to do a set of servo routines, I kinda wanted TIMER1 to be available. So I went back and did a new set of PWM routines for the motors using TIMER0. (If you look at the schematic on the Orangutan and Baby-O, each motor can be driven directly using either timer.) This version is included in the new code on Sourceforge.
TIMER0 is an 8-bit timer, so the new motor_init() routine doesn’t take any arguments to set the resolution. It’s 8-bit resolution PWM only. To keep things straight, rather than using “motor” at the front of each of the commands it uses “pwm0”. My apologies for changing command names, but it really is a work in progress.
I do need to go back and fix the TIMER1 motor_init code, though. I’ve got an application that may need more than 256 bits of PWM resolution. Only time will tell. As soon as I have it nailed down a little more, I’ll post the hardware and software. It’s a magnetic levitation setup similar to what you see with those levitating globes and things. Basically it’s a neat example of a PID position feedback loop, and would be a good illustration for how PID loops work. (Besides, how often do you get to make things float in mid-air at a robot club meeting?)
I’m going to try to nail that down this week, so I really do hope to post details soon.
Tom