Ooof! I thought I was starting to get the hang of all this, but I'm starting to question my learning now after reading your post.
I'm still a bit green, so let me take it nice and slow, bit by bit - bear with me!
CrossRoads:
delayMicroseconds(1); // data setup/hold = 40/20 nanoseconds
I believe the info page also says this is only reliable down to 3-4uS.
I was just getting my info from AVRfreaks forum where I read:
The fastest xmega runs at 32 MHZ, which means that the shortest delay possible (one NOP) is 31.25ns.
Therefore, I was assuming that my 16Mhz Pro Mini would a minimum "one NOP" clock cycle of around 64ns.
But in any case, if the data setup/hold time is 40/20 nanoseconds, that's a total of 60 nanoseconds, there are 1,000 nS in a uS, so even if "it" (whatever "it is") is 3-4us, isn't that still around 66 times longer than my minimum 64ns, and therefore "safe"?
CrossRoads:
Just toggle the bit in question. Say it was on PORTB, bit 2, then:
PINB = 0b00000100; // flip bit 2
PINB = 0b00000100; // flip bit 2 back
Uh oh! Again, I've gone from clarity back to confusion! From the docs:
PINx is used to READ the logic state of a port (x = A,B,...)
PORTx is used to set (OUTPUT) the logical output state of a port.
DDRx is used to control how the port behaves as an output (or input).
or
DDRB - The Port B Data Direction Register - read/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only
If PINC is readonly, how can you set it? I'm going to assume that might have been a typo(?) but even if you meant PORTB, how does setting it twice to be the same thing "flip" it? Wouldn't you need a & or an | in there somewhere?
PINB = 0b00000100;
Ah. I didn't know you could do that - the docs on integer constants only say
Binary is base two. Only characters 0 and 1 are valid.
Example:
B101 // same as 5 decimal ((1 * 2^2) + (0 * 2^1) + 1)
The binary formatter only works on bytes (8 bits) between 0 (B0) and 255 (B11111111).
myInt = (B11001100 * 256) + B10101010; // B11001100 is the high byte
and I can't find this alternative define listed in the binary constants header file.
But your method works - I'm guessing the compiler actually takes care of this? AND it's MUCH easier for me as it fits better with the 0x notation of hex, and google calc uses the 0b notation too, so, much easier if I'm just checking something there. Thanks!
CrossRoads:
This:
pulseEnable();
is calling some other function? That adds time too.
and then you've got the whole outer function thing:
void OLEDFourBit::write4bits(uint8_t value)
which takes time to call and return.
If you really want speed, inline whole thing and get rid of the functions.
Pretty much since I've been first learning about this, most of what I've read (rightly or wrongly) has been about making the code modular and understandable as possible, use the single responsibility principle, and let the compiler decide on whether to inline or not.
CrossRoads:
Is your code soooooooo big that you really need to save a few bytes making all those functions? Probably not.
Well, the LiquidCrystal library I'm using which comes with the Arduino IDE was written by MIT's David Mellis, (one of the Arduino founders), and Limor Fried of Adafruit, so I was trusting their judgement on whether they made them into functions or not 