What's a good way to be hardware independent?

[quote author=Nick Gammon link=topic=128943.msg971189#msg971189 date=1351199656]
It's going to be difficult to achieve that. For one thing, on the Uno, only one port (D) gives access to 8 bits and even then two are shared with the serial ports. And on other processor what if the user happens to want to use pins that aren't in a single port?[/quote]

This is exactly the type of thing I'm concerned about. Depending on the application, giving up the serial port may be of no consequence, while SPI is mandatory. Or vice versa. The details are of course only an example. This isn't an Uno problem, or a serial problem, or anything like that. It's about not enforcing restrictions based on my current priorities.

And there's considerable cost to that, which may or may not be forgivable in exchange for the convenience. Again, depending on the application. :slight_smile:

[quote author=Nick Gammon link=topic=128943.msg971189#msg971189 date=1351199656]

You can gain a ton of efficiency by using atomic 8-bit operations on a whole PORT instead.

It will be faster. I don't know about quantifying it like that. A bit depends how often you write to the LCD. A panel showing the room temperature, for example, won't matter if it updates a few microseconds faster.[/quote]

Well, yeah, naturally, but you're getting lost in the particulars of an example. For the display on a digital clock, you're absolutely right. Now what about the audio processing unit from a Super NES? That's four address bits, 8 data bits, and the usual RSET, RD, WR, CS pins. Exactly two 8-bit ports. If you want to stream audio to it, using a dozen or more calls to digitalWrite for every byte of data is out of the question since digitalWrite will have to map the pin to a physical port, ensure it's a sane request and/or that the port is in the proper state, do a read-modify-write, then repeat the whole process for the very next bit in the same byte. That's hugely inefficient, at well over 10 times the overhead. This would apply to any external peripheral on a parallel bus that is subject to performance constraints. By that point, if you had to choose between parallel RAM and SPI-based RAM for example, SPI could very well be faster.

Huh? No, that's not at all what I'm proposing. I'm really not proposing anything, actually. I'm asking if there's a buried macro or trick that anyone knows of that can allow passing (full or partial) PORTS as parameters. If you look at the avr-libc headers, this is what happens with raw PIN access (example taken from the ATtiny 2313):

  // io2313.h, line 77
  #define PINB	_SFR_IO8(0x16)
  
  // sfr_defs.h, line 179
  #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
  // sfr_defs.h, line 128
  #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

So, 0x16 is the address. To use it, the macros just cast a pointer to that address, then resolve it as an anonymous variable. The Offset bit is necessary for certain instructions that access addresses as either raw memory or as I/O. All I need is a way to get that address, and then a macro to Do The Right Thing with it. AFAICT, there isn't an existing method built for that, but I thought I'd ask... I guess for now, dhenry is about spot on.