Shop OBEX P1 Docs P2 Docs Learn Events
Help with assembly language OUTA bit order — Parallax Forums

Help with assembly language OUTA bit order

mynet43mynet43 Posts: 644
edited 2014-04-19 20:04 in Propeller 1
I have a display screen routine that works fine in spin. I'm trying to convert parts of it to assembly language to increase the speed.

Part of the current code looks something like this:
CON
  _clkmode      = xtal1 + pll16x
  _xinfreq      = 5_000_000

  HorizontalMax = 800
  VerticalMax   = 480

  HorizontalPulseWidth = 1
  HorizontalFrontPorch = 45
  HorizontalBackPorch  = 210

  VerticalPulseWidth   = 1
  VerticalFrontPorch   = 10
  VerticalBackPorch    = 34
 
  ' PIN ASSIGNMENT
  PWM           = 6
  RST           = 7
  
  D15           = 8
  D0            = 23
  
  RD_           = 24
  WR_           = 25
  RS            = 26
  CS            = 27

DAT
  SoftReset     long    $01     ' Software reset
  DispOn        long    $29     ' Turn display on
  ColumnCmd     long    $2A     ' Column start      
  PageCmd       long    $2B     ' Page start
  MemStart      long    $2C     ' Set to start at beginning of memory
  PixelFormat   long    $3A     ' Set Pixel Format
  SetPanelMode  long    $B0     ' Set Panel Mode and Resolution         
  SetHPeriod    long    $B4     ' Horizontal Period
  SetVPeriod    long    $B6     ' Vertical Period
  PWM_Conf      long    $BE     ' Configuration for PWM
  PLLStart      long    $E0     ' Start PLL
  SetPLLMN      long    $E2     ' Set M and N values                 
  SetPCLK       long    $E6     ' Set PCLK
  DataInterface long    $F0     ' Set Pixel Data Interface


PRI ClearScreen | counter, x, y
  SetArea(0, 0, HorizontalMax-1, VerticalMax-1)
  WriteCmd(MemStart)            ' Start at beginning of memory
  outa[CS]~

  repeat y from 0 to VerticalMax-1                    ' Go down
    repeat x from 0 to HorizontalMax-1                ' Go across
      WriteData(BackgroundColor)

  outa[CS]~~

PRI WriteCmd(cmd)
  outa[RS]~
  outa[D15..D0] := cmd
  outa[CS]~
  outa[WR_]~
  outa[WR_]~~
  outa[CS]~~

PRI WriteData(data)
  outa[RS]~~
  outa[D15..D0] := data
  outa[WR_]~
  outa[WR_]~~


This all works, and clears the screen to the selected color. But it's not fast enough.

My question has only to do with the outa[D15..D0] command used in WriteCmd and WriteData. Note that D15 is defined as pin 8 and D0 as pin 23, so the display pin order are opposite the propeller pin order.

The outa[D15..D0] automatically puts the bits in the right order needed by the display.

My question is: how do I do this outa[D15..D0] in assembly language, and still keep the bits in the right order? In other words, how do I code WriteCmd and WriteData in assembly language? I think I've got the rest of it figured out.

Thank you for your help.

Jim

