Using FlexProp to help convert Spin2 to assembly
Converting this OLED code to inline assembly and came to this:PinWrite(D0_pin..D7_pin, d)
Started thinking about how to do this in assembly and not seeing an easy way to do it when D0_pin and D7_pin are arbitrary. (I should probably force the data bus to have a base pin that is multiple of 8 to make things simple.) But, was wondering if I was missing something...
Occurred to me that I can just use FlexProp to compile this line and see what it makes in the pasm file it generates...
Just made this simple .spin2 file:
CON 'Testing
PUB main()|d
    d:=8
    PinWrite (7..0, d)
Compiled, and it worked. Now, I see the "__system___pinwrite" function is about as complex as I imagined. No shortcuts. Not sure how 7..0 becomes #448 or how the code works, but now I know that I definitely need to restrict pins to basepin, multiple of 8, this is just too much...
' PUB main()|d
_main
'   d:=8
'   PinWrite (7..0, d)
    mov arg01, #448
    mov arg02, #8
    call    #__system___pinwrite
_main_ret
    ret
hubexit
    jmp #cogexit
__system___pinwrite
    mov _var01, arg01
    and _var01, #31
    test    arg01, #32 wz
    shr arg01, #6
    bmask   arg01, arg01
    shl arg01, _var01
    shl arg02, _var01
 if_e   jmp #LR__0001
    or  dirb, arg01
    mov _var01, outb
    andn    _var01, arg01
    and arg02, arg01
    or  _var01, arg02
    mov outb, _var01
    jmp #LR__0002
LR__0001
    or  dira, arg01
    mov _var01, outa
    andn    _var01, arg01
    and arg02, arg01
    or  _var01, arg02
    mov outa, _var01
LR__0002
__system___pinwrite_ret
    ret
                
                            
Comments
Realized I can't move data bus to multiple of 8 very easily in my setup...
https://forums.parallax.com/discussion/175283
But, this does the trick:
testb d,#7 wc drvc #D7_pin testb d,#6 wc drvc #D6_pin testb d,#5 wc drvc #D5_pin testb d,#4 wc drvc #D4_pin testb d,#3 wc drvc #D3_pin testb d,#2 wc drvc #D2_pin testb d,#1 wc drvc #D1_pin testb d,#0 wc drvc #D0_pinWhen I want to translate Spin2 straight PASM2 I look in the PNut compiler which Chip includes in the download. In some cases he uses skip sequences, but comments in the code make those easy to sort out when instructions are tightly wound. For pinwrite(), it has its own routine which is setup to work with outa or outb registers (I think I tested and it does not work across the p31/p32 boundary).
pinw_ ror y,#6 wc 'y=pins, w=val (begins at pop2 in LUT) bitc pinw_reg,#9 'select outa/outb for writing bmask v,y 'make mask rol y,#6 rol v,y 'justify mask rol w,y 'justify val setq v 'mux val into outa/outb using mask pinw_reg muxq outa,w _ret_ dirh y 'enable outputsOf course, if you're writing to a fixed set of outputs, you can simplify, I did a quick test using P59..56 on the Eval board.
pub write4(value) | m org mov m, #%1111 ' 4-bit mask shl m, #(56-32) ' align with lsb andn outb, m ' clear old outputs and value, #%1111 ' truncate to 4 bits shl value, #(56-32) ' align with lsb or outb, value ' output new bits or dirb, value endThe P2 deals with pin groups, so 7..0 is the same as 0 addpins 7 which is 0 + (7 << 6) which is 448.
While a tad longer, the advantage of your testb/drvc code is that it works across the P31/P32 boundary.