Shop OBEX P1 Docs P2 Docs Learn Events
Assembly I/O with 8-bit bus with variable basepin — Parallax Forums

Assembly I/O with 8-bit bus with variable basepin

For a TFT driver I'm working on, want to have an 8-bit bus with a basepin provided by the top level .spin2 file, not a constant in the low level file.

When the basepin is a CON value, it's easier to move data to the right position using outa+something constant.

But, when basepin is a variable, I'm not seeing an easy way to do it.
Looks to me like I have to self-modify the code that reads or writes to the 8-bit bus pins.
Or, am I missing something?

Comments

  • You want ALTSB/ALTGB (which you need, anyways, since the byte number in GETBYTE/SETBYTE must be constant). 2 cycles extra though.

  • RaymanRayman Posts: 14,640

    That sounds good, thanks.

    I guess that’s an easier form of self modifying code.

    Still need to do something to pick between porta and portb.

    Probably need to look at alts or altd for that, right?

  • evanhevanh Posts: 15,915
    edited 2022-06-25 01:11

    https://forums.parallax.com/discussion/comment/1539934/#Comment_1539934

    PS: For parallel data throughput, the better way is to employ the streamer.

  • JonnyMacJonnyMac Posts: 9,102
    edited 2022-06-25 02:03

    I needed 8 parallel outputs for a project so I looked at the Spin2 interpreter code for pinw(). This little inline method simulates that. Of course, in your driver you only need to do the top part once.

    pub wr_bus(base, value) | mask, outs
    
      org
                            testb     base, #5              wc      ' outa or outb
                            bitc      wr_bits, #9
                            mov       mask, #$FF                    ' make mask
                            shl       mask, base
                            mov       outs, base                    ' make pins group
                            mov       pr0, #7
                            shl       pr0, #6
                            or        outs, pr0                      
    
                            shl       value, base
                            setq      mask
    wr_bits                 muxq      outa, value
            _ret_           dirh      outs              
      end
    
  • @Rayman said:
    That sounds good, thanks.

    I guess that’s an easier form of self modifying code.

    Still need to do something to pick between porta and portb.

    Probably need to look at alts or altd for that, right?

    No, altgb/altsb index between longs, too.

    mov x,#5
    altsb x,#outa
    setbyte #255
    

    will set pins 40..47 high

  • RaymanRayman Posts: 14,640

    @Wuerfel_21 Ok, that sounds perfect then.

    @evanh I can see the streamer is being the best way, but would like there to be an easy way to deal with timing.
    Be nice to do a "xcont" or something and have the data show up immediately and have it stay there indefinitely, without having to worry about the streamer running out of data and doing something undefined.

  • Streamer just holds the last value when it runs out of data. No funny business like P1 waitvid.

  • evanhevanh Posts: 15,915
    edited 2022-06-25 12:02

    Here's the generic timing solution for streamer + clock smartpin to phase align the clock and data output:

            rdfast  #0, hubaddr
            setxfrq ratio
            mov pb, datapins
            and pb, #$38    'confine to group base pin, strip ADDPINS
            shl pb, #17
            or  pb, ##X_RFBYTE_8P_1DAC8 | X_PINS_ON
            or  pb, bytecount
    
    'timing critical code
            dirh    PIN_CLK    'clock smartpin cycle period starts from now
            waitx   phasedelay    'can be tuned to either SPI clock mode 0 or mode 3
            xinit   pb, #0    'data pins are registered - adds one sysclock latency to data
            wypin   bytecount, PIN_CLK    'start pulses on next smartpin period
    'end of critical code
    
  • evanhevanh Posts: 15,915
    edited 2022-06-25 12:10

    The value in phasedelay depends on ratio, pin registration and SPI clock mode0/3 choice. But not affected by sysclock frequency when transmitting, sysclock frequency affects receiving only.

    PS: The value in PB can be predefined in another register. I mainly left it that way for clarity on setting up the XINIT.
    PPS: Clock smartpin mode is something like:

        pinstart( PIN_CLK, P_PULSE | P_OE | P_INVERT_OUTPUT, ratio | (ratio>>1)<<16, 0 )    'CPOL=1
        ratio := $8000_0000 / ratio    'convert to suit SETXFRQ
    
  • RaymanRayman Posts: 14,640

    @evanh
    Ok that is the fancy, fully automated way. This particular thing doesn’t need to be that fast. I think 15 MHz is the limit. Think can just xcont or something with actual data instead of having it automatically read from hub, right?

    Transfers may also be small, maybe just one byte. So, the fully automated way is overkill I think …

  • evanhevanh Posts: 15,915
    edited 2022-06-25 12:24

    Is is not refreshing a whole LCD?

  • RaymanRayman Posts: 14,640

    So, this particular lcd has memory so does not have to do full refresh.

    That can be useful if low on hub ram.

  • evanhevanh Posts: 15,915
    edited 2022-06-25 12:25

    Okay, if only wanting to write single bytes from the cog then ALTSB+SETBYTE is fine.

  • RaymanRayman Posts: 14,640

    I’ll keep this streamer info in mind though for some other LCDs that don’t have memory.

  • RaymanRayman Posts: 14,640
    edited 2022-06-25 20:23

    Ok, thanks for the help, think have it now...

    In the beginning, calculate "BusAlt" from Base pin, "PinBus", and then use it on DIRA like this:

                  mov       BusAlt,PinBus
                  shr       BusAlt,#3
                  altsb     BusAlt,#dira
                  setbyte   #$FF
    

    Then later on, use "BusAlt" to apply byte in "garg1" to OUTA like this:

                  altsb     BusAlt,#outa
                  setbyte   garg1
    
  • evanhevanh Posts: 15,915

    Excellent example. Shows the flexibility and tidiness at once.

  • RaymanRayman Posts: 14,640

    This altgb/altsb combined with getbyte/setbyte is great. Sure I knew about this a couple years ago and then forgot...

    As I remember now, you can actually use this to index a large table of bytes in hub ram, not just for putting 8-bits on a bus with arbitrary base pin.

Sign In or Register to comment.