yes, I know the code doesn't generate anything. It was just a simple example to showcase the problem.
I use the PORT, PIN and ADDRESS variables in another function of the class after declaring them. But i now need to declare another instance of the class on a different port, so I'd like to somehow instantiate the class with those variables.
I copied the old code and added the modifications you mentioned. That's why there were some #define statements left there. I should erase them all, yes.
It would seem that I missed some "*" in front of some variables that didn't make the whole thing work the first time around. It is now working quite well with a few exceptions.
I cannot get some of the assembler language expressions like the following to work
It uses C++ templates to allow you to define "pins" and then access them with assignments, like:
DigitalPin<12> clockPin;
DigitalPin<13> dataPin;
//------------------------------------------------------------------------------
// Time to send one bit is ten cycles or 625 ns for 16 MHz CPU.
inline __attribute__((always_inline))
void sendBit(uint8_t bit, uint8_t data) {
dataPin = data & (1 << bit);
clockPin = 1;
// may want a nop here - clock pulse is 125 ns wide
clockPin = 0;
}
Don't the AVR shift opcodes only shift 1 bit? If so the execution time depends on which bit.
Detail, details... Yeah, I noticed that too. But it's also "always_inline", and perhaps got used in a way where the compiler is able to optimize better than that. In any case, it's just example code of using the "DigitalPin" template...
Again, it's just a simple example, I know the code doesn't compile to anything, it is just a small section of a larger assembler code block I have in my main code.
To answer your question, I only need the pin numbers defined at compile time, not at run time.
If you want a single class for any or all ports then the class itself can't be limited to 1 particular port as your example does.
Even if you have a PORT address (and PIN and DDR) compiled, the mode has to be set at runtime.
I went through this making a button class years ago, easiest and lest RAM using solution involved a .init() method to run in setup().
You can put bitmask values in an enum or array if you want faster running code or use the bit() function to save RAM at cost to speed.
The AVR IO instructions (IN, OUT) require that the Port be a CONSTANT, that is encoded into the actual instruction. The SBI and CBI instructions require that both the Port and the Bit be constants.
This means that if you had something that generated:
SBI _SFR_IO_ADDR(PORTD), 3
And wanted to replace PORTD with something that changed at runtime, you'd have to generate something like:
LD Rtmp, X
SBR Rtmp, 3
ST Ttemp, X
(and you'd have to change your inline ASM statement to pass it the address of the port in X, rather than the absolute port number:
thing is, i don't need it to change during runtime, I just have two devices that use separate ports but require the same ASM code to be accessed.
I could just create two functions, but that's inelegant and bloated, i'd rather just pass a variable (in this case the port) and have it set in the ASM code depending which device i'm using.
I will post the whole code as it might be of better help