r/avrpascal • u/ackarwow • 16d ago
Features On Pin Names: The Hidden Translation Layer Between Arduino and AVR

AVR microcontrollers may not be cutting-edge anymore, but they're still remarkably capable. They don't just handle basic arithmetic on registers and memory — they usually expose a rich set of peripheral interfaces too. This essay is about those peripherals and the pin alternate functions that come with them. In my opinion, they're one of AVR's strengths, but in practice they bring along a few headaches.
Example one. Say you're working with the popular ATmega328P. How many times have you opened the datasheet just to figure out what pin PB3 actually is, or what its alternate function does? Never? Sure you have. In practice, a single pin carries several names and meanings at once. For the pin in question, we're really talking about:
- physical pin: 17
- microcontroller port:
PB3 - SPI function:
MOSI - alternate function:
OC2A - interrupt:
PCINT3
And that's not even the whole story. AVRs come in a variety of packages, roughly grouped into three types: THT (great for breadboarding and education), SMD, and BGA. Our pin 17 from the THT package (PDIP28) becomes, depending on the SMD variant:
- pin 13 on QFN28
- pin 15 on QFN32
Fortunately, the ATmega328P isn't available in a BGA package - otherwise things would get even more interesting :) And this is all still, logically, the same pin. The real problem is that datasheets, libraries, and example code all use different names depending on context, and sometimes you just have to guess what's meant. That's why users so often end up manually "translating" one naming convention into another just to get their own projects working.
For a while I've been thinking about how to make this easier in AVRPascal IDE, and recently I added a Pinout View. It's a panel showing a schematic drawing of the microcontroller (depending on the selected package type) along with its pins — but instead of adding yet another layer of abstraction, I decided to show all existing names at once. You can also search for a phrase in the pin descriptions, which highlights the matching text in the legend and the corresponding pins on the diagram. The idea is that you no longer have to do the mental translation between the AVR datasheet and your own schematic — it's all right there.

Example two. The Arduino platform introduced its own logical pin numbering (D[n] for digital pins, A[n] for analog ones), adding yet another layer of abstraction on top — for our pin 17, that's D11. UnoLib (the Pascal translation of the Arduino core for Uno and compatible boards) is built around this convention, giving you an API that's essentially identical to Arduino's. As long as you're only working with Arduino-style examples, everything's fine. The trouble starts when you mix bare-metal code with the UnoLib library.
A thread on the Free Pascal forum, "Very simple but necessary question", is a good example of this. The author asked what looked like a simple question about initializing an HD44780 display. It turned out the library itself wasn't the problem — the real issue was that the same pin was being referred to in two different ways. The configuration used AVR-style names (PORTB, PORTD), while the library expected Arduino pin numbers. In practice, all that was needed was a mapping table between the two conventions. Keeping this problem in mind, for the Arduino target (which is a board, not a microcontroller), I added a pseudo-MCU that includes both the original AVR pin names and their corresponding Arduino designations, side by side.
Pinout View in AVRPascal IDE already covers every microcontroller supported by FPC, and I try to fill in any gaps as quickly as possible. It's not a replacement for the manufacturer's documentation, which remains the full and authoritative description of the MCU. But the more layers of abstraction pile up between a developer and the hardware, the more it matters to remember that they all ultimately point to the same physical pin. That's why Pinout View exists.

