Help with assembly language OUTA bit order
mynet43
Posts: 644
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:
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
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
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 locationYes, 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.
I'll read them all over again carefully and see if I can pull it off.
Thanks everyone for the great support!
Jim
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
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 496Thanks 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
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