Comments

  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-04-17 21:26
    Is there really a 16-bit data buss? What display are you using?
  • Mike GreenMike Green Posts: 23,101
    edited 2014-04-17 21:43
    You need a mask for bits D15..D0 (really 8..23). You can reverse the order of the information you're writing to those pins by using a REV instruction like this:
    mov  temp,cmd   ' work on a temporary copy of cmd
            rev  temp,#16   ' reverse the least significant 16 bits
            shl  temp,#8   ' position so first bit is #8
            andn outa,mask   ' zero bits 8..23
            or   outa,temp   ' copy to bits 8..23
    
    mask    long  $00FFFF00   ' mask for bits 8..23
    temp    long  0   ' temporary location
    
  • mynet43mynet43 Posts: 644
    edited 2014-04-18 06:36
    Hi Jonny,

    Yes, it's really a 16 bit bus. The commands are 8-bit commands. The color data are sent as 16-bit RGB. (5-red, 6-green, 5-blue). It works fine. The display is a 7" touchscreen I got off eBay with a resolution of 800 x 480. It uses the SSD1963 driver chip. Right now I'm running from a prop proto board. I finally got the driver code working. I need to speed it up.

    Now if I can just get my head around that bit order.

    I seem to be getting conflicting answers. :) Some say the bits are in the right order, some say they need to be reversed.

    I'll read them all over again carefully and see if I can pull it off.

    Thanks everyone for the great support!

    Jim
  • mynet43mynet43 Posts: 644
    edited 2014-04-18 06:39
    Hi Mike,

    Thanks for the info on the rev command. I've never used it and the description isn't too easy to understand.

    What you said all makes sense. I think I'll try it this way.

    Thanks!

    Jim
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-04-18 10:07
    Here's a blob of PASM I did as my morning "coffee coding" exercise. I imagine that you would pass the hub address of an array of pins (from a DAT table) to the code. The code will determin if your D15 and D0 pins are physically reversed and handle things transparently from there.

    You pack the cmd byte and data into a long that is put into par -- a non-zero value causes the code to take off.
    dat
    
                            org     0
    
    entry                   mov     r1, par                         ' hub address of parameters
                            rdbyte  d0pin, r1
                             
                            add     r1, #1
                            rdbyte  d15pin, r1
                            
                            mov     bussrev, #0                     ' assume no reversal needed
                            cmp     d15pin, d0pin           nr, wc  ' check for reversed buss
                            muxc    bussrev, #1                     ' update reverse bit
            if_nc           mov     busslsb, d0pin                  ' set buss lsb pin
            if_c            mov     busslsb, d15pin
                            shl     bussmask, busslsb               ' adjust mask
                            
                            add     r1, #1
                            rdbyte  r2, r1                          ' get RD pin
                            mov     rdmask, #1                      ' create mask
                            shl     rdmask, r2
                            or      outa, rdmask                    ' make high
                            or      dira, rdmask                    ' make output
    
                            add     r1, #1
                            rdbyte  r2, r1                          ' get WR pin
                            mov     wrmask, #1 
                            shl     wrmask, r2
                            or      outa, wrmask   
                            or      dira, wrmask                  
    
                            add     r1, #1
                            rdbyte  r2, r1                          ' get RS pin
                            mov     rsmask, #1 
                            shl     rsmask, r2
                            or      dira, rsmask
    
                            add     r1, #1
                            rdbyte  r2, r1                          ' get CS pin
                            mov     csmask, #1                      
                            shl     csmask, r2
                            or      outa, csmask   
                            or      dira, csmask
    
    clear_cmd               mov     r1, #0
                            wrlong  r1, par
    
    get_cmd                 rdlong  r1, par                 wz
            if_z            jmp     #get_cmd
    
                            mov     cmd, r1                         ' copy cmd + data
                            and     cmd, #$FF                       ' isolate cmd
    
                            mov     dispdata, r1                    ' copy cmd + data
                            shr     dispdata, #8                    ' isolate data
                            or      bussrev, bussrev        wc      ' check reverse bit
            if_c            rev     dispdata, #16                   ' if set, reverse data
                            shl     dispdata, busslsb               ' adjust for buss pins
    
    check_cmd1              cmp     cmd, #1                 wz
            if_e            jmp     #write_cmd
    
    check_cmd2              cmp     cmd, #2                 wz
            if_e            jmp     #write_data
    
                            jmp     #clear_cmd
    
    {
    PRI WriteCmd(cmd)
      outa[RS]~
      outa[D15..D0] := cmd
      outa[CS]~
      outa[WR_]~
      outa[WR_]~~
      outa[CS]~~
    }
    
    write_cmd               andn    outa, rsmask
                            andn    outa, bussmask                  ' clear old buss value
                            or      outa, dispdata                  ' write new buss value
                            andn    outa, csmask
                            andn    outa, wrmask
                            nop
                            or      outa, wrmask
                            or      outa, csmask
                            jmp     #clear_cmd
    
    {
    PRI WriteData(data)
      outa[RS]~~
      outa[D15..D0] := data
      outa[WR_]~
      outa[WR_]~~
    }
    
    write_data              or      outa, rsmask
                            andn    outa, bussmask
                            or      outa, dispdata
                            andn    outa, wrmask
                            nop
                            or      outa, wrmask
                            jmp     #clear_cmd                        
    
    ' --------------------------------------------------------------------------------------------------
    
    bussmask                long    $0000_FFFF                      ' 16-bit buss
    
    d0pin                   res     1                               ' buss pins
    d15pin                  res     1
    bussrev                 res     1                               ' 1 if D15 < D0
    busslsb                 res     1                               ' physical LSB pin on chip
    rdmask                  res     1                               ' mask for RD pin
    wrmask                  res     1                               ' mask for WR pin
    rsmask                  res     1                               ' mask for RS pin
    csmask                  res     1                               ' mask for CS pin
    
    cmd                     res     1
    dispdata                res     1
    
    r1                      res     1                               ' work vars
    r2                      res     1
    
                            fit     496
    
  • mynet43mynet43 Posts: 644
    edited 2014-04-18 10:22
    Hi Jonny,

    Thanks for the code, I appreciate it.

    I've been doing the same thing at the same time. :)

    I'll compare what I have with yours to see if I can catch some errors or do it better than I am now.

    I'll post mine when I finish.

    Thanks again,

    Jim
  • mynet43mynet43 Posts: 644
    edited 2014-04-19 20:04
    Hi again.

    Here's an update of where I'm at now. I'm trying to write a driver for a 7" touchscreen that uses the SSD1963 control chip. So far it works great in spin, but slow. I'm having trouble getting the assembly language routines to work.

    I received some great code from JonnyMac and Mike Green. The assembly code I was writing was quite similar to JonnyMac's, so I added a couple of changes he provided and the reverse command code from Mike.

    Right now I'm focusing on the _Write_Data routine in the assembly language section. I've stared at it for a long time and it appears identical in function to the spin code for the same function. But it doesn't work. :(

    I've added debug code, to be able to print out values from the assembly language routines. I've displayed the parameter data passed, the masks used, etc. I've even tried adding time delays between the assembly instructions to make it slower, like spin. All the debug data looks right that I get from the assembly routines.

    I've written the main program so it's easy to switch from the spin code to assembly code that does the same function. When I run the program in spin only mode, it works perfectly and clears the screen to many different colors.

    When I switch to using the assembly language _Write_Data routine, and leave everything else in spin, it runs fine, but it doesn't display any color on the screen.

    It's frustrating because it's very fast in the assembly routines, but it doesn't quite work.

    I've attached the source file for the code I'm testing.

    Would someone please take a look at the code to see if you can spot my mistakes in the _Write_Data implementation in the assembly code? See lines 132 and 133 in the spin code. All I have to do is switch these and one works, the other doesn't. They're supposed to be identical functions.

    Thank you for your help and support.

    Jim
Sign In or Register to comment.