Ich wollte das eben nochmal nachvollziehen.
Hat aber nicht geklappt. Bei der reinen Assemblerprozedur wird - unabhängig von der Optimierung - self immer in r24,r25 übertragen.
Zu der Frage der Adressierung von Objektfeldern.
Code: Alles auswählen
TNeoPixel = object // Offset
private
fBegun : boolean; // 0 ///< true if _begin() previously called
fnumBytes : word; // 2 ///< Size of 'pixels' buffer below
fnumLEDs : word; // 4 ///< Number of RGB(W) LEDs in strip
fPin : int16; // 6 ///< Output pin number (-1 if not yet set)
fbrightness : byte; // 8 ///< Strip brightness 0-255 (stored as +1)
fEndTime : dword; // 10 ///< Latch timing reference
fPixels : Pbyte; // 14 ///< Holds LED color values (3 or 4 bytes each)
...
public
procedure show;
...
end;
procedure TNeoPixel.show; assembler; nostackframe;
label wait, NextBit, NextByte;
asm
push r29 // verwendete Register sichern
push r28 // r28/r29 fnumBytes
push r18 // hi PinMask
push r19 // lo PinMask
push r20 // Bit Zähler
push r21 // aktuell ausgegebenes Byte
push r22 // next
push r30 // Z zeigt auf fPixels
push r31 //
push r24 // Das Ergebnis von canShow wird in r24 zurückgegeben
wait:
call canShow
tst r24
breq wait
pop r24
mov r30,r24 // load self in Z register
mov r31,r25
ldd r28,Z+2 // Load fnumBytes in r28/r29
ldd r29,Z+3
ldd r24,Z+6 // Pin auslesen
call digitalPinToBitmask
in r18,PIND // aktuellen Portzustand auslesen
mov r19,r18 // und diesen auch nach lo schreiben
or r18,r24 // Pin Bit setzen (hi)
and r19,r24 // alles ausser Pin Bit löschen (lo)
ldi r20,8 // Bit Zähler
ld r21,X+ // erstes Byte laden und X Register erhöhen
nop // Zum auffinden dieser Stelle im disassembler
nop
nop
nop
nop
ldd r26,Z+13 // fPixels in X Register laden
ldd r27,Z+14
cli // Interrupts sperren
NextBit:
out PORTD,r18 // PORT := hi
sbrc r21,7 // if (Byte and 128) then
mov r22,r18 // next := hi
dec r20 // Bit := Bit - 1
out PORTD,r22 // Port := next
mov r22,r19 // next := lo
breq NextByte // if Bit = 0 then NextByte
rol r21 // Rotate Left on Byte
rjmp +0 // dirty trick, macht das gleiche wie zweimal nop, belegt aber ein Byte weniger Speicher
nop //
out PORTD,r19 // Port := lo
nop // 3 Takte Pause machen
rjmp +0 //
rjmp NextBit // Nächstes Bit ausgeben
NextByte:
ldi r20,8 // Bit := 8
ld r21,X+ // Nächstes Byte von fPixels laden
out PORTD,r19 // Port := lo
nop // 1 Takt warten
sbiw r28,1 // Bytezähler decrementieren
brne NextBit // Nicht Null? nächstes Bit ausgeben
sei // Interrupts wieder zulassen
pop r31
pop r30
pop r22
pop r21
pop r20
pop r19
pop r18
pop r28
pop r29
end;
Um in TNeoPixel.show an die Anzahl auszugebender Bytes zum kommen, muß ich auf self.fNumBytes zugreifen.
Das geschieht in der Zeile ldd r28,z+2 bzw ldd r29,z+2
Da fnumBytes nach fbegun steht (Offset 2)
Gibt es keine syntaktische Möglichkeit statt der 2 eine Referenz auf das Objektfeld per Name zu machen?
Zumal sich das Offset ja auch ändert wenn {$packrecords on} definiert wird.
Edit: Mir ist eben aufgefallen, daß ich fPixels nicht in das X Register sondern in das Z Register lade. Das ist natürlich falsch.