Very nice work! I will have to examine your implementation closer. You seem to have optimized this a bit. I am still fighting ASM. I can't seem to get my dat block working properly.
DAT'initorg0
entry movouta, PinsInit 'set pins to inital state movdira, DirsEnabled 'enables p0 - p15mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup movdira, DirsDisabled 'enables p0 - p15wrlong zero, bufferaddress 'set par to zero to confirm load done'get write command from buffer, and check if it's 0
Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD datacmp Lcd_Data, #0wz'and check if it's 0if_zjmp #get 'if it is, try again.'if not, prepare transfermovouta, PinsInit 'set pins to inital state movdira, DirsEnabled 'enables p0 - p15mov LCD_cmd, LCD_Data 'copy lcd command to lcd dataand LCD_Data, lowWordMask 'mask off High word of Lcd_Datashr LCD_cmd, #16'move lcd command 16 bit to the right if not gddr write' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfermov pntr, Lcd_cmd
:wait0 djnz pntr, :wait0
WrCmd movouta, #$22mov pntr, #$f
:wait0 djnz pntr, :wait0
add zero, #0wzmuxzdira, RSpin
mov pntr, #$f
:wait1 djnz pntr, :wait1
muxzdira, WritePin
mov pntr, #$f
:wait2 djnz pntr, :wait2
muxnzdira, WritePin
mov pntr, #$f
:wait3 djnz pntr, :wait3
muxnzdira, RSpin
mov pntr, #$f
:wait4 djnz pntr, :wait4
:WrDataPortion
movouta, LCD_Data
mov pntr, #$f
:wait5 djnz pntr, :wait5
add zero, #0wzmuxzdira, WritePin
mov pntr, #$f
:wait6 djnz pntr, :wait6
muxnzdira, WritePin
mov pntr, #$f
:wait7 djnz pntr, :wait7 ''add asmColor,#1'max asmColor, BackgroundColorASMmov pntr, #$f
:wait8 djnz pntr, :wait8
movdira, DirsDisabled 'disables p0 - p15wrlong zero, bufferaddress
jmp #Get
zero long$0
lowWordMask long$0000_ffff
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1fit
The dat block will print color data, but I'm still trying to get everything working properly. Writes are a bit faster.
Sorry to hijack for a post, but I can't seem to get my screen to do anything but light up the backlight. I have wired up my screen directly to the Prop according to the schematic in post #1 and am using the test code from post #2. The Screen is one of these :
There are 8 connections I do not have connected on the 40 pin connector (An old 40 pin hard drive connector).
The 8 pins not connected are :
Pin 3 - Not Used
Pin 16 - F_CS
Pin 18 - Not Used
Pin 20 - Not Used
Pin 32 - D_BUSY
Pin 34 - D_Penirq (Not sure what this is)
Pin 39 - F_WP
Pin 40 - F_HOLD
Is there something I am missing? I have the Data IN and Data Out pins shared on pins 24 and 25 on the Prop. No pull up or pull down resistors are in place for the LCD circuitry.
No worries eagle, you need to change the initialization values to match those in the datasheet. They are different for your screen. That should help.
Current version is much faster. Fully working?
CON_clkmode = xtal1 + pll16x' use crystal x 16_xinfreq = 5_000_000
RS = 16''PINS FOR CS - TO KEEP FROM FLOATING
LCD_WR = 17
DEV_SD_CLK = 18
DEV_SD_DI = 19
DEV_SD_DO = 20
DEV_SPI_EN = 21
DEV_SPI_ADD0 = 22
DEV_SPI_ADD1 = 23
DEV_SPI_ADD_LE = 24
DEV_SPI_LCD_RES = 0
DEV_SPI_SDC_CS = 1
DEV_SPI_TSC_CS = 2
DEV_SPI_EXT_CS = 3
DEV_SPI_EXT_POT_CS = 0
DEV_SPI_EXT_SW_CS = 1''LCD REGISTERS
REG_OSCILLATOR = $0000''Oscillator (R00h) (POR = 0000h)
REG_DRIVEROUTPUTCONTROL = $0001''Driver Output Control (R01h) (POR = 2B3Fh)
REG_LCDDRIVINGWAVFORM = $0002''LCD-Driving-Waveform Control (R02h) (POR = 0000h)
REG_POWERCONTROL1 = $0003'' (R03H)
REG_DISPLAYCONTROL = $0007''Display Control (R07h) (POR = 0000h)
REG_FRAMECYCLECONTROL = $000B''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET
REG_POWERCONTROL2 = $000C'' (R0Ch) (POR = 0004)
REG_POWERCONTROL3 = $000D''
REG_POWERCONTROL4 = $000E''
REG_GATESCANPOSITION = $000F''Gate Scan Position (R0Fh) (POR = 0000h)
REG_SLEEPMODE = $0010''Sleep mode (R10h) (POR = 0001h)
REG_ENTRYMODE = $0011''Entry Mode (R11h) (POR = 6830h)
REG_HPORCH = $0016'' (R16h) (POR = EF1Ch)
REG_VPORCH = $0017'' (R17h) (POR = 0003h)
REG_POWERCONTROL5 = $001E''
REG_RAMDATAWRITE = $0022''
REG_RAMWRITEDATAMASK1 = $0023'' (R23h) (POR = 0000h)
REG_RAMWRITEDATAMASK2 = $0024'' (R24h) (POR = 0000h)
REG_VERTICALSCROLCONTROL1 = $0041'' (R41h) (POR = 0000h)
REG_VERTICALSCROLCONTROL2 = $0042'' (R42h) (POR = 0000h)
REG_HORIZONTALRAMADDRESSPOS = $0044'' (R44h) (POR = EF00h)
REG_VERTICALRAMADDRESSSTART = $0045'' (R45h) (POR = 0000h)
REG_VERTICALRAMADDRESSEND = $0046'' (R46h) (POR = 013Fh)
REG_FIRSTWINDOWSTART = $0048'' (R48h) (POR = 0000h)
REG_FIRSTWINDOWEND = $0049'' (R49h) (POR = 013Fh)
REG_SECONDWINDOWSTART = $004A'' (R4Ah) (POR = 0000h)
REG_SECONDWINDOWEND = $004B'' (R4Bh) (POR = 013Fh)
REG_SETGDDRXADDRESSCOUNTER = $004E'' (R4Eh) (POR = 0000h)
REG_SETGDDRYADDRESSCOUNTER = $004F'' (R4Fh) (POR = 0000h)
FONT_ROM_ADDRESS = $8000
BGCOLOR = $ffff
TXTCOLOR = $0000
NotPressedBGC = $ffff
NotPressedATC = $0000
PressedBGC = $0000
PressedATC = $ffff
Pressed = 1
NotPressed = 0VARlong BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2
long ScreenBuffer
long stringptr[65]
BYTE Fader0[3], Fader1[3], Fader2[3], Fader3[3], faderOrentation, faderpos, faderval, oldfader, ButtonName 'Fader POS, New Fader Value, Old Fader Value, FaderOrentation holds 0 for landscape, portrait not enabledword Button0[3], Button1[3], Button2[3], Button3[3], Button4[3], Button5[3], ButtonGroup, ButtonX, ButtonY, ButtonState
obj wait : "timing"
pst : "parallax serial terminal"PUBBOOT | cr, idxr'bootstrapdirA[DEV_SPI_ADD0] := 1dirA[DEV_SPI_ADD1] := 1dirA[DEV_SPI_EN] := 1OUTA[LCD_WR] := 0OUTA[RS] := 0OUTA[DEV_SPI_EN] := 1OUTA[DEV_SPI_ADD_LE] := 0
PST_Init
Init_SSD1289
EnableDisplayPins
TristateDisplayPins
StartAsm
pst.newline
pst.str(string("Starting Asm"))
pst.newline
ClearScreenAsm($ffff)
helloworld
deadend
PUBStartAsm'Method to load a cog with screen driverlong[@screenbuffer] := $ffff''make sure screen buffer does not equal 0cognew(@entry,@Long[@screenbuffer]) ''start write driver and pass it the address of screen bufferPUBPST_Init | PstCog''Starts Parallax Serial Terminal for debugging.
PstCog := (pst.Start(115200) -1) '' returns the cog pst started in
pst.Str(String("Parallax Serial Terminal started in cog ")) '' talk to human
pst.Dec(PstCog) '' displays cog on PST ''
wait.pause1s(1)
PUBHelloWorld
WriteActiveCrAsm(72, 0, 0*16, 0, 0, BGCOLOR, TXTCOLOR)
WriteNextActiveCrAsm(101)
WriteNextActiveCrAsm(108)
WriteNextActiveCrAsm(108)
WriteNextActiveCrAsm(111)
WriteNextActiveCrAsm(32)
WriteNextActiveCrAsm(87)
WriteNextActiveCrAsm(111)
WriteNextActiveCrAsm(114)
WriteNextActiveCrAsm(108)
WriteNextActiveCrAsm(100)
PUBWriteNextActiveCrAsm(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2
odd_even := character & $0001
characterpointer := character & $fffe
characterpointer >>= 1
characterpointer *= 32repeat idx from0to31
bitpatern[idx] := long[FONT_ROM_ADDRESS][characterpointer + idx]
y1 := Col + ColBorder
y2 := (Col + 15) - ColBorder
x1 := Row + RowBorder
x2 := (Row + 31) - RowBorder
SetWindowAsm(x1, y1, x2, y2)
SetGAddressAsm(x1,y1)
repeat idx from RowBorder to31 - RowBorder
repeat pxlidx from odd_even + (ColBorder*2) to (odd_even + 30) - (ColBorder*2) step2
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
Lcd_Write_Asm(ActiveTextColor + ($22 << 16))
else
Lcd_Write_Asm(BackgroundColor + ($22 << 16))
if (((Col + 16) > 319 ) and ((Row + 32) > 223))
Row := 0
Col := 0elseif (((Col + 16) > 319 ) and ((Row + 32) < 223))
Row := Row + 32
Col := 0else
Col := Col + 16' SetWindow(0, 0, 239, 319)PUBWriteActiveCrAsm(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2
odd_even := character & $0001
characterpointer := character & $fffe
characterpointer >>= 1
characterpointer *= 32repeat idx from RBorder to31 - RBorder
bitpatern[idx] := long[FONT_ROM_ADDRESS][characterpointer + idx]
Row := PosR
Col := PosC
RowBorder := RBorder
ColBorder := CBorder
BackgroundColor := BgC
ActiveTextColor := Txc
y1 := PosC + CBorder
y2 := (PosC + 15) - CBorder
x1 := PosR + RBorder
x2 := (PosR + 31) - RBorder
SetWindowAsm(x1, y1, x2, y2)
SetGAddressAsm(x1,y1)
repeat idx from RBorder to31 - RBorder
repeat pxlidx from odd_even + (CBorder*2) to (odd_even + 30) - (CBorder*2) step2
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
Lcd_Write_Asm(ActiveTextColor + ($22 << 16))
else
Lcd_Write_Asm(BackgroundColor + ($22 << 16))
if (((Col + 16) > 319 ) and ((Row + 32) > 223))
Row := 0
Col := 0elseif (((Col + 16) > 319 ) and ((Row + 32) < 223))
Row := Row + 32
Col := 0else
Col := Col + 16returnPUBClearScreenAsm(color) | idxr, idxc
SetWindowAsm(0, 0, 239, 319)
SetGAddressAsm(0,0)
color += ($22 << 16)
repeat idxr from0to76800
Lcd_Write_Asm(Color)
Row := 0
Col := 0PUBSetWindowAsm(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS
WindowX1 := x1
WindowX2 := x2
WindowY1 := y1
WindowY2 := y2
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
Lcd_Write_Asm ($0044_0000 + HORIZONTALRAMADDRESSPOS)
Lcd_Write_Asm(y1 + $0045_0000)
Lcd_Write_Asm(y2 + $0046_0000)
PUBSetGAddressAsm(x,y)
Lcd_Write_Asm ($004E_0000 + x) ''max %1111_1111, $FF
Lcd_Write_Asm ($004F_0000 + y) ''max %1_0011_1111, $13f'' (R4Eh) (POR = 0000h) PUBEnableDisplayPinsDIRA:=%00000001_11100000_11111111_11111111' , Reset, WR, RS and 16 data lines active PUBTristateDisplayPins' tristate all pins - DIRA:=%00000001_11100000_00000000_00000000''PRILcd_Write_Asm(V)'handler for asm writesrepeatwhile (screenbuffer <> 0)
long[@screenbuffer] := V 'makes screen buffer = vPRILCD_Writ_Bus(V)OUTA[15..0] := V
WriteLow ' write pin low
WriteHigh ' toggle write pinPRILcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
PRILcd_Write_Data(V)
RSHigh
LCD_Writ_Bus(V)
PRIRSLowdira[RS] := 1PRIRSHighdira[RS] := 0'PRIWriteLowdira[LCD_WR] := 1' PRIWriteHighdira[LCD_WR] := 0pubdeadendrepeat
wait.pause1s(1)
PUBInit_SSD1289''Init Display
EnableDisplayPins ''enable pins 0 to 15' WriteHigh'LCD_Reset ''reset screen'wait.pause1ms(5) 'LCD_Reset ''then init screen'wait.pause1ms(5)
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01
Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h)
Lcd_Write_Data($0001) ''Turn on oscillator
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11
Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h)
Lcd_Write_Data($0000) '' ''exit sleep mode
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11
Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h)
Lcd_Write_Data($6838) ''
Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000)
Lcd_Write_Data($1000) '' ''
Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000)
Lcd_Write_Data($0000) '' ''''
Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F)
Lcd_Write_Data($6B3F) '' ''
Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
Lcd_Write_Data($5308) '''
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033)
Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11 'TristateDisplayPins'deadendDAT'init Display driver'designed for optimized hardware, pull-up resistors on RS and WR pins.org0
entry movouta, PinsInit 'set pins to inital state movdira, DirsEnabled 'enables p0 - p15mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup movdira, DirsDisabled 'enables p0 - p15wrlong zero, bufferaddress 'set par to zero to confirm load done'get write command from buffer, and check if it's 0
Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD datacmp Lcd_Data, #0wz'and check if it's 0if_zjmp #get 'if it is, try again.'if not, prepare transfermovouta, PinsInit 'set pins to inital state movdira, DirsEnabled 'enables p0 - p15mov LCD_cmd, LCD_Data 'copy lcd command to lcd dataand LCD_Data, lowWordMask 'mask off High word of Lcd_Datashr LCD_cmd, #16'move lcd command 16 bit to the right if not gddr write' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfermov pntr, #$f'set wait period
:wait0 djnz pntr, :wait0 'and wait
WrCmd movouta, LCD_Cmd 'place LCD_Cmd on write busmov pntr, #$f'set wait period
:wait0 djnz pntr, :wait0 'and wait add zero, #0wz'prime WZ flag muxzdira, RSpin 'make RS pin low by enabling its DIR REGmov pntr, #$f'set wait period
:wait1 djnz pntr, :wait1 'and wait muxzdira, WritePin 'make Write Pin low by enabling its DIR REGmov pntr, #$f'set wait period
:wait2 djnz pntr, :wait2 'and wait muxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$f'set wait period
:wait3 djnz pntr, :wait3 'and waitmuxnzdira, RSpin 'make RS pin high by disabling its DIR REGmov pntr, #$f'set wait period
:wait4 djnz pntr, :wait4 'and wait
:WrDataPortion
movouta, LCD_Data 'place LCD_Data on write busmov pntr, #$f'set wait period
:wait5 djnz pntr, :wait5 'and waitadd zero, #0wz'prime WZ flagmuxzdira, WritePin 'make Write Pin low by enabling its DIR REGmov pntr, #$f'set wait period
:wait6 djnz pntr, :wait6 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$f'set wait period
:wait7 djnz pntr, :wait7 'and waitmov pntr, #$f'set wait period
:wait8 djnz pntr, :wait8 'and waitmovdira, DirsDisabled 'disables p0 - p15wrlong zero, bufferaddress
jmp #Get 'do it all again
zero long$0
lowWordMask long$0000_ffff
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111'' (R4Fh) (POR = 0000h)
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1
I think I found the right area to get the information for the initialization, but I don't really know what I am looking at. The code has hex but the datasheet does not have a hex value from what I can see. I have attached the PDF for the screen that I have. On page 55 is the LCD Driving Wave Control (R02h). Where or how do I get the value from this to put in the code you posted above?
@eagletalontim
Thanks for the link. There's a lot of good info there and will help me in my design. It is interesting that it says it only handles 8 bit mode. Has anyone had trouble interfacing 16 bit data? Also I was thinking if the problems with the SD cards is because it is expecting 5V rather than 3.3V since it has series resistors.
I've played with the sd card a bit, and still no luck. Even with an external breakout. I think I have incompatible cards. If you give me a few I'll check into the datasheet. I don't know if you'll have luck using my code if your display is only 8-bit. You might check with Dr. A as I think he has the same screen. I would start with his initialization values. Let me see if I can find them.
.
*edit*
From Dr. Acula's initalization. Format is Command, Data. ' ************* Start Initial Sequence **********
ILIcmd($00E5,$78F0) ' set SRAM internal timing
ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait
ILIcmd($0002,$0700) ' set 1 line inversion
ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030
ILIcmd($0004,$0000) ' Resize register
ILIcmd($0008,$0207) ' set the back porch and front porch
ILIcmd($0009,$0000) ' set non-display area refresh cycle ISC[3:0]
ILIcmd($000A,$0000) ' FMARK function
ILIcmd($000C,$0000) ' RGB interface setting
ILIcmd($000D,$0000) ' Frame marker Position
ILIcmd($000F,$0000) ' RGB interface polarity ' *************Power On sequence ****************//
ILIcmd($0010,$0000) ' SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0007) ' DC1[2:0], DC0[2:0], VC[2:0]
ILIcmd($0012,$0000) ' VREG1OUT voltage
ILIcmd($0013,$0000) ' VDV[4:0] for VCOM amplitude
ILIcmd($0007,$0001)
wait.pause1ms(50) ' Dis-charge capacitor power voltage
ILIcmd($0010,$1090) ' 1490//SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0227) ' DC1[2:0], DC0[2:0], VC[2:0]
wait.pause1ms(50) ' delay
ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci;
wait.pause1ms(50) ' delay
ILIcmd($0013,$1500) ' $1000//1400 Set VDV[4:0] for VCOM amplitude 1A00
ILIcmd($0029,$0027) ' $0012 //001a Set VCM[5:0] for VCOMH //$0025 0034
ILIcmd($002B,$000D) ' Set Frame Rate 000C
wait.pause1ms(50) ' delay
ILIcmd($0020,$0000) ' GRAM horizontal Address
ILIcmd($0021,$0000) ' GRAM Vertical Address ' ----------- Adjust the Gamma Curve ----------//
ILIcmd($0030,$0000)
ILIcmd($0031,$0707)
ILIcmd($0032,$0307)
ILIcmd($0035,$0200)
ILIcmd($0036,$0008)
ILIcmd($0037,$0004)
ILIcmd($0038,$0000)
ILIcmd($0039,$0707)
ILIcmd($003C,$0002)
ILIcmd($003D,$1D04)
' ------------------ Set GRAM area ---------------//
ILIcmd($0050,$0000) ' Horizontal GRAM Start Address
ILIcmd($0051,$00EF) ' Horizontal GRAM End Address
ILIcmd($0052,$0000) ' Vertical GRAM Start Address
ILIcmd($0053,$013F) ' Vertical GRAM Start Address
ILIcmd($0060,$A700) ' Gate Scan Line
ILIcmd($0061,$0001) ' NDL,VLE, REV
ILIcmd($006A,$0000) ' set scrolling line ' -------------- Partial Display Control ---------/
ILIcmd($0080,$0000)
ILIcmd($0081,$0000)
ILIcmd($0082,$0000)
ILIcmd($0083,$0000)
ILIcmd($0084,$0000)
ILIcmd($0085,$0000)
' //-------------- Panel Control -------------------//
ILIcmd($0090,$0010)
ILIcmd($0092,$0600)
ILIcmd($0007,$0133) ' 262K color and display ON
@eagletalontim - sorry this is not so easy. I have a board on the way which hopefully will be a 'plug and play' affair but until that arrives, average joe and me are not even using the same schematic.
I don't understand any of the startup code either and I started off with only C code to work with, so I'll document how I got the display working.
First thing was to just work on the display, so forget about the SD card and the touchscreen.
5V, 0V, 16 data lines and 5 control lines.
Of those control lines, I am not sure which ones you can leave out. I'm pretty sure now that /rd is not needed. But I see that average joe has left out /cs and I don't know about that one.
So let's say 4 control lines, and tie /rd high.
I then coded some spin code to set each of these high and each of these low. Things like ResetHigh, and ChipSelectLow. 8 PUB routines in total. I then tested each of those with a LED on the appropriate pin. Did the code do what it was supposed to?
Comment out the writelow and writehigh for the moment and put a "repeat" there instead so the program hangs.
Now pass some numbers in VH and VL and see if the pins do what they are supposed to. I used Windows Calculator a lot to convert numbers to binary. Pick a random number, work out its binary, send it out and then check with a logic probe the pins are as they are supposed to be.
Then remove that 'repeat' and put back in the writelow writehigh.
add this code
PRIILIcmd(c,d)' instruction in one method
Lcd_Write_Com(c >> 8,c & 255) ' split a word into two bytes, send command then data
Lcd_Write_Data(d >> 8,d & 255)
PRILcd_Write_Com(VH,VL)
RSLow
LCD_Writ_Bus(VH,VL)
PRILcd_Write_Data(VH,VL)
RSHigh
LCD_Writ_Bus(VH,VL)
Then try dropping in this startup code.
PUBStart_ILI9325' pass orientation true = portrait, false = landscape
DisplayPins := %00000000_00000000_00000000_00000000' store the status of the display pins
ResetHigh
wait.pause1ms(5)
ResetLow
wait.pause1ms(5)
ResetHigh
ChipSelectHigh
ReadHigh
WriteHigh
wait.pause1ms(5)
ChipSelectLow
' ************* Start Initial Sequence **********
ILIcmd($00E5,$78F0) ' set SRAM internal timing
ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait
ILIcmd($0002,$0700) ' set 1 line inversion
ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030
ILIcmd($0004,$0000) ' Resize register
ILIcmd($0008,$0207) ' set the back porch and front porch
ILIcmd($0009,$0000) ' set non-display area refresh cycle ISC[3:0]
ILIcmd($000A,$0000) ' FMARK function
ILIcmd($000C,$0000) ' RGB interface setting
ILIcmd($000D,$0000) ' Frame marker Position
ILIcmd($000F,$0000) ' RGB interface polarity ' *************Power On sequence ****************//
ILIcmd($0010,$0000) ' SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0007) ' DC1[2:0], DC0[2:0], VC[2:0]
ILIcmd($0012,$0000) ' VREG1OUT voltage
ILIcmd($0013,$0000) ' VDV[4:0] for VCOM amplitude
ILIcmd($0007,$0001)
wait.pause1ms(50) ' Dis-charge capacitor power voltage
ILIcmd($0010,$1090) ' 1490//SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0227) ' DC1[2:0], DC0[2:0], VC[2:0]
wait.pause1ms(50) ' delay
ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci;
wait.pause1ms(50) ' delay
ILIcmd($0013,$1500) ' $1000//1400 Set VDV[4:0] for VCOM amplitude 1A00
ILIcmd($0029,$0027) ' $0012 //001a Set VCM[5:0] for VCOMH //$0025 0034
ILIcmd($002B,$000D) ' Set Frame Rate 000C
wait.pause1ms(50) ' delay
ILIcmd($0020,$0000) ' GRAM horizontal Address
ILIcmd($0021,$0000) ' GRAM Vertical Address ' ----------- Adjust the Gamma Curve ----------//
ILIcmd($0030,$0000)
ILIcmd($0031,$0707)
ILIcmd($0032,$0307)
ILIcmd($0035,$0200)
ILIcmd($0036,$0008)
ILIcmd($0037,$0004)
ILIcmd($0038,$0000)
ILIcmd($0039,$0707)
ILIcmd($003C,$0002)
ILIcmd($003D,$1D04)
' ------------------ Set GRAM area ---------------//
ILIcmd($0050,$0000) ' Horizontal GRAM Start Address
ILIcmd($0051,$00EF) ' Horizontal GRAM End Address
ILIcmd($0052,$0000) ' Vertical GRAM Start Address
ILIcmd($0053,$013F) ' Vertical GRAM Start Address
ILIcmd($0060,$A700) ' Gate Scan Line
ILIcmd($0061,$0001) ' NDL,VLE, REV
ILIcmd($006A,$0000) ' set scrolling line ' -------------- Partial Display Control ---------/
ILIcmd($0080,$0000)
ILIcmd($0081,$0000)
ILIcmd($0082,$0000)
ILIcmd($0083,$0000)
ILIcmd($0084,$0000)
ILIcmd($0085,$0000)
' //-------------- Panel Control -------------------//
ILIcmd($0090,$0010)
ILIcmd($0092,$0600)
ILIcmd($0007,$0133) ' 262K color and display ON
For my display, cs is not needed. My module seems to be fine without reset. YMMV. I would like to pick up one the the 2.4"s so I could work on that too. One place I found an optimization * or maybe not* is using 10k pullups on WR and RS lines. In spin it doesn't seem to matter, but in asm, it cuts out a few instructions per write.
Dr A has a good method to get up and running. I actually used his code to develop a template for mine. I changed the initialization values for the display, and then modified his writing method.
PRILCD_Writ_Bus(V)OUTA[15..0] := V
WriteLow ' write pin low
WriteHigh ' toggle write pinPRILcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
PRILcd_Write_Data(V)
RSHigh
LCD_Writ_Bus(V)
PRIRSLow'these are for pullup version, non pullup will be dira[RS] := 1'outa[RS] := 0PRIRSHigh'these are for pullup version, non pullup will bedira[RS] := 0'outa[RS] := 1 PRIWriteLow'these are for pullup version, non pullup will bedira[LCD_WR] := 1'outa[LCD_WR] := 0 ' PRIWriteHigh'these are for pullup version, non pullup will bedira[LCD_WR] := 0'outa[LCD_WR] := 1
This could be modified for 8 bit writes if necessary.
How far away can the display be from the prop? I have an old HD cable which I cut about 2 inches away from the connector and tinned all the tips to it will plug into my bread board. The pins are connected right at the prop pins. What I would like to do is to add a few more inches for testing purposes to the pins from the header so I can plug them into a different area away from the prop and run single wires to where they need to go for the display. This will help clean my breadboard up so debugging will be easier. Since I am connecting all the display pins directly to the prop, I will have to redo quite a bit of the code Dr_Acula is using since he is using latches. That is the point where I get lost
I will be writing compatible drivers for Dr. A's stuff soon. Real soon. I'm not sure what the limit would be, but I'm using an old HD cable *they work as long as they're the 40 pin cables, the 80's don't to my knowledge* and I have about 2" + between the display and my propRPM. I would say you'll be fine.
I've got ASM running good.
*Edit*
Here's version 2! It runs pretty fast and can be optimized further.
Program: 345 Longs
Variable: 17 Longs
not too bad!
For spin, it could be 50cm or more. Pasm might need shorter distances, but spin is slower so distance should not be a problem. My display is 10cm from the prop.
Start with the reset line. Write some code to make that line high, then wait 1ms then low, wait 1ms, then high again. Change the delay to 1 second for debugging. Put a led on that pin, and run the code. That should reset the display which should get something to change on the display.
Not in pasm, no. In spin, it is standard spin "turn a led on, turn a led off" code for the 4 control lines, and then send out a word on 16 prop pins which is your code.
For pasm, the code I'm going to be writing for the new board will be very different. The design uses a ram chip and was built to transfer data from the ram chip to the display as fast as possible, with the transfer speed between the prop and ram a secondary consideration. So there is a bus between ram and the display, and there are some isolating 245 buffer chips so that bus is independent of the propeller.
If it doesn't work - back to the drawing board. If it does work, well I'm getting 10 boards made so some could be available for others to test out...
OK, I will be playing around with some compatibility issues. I am currently trying to figure out the RIGHT way to do this...
So, I my "terminal" object *MAIN* to create an area in main memory, and pass that address to another object *PFW*, which starts the cog that loads the data from main memory.
var Screen_Buffer
pubinit
...do something
long[@Screen_Buffer] := $ffff'make sure screen buffer does not equal 0
pfw.Start(@Long[@Screen_Buffer]) 'Start Asm Driver, needs to be changed to pass screen buffer from top object
....do more
that's the main object and it's call, the pfw object is
varlong screenbufferaddress
PUBStart(ScreenBufferAdd)'Method to Init display, then load a cog with screen driver
screenbufferaddress := ScreenBufferAdd 'store buffer address in long
Init_SSD1289
'init screenresult := cognew(@entry,ScreenBufferAdd ]) 'start write driver and pass it the address of screen bufferPRILcd_Write_Asm(V)'handler for asm writesrepeatwhile (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbufferlong[@screenbufferaddress] := V 'makes screen buffer = v
entry movouta, PinsInit 'set pins to inital state 'mov dira, DirsEnabled 'enables p0 - p15mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup movdira, DirsDisabled 'enables p0 - p15wrlong zero, bufferaddress 'set par to zero to confirm load done
...do more
what is the RIGHT way to pass this address. I'm lost.
... what is the RIGHT way to pass this address. I'm lost.
There is no right way. See example below. For easier testing I kept the start method in the same file. It can easily be moved to a different object (then you'll have to un-comment the {pfw.} bit). The main program is only allowed to continue (toggling an LED) when the PASM part gets the right value (42).
VARlong screen
PUBnull
screen := 42' start not equal zero
[COLOR="orange"]{pfw.}[/COLOR]start(@screen) ' communicate addressrepeatwhile screen ' wait until it reached PASMdira[16]~~
repeat
!outa[16]
waitcnt(clkfreq/2 + cnt)
[COLOR="blue"]PUB start(address)
cognew(@entry, address)
DATorg0
entry rdlong temp, par' par == @screen (4n limitation)cmp temp, #42wzif_ewrlong zero, par' release caller if ID checks outwaitpeq $, #0' stop
temp res1fitCON
zero = $1F0' parDAT[/COLOR]
Thanks! That was a HUGE help. I'm still trying to get the hang of PASM. I have raw data writes being processed in spin, now to implement a buffer and do some other optimizations. I am very happy with the results so far. Offloading writes improved performance quite a bit, even being controlled from spin. Now to push the reading of pixel data into the cog. I think I can eek some more performance from this driver. It is about twice as fast as it was when drawing a blank screen. Text generation is still slow.
[video=youtube_share;_w6VCS-_8X0]
I got some stuff working, but there may be bugs still. It display characters correctly I think. It's a start, I still need to get fifo's working...
TOF object
CON
zero = $1F0' parvarlong command, cog
word font[32]
PUBnull'' This is not a top level object.PUBStartresult := cog := cognew(@fillchar, @command) + 1' start cog PUBGetChar(c)
command := $200|c.byte{0}' query bitmaprepeat' |while command ' wait for completionreturn @font{0}DATorg0
fillchar mov addr, par' @font[0]
:idle rdlong char, parwzif_zjmp #$-1mov temp, char ' where to beginshr temp, #1' 2 chars/longshl temp, #7' 32 longs/chartest char, #1wcmuxnc shft, #1' even/oddmov lcnt, #32' 32 rows
:loop rdlong char, temp ' read line from ROMshl char, shft ' adjust for even/oddshl char, #2wcrcl line, #1' bit 15shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1' bit 12shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1' bit 8shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1' bit 4shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1shl char, #2wcrcl line, #1' bit 0wrword line, addr ' update hub arrayadd addr, #2' advance dstadd temp, #4' advance srcdjnz lcnt, #:loop ' repeatwrlong zero, par
:chktbl rdword line, addr wz'get font table andif_nzjmp #:chktbl 'wait till character is printedsub addr, #64' rewindjmp #:idle
' initialised data and/or presets
addr long8
shft long0' uninitialised data and/or temporaries
temp res1
char res1
lcnt res1
line res1fit
Then we have propfont_asm
CON''PINS
LCD_RS = 16''LCD RS pin
LCD_WR = 17''LCD WR pin''LCD REGISTER Enumeration, for SSM1289
REG_OSCILLATOR = $0000''Oscillator (R00h) (POR = 0000h)
REG_DRIVEROUTPUTCONTROL = $0001''Driver Output Control (R01h) (POR = 2B3Fh)
REG_LCDDRIVINGWAVFORM = $0002''LCD-Driving-Waveform Control (R02h) (POR = 0000h)
REG_POWERCONTROL1 = $0003'' (R03H)
REG_DISPLAYCONTROL = $0007''Display Control (R07h) (POR = 0000h)
REG_FRAMECYCLECONTROL = $000B''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET
REG_POWERCONTROL2 = $000C'' (R0Ch) (POR = 0004)
REG_POWERCONTROL3 = $000D''
REG_POWERCONTROL4 = $000E''
REG_GATESCANPOSITION = $000F''Gate Scan Position (R0Fh) (POR = 0000h)
REG_SLEEPMODE = $0010''Sleep mode (R10h) (POR = 0001h)
REG_ENTRYMODE = $0011''Entry Mode (R11h) (POR = 6830h)
REG_HPORCH = $0016'' (R16h) (POR = EF1Ch)
REG_VPORCH = $0017'' (R17h) (POR = 0003h)
REG_POWERCONTROL5 = $001E''
REG_RAMDATAWRITE = $0022''
REG_RAMWRITEDATAMASK1 = $0023'' (R23h) (POR = 0000h)
REG_RAMWRITEDATAMASK2 = $0024'' (R24h) (POR = 0000h)
REG_VERTICALSCROLCONTROL1 = $0041'' (R41h) (POR = 0000h)
REG_VERTICALSCROLCONTROL2 = $0042'' (R42h) (POR = 0000h)
REG_HORIZONTALRAMADDRESSPOS = $0044'' (R44h) (POR = EF00h)
REG_VERTICALRAMADDRESSSTART = $0045'' (R45h) (POR = 0000h)
REG_VERTICALRAMADDRESSEND = $0046'' (R46h) (POR = 013Fh)
REG_FIRSTWINDOWSTART = $0048'' (R48h) (POR = 0000h)
REG_FIRSTWINDOWEND = $0049'' (R49h) (POR = 013Fh)
REG_SECONDWINDOWSTART = $004A'' (R4Ah) (POR = 0000h)
REG_SECONDWINDOWEND = $004B'' (R4Bh) (POR = 013Fh)
REG_SETGDDRXADDRESSCOUNTER = $004E'' (R4Eh) (POR = 0000h)
REG_SETGDDRYADDRESSCOUNTER = $004F'' (R4Fh) (POR = 0000h)
FONT_ROM_ADDRESS = $8000VARlong screenbufferaddress
long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2
obj wait : "timing"
cr : "crReader"'pst : "parallax serial terminal" 'used for debugging..PUBBOOT'not a standalone objectPUBStart(ScreenBufferAdd)'Method to Init display, then load a cog with screen driver
screenbufferaddress := ScreenBufferAdd 'store buffer address in long
Init_SSD1289 'init screenlong[@screenbufferaddress] := $ffff'make sure screen buffer does not equal 0result := cognew(@entry,@long[@screenbufferaddress]) 'start write driver and pass it the address of screen buffer
cr.Start
PUBWriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
fontaddress := Cr.GetChar(Character)
'odd_even := character & $0001' characterpointer := character & $fffe'characterpointer >>= 1'characterpointer *= 32repeat idx from0to31
bitpatern[idx] := word[fontaddress][idx]
word[fontaddress] := 0
y1 := Col + ColBorder
y2:= (Col + 15) - ColBorder
x1 := Row + RowBorder
x2:= (Row + 31) - RowBorder
SetWindow(x1, y1, x2, y2)
SetGAddress(x1,y1)
repeat idx from RowBorder to31 - RowBorder
repeat pxlidx from ColBorder to15 - ColBorder
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16))
else
Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16))
repeatwhileword[fontaddress] := 0if (((Col + 16) > 319 ) and ((Row + 32) > 223))
Row := 0
Col := 0elseif (((Col + 16) > 319 ) and ((Row + 32) < 223))
Row := Row + 32
Col := 0else
Col := Col + 16' SetWindow(0, 0, 239, 319)PUBWriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
fontaddress := Cr.GetChar(Character)
Row := PosR
Col := PosC
RowBorder := RBorder
ColBorder := CBorder
BackgroundColor := BgC
ActiveTextColor := Txc
repeat idx from0to31
bitpatern[idx] := word[fontaddress][idx]
word[fontaddress] := 0
y1 := Col + ColBorder
y2:= (Col + 15) - ColBorder
x1 := Row + RowBorder
x2:= (Row + 31) - RowBorder
SetWindow(x1, y1, x2, y2)
SetGAddress(x1,y1)
repeat idx from RowBorder to31 - RowBorder
repeat pxlidx from ColBorder to15 - ColBorder
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16))
else
Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16))
repeatwhileword[fontaddress] := 0if (((Col + 16) > 319 ) and ((Row + 32) > 223))
Row := 0
Col := 0elseif (((Col + 16) > 319 ) and ((Row + 32) < 223))
Row := Row + 32
Col := 0else
Col := Col + 16PUBClearScreen(color) | idxr, idxc
SetWindow(0, 0, 239, 319)
SetGAddress(0,0)
color += (REG_RAMDATAWRITE << 16)
repeat idxr from0to76800
Lcd_Write_Asm(Color)
Row := 0
Col := 0PUBSetWindow(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS'Set window to draw in
WindowX1 := x1 'update draw window in main memory
WindowX2 := x2 'update draw window in main memory
WindowY1 := y1 'update draw window in main memory
WindowY2 := y2 'update draw window in main memory
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) 'combine x1 and x2 values
Lcd_Write_Asm ((REG_HORIZONTALRAMADDRESSPOS << 16) + HORIZONTALRAMADDRESSPOS) 'and write to display
Lcd_Write_Asm(y1 + (REG_VERTICALRAMADDRESSSTART << 16)) 'send v-address start
Lcd_Write_Asm(y2 + (REG_VERTICALRAMADDRESSEND << 16)) 'send v-address endPUBSetGAddress(x,y)'Set address for gddr writes
Lcd_Write_Asm ((REG_SETGDDRXADDRESSCOUNTER << 16) + x) ''max %1111_1111, $FF
Lcd_Write_Asm ((REG_SETGDDRYADDRESSCOUNTER << 16) + y) ''max %1_0011_1111, $13fPRIdeadend'loop for testingrepeatrepeat'endlessly wait
wait.pause1s(1) '' PRIEnableDisplayPins'enable all pins -DIRA:=%00000000_00000000_11111111_11111111''enable p15 - p0 PRITristateDisplayPins'tristate all pins - DIRA:=%00000000_00000000_00000000_00000000''release p15 - p0PRILcd_Write_Asm(V)'handler for asm writesrepeatwhile (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbufferlong[@screenbufferaddress] := V 'makes screen buffer = vPRILCD_Writ_Bus(V)'write to displayOUTA[15..0] := V ' copy V onto pins
WriteLow ' write pin low
WriteHigh ' toggle write pinPRILcd_Write_Com(V)'write command to display
LCD_RSLow 'Sets command
LCD_Writ_Bus(V) 'Do writePRILCD_Write_Data(V)'write data to display
LCD_RSHigh 'Sets data
LCD_Writ_Bus(V) 'do writePRILCD_RSLowouta[LCD_RS] := 0'controls RS pin with DIR-A dira[LCD_RS] := 1'see hardware revisionPRILCD_RSHigh'controls RS pin with DIR-Adira[LCD_RS] := 0'see hardware revision PRIWriteLowouta[LCD_WR] := 0'controls WR pin with DIR-A dira[LCD_WR] := 1'see hardware revision ' PRIWriteHigh'controls WR pin with DIR-A dira[LCD_WR] := 0'see hardware revision PRIInit_SSD1289''Init Display
EnableDisplayPins
outa[21] := 1dira[21] := 1
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01
Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h)
Lcd_Write_Data($0001) ''Turn on oscillator
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11
Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h)
Lcd_Write_Data($0000) '' ''exit sleep mode
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11
Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h)
Lcd_Write_Data($6838) ''
Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000)
Lcd_Write_Data($1000) '' ''
Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000)
Lcd_Write_Data($0000) '' ''''
Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F)
Lcd_Write_Data($6B3F) '' ''
Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
Lcd_Write_Data($5308) '''
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033)
Lcd_Write_Data($0033)
TristateDisplayPins ''Release pins'PUB PST_Init | PstCog ''Starts Parallax Serial Terminal for debugging.' PstCog := (pst.Start(115200) -1) '' returns the cog pst started in' pst.Str(String("Parallax Serial Terminal started in cog ")) '' talk to human' pst.Dec(PstCog) '' displays cog on PST ''' wait.pause1s(1)PUBHelloWorld
WriteActiveCr("H", 0, 0*16, 0, 0, $ffff, $0000)
WriteNextActiveCr("e")
WriteNextActiveCr("l")
WriteNextActiveCr("l")
WriteNextActiveCr("o")
WriteNextActiveCr(" ")
WriteNextActiveCr("W")
WriteNextActiveCr("o")
WriteNextActiveCr("r")
WriteNextActiveCr("l")
WriteNextActiveCr("d")
DAT'init Display driver'designed for optimized hardware, pull-up resistors on RS and WR pins.org0
entry movouta, PinsInit 'set pins to inital statemovdira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup 'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done'get write command from buffer, and check if it's 0
Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD datacmp Lcd_Data, #0wz'and check if it's 0if_zjmp #get 'if it is, try again.'if not, prepare transfer'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd datashr LCD_cmd, #16'move lcd command 16 bit to the right if not gddr write' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer'enables p0 - p15 mov pntr, #$8'set wait period
:wait0 djnz pntr, :wait0 'and wait
WrCmd movouta, LCD_Cmd 'place LCD_Cmd on write busmov pntr, #$8'set wait period
:wait0 djnz pntr, :wait0 'and waitadd zero, #0wz'prime WZ flag muxzdira, RSpin 'make RS pin low by enabling its DIR REGmov pntr, #$8'set wait period
:wait1 djnz pntr, :wait1 'and waitmuxzdira, WritePin 'make Write Pin low by enabling its DIR REGand LCD_Data, lowWordMask 'mask off High word of Lcd_Datamov pntr, #$f'set wait period
:wait2 djnz pntr, :wait2 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$8'set wait period
:wait3 djnz pntr, :wait3 'and waitmuxnzdira, RSpin 'make RS pin high by disabling its DIR REGmov pntr, #$8'set wait period
:wait4 djnz pntr, :wait4 'and wait
:WrDataPortion
movouta, LCD_Data 'place LCD_Data on write buswrlong zero, bufferaddress 'wzmov pntr, #$8'set wait period
:wait5 djnz pntr, :wait5 'and waitadd zero, #0wz'prime WZ flagmuxzdira, WritePin 'make Write Pin low by enabling its DIR REG'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data mov pntr, #$8'set wait period
:wait6 djnz pntr, :wait6 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$8'set wait period
:wait7 djnz pntr, :wait7 'and wait'mov dira, DirsDisabled 'disables p0 - p15jmp #Get 'do it all again
zero long$0
lowWordMask long$0000_ffff'pin settings
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111'' (R4Fh) (POR = 0000h)
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1
ForegroundFormat res1
BackgroundFormat res1
ForegroundScreen res1
BackgroundScreen res1fit
zero long$0
lowWordMask long$0000_ffff'pin settings
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111'' (R4Fh) (POR = 0000h)
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1
ForegroundFormat res1
BackgroundFormat res1
ForegroundScreen res1
BackgroundScreen res1fit
writes WAY faster, and still single character? about 5 or 6 seconds to draw full screen? haven't tested much yet. Still no sd card. I think either the cable I attached *about 3'* is too long, those damn pullup resistors or the cards I have are incompat.
varlong command, cog
word font[32]
...
[COLOR="red"]:chktbl rdword line, addr wz'get font table andif_nzjmp #:chktbl 'wait till character is printed[/COLOR]sub addr, #64' rewindjmp #:idle
What's the purpose of this? addr points to after the font array so whether you continue or not depends on whoever controls the next two bytes. Besides why do you feel you need the sync op here? The cog only writes to the font array while you're in the GetChar method.
That's an artifact of testing. Sorry, I thought I removed that. I have to admit it's primitive ATM. I'm working on a Character test now. Touchscreen enabled. I will make sure to clean this up. Thank you very much for your example. It streamlines in quite nicely. I am sure I can speed writes up even more, but every time I mess around with the timing, I end up breaking things. LOL
I have though about it, and will probably do it. But I just put it in the analog hardware and total failure! Clock and Data? are all over the signal. There's also some bugs. I want to turn the faders and buttons into objects, but there's a ton of work there. Including changing orientation and making them hold their own TouchScreen bounds. I've gotta take a second look at the hardware now
PRILcd_Write_Asm(V)'handler for asm writesrepeatwhile (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbufferlong[@screenbufferaddress] := V 'makes screen buffer = v
And the dat block
DAT'init Display driver'designed for optimized hardware, pull-up resistors on RS and WR pins.org0
entry movouta, PinsInit 'set pins to inital statemovdira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup 'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done'get write command from buffer, and check if it's 0
Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD datacmp Lcd_Data, #0wz'and check if it's 0if_zjmp #get 'if it is, try again.'if not, prepare transfer'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd datashr LCD_cmd, #16'move lcd command 16 bit to the right if not gddr write' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer'enables p0 - p15 ' mov pntr, #$1 'set wait period':wait0 djnz pntr, :wait0 'and wait
WrCmd movouta, LCD_Cmd 'place LCD_Cmd on write bus' mov pntr, #$1 'set wait period':wait0 djnz pntr, :wait0 'and waitadd zero, #0wz'prime WZ flag muxzdira, RSpin 'make RS pin low by enabling its DIR REG' mov pntr, #$1 'set wait period':wait1 djnz pntr, :wait1 'and waitmuxzdira, WritePin 'make Write Pin low by enabling its DIR REGand LCD_Data, lowWordMask 'mask off High word of Lcd_Data' mov pntr, #1 'set wait period':wait2 djnz pntr, :wait2 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$1'set wait period
:wait3 djnz pntr, :wait3 'and waitmuxnzdira, RSpin 'make RS pin high by disabling its DIR REGmov pntr, #$1'set wait period
:wait4 djnz pntr, :wait4 'and wait
:WrDataPortion
movouta, LCD_Data 'place LCD_Data on write buswrlong zero, bufferaddress 'wzmov pntr, #$1'set wait period
:wait5 djnz pntr, :wait5 'and waitadd zero, #0wz'prime WZ flagmuxzdira, WritePin 'make Write Pin low by enabling its DIR REG'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data mov pntr, #$2'set wait period
:wait6 djnz pntr, :wait6 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$1'set wait period
:wait7 djnz pntr, :wait7 'and wait'mov dira, DirsDisabled 'disables p0 - p15jmp #Get 'do it all again
zero long$0
lowWordMask long$0000_ffff'pin settings
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111'' (R4Fh) (POR = 0000h)
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1
Wow! The ASM code makes the display much faster. Good work! I was orginally adapting your spin code for the screen for my purposes, but I think i'll see if I can't get ASM to work as you have done. I'm sure it will be a bit of work(i'm hopless a ASM ). Just a quick question is there a way to "Debug" a string to the display from the font in ram(i haven't got my sd card to work yet) instead of havening to put each character to the screen separately and defining it's position separately?
I was planning a terminal type front end, but I have not got that far yet. The font I'm using is actually in rom. If you look at my calls, I have 2 propfont writers. One is active character, and the other is next character. Writing to the display is pretty simple, just call active character with the parameters for the first character, and then you can call next character with just the character.
this writes font to the display starting a row 0 column 8, no borders.
if you want, I can help you with the asm modifications. Should not be too hard.
*edited*
I fixed my analog hardware, and now I'm trying to get the HW to bind with the SW values. THIS VERSION IS NOT STABLE!!! I'm working on it
The HW version has optimizations I really recommend. Those pullup resistors on RS and WR are REALLY cool. I was going to pull all lines up or down for a correct init, but address comes out 0 which is screen reset, with enable floating that holds the screen in reset till the prop takes over.
I have been busy with school so not much time to update code. The analog hardware failure has been a big setback although I was able to find the fault. I am debating repairing this board as I have designed an actual PCB to replace the tangled mess of wire. I have also ordered brand new IC's and am replacing all tl074's with tl082's. Much work to be done.
What I'm wondering about now is the best way to regain the eeprom pins after startup. I have lcd_reset line that could be used to indicate a reset status as it is active when spi_en and spi_address lines are inputs. So my thought is to use a `244 to connect the pins to the external devices *midi out and midi in.* Do I need to use both sections of the 244, one for midi active, the other for eeprom active, or can I get away with leaving the eeprom in circuit. I've made enough modifications to the PropRPM that I feel sorry for it. I'm totally willing to cut traces if I have to, but would rather not. I also want to replace the eeprom with the largest one I can, and not sure which part to order. I'm looking at the AT24C512, not sure if this is the best choice.
Another consideration is how to connect my foot controller. I have 18 buttons, 3 digit - 7 segment display, 8 leds and a photo-sensor. I was using my BS2, but would like to free this up so my wife can build the boe-bot. I have a couple of PIC 18F's laying around, but no desire to build a board and develop code for what I consider to be an obsolete and overpriced micro. I will probably end up grabbing a couple more 40pin props and eeproms to match.
I keep saying I'm going to get the SD card working, but have had nothing but failure. I'm wondering if this is because when I'm starting the sd driver, the enable pin is set as an output by the calling cog. I will be conducting more tests later. Fingers crossed.
I also plan on turning the fader code into its own object. I'm trying to wrap my head around the process of this. The idea is to declare multiple instances of the fader object something like
obj
fader[4] : "faderObject"
Then update each fader instance, which will hold all necessary information for controlling it. Or something like this?
I also received a 16-bit drivers from another member today so I will be looking at those. Anyway, here's some pictures of the progress so far.
Once again, I've worked on the sd card and failed. I wired the breakout slot directly to the proprpm. No pin sharing, CS, D0, CK, DI. I did not install resistors yet since no-one else seems to need them. I will add those later to establish that is not the problem. I have tested with the only 2 sd cards I can get my hands on. SanDisk 64m and samsung micro-sd 2g. Both received fresh fat16 formats. I'm stumped as to why I can't get it to work. Pins are set to inputs at start of method. I'm using:
SD-MMC File Allocation Table Engine
Version: 2.0 - Special
Both calls return -1
I have no idea what else to try, other than add the resistors which I will be doing shortly. I will quadruple check my wiring, but doubt that's it. Does anyone have any insight? This is driving me crazy!
*EDIT*
I'm working on a new controller. Here's the initial idea.. I plan on using 2x - 18F452 or 18F4620's. I will be using one of each at first. These use the PSP bus and will be programmable via PROP. Once bootstrap is installed, updates will be handled from sd card, *opcode $F*. Instructions will be 4 bit, 2 bit priority, 2 bits reserved. 8 bit address, 8 or 16 bit data. Prop to PIC transfers will be 1 byte, 2 byte, 3 byte or 4 byte. Still working out all the details, but this will give 2 bidirectional USARTs, 3 SPI busses, 2x8 - bit digital pic bus *B, 2x6 10-bit analog bus. The configuration will be left up to user. There are a ton of built in's that will be very handy. I want to add Dr. Acula's Ram chips on. Any thoughts?
I DID IT! The sd card is working, although I've had some interesting results. I was unable to get kye's sd driver going. I spent about 4 hours working on it after I got fsrw1.7 going and gave up. I then spent another 8 hours getting fsrw 2.6 running. The interesting thing is, my micro-sd card worked in fsrw1.7... I THINK. I only have one card that works in fsrw 2.6 and I'm still not sure why. I will do some more debugging later and post the results.
SO, the next task after getting sd cards working was getting Dr. Acula's fonts working. That took about a week. The code needs a ton of work, but it's a start. I'm kinda put off by how the parallax font looks. That 7 is KILLIN me. I still think it looks better than the rom font at half size. Pix to come.
Dr. Acula's font test
CON{''Hardware version 3.11 - see diagram.
''
}_clkmode = xtal1 + pll16x' use crystal x 16_xinfreq = 5_000_000'with 5mhz crystal
DEV_SD_CLK = 18
DEV_SD_DI = 19
DEV_SD_DO = 20
DEV_SPI_EN = 21''SPI Enable enumeration
DEV_SPI_ADD0 = 22''Device address 0 enumeration
DEV_SPI_ADD1 = 23''Device address 1 enumeration
DEV_SPI_ADD_LE = 24
DEV_SPI_LCD_RES = 0''Device id for LCD reset
SDC = 1
TSC = 2
EXT = 3
DEV_SPI_EXT_POT_CS = 0
DEV_SPI_EXT_SW_CS = 1
BGCOLOR = $ffff
TXTCOLOR = $0000
Pressed = 1
NotPressed = 0
faderUpBtnBound = 499''y < 499
faderDnBtnBound = 3700''y > 3699 3200, 1600, 320
fadertouchoffset = 320''3375 < y < 825 range e
cols = 40
rows = 15
screensize = cols * rows
lastrow = screensize - cols
offset = 8 * 2048' the block offset of where we do writes
RamText = 169984
VT100 = 202752
FontTable = 206080VARlong Screen_Buffer, CRbuffer
byte FontHeight ' size of the current loaded font (pixels = fontsize *.75)word BackFontColor ' the background color in RRRRRGGG GGGBBBBB formatword curx ' current cursor x position in pixelsword cury ' current cursor y position in pixelsbyte Orientation ' true for portrait, false for landscapeword ScreenWidth ' either 240 in portrait or 320 in landscapeword ScreenHeight ' 320 in portrait or 240 in landscapebyte screen[screensize]
long col,row,flag
'byte font[13312], sdbuffer[512],buffer2[512] ' 512 byte buffer for sd card interface'byte tbuf[20]'byte bigbuf[8192]long BackgroundColor, ActiveTextColor, stringptr[32], maxdur,sr ,speedresults
OBJ pfw :"PropFont_asmDone"
wait : "timing"'pst : "parallax serial terminal"
spi : "spi_asm"
sdfat: "fsrw"'block: "safe_spi"'ILI9325:"ILI9325_Dracblade" PUBBOOT | f'bootstrap, initalizes pins, then starts pst, init display, start asm, clear screen and display hello world
WAIT.PAUSE1S(5)
initPins
SetOrientation(false)
BackgroundColor := $ffe0
ActiveTextColor := %0000long[@Screen_Buffer] := $ffff'make sure screen buffer does not equal 0
pfw.Start(@Long[@Screen_Buffer]) 'Start Asm Driver, needs to be changed to pass screen buffer from top object
pfw.size(1)
pfw.setChar(0, 8, 0, 0, BackgroundColor, ActiveTextColor)
spi.start(3,0)
'pfw.ClearScreen(BackgroundColor) 'Draw White Screen with asm' DracFont'pfw.dec(\SD_speedtest)'wait.pause1s(5)repeat
DracFont
PubDracFont |c'pfw.clearscreen($FFFF)
pfw.size(2)
'pfw.str(string(" setting enable output "))OUTA[DEV_SPI_EN] := 1outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC
dira[DEV_SPI_EN..DEV_SD_CLK] := 0dira[DEV_SPI_ADD1..DEV_SPI_ADD0] := 3'pfw.newline 'pfw.str(string(" setting enable output ok "))'pfw.newline'pfw.str(string(" trying to mount sd card ")) 'pfw.newline'wait.pause1s(1) if \sdfat.mount(18) < -1' pfw.str(string("Mount Failed"))'wait.pause1s(3)
sdfat.unmount
else'pfw.str(string(" Mounting OK "))
\NewFont(string("Par16.ifn"))
sdfat.unmount
Text_cls
'tswaitrepeatrepeat c from32to125
wait.pause1ms(100)
text_out(c) '' Text_str(string("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"))
Text_str(string("Basic text display for the ILI9325"))
Text_crlf
Text_str(string("Print decimal value "))
Text_dec(100)
Text_crlf
text_str(string("Hex value 500 = "))
Text_hex(500,4)
text_crlf
'wait.pause1s(5)PUBText_Str(rstringptr)'' Print a zero-terminated stringrepeatstrsize(rstringptr)
Text_out(byte[rstringptr++])
PUBText_out(c) | i, k'' Output a character'''' $08 = backspace'' $09 = tab (8 spaces per)'' $01 = set X position (X follows)'' $0B = set Y position (Y follows)'' $0C = set color (color follows) (not on this simple terminal)'' $0A = line feed'' $0D = carriage return (col = 0)'' others = printable characterscase flag
$00: case c
$08: if col ' not zero so can subtract one
col--
Text_print(" ") ' backspace and rubout
col--
'Text_RedrawLine$09: repeat
Text_print(" ")
while col & 7$01: flag := c
return$0B: flag := c
return$0C: flag := c
return$0A: Text_newline ' linefeed/new line $0D: col := 0' carriage returnother: Text_print(c)
$0A: col := c // cols
$0B: row := c // rows
'$0C: color := c & 7
flag := 0PRIText_print(c)' private routine from routine above
screen[row * cols + col] := c ' store in the screen text buffer
ILIChar(c,col<<3,row <<4) ' print on the screen col*8 and row *16 as this is the font sizeif ++col == cols
Text_newline 'PUBText_hex(value, digits){{ Send value as hexadecimal characters up to digits in length.
''
'' `Parameters:
''
'' `value: byte, word, or long value to send as hexadecimal characters.
'' `digits: number of hexadecimal digits to send. Will be zero padded if necessary.
''
'' `Return: none.
''
'' `Example: pst.Hex(1234, 5)
''
'' Output decimal 1234 as five hex digits. Outputs `004D2.
'' Next lines, if needed...
}}
if (digits > 8)
repeat digits - 8
Text_out("0")
digits := 8else
value <<= (8 - digits) << 2repeat digits
Text_out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUBText_dec(value) | i'' Print a decimal numberif value < 0
-value
Text_out("-")
i := 1_000_000_000repeat10if value => i
Text_out(value / i + "0")
value //= i
result~~
elseifresultor i == 1
Text_out("0")
i /= 10PRIText_newline | i
col := 0if ++row == rows
row--
bytemove(@screen, @screen[cols], lastrow) 'scroll linesbytefill(@screen[lastrow], " ", cols) 'clear new line
Text_RedrawScreen ' all lines shuffle up one so need to redraw all the screenPUBText_RedrawScreen | x,y,i
ClearFontBackground(0,0,screenheight,screenwidth)
ILIsetcursor(0,0)
i := 0repeat y from0to rows -1repeat x from0to cols -1
curx := ILIChar(screen[i],curx,cury)
i++
curx :=0
cury +=fontheight
PRIText_RedrawLine | oldcurx,i' redraw current row, for backspace
oldcurx := curx' store
ClearFontBackground(0,row <<4 ,screenwidth,row <<4 + FontHeight) ' clear background line to the background color ready to draw
curx := 0
cury := row <<4' times 16
i := row * cols ' variable row times constant colsrepeat cols ' do 40x
curx := ILIChar(screen[i],curx,cury)
i++
curx := oldcurx ' restore curxPUBILIChar(ascii,x,y) | jump,size,width,height,ramaddress,xoffset,yoffset,xadvance' read out a character from a .ifn file stored in ram
jump := long[@font + (ascii << 2) + 256]' jump location = ascii *4 plus fonttable + 256
jump += @font
size := long[jump] ' size precalculated = width x height x 2
xadvance := long[jump][5] ' ' amount to move to next character offset = 20 which is 5 longsif size > 0and ascii <> 32' no need to print anything if size is zero or read more font data
width := long[jump][1] ' width value of offset is 1 long
height := long[jump][2] ' height
xoffset := long[jump][3] ' xoffset to move
yoffset := long[jump][4] ' yoffset to moveif (x+width -1 + xoffset) > screenwidth
ILIcrlf ' do a new line if it won't fit
x :=curx
y :=cury
pfw.draw( x+xoffset, y+yoffset, x+width-1+xoffset,y+height-1+yoffset) ' draw on screen
pfw.hub(jump+32,size) ' move bytes from ram out to the display return x + xadvance
PUBSetOrientation(e)' change orientation true = portrait. Changes global variable 'orientation' and also screen width and height
orientation := e
pfw.ChangeOrientation(orientation)
if orientation
screenwidth :=239
screenheight :=319else
screenwidth :=319
screenheight :=239PUBText_crlf
Text_out(13)
Text_out(10)
PUBText_clsbytefill(@screen, " ", screensize)
col := row := 0PUBILISetCursor(x,y)
curx := x
cury := y
PUBILIcrlf
curx := 0
cury += FontHeight
PUBNewFont(nstrpointer)
ILIloadfont(nstrpointer)
' only call this routine with the cursor curx at zero'pfw.newline'pfw.str(string("calling font clear with curx"))' pfw.dec(curx)'pfw.newline'pfw.str(string("cury"))' pfw.dec(cury)'pfw.newline'pfw.str(string("screenwitdth"))'pfw.dec(screenwidth)'pfw.newline' pfw.str(string("screenheight"))'pfw.dec(screenheight)'pfw.newline''tswait'pfw.str(string("go"))
ClearFontBackground(0,0,screenheight,screenwidth) ' clear an area the same color as the font background'pfw.str(string("cleared?"))
ILIsetcursor(0,0)
PUBILILoadFont(nstringptr)| filesize,i' hub version' pass file name in stringptr' the variable "i" must start on 0,256,512,768 etc for the block move to work
i := 0'pfw.newline'pfw.str(string("Opening file "))'pfw.str(nstringptr)'pfw.newline
sdfat.popen(nstringptr,"r") ' store at the constant 'fonttable' location 'pfw.str(string("Opening file ok "))'pfw.newline'pfw.str(string("Getting filesize"))'pfw.newline
filesize := sdfat.get_filesize
'pfw.str(string("Filesize is "))'pfw.dec(filesize)'pfw.newline'pfw.str(string("loading font into hub"))'pfw.newlinerepeat (filesize >> 8) ' read in this number of 256 byte blocks
sdfat.pread(@font+i,256) ' get 256 bytes from sd card
i += 256' add 256'pfw.str(string(" read complete "))'pfw.newline'pfw.str(string(" closing filesystem "))
sdfat.pclose
'pfw.str(string(" closed "))'pfw.newline'pfw.str(string("loading font height"))
FontHeight := font[251]
'pfw.dec(FontHeight)'pfw.newline'pfw.str(string("getting bgcolor"))'pfw.newline repeat i from0to2
sdbuffer[i] := font[35+i] ' read the 3 RGB bytes'pfw.str(string("bg color is "))'repeat i from 0 to 2'pfw.dec(sdbuffer[i])'pfw.newline 'pfw.str(string("converting colors "))
pfw.convertColors(@sdbuffer,@buffer2,1)
'pfw.str(string("conversion done"))'tswait'pfw.clearscreen($4893)'pfw.str(string("new colors are"))
BackFontColor := word[@buffer2] ' background color in ILI two byte format'pfw.dec(BackFontColor)'pfw.newline'pfw.str(string("returing with filesize"))'pfw.dec(filesize)result := filesize
''tswaitPUBClearFontBackground(x1,y1,x2,y2) | i,size,remainder' clears an area of the screen to the current font background color
size := (x2-x1+1) * (y2 - y1 +1) ' number of pixels
remainder := (size & 255) << 1' if not a whole number of 256 pixelsrepeat i from0to510step2' move the background font colour to the buffer
sdbuffer[i] := BackFontColor & 255' and replicate for 256 pixels
sdbuffer[i+1] := BackFontColor >> 8
pfw.draw(y1,x1,y2,x2) ' set up the area of the screen to draw inrepeat size >> 8' 512 byte blocks
pfw.hub(@sdbuffer,512) ' 2 = 2 bytes which = one pixel *was 512if remainder <> 0
pfw.hub(@sdbuffer,remainder) ' do the remainderPUBTSWait | yval, xval,x,yOUTA[DEV_SPI_ADD1..DEV_SPI_ADD0] := TSC ''Old format was OUTA[TS_CS] := 0 ' enable the touch screen ' dirA[DEV_SPI_EN] := 1dirA[DEV_SPI_ADD1] :=1dirA[DEV_SPI_ADD0] := 1outa[DEV_SPI_EN] := 1
wait.pause1ms(100)
repeatOUTA[DEV_SPI_EN] := 0
SPI.SHIFTOUT(DEV_SD_DI, DEV_SD_CLK, 5, 8 , %1101_0000) ' reads x from 500 to 3700 (off < 500 )
xval := SPI.SHIFTIN(DEV_SD_DO, DEV_SD_CLK,2, 12)
SPI.SHIFTOUT(DEV_SD_DI, DEV_SD_CLK, 5, 8 , %1001_0000) ' reads y from 400 to 3800 (off > 3800 )
yval := SPI.SHIFTIN(DEV_SD_DO,DEV_SD_CLK,2, 12)
if xval <> 0result := xval + (yval << 16)
OUTA[DEV_SPI_EN] := 1outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC
RETURNELSE
wait.pause1ms(100)
PUBStrobeCSOUTA[DEV_SPI_EN] := 0
wait.pause1ms(10)
OUTA[DEV_SPI_EN] := 1priinitPinsdirA[DEV_SPI_ADD0] := 1'makes address 0 and 1 dirA[DEV_SPI_ADD1] := 1'outputsdirA[DEV_SPI_EN] := 1'and enable an output as wellOUTA[DEV_SPI_ADD1..DEV_SPI_ADD0] := 2'sd_card is defaultOUTA[DEV_SPI_EN] := 1'Disable - Reset Screen'pri SD_speedtest | r, sta, bytes, CHAR ''works?' OUTA[DEV_SPI_EN] := 1 ' outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC' dira[DEV_SPI_EN..DEV_SD_CLK] := 0' dira[DEV_SPI_ADD1..DEV_SPI_ADD0] := 3' pfw.size(2)' pfw.clearscreen(0)' pfw.setColors($0000,$FFFF) ' pfw.Str(string("Starting SD card")) ' helpful message if card is out, better than just a blank screen' pfw.newline ' Pfw.str(string("Mounting."))' pfw.newline ' sdfat.mount(18)' Pfw.str(string("Mounted."))' pfw.newline' wait.Pause1s(1)' Pfw.str(string("Dir:"))' pfw.newline' sdfat.opendir' repeat while 0 == sdfat.nextfile(@tbuf)' Pfw.str(@tbuf)' Pfw.newline ' Pfw.str(string("That's the dir")) ' sta := cnt' r := sdfat.popen(string("speed.txt"), "w")' repeat 256 ' sdfat.pwrite(@bigbuf, 8192) 'r := (cnt - sta) >> 2' sdfat.pclose'pfw.newline'Pfw.str(string("Writing 2M took "))' pfw.dec(r)'Pfw.newline'sta := cnt'r := sdfat.popen(string("speed.txt"), "r")'repeat 256' sdfat.pread(@bigbuf, 8192)'r := (cnt - sta) >> 2 'sdfat.pclose'sdfat.release'sdfat.unmount'Pfw.str(string("Reading 2M took "))'pfw.dec(r)'Pfw.newline'Pfw.str(string("That's, all, folks! "))'pfw.size(1) 'tswait 'pub deadend 'loop for testing' repeat 'endlessly wait' repeat' waitcnt(2_000 + cnt)DAT
sdbuffer byte$0[512] ' 512 byte buffer for sd card interface
buffer2 byte$0[512] ' 512 general purpose hub buffer
font byte$0[13312]
and the helpers
propFont, now has passthrough functions...
CON''PINS
LCD_RS = 16''LCD RS pin
LCD_WR = 17''LCD WR pin''LCD REGISTER Enumeration, for SSM1289
REG_OSCILLATOR = $0000''Oscillator (R00h) (POR = 0000h)
REG_DRIVEROUTPUTCONTROL = $0001''Driver Output Control (R01h) (POR = 2B3Fh)
REG_LCDDRIVINGWAVFORM = $0002''LCD-Driving-Waveform Control (R02h) (POR = 0000h)
REG_POWERCONTROL1 = $0003'' (R03H)
REG_DISPLAYCONTROL = $0007''Display Control (R07h) (POR = 0000h)
REG_FRAMECYCLECONTROL = $000B''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET
REG_POWERCONTROL2 = $000C'' (R0Ch) (POR = 0004)
REG_POWERCONTROL3 = $000D''
REG_POWERCONTROL4 = $000E''
REG_GATESCANPOSITION = $000F''Gate Scan Position (R0Fh) (POR = 0000h)
REG_SLEEPMODE = $0010''Sleep mode (R10h) (POR = 0001h)
REG_ENTRYMODE = $0011''Entry Mode (R11h) (POR = 6830h)
REG_HPORCH = $0016'' (R16h) (POR = EF1Ch)
REG_VPORCH = $0017'' (R17h) (POR = 0003h)
REG_POWERCONTROL5 = $001E''
REG_RAMDATAWRITE = $0022''
REG_RAMWRITEDATAMASK1 = $0023'' (R23h) (POR = 0000h)
REG_RAMWRITEDATAMASK2 = $0024'' (R24h) (POR = 0000h)
REG_VERTICALSCROLCONTROL1 = $0041'' (R41h) (POR = 0000h)
REG_VERTICALSCROLCONTROL2 = $0042'' (R42h) (POR = 0000h)
REG_HORIZONTALRAMADDRESSPOS = $0044'' (R44h) (POR = EF00h)
REG_VERTICALRAMADDRESSSTART = $0045'' (R45h) (POR = 0000h)
REG_VERTICALRAMADDRESSEND = $0046'' (R46h) (POR = 013Fh)
REG_FIRSTWINDOWSTART = $0048'' (R48h) (POR = 0000h)
REG_FIRSTWINDOWEND = $0049'' (R49h) (POR = 013Fh)
REG_SECONDWINDOWSTART = $004A'' (R4Ah) (POR = 0000h)
REG_SECONDWINDOWEND = $004B'' (R4Bh) (POR = 013Fh)
REG_SETGDDRXADDRESSCOUNTER = $004E'' (R4Eh) (POR = 0000h)
REG_SETGDDRYADDRESSCOUNTER = $004F'' (R4Fh) (POR = 0000h)
FONT_ROM_ADDRESS = $8000VARlong screenbufferaddress, Fontsize, pcog
long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2
byte orientation
word entrymode
obj wait : "timing"
cr : "crReader"'pst : "parallax serial terminal" 'used for debugging..
num : "numbers"PUBnul'not a standalone objectPUBdraw(x1, y1,x2, y2)'compatibility passthrough for DRAC
SetWindow( y1,x1, y2,x2 )
SetGAddress(y1,x1)
col :=0
row :=0PUBChangeOrientation(n)' pass true = portrait or false = landscape, changes global variable orientation in this object' EnableDisplayPins
orientation := n
' if orientation' Lcd_Write_Com($0001,$0100) ' set SS and SM bit 0001 0100 portrait' Lcd_Write_Com$0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030 ' else' Lcd_Write_Com($0001,$0000) ' set SS and SM bit 0001 0000 landscape ' Lcd_Write_Com($0003,$1038) ' landscape $1028 = original but 1038 is correct - not mirror image' pubconvertColors(inadd, outadd, len ) |red, green, blue, ilihigh, ililow' takes a .raw 3 byte RRRRRRRR GGGGGGGG BBBBBBBB and converts to 2 byte RRRRRGGG GGGBBBBB' pass hubaddr, ramaddr and len' hubaddr is source location, len is number of pixels' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklengthrepeat len
red := byte[inadd]
inadd++
green := byte[inadd]
inadd++
blue := byte[inadd]
inadd++
red >>= 3
red <<= 3
green >>= 2
ilihigh:= green
ilihigh >>= 3
ilihigh |= red
green &=%00000111
green <<= 5
ililow := green
blue >>= 3
ililow |= blue
word[outadd] := ilihigh +(ililow << 8)
outadd++
PUBhub(address,l) | p, pl, phrepeat l / 2
pl := byte[address++]
ph := byte[address++]
p:= ph +(pl << 8)
Lcd_Write_Asm((REG_RAMDATAWRITE << 16)+ p )
'PUB setEntryModeDefault' setEntryMode(3,1)pubsetEntryMode' 5..4 3'entry vs dfm trans- oe wm d0..1 ty id AM LG'mode Mode 1..0 parent def mode mode 1..0
entrymode := %0110______1000____0000____1000' default $6838
Lcd_Write_Asm((REG_ENTRYMODE << 16) + entrymode )
pubsetDriverOutputControl | reverse,bgr,tb,rl'reverse'bgr'tb 'rlpubpixel(p)
Lcd_Write_Asm((REG_RAMDATAWRITE << 16)+ p )
pubsize(s)
fontsize := s
PUBStr(ptr) | cbuf
cbuf := byte[ptr++]
WriteActiveCr(cbuf, row, col, 0, 0, BackgroundColor, ActiveTextColor)
repeat (strsize(ptr) )
WriteNextActiveCr(byte[ptr++])
PUBdec(n) | t, t2, t3, t4, t5, t6, t7, t8, t9, t10, pl, im
str(num.tostr(n, %000_010_001_0_0_000000_01010))
pubnewline
Row := Row + (32 >> (fontsize -1))
Col := 0pubsetRow(PosR )
Row := PosR
pubsetCol(PosC)
Col := PosC
pubsetBorders(RBorder, CBorder)
RowBorder := RBorder
ColBorder := CBorder
pubsetColors( BgC, TxC)
BackgroundColor := BgC
ActiveTextColor := Txc
PUBsetChar(PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
setRow(PosR)
setCol(PosC)
setBorders(RBorder, CBorder)
setColors(BgC, TxC)
PUBStart(ScreenBufferAdd)'Method to Init display, then load a cog with screen driver
screenbufferaddress := ScreenBufferAdd 'store buffer address in long
Init_SSD1289 'init screenlong[@screenbufferaddress] := $ffff'make sure screen buffer does not equal 0result := pcog := cognew(@entry,@long[@screenbufferaddress]) 'start write driver and pass it the address of screen buffer
cr.Start
num.init
PUBStopcogstop(pcog)
PUBChar(c)
WriteNextActiveCr(c)
PUBWriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
fontaddress := Cr.GetChar(Character)
repeat idx from0to31
bitpatern[idx] := word[fontaddress][idx]
y1 := Col + ColBorder
y2 := (Col + (15 / fontsize ) - ColBorder)
x1 := Row + RowBorder
x2 := (Row + (31 / fontsize ) - RowBorder)
SetWindow(x1, y1, x2, y2)
SetGAddress(x1,y1)
repeat idx from RowBorder to31 - RowBorder step Fontsize
repeat pxlidx from ColBorder to15 - ColBorder step Fontsize
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16))
else
Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16))
repeatwhileword[fontaddress] := 0if (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) > 223)))
Row := 0
Col := 0elseif (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) < 223)))
Row := Row + (32 >> (fontsize -1))
Col := 0else
Col := Col + (16 >> (fontsize - 1))
PUBWriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
setChar(PosR, PosC, RBorder, CBorder, BgC, TxC)
WriteNextActiveCr(Character)
PUBClearScreen(color) | idxr, idxc
SetWindow(0, 0, 239, 319)
SetGAddress(0,0)
color += (REG_RAMDATAWRITE << 16)
repeat idxr from0to76800
Lcd_Write_Asm(Color)
Row := 0
Col := 0'BackgroundColor := color'ActiveTextColor := $ffffPUBSetWindow(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS'Set window to draw in
WindowX1 := x1 'update draw window in main memory
WindowX2 := x2 'update draw window in main memory
WindowY1 := y1 'update draw window in main memory
WindowY2 := y2 'update draw window in main memory
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) 'combine x1 and x2 values
Lcd_Write_Asm ((REG_HORIZONTALRAMADDRESSPOS << 16) + HORIZONTALRAMADDRESSPOS) 'and write to display
Lcd_Write_Asm(y1 + (REG_VERTICALRAMADDRESSSTART << 16)) 'send v-address start
Lcd_Write_Asm(y2 + (REG_VERTICALRAMADDRESSEND << 16)) 'send v-address endPUBSetGAddress(x,y)'Set address for gddr writes
Lcd_Write_Asm ((REG_SETGDDRXADDRESSCOUNTER << 16) + x) ''max %1111_1111, $FF
Lcd_Write_Asm ((REG_SETGDDRYADDRESSCOUNTER << 16) + y) ''max %1_0011_1111, $13f'' PRIEnableDisplayPins'enable all pins -DIRA:=%00000000_11000000_11111111_11111111''enable p15 - p0 PRITristateDisplayPins'tristate all pins - DIRA:=%00000000_11000000_00000000_00000000''release p15 - p0PRILcd_Write_Asm(V)'handler for asm writesrepeatwhile (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbufferlong[@screenbufferaddress] := V 'makes screen buffer = vPRILCD_Writ_Bus(V)'write to displayOUTA[15..0] := V ' copy V onto pins
WriteLow ' write pin low
WriteHigh ' toggle write pinPRILcd_Write_Com(V)'write command to display
LCD_RSLow 'Sets command
LCD_Writ_Bus(V) 'Do writePRILCD_Write_Data(V)'write data to display
LCD_RSHigh 'Sets data
LCD_Writ_Bus(V) 'do writePRILCD_RSLowouta[LCD_RS] := 0'controls RS pin with DIR-A dira[LCD_RS] := 1'see hardware revisionPRILCD_RSHigh'controls RS pin with DIR-Adira[LCD_RS] := 0'see hardware revision PRIWriteLowouta[LCD_WR] := 0'controls WR pin with DIR-A dira[LCD_WR] := 1'see hardware revision ' PRIWriteHigh'controls WR pin with DIR-A dira[LCD_WR] := 0'see hardware revision PRIInit_SSD1289''Init Display
EnableDisplayPins
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01
Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h)
Lcd_Write_Data($0001) ''Turn on oscillator
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11
Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h)
Lcd_Write_Data($0000) '' ''exit sleep mode
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h)
Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11
Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h) 6838
Lcd_Write_Data($6838) ''
Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000)
Lcd_Write_Data($1000) '' ''
Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000)
Lcd_Write_Data($0000) '' ''''
Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F) 6838
Lcd_Write_Data($6B3F) '' '' Bit 14 - Invert Color bit9-TB
Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
Lcd_Write_Data($5308) '''
Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033)
Lcd_Write_Data($0033)
TristateDisplayPins ''Release pinsPUBHelloWorld
WriteActiveCr("H", 0, 0*16, 0, 0, $ffff, $0000)
WriteNextActiveCr("e")
WriteNextActiveCr("l")
WriteNextActiveCr("l")
WriteNextActiveCr("o")
WriteNextActiveCr(" ")
WriteNextActiveCr("W")
WriteNextActiveCr("o")
WriteNextActiveCr("r")
WriteNextActiveCr("l")
WriteNextActiveCr("d")
DAT'init Display driver'designed for optimized hardware, pull-up resistors on RS and WR pins.org0
entry movouta, PinsInit 'set pins to inital statemovdira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par'store par in bufferaddress, par is screen buffer address at startup'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done'get write command from buffer, and check if it's 0
Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD datacmp Lcd_Data, #0wz'and check if it's 0if_zjmp #get 'if it is, try again.'if not, prepare transfer'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd datashr LCD_cmd, #16'move lcd command 16 bit to the right if not gddr write' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer'enables p0 - p15 ' mov pntr, #$1 'set wait period':wait0 djnz pntr, :wait0 'and wait
WrCmd movouta, LCD_Cmd 'place LCD_Cmd on write bus' mov pntr, #$1 'set wait period':wait0 djnz pntr, :wait0 'and waitadd zero, #0wz'prime WZ flag muxzdira, RSpin 'make RS pin low by enabling its DIR REG' mov pntr, #$1 'set wait period':wait1 djnz pntr, :wait1 'and waitmuxzdira, WritePin 'make Write Pin low by enabling its DIR REGand LCD_Data, lowWordMask 'mask off High word of Lcd_Data' mov pntr, #1 'set wait period':wait2 djnz pntr, :wait2 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REGmov pntr, #$1'set wait period
:wait3 djnz pntr, :wait3 'and waitmuxnzdira, RSpin 'make RS pin high by disabling its DIR REGmov pntr, #$2'set wait period
:wait4 djnz pntr, :wait4 'and wait
:WrDataPortion
movouta, LCD_Data 'place LCD_Data on write busmov pntr, #$1'set wait period
:wait5 djnz pntr, :wait5 'and waitadd zero, #0wz'prime WZ flagmuxzdira, WritePin 'make Write Pin low by enabling its DIR REG'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data ' mov pntr, #$2 'set wait period':wait6 djnz pntr, :wait6 'and waitmuxnzdira, WritePin 'make Write Pin high by disabling its DIR REG' mov pntr, #$1 'set wait period':wait7 djnz pntr, :wait7 'and wait'mov dira, DirsDisabled 'disables p0 - p15wrlong zero, bufferaddress
jmp #Get 'do it all again
zero long$0
lowWordMask long$0000_ffff'pin settings
WritePin long%00000000_00000010_00000000_00000000
RSPin long%00000000_00000001_00000000_00000000
PinsInit long%00000000_00000000_00000000_00000000
DirsDisabled long%00000000_00000000_00000000_00000000
DirsEnabled long%00000000_00000000_11111111_11111111'' (R4Fh) (POR = 0000h)
bufferaddress res1
LCD_cmd res1
LCD_data res1
Pntr res1
ForegroundFormat res1
BackgroundFormat res1
ForegroundScreen res1
BackgroundScreen res1fit
and my fsrw stuff for good measure
{{
' fsrw 2.6 Copyright 2009 Tomas Rokicki and Jonathan Dummer
'
' See end of file for terms of use.
'
' This object provides FAT16/32 file read/write access on a block device.
' Only one file open at a time. Open modes are 'r' (read), 'a' (append),
' 'w' (write), and 'd' (delete). Only the root directory is supported.
' No long filenames are supported. We also support traversing the
' root directory.
'
' In general, negative return values are errors; positive return
' values are success. Other than -1 on popen when the file does not
' exist, all negative return values will be "aborted" rather than
' returned.
'
' Changes:
' v1.1 28 December 2006 Fixed offset for ctime
' v1.2 29 December 2006 Made default block driver be fast one
' v1.3 6 January 2007 Added some docs, and a faster asm
' v1.4 4 February 2007 Rearranged vars to save memory;
' eliminated need for adjacent pins;
' reduced idle current consumption; added
' sample code with abort code data
' v1.5 7 April 2007 Fixed problem when directory is larger
' than a cluster.
' v1.6 23 September 2008 Fixed a bug found when mixing pputc
' with pwrite. Also made the assembly
' routines a bit more cautious.
' v2.1 12 July 2009 FAT32, SDHC, multiblock, bug fixes
' v2.4 26 September 2009 Added seek support. Added clustersize.
' v2.4a 6 October 2009 modified setdate to explicitly set year/month/etc.
' v2.5 13 November 2009 fixed a bug on releasing the pins, added a "release" pass through function
' v2.6 11 December 2009: faster transfer hub <=> cog, safe_spi.spin uses 1/2 speed reads, is default
}}
'' Constants describing FAT volumes.'con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSIZE = 32
DIRSHIFT = 5'' The object that provides the block-level access.'obj'sdspi : "sdspiqasm" ' old? no release 'sdspi: "mb_spi" nogood'sdspi: "mb_rawb_spi" noope'sdspi: "mb_small_spi" 'no work
sdspi: "safe_spi"var''' Variables concerning the open file.'long fclust ' the current cluster numberlong filesize ' the total current size of the filelong floc ' the seek position of the filelong frem ' how many bytes remain in this cluster from this filelong bufat ' where in the buffer our current character islong bufend ' the last valid character (read) or free position (write)long direntry ' the byte address of the directory entry (if open for write)long writelink ' the byte offset of the disk location to store a new clusterlong fatptr ' the byte address of the most recently written fat entrylong firstcluster ' the first cluster of this file'' Variables used when mounting to describe the FAT layout of the card' (moved to the end of the file in the Spin version).''' Variables controlling the caching.''' Buffering: two sector buffers. These two buffers must be longword' aligned! To ensure this, make sure they are the first byte variables' defined in this object.'byte buf[SECTORSIZE] ' main data bufferpubrelease'' This is just a pass-through function to allow the block layer' to tristate the I/O pins to the card.'
sdspi.release
priwriteblock2(n, b)'' On metadata writes, if we are updating the FAT region, also update' the second FAT region.'
sdspi.writeblock(n, b)
if (n => fat1)
if (n < fat1 + sectorsperfat)
sdspi.writeblock(n+sectorsperfat, b)
priflushifdirty'' If the metadata block is dirty, write it out.'if (dirty)
writeblock2(lastread, @buf2)
dirty := 0prireadblockc(n)'' Read a block into the metadata buffer, if that block is not already' there.'if (n <> lastread)
flushifdirty
sdspi.readblock(n, @buf2)
lastread := n
pribrword(b)'' Read a byte-reversed word from a (possibly odd) address.'return (byte[b]) + ((byte[b][1]) << 8)
pribrlong(b)'' Read a byte-reversed long from a (possibly odd) address.'return brword(b) + (brword(b+2) << 16)
pribrclust(b)'' Read a cluster entry.'if (filesystem == 1)
return brword(b)
elsereturn brlong(b)
pribrwword(w, v)'' Write a byte-reversed word to a (possibly odd) address, and' mark the metadata buffer as dirty.'byte[w++] := v
byte[w] := v >> 8
dirty := 1pribrwlong(w, v)'' Write a byte-reversed long to a (possibly odd) address, and' mark the metadata buffer as dirty.'
brwword(w, v)
brwword(w+2, v >> 16)
pribrwclust(w, v)'' Write a cluster entry.if (filesystem == 1)
brwword(w, v)
else
brwlong(w, v)
'' This may do more complicated stuff later.'pubunmount
pclose
sdspi.stop
prigetfstype : rif (brlong(@buf+$36) == constant("F" + ("A" << 8) + ("T" << 16) + ("1" << 24)) and buf[$3a]=="6")
return1if (brlong(@buf+$52) == constant("F" + ("A" << 8) + ("T" << 16) + ("3" << 24)) and buf[$56]=="2")
return2' return r (default return)pubmount_explicit(DO, CLK, DI, CS) : r | start, sectorspercluster, reserved, rootentries, sectors{{
' Mount a volume. The address passed in is passed along to the block
' layer; see the currently used block layer for documentation. If the
' volume mounts, a 0 is returned, else abort is called.
}}
if (pdate == 0)
pdate := constant(((2009-1980) << 25) + (1 << 21) + (27 << 16) + (7 << 11))
unmount
sdspi.start_explicit(DO, CLK, DI, CS)
lastread := -1
dirty := 0
sdspi.readblock(0, @buf)
if (getfstype > 0)
start := 0else
start := brlong(@buf+$1c6)
sdspi.readblock(start, @buf)
filesystem := getfstype
if (filesystem == 0)
abort(-20) ' not a fat16 or fat32 volumeif (brword(@buf+$0b) <> SECTORSIZE)
abort(-21) ' bad bytes per sector
sectorspercluster := buf[$0d]
if (sectorspercluster & (sectorspercluster - 1))
abort(-22) ' bad sectors per cluster
clustershift := 0repeatwhile (sectorspercluster > 1)
clustershift++
sectorspercluster >>= 1
sectorspercluster := 1 << clustershift
clustersize := SECTORSIZE << clustershift
reserved := brword(@buf+$0e)
if (buf[$10] <> 2)
abort(-23) ' not two FATs
sectors := brword(@buf+$13)
if (sectors == 0)
sectors := brlong(@buf+$20)
fat1 := start + reserved
if (filesystem == 2)
rootentries := 16 << clustershift
sectorsperfat := brlong(@buf+$24)
dataregion := (fat1 + 2 * sectorsperfat) - 2 * sectorspercluster
rootdir := (dataregion + (brword(@buf+$2c) << clustershift)) << SECTORSHIFT
rootdirend := rootdir + (rootentries << DIRSHIFT)
endofchain := $ffffff0else
rootentries := brword(@buf+$11)
sectorsperfat := brword(@buf+$16)
rootdir := (fat1 + 2 * sectorsperfat) << SECTORSHIFT
rootdirend := rootdir + (rootentries << DIRSHIFT)
dataregion := 1 + ((rootdirend - 1) >> SECTORSHIFT) - 2 * sectorspercluster
endofchain := $fff0if (brword(@buf+$1fe) <> $aa55)
abort(-24) ' bad FAT signature
totclusters := ((sectors - dataregion + start) >> clustershift)
' return r (default return)'' For compatibility, a single pin.'pubmount(basepin) : r | start, sectorspercluster, reserved, rootentries, sectorsreturn mount_explicit(basepin+2, basepin, basepin+1, basepin+3)
prireadbytec(byteloc)'' Read a byte address from the disk through the metadata buffer and' return a pointer to that location.'
readblockc(byteloc >> SECTORSHIFT)
return @buf2 + (byteloc & constant(SECTORSIZE - 1))
prireadfat(clust)'' Read a fat location and return a pointer to the location of that' entry.'
fatptr := (fat1 << SECTORSHIFT) + (clust << filesystem)
return readbytec(fatptr)
prifollowchain : r'' Follow the fat chain and update the writelink.'
r := brclust(readfat(fclust))
writelink := fatptr
' return r (default return)prinextcluster : r'' Read the next cluster and return it. Set up writelink to' point to the cluster we just read, for later updating. If the' cluster number is bad, return a negative number.'
r := followchain
if (r < 2or r => totclusters)
abort(-9) ' bad cluster value' return r (default return)prifreeclusters(clust) | bp'' Free an entire cluster chain. Used by remove and by overwrite.' Assumes the pointer has already been cleared/set to end of chain.'repeatwhile (clust < endofchain)
if (clust < 2)
abort(-26) ' bad cluster number")
bp := readfat(clust)
clust := brclust(bp)
brwclust(bp, 0)
flushifdirty
pridatablock'' Calculate the block address of the current data location.'return (fclust << clustershift) + dataregion + ((floc >> SECTORSHIFT) & ((1 << clustershift) - 1))
priuc(c)'' Compute the upper case version of a character.'if ("a" =< c and c =< "z")
return c - 32return c
pripflushbuf(rcnt, metadata) : r | cluststart, newcluster, count, i'' Flush the current buffer, if we are open for write. This may' allocate a new cluster if needed. If metadata is true, the' metadata is written through to disk including any FAT cluster' allocations and also the file size in the directory entry.'if (direntry == 0)
abort(-27) ' not open for writingif (rcnt > 0) ' must *not* allocate cluster if flushing an empty bufferif (frem < SECTORSIZE)
' find a new clustercould be anywhere! If possible, stay on the' same page used for the last cluster.
newcluster := -1
cluststart := fclust & (!((SECTORSIZE >> filesystem) - 1))
count := 2repeat
readfat(cluststart)
repeat i from0to SECTORSIZE - 1<<filesystem step1<<filesystem
if (buf2[i] == 0)
if (brclust(@buf2+i) == 0)
newcluster := cluststart + (i >> filesystem)
if (newcluster => totclusters)
newcluster := -1
quit
if (newcluster > 1)
brwclust(@buf2+i, endofchain+$f)
if (writelink == 0)
brwword(readbytec(direntry)+$1a, newcluster)
writelink := (direntry&(SECTORSIZE-filesystem))
brwlong(@buf2+writelink+$1c, floc+bufat)
if (filesystem == 2)
brwword(@buf2+writelink+$14, newcluster>>16)
else
brwclust(readbytec(writelink), newcluster)
writelink := fatptr + i
fclust := newcluster
frem := clustersize
quit
else
cluststart += (SECTORSIZE >> filesystem)
if (cluststart => totclusters)
cluststart := 0
count--
if (rcnt < 0)
rcnt := -5' No space left on device
quit
if (frem => SECTORSIZE)
sdspi.writeblock(datablock, @buf)
if (rcnt == SECTORSIZE) ' full buffer, clear it
floc += rcnt
frem -= rcnt
bufat := 0
bufend := rcnt
if (rcnt < 0or metadata) ' update metadata even if error
readblockc(direntry >> SECTORSHIFT) ' flushes unwritten FAT too
brwlong(@buf2+(direntry & (SECTORSIZE-filesystem))+$1c, floc+bufat)
flushifdirty
if (rcnt < 0)
abort(rcnt)
return rcnt
pubpflush{{
' Call flush with the current data buffer location, and the flush
' metadata flag set.
}}
return pflushbuf(bufat, 1)
pripfillbuf : r'' Get some data into an empty buffer. If no more data is available,' return -1. Otherwise return the number of bytes read into the' buffer.'if (floc => filesize)
return -1if (frem == 0)
fclust := nextcluster
frem := (clustersize) <# (filesize - floc)
sdspi.readblock(datablock, @buf)
r := SECTORSIZE
if (floc + r => filesize)
r := filesize - floc
floc += r
frem -= r
bufat := 0
bufend := r
' return r (default return)pubpclose : r{{
' Flush and close the currently open file if any. Also reset the
' pointers to valid values. If there is no error, 0 will be returned.
}}
if (direntry)
r := pflush
bufat := 0
bufend := 0
filesize := 0
floc := 0
frem := 0
writelink := 0
direntry := 0
fclust := 0
firstcluster := 0
sdspi.release
' return r (default return)pubsetdate(year, month, day, hour, minute, second){{
' Set the current date and time, as a long, in the format
' required by FAT16. Various limits are not checked.
}}
pdate := ((year-1980) << 25) + (month << 21) + (day << 16)
pdate += (hour << 11) + (minute << 5) + (second >> 1)
pubpopen(s, mode) : r | i, sentinel, dirptr, freeentry{{
' Close any currently open file, and open a new one with the given
' file name and mode. Mode can be "r" "w" "a" or "d" (delete).
' If the file is opened successfully, 0 will be returned. If the
' file did not exist, and the mode was not "w" or "a", -1 will be
' returned. Otherwise abort will be called with a negative error
' code.
}}
pclose
i := 0repeatwhile (i<8andbyte[s] andbyte[s] <> ".")
padname[i++] := uc(byte[s++])
repeatwhile (i<8)
padname[i++] := " "repeatwhile (byte[s] andbyte[s] <> ".")
s++
if (byte[s] == ".")
s++
repeatwhile (i<11andbyte[s])
padname[i++] := uc(byte[s++])
repeatwhile (i < 11)
padname[i++] := " "
sentinel := 0
freeentry := 0repeat dirptr from rootdir to rootdirend - DIRSIZE step DIRSIZE
s := readbytec(dirptr)
if (freeentry == 0and (byte[s] == 0orbyte[s] == $e5))
freeentry := dirptr
if (byte[s] == 0)
sentinel := dirptr
quit
repeat i from0to10if (padname[i] <> byte[s][i])
quit
if (i == 11and0 == (byte[s][$0b] & $18)) ' this always returns
fclust := brword(s+$1a)
if (filesystem == 2)
fclust += brword(s+$14) << 16
firstcluster := fclust
filesize := brlong(s+$1c)
if (mode == "r")
frem := (clustersize) <# (filesize)
return0if (byte[s][11] & $d9)
abort(-6) ' no permission to writeif (mode == "d")
brwword(s, $e5)
if (fclust)
freeclusters(fclust)
flushifdirty
return0if (mode == "w")
brwword(s+$1a, 0)
brwword(s+$14, 0)
brwlong(s+$1c, 0)
writelink := 0
direntry := dirptr
if (fclust)
freeclusters(fclust)
bufend := SECTORSIZE
fclust := 0
filesize := 0
frem := 0return0elseif (mode == "a")
' this code will eventually be moved to seek
frem := filesize
freeentry := clustersize
if (fclust => endofchain)
fclust := 0repeatwhile (frem > freeentry)
if (fclust < 2)
abort(-7) ' eof repeat while following chain
fclust := nextcluster
frem -= freeentry
floc := filesize & constant(!(SECTORSIZE - 1))
bufend := SECTORSIZE
bufat := frem & constant(SECTORSIZE - 1)
writelink := 0
direntry := dirptr
if (bufat)
sdspi.readblock(datablock, @buf)
frem := freeentry - (floc & (freeentry - 1))
elseif (fclust < 2or frem == freeentry)
frem := 0else
frem := freeentry - (floc & (freeentry - 1))
if (fclust => 2)
followchain
return0elseabort(-3) ' bad argumentif (mode <> "w"and mode <> "a")
return -1' not found
direntry := freeentry
if (direntry == 0)
abort(-2) ' no empty directory entry' write (or new append): create valid directory entry
s := readbytec(direntry)
bytefill(s, 0, DIRSIZE)
bytemove(s, @padname, 11)
brwword(s+$1a, 0)
brwword(s+$14, 0)
i := pdate
brwlong(s+$e, i) ' write create time and date
brwlong(s+$16, i) ' write last modified date and timeif (direntry == sentinel and direntry + DIRSIZE < rootdirend)
brwword(readbytec(direntry+DIRSIZE), 0)
flushifdirty
writelink := 0
fclust := 0
bufend := SECTORSIZE
' return r (default return)pubget_filesizereturn filesize
pubpread(ubuf, count) : r | t{{
' Read count bytes into the buffer ubuf. Returns the number of bytes
' successfully read, or a negative number if there is an error.
' The buffer may be as large as you want.
}}
repeatwhile (count > 0)
if (bufat => bufend)
t := pfillbuf
if (t =< 0)
if (r > 0)
' parens below prevent this from being optimized outreturn (r)
return t
t := (bufend - bufat) <# (count)
if ((t | (ubuf) | bufat) & 3)
bytemove(ubuf, @buf+bufat, t)
elselongmove(ubuf, @buf+bufat, t>>2)
bufat += t
r += t
ubuf += t
count -= t
' return r (default return)pubpgetc | t{{
' Read and return a single character. If the end of file is
' reached, -1 will be returned. If an error occurs, a negative
' number will be returned.
}}
if (bufat => bufend)
t := pfillbuf
if (t =< 0)
return -1return (buf[bufat++])
pubpwrite(ubuf, count) : r | t{{
' Write count bytes from the buffer ubuf. Returns the number of bytes
' successfully written, or a negative number if there is an error.
' The buffer may be as large as you want.
}}
repeatwhile (count > 0)
if (bufat => bufend)
pflushbuf(bufat, 0)
t := (bufend - bufat) <# (count)
if ((t | (ubuf) | bufat) & 3)
bytemove(@buf+bufat, ubuf, t)
elselongmove(@buf+bufat, ubuf, t>>2)
r += t
bufat += t
ubuf += t
count -= t
' return r (default return){{
' Write a null-terminated string to the file.
}}
pubpputs(b)return pwrite(b, strsize(b))
pubpputc(c) : r{{
' Write a single character into the file open for write. Returns
' 0 if successful, or a negative number if some error occurred.
}}
if (bufat == SECTORSIZE)
if (pflushbuf(SECTORSIZE, 0) < 0)
return -1
buf[bufat++] := c
' return r (default return){{
' Seek. Right now will only seek within the current cluster.
' Added for PrEdit so he can debug; do not use with files larger
' than one cluster (and make that cluster size 32K please.)
'
' Returns -1 on failure. Make sure to check this return code!
'
' We only support reads right now (but writes won"t be too hard to
' add).
}}
pubseek(pos) | deltaif (direntry or pos < 0or pos > filesize)
return -1
delta := (floc - bufend) & - clustersize
if (pos < delta)
fclust := firstcluster
frem := (clustersize) <# (filesize)
floc := 0
bufat := 0
bufend := 0
delta := 0repeatwhile (pos => delta + clustersize)
fclust := nextcluster
floc += clustersize
delta += clustersize
frem := (clustersize) <# (filesize - floc)
bufat := 0
bufend := 0if (bufend == 0or pos < floc - bufend or pos => floc - bufend + SECTORSIZE)
' must change buffer
delta := floc + frem
floc := pos & - SECTORSIZE
frem := delta - floc
pfillbuf
bufat := pos & (SECTORSIZE - 1)
return0pubtellreturn floc + bufat - bufend
pubopendir | off{{
' Close the currently open file, and set up the read buffer for
' calls to nextfile.
}}
pclose
off := rootdir - (dataregion << SECTORSHIFT)
fclust := off >> (clustershift + SECTORSHIFT)
floc := off - (fclust << (clustershift + SECTORSHIFT))
frem := rootdirend - rootdir
filesize := floc + frem
return0pubnextfile(fbuf) | i, t, at, lns{{
' Find the next file in the root directory and extract its
' (8.3) name into fbuf. Fbuf must be sized to hold at least
' 13 characters (8 + 1 + 3 + 1). If there is no next file,
' -1 will be returned. If there is, 0 will be returned.
}}
repeatif (bufat => bufend)
t := pfillbuf
if (t < 0)
return t
if (((floc >> SECTORSHIFT) & ((1 << clustershift) - 1)) == 0)
fclust++
at := @buf + bufat
if (byte[at] == 0)
return -1
bufat += DIRSIZE
if (byte[at] <> $e5and (byte[at][$0b] & $18) == 0)
lns := fbuf
repeat i from0to10byte[fbuf] := byte[at][i]
fbuf++
if (byte[at][i] <> " ")
lns := fbuf
if (i == 7or i == 10)
fbuf := lns
if (i == 7)
byte[fbuf] := "."
fbuf++
byte[fbuf] := 0return0{{
' Utility routines; may be removed.
}}
pubgetclustersizereturn clustersize
pubgetclustercountreturn totclusters
{{
' Permission is hereby granted, free of charge, to any person obtaining
' a copy of this software and associated documentation files
' (the "Software"), to deal in the Software without restriction,
' including without limitation the rights to use, copy, modify, merge,
' publish, distribute, sublicense, and/or sell copies of the Software,
' and to permit persons to whom the Software is furnished to do so,
' subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included
' in all copies or substantial portions of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
' EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
' MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
' IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
' CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
' TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
' SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}
DAT
filesystem long0' 0 = unmounted, 1 = fat16, 2 = fat32
rootdir long0' the byte address of the start of the root directory
rootdirend long0' the byte immediately following the root directory.
dataregion long0' the start of the data region, offset by two sectors
clustershift long0' log base 2 of blocks per cluster
clustersize long0' total size of cluster in bytes
fat1 long0' the block address of the fat1 space
totclusters long0' how many clusters in the volume
sectorsperfat long0' how many sectors per fat
endofchain long0' end of chain marker (with a 0 at the end)
pdate long0' current date
lastread long0' the block address of the buf2 contents
dirty long0' nonzero if buf2 is dirty
buf2 byte0[SECTORSIZE] ' main metadata buffer
padname byte0[11] ' filename buffer
I made small changes to fsrw, made the mount command work *sometimes?*
The test code I was having problems with is
[code]
CON
{''Hardware version 3.11 - see diagram.
''
}
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000 'with 5mhz crystal
Comments
DAT 'init org 0 entry mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup mov dira, DirsDisabled 'enables p0 - p15 wrlong zero, bufferaddress 'set par to zero to confirm load done 'get write command from buffer, and check if it's 0 Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data cmp Lcd_Data, #0 wz 'and check if it's 0 if_z jmp #get 'if it is, try again. 'if not, prepare transfer mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov LCD_cmd, LCD_Data 'copy lcd command to lcd data and LCD_Data, lowWordMask 'mask off High word of Lcd_Data shr LCD_cmd, #16 'move lcd command 16 bit to the right if not gddr write ' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer mov pntr, Lcd_cmd :wait0 djnz pntr, :wait0 WrCmd mov outa, #$22 mov pntr, #$f :wait0 djnz pntr, :wait0 add zero, #0 wz muxz dira, RSpin mov pntr, #$f :wait1 djnz pntr, :wait1 muxz dira, WritePin mov pntr, #$f :wait2 djnz pntr, :wait2 muxnz dira, WritePin mov pntr, #$f :wait3 djnz pntr, :wait3 muxnz dira, RSpin mov pntr, #$f :wait4 djnz pntr, :wait4 :WrDataPortion mov outa, LCD_Data mov pntr, #$f :wait5 djnz pntr, :wait5 add zero, #0 wz muxz dira, WritePin mov pntr, #$f :wait6 djnz pntr, :wait6 muxnz dira, WritePin mov pntr, #$f :wait7 djnz pntr, :wait7 ' 'add asmColor,#1 'max asmColor, BackgroundColorASM mov pntr, #$f :wait8 djnz pntr, :wait8 mov dira, DirsDisabled 'disables p0 - p15 wrlong zero, bufferaddress jmp #Get zero long $0 lowWordMask long $0000_ffff WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1 fit
The dat block will print color data, but I'm still trying to get everything working properly. Writes are a bit faster.http://www.ebay.com/itm/2-4-TFT-LCD-Module-Display-Touch-Panel-PCB-adapter-/190477028273?pt=LH_DefaultDomain_0&hash=item2c5950cbb1
There are 8 connections I do not have connected on the 40 pin connector (An old 40 pin hard drive connector).
The 8 pins not connected are :
Pin 3 - Not Used
Pin 16 - F_CS
Pin 18 - Not Used
Pin 20 - Not Used
Pin 32 - D_BUSY
Pin 34 - D_Penirq (Not sure what this is)
Pin 39 - F_WP
Pin 40 - F_HOLD
Is there something I am missing? I have the Data IN and Data Out pins shared on pins 24 and 25 on the Prop. No pull up or pull down resistors are in place for the LCD circuitry.
Current version is much faster. Fully working?
CON _clkmode = xtal1 + pll16x ' use crystal x 16 _xinfreq = 5_000_000 RS = 16 ''PINS FOR CS - TO KEEP FROM FLOATING LCD_WR = 17 DEV_SD_CLK = 18 DEV_SD_DI = 19 DEV_SD_DO = 20 DEV_SPI_EN = 21 DEV_SPI_ADD0 = 22 DEV_SPI_ADD1 = 23 DEV_SPI_ADD_LE = 24 DEV_SPI_LCD_RES = 0 DEV_SPI_SDC_CS = 1 DEV_SPI_TSC_CS = 2 DEV_SPI_EXT_CS = 3 DEV_SPI_EXT_POT_CS = 0 DEV_SPI_EXT_SW_CS = 1 ''LCD REGISTERS REG_OSCILLATOR = $0000 ''Oscillator (R00h) (POR = 0000h) REG_DRIVEROUTPUTCONTROL = $0001 ''Driver Output Control (R01h) (POR = 2B3Fh) REG_LCDDRIVINGWAVFORM = $0002 ''LCD-Driving-Waveform Control (R02h) (POR = 0000h) REG_POWERCONTROL1 = $0003 '' (R03H) REG_DISPLAYCONTROL = $0007 ''Display Control (R07h) (POR = 0000h) REG_FRAMECYCLECONTROL = $000B ''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET REG_POWERCONTROL2 = $000C '' (R0Ch) (POR = 0004) REG_POWERCONTROL3 = $000D '' REG_POWERCONTROL4 = $000E '' REG_GATESCANPOSITION = $000F ''Gate Scan Position (R0Fh) (POR = 0000h) REG_SLEEPMODE = $0010 ''Sleep mode (R10h) (POR = 0001h) REG_ENTRYMODE = $0011 ''Entry Mode (R11h) (POR = 6830h) REG_HPORCH = $0016 '' (R16h) (POR = EF1Ch) REG_VPORCH = $0017 '' (R17h) (POR = 0003h) REG_POWERCONTROL5 = $001E '' REG_RAMDATAWRITE = $0022 '' REG_RAMWRITEDATAMASK1 = $0023 '' (R23h) (POR = 0000h) REG_RAMWRITEDATAMASK2 = $0024 '' (R24h) (POR = 0000h) REG_VERTICALSCROLCONTROL1 = $0041 '' (R41h) (POR = 0000h) REG_VERTICALSCROLCONTROL2 = $0042 '' (R42h) (POR = 0000h) REG_HORIZONTALRAMADDRESSPOS = $0044 '' (R44h) (POR = EF00h) REG_VERTICALRAMADDRESSSTART = $0045 '' (R45h) (POR = 0000h) REG_VERTICALRAMADDRESSEND = $0046 '' (R46h) (POR = 013Fh) REG_FIRSTWINDOWSTART = $0048 '' (R48h) (POR = 0000h) REG_FIRSTWINDOWEND = $0049 '' (R49h) (POR = 013Fh) REG_SECONDWINDOWSTART = $004A '' (R4Ah) (POR = 0000h) REG_SECONDWINDOWEND = $004B '' (R4Bh) (POR = 013Fh) REG_SETGDDRXADDRESSCOUNTER = $004E '' (R4Eh) (POR = 0000h) REG_SETGDDRYADDRESSCOUNTER = $004F '' (R4Fh) (POR = 0000h) FONT_ROM_ADDRESS = $8000 BGCOLOR = $ffff TXTCOLOR = $0000 NotPressedBGC = $ffff NotPressedATC = $0000 PressedBGC = $0000 PressedATC = $ffff Pressed = 1 NotPressed = 0 VAR long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2 long ScreenBuffer long stringptr[65] BYTE Fader0[3], Fader1[3], Fader2[3], Fader3[3], faderOrentation, faderpos, faderval, oldfader, ButtonName 'Fader POS, New Fader Value, Old Fader Value, FaderOrentation holds 0 for landscape, portrait not enabled word Button0[3], Button1[3], Button2[3], Button3[3], Button4[3], Button5[3], ButtonGroup, ButtonX, ButtonY, ButtonState obj wait : "timing" pst : "parallax serial terminal" PUB BOOT | cr, idxr 'bootstrap dirA[DEV_SPI_ADD0] := 1 dirA[DEV_SPI_ADD1] := 1 dirA[DEV_SPI_EN] := 1 OUTA[LCD_WR] := 0 OUTA[RS] := 0 OUTA[DEV_SPI_EN] := 1 OUTA[DEV_SPI_ADD_LE] := 0 PST_Init Init_SSD1289 EnableDisplayPins TristateDisplayPins StartAsm pst.newline pst.str(string("Starting Asm")) pst.newline ClearScreenAsm($ffff) helloworld deadend PUB StartAsm 'Method to load a cog with screen driver long[@screenbuffer] := $ffff ''make sure screen buffer does not equal 0 cognew(@entry,@Long[@screenbuffer]) ''start write driver and pass it the address of screen buffer PUB PST_Init | PstCog ''Starts Parallax Serial Terminal for debugging. PstCog := (pst.Start(115200) -1) '' returns the cog pst started in pst.Str(String("Parallax Serial Terminal started in cog ")) '' talk to human pst.Dec(PstCog) '' displays cog on PST '' wait.pause1s(1) PUB HelloWorld WriteActiveCrAsm(72, 0, 0*16, 0, 0, BGCOLOR, TXTCOLOR) WriteNextActiveCrAsm(101) WriteNextActiveCrAsm(108) WriteNextActiveCrAsm(108) WriteNextActiveCrAsm(111) WriteNextActiveCrAsm(32) WriteNextActiveCrAsm(87) WriteNextActiveCrAsm(111) WriteNextActiveCrAsm(114) WriteNextActiveCrAsm(108) WriteNextActiveCrAsm(100) PUB WriteNextActiveCrAsm(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2 odd_even := character & $0001 characterpointer := character & $fffe characterpointer >>= 1 characterpointer *= 32 repeat idx from 0 to 31 bitpatern[idx] := long[FONT_ROM_ADDRESS][characterpointer + idx] y1 := Col + ColBorder y2 := (Col + 15) - ColBorder x1 := Row + RowBorder x2 := (Row + 31) - RowBorder SetWindowAsm(x1, y1, x2, y2) SetGAddressAsm(x1,y1) repeat idx from RowBorder to 31 - RowBorder repeat pxlidx from odd_even + (ColBorder*2) to (odd_even + 30) - (ColBorder*2) step 2 pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + ($22 << 16)) else Lcd_Write_Asm(BackgroundColor + ($22 << 16)) if (((Col + 16) > 319 ) and ((Row + 32) > 223)) Row := 0 Col := 0 elseif (((Col + 16) > 319 ) and ((Row + 32) < 223)) Row := Row + 32 Col := 0 else Col := Col + 16 ' SetWindow(0, 0, 239, 319) PUB WriteActiveCrAsm(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2 odd_even := character & $0001 characterpointer := character & $fffe characterpointer >>= 1 characterpointer *= 32 repeat idx from RBorder to 31 - RBorder bitpatern[idx] := long[FONT_ROM_ADDRESS][characterpointer + idx] Row := PosR Col := PosC RowBorder := RBorder ColBorder := CBorder BackgroundColor := BgC ActiveTextColor := Txc y1 := PosC + CBorder y2 := (PosC + 15) - CBorder x1 := PosR + RBorder x2 := (PosR + 31) - RBorder SetWindowAsm(x1, y1, x2, y2) SetGAddressAsm(x1,y1) repeat idx from RBorder to 31 - RBorder repeat pxlidx from odd_even + (CBorder*2) to (odd_even + 30) - (CBorder*2) step 2 pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + ($22 << 16)) else Lcd_Write_Asm(BackgroundColor + ($22 << 16)) if (((Col + 16) > 319 ) and ((Row + 32) > 223)) Row := 0 Col := 0 elseif (((Col + 16) > 319 ) and ((Row + 32) < 223)) Row := Row + 32 Col := 0 else Col := Col + 16 return PUB ClearScreenAsm(color) | idxr, idxc SetWindowAsm(0, 0, 239, 319) SetGAddressAsm(0,0) color += ($22 << 16) repeat idxr from 0 to 76800 Lcd_Write_Asm(Color) Row := 0 Col := 0 PUB SetWindowAsm(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS WindowX1 := x1 WindowX2 := x2 WindowY1 := y1 WindowY2 := y2 HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) Lcd_Write_Asm ($0044_0000 + HORIZONTALRAMADDRESSPOS) Lcd_Write_Asm(y1 + $0045_0000) Lcd_Write_Asm(y2 + $0046_0000) PUB SetGAddressAsm(x,y) Lcd_Write_Asm ($004E_0000 + x) ''max %1111_1111, $FF Lcd_Write_Asm ($004F_0000 + y) ''max %1_0011_1111, $13f '' (R4Eh) (POR = 0000h) PUB EnableDisplayPins DIRA:=%00000001_11100000_11111111_11111111 ' , Reset, WR, RS and 16 data lines active PUB TristateDisplayPins ' tristate all pins - DIRA:=%00000001_11100000_00000000_00000000 '' PRI Lcd_Write_Asm(V) 'handler for asm writes repeat while (screenbuffer <> 0) long[@screenbuffer] := V 'makes screen buffer = v PRI LCD_Writ_Bus(V) OUTA[15..0] := V WriteLow ' write pin low WriteHigh ' toggle write pin PRI Lcd_Write_Com(V) RSLow LCD_Writ_Bus(V) PRI Lcd_Write_Data(V) RSHigh LCD_Writ_Bus(V) PRI RSLow dira[RS] := 1 PRI RSHigh dira[RS] := 0 ' PRI WriteLow dira[LCD_WR] := 1 ' PRI WriteHigh dira[LCD_WR] := 0 pub deadend repeat wait.pause1s(1) PUB Init_SSD1289 ''Init Display EnableDisplayPins ''enable pins 0 to 15 ' WriteHigh 'LCD_Reset ''reset screen 'wait.pause1ms(5) 'LCD_Reset ''then init screen 'wait.pause1ms(5) Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01 Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h) Lcd_Write_Data($0001) ''Turn on oscillator Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11 Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h) Lcd_Write_Data($0000) '' ''exit sleep mode Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11 Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h) Lcd_Write_Data($6838) '' Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) Lcd_Write_Data($1000) '' '' Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000) Lcd_Write_Data($0000) '' '' '' Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F) Lcd_Write_Data($6B3F) '' '' Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308) Lcd_Write_Data($5308) '' ' Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033) Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11 'TristateDisplayPins 'deadend DAT 'init Display driver 'designed for optimized hardware, pull-up resistors on RS and WR pins. org 0 entry mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup mov dira, DirsDisabled 'enables p0 - p15 wrlong zero, bufferaddress 'set par to zero to confirm load done 'get write command from buffer, and check if it's 0 Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data cmp Lcd_Data, #0 wz 'and check if it's 0 if_z jmp #get 'if it is, try again. 'if not, prepare transfer mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov LCD_cmd, LCD_Data 'copy lcd command to lcd data and LCD_Data, lowWordMask 'mask off High word of Lcd_Data shr LCD_cmd, #16 'move lcd command 16 bit to the right if not gddr write ' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer mov pntr, #$f 'set wait period :wait0 djnz pntr, :wait0 'and wait WrCmd mov outa, LCD_Cmd 'place LCD_Cmd on write bus mov pntr, #$f 'set wait period :wait0 djnz pntr, :wait0 'and wait add zero, #0 wz 'prime WZ flag muxz dira, RSpin 'make RS pin low by enabling its DIR REG mov pntr, #$f 'set wait period :wait1 djnz pntr, :wait1 'and wait muxz dira, WritePin 'make Write Pin low by enabling its DIR REG mov pntr, #$f 'set wait period :wait2 djnz pntr, :wait2 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$f 'set wait period :wait3 djnz pntr, :wait3 'and wait muxnz dira, RSpin 'make RS pin high by disabling its DIR REG mov pntr, #$f 'set wait period :wait4 djnz pntr, :wait4 'and wait :WrDataPortion mov outa, LCD_Data 'place LCD_Data on write bus mov pntr, #$f 'set wait period :wait5 djnz pntr, :wait5 'and wait add zero, #0 wz 'prime WZ flag muxz dira, WritePin 'make Write Pin low by enabling its DIR REG mov pntr, #$f 'set wait period :wait6 djnz pntr, :wait6 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$f 'set wait period :wait7 djnz pntr, :wait7 'and wait mov pntr, #$f 'set wait period :wait8 djnz pntr, :wait8 'and wait mov dira, DirsDisabled 'disables p0 - p15 wrlong zero, bufferaddress jmp #Get 'do it all again zero long $0 lowWordMask long $0000_ffff WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 '' (R4Fh) (POR = 0000h) bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1
REG_OSCILLATOR = $0000 ''Oscillator (R00h) (POR = 0000h) REG_DRIVEROUTPUTCONTROL = $0001 ''Driver Output Control (R01h) (POR = 2B3Fh) REG_LCDDRIVINGWAVFORM = $0002 ...
I am terrible at understanding datasheets! Hopefully I can find the right one. I actually bought the screen from here :
http://iteadstudio.com/store/index.php?main_page=product_info&cPath=57_58&products_id=55
But..... It is also on Ebay for cheaper. Same screen though.
Thanks for the link. There's a lot of good info there and will help me in my design. It is interesting that it says it only handles 8 bit mode. Has anyone had trouble interfacing 16 bit data? Also I was thinking if the problems with the SD cards is because it is expecting 5V rather than 3.3V since it has series resistors.
Edit : eagletalontim look at http://www.rayslogic.com/Propeller/Products/Psm/psm.htm. You'll find Prop code for initialization of the LCD screen there. Also I have attached an pdf with the c code to run this
.
*edit*
From Dr. Acula's initalization. Format is Command, Data. ' ************* Start Initial Sequence ********** ILIcmd($00E5,$78F0) ' set SRAM internal timing ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait ILIcmd($0002,$0700) ' set 1 line inversion ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030 ILIcmd($0004,$0000) ' Resize register ILIcmd($0008,$0207) ' set the back porch and front porch ILIcmd($0009,$0000) ' set non-display area refresh cycle ISC[3:0] ILIcmd($000A,$0000) ' FMARK function ILIcmd($000C,$0000) ' RGB interface setting ILIcmd($000D,$0000) ' Frame marker Position ILIcmd($000F,$0000) ' RGB interface polarity ' *************Power On sequence ****************// ILIcmd($0010,$0000) ' SAP, BT[3:0], AP, DSTB, SLP, STB ILIcmd($0011,$0007) ' DC1[2:0], DC0[2:0], VC[2:0] ILIcmd($0012,$0000) ' VREG1OUT voltage ILIcmd($0013,$0000) ' VDV[4:0] for VCOM amplitude ILIcmd($0007,$0001) wait.pause1ms(50) ' Dis-charge capacitor power voltage ILIcmd($0010,$1090) ' 1490//SAP, BT[3:0], AP, DSTB, SLP, STB ILIcmd($0011,$0227) ' DC1[2:0], DC0[2:0], VC[2:0] wait.pause1ms(50) ' delay ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci; wait.pause1ms(50) ' delay ILIcmd($0013,$1500) ' $1000//1400 Set VDV[4:0] for VCOM amplitude 1A00 ILIcmd($0029,$0027) ' $0012 //001a Set VCM[5:0] for VCOMH //$0025 0034 ILIcmd($002B,$000D) ' Set Frame Rate 000C wait.pause1ms(50) ' delay ILIcmd($0020,$0000) ' GRAM horizontal Address ILIcmd($0021,$0000) ' GRAM Vertical Address ' ----------- Adjust the Gamma Curve ----------// ILIcmd($0030,$0000) ILIcmd($0031,$0707) ILIcmd($0032,$0307) ILIcmd($0035,$0200) ILIcmd($0036,$0008) ILIcmd($0037,$0004) ILIcmd($0038,$0000) ILIcmd($0039,$0707) ILIcmd($003C,$0002) ILIcmd($003D,$1D04) ' ------------------ Set GRAM area ---------------// ILIcmd($0050,$0000) ' Horizontal GRAM Start Address ILIcmd($0051,$00EF) ' Horizontal GRAM End Address ILIcmd($0052,$0000) ' Vertical GRAM Start Address ILIcmd($0053,$013F) ' Vertical GRAM Start Address ILIcmd($0060,$A700) ' Gate Scan Line ILIcmd($0061,$0001) ' NDL,VLE, REV ILIcmd($006A,$0000) ' set scrolling line ' -------------- Partial Display Control ---------/ ILIcmd($0080,$0000) ILIcmd($0081,$0000) ILIcmd($0082,$0000) ILIcmd($0083,$0000) ILIcmd($0084,$0000) ILIcmd($0085,$0000) ' //-------------- Panel Control -------------------// ILIcmd($0090,$0010) ILIcmd($0092,$0600) ILIcmd($0007,$0133) ' 262K color and display ON
I don't understand any of the startup code either and I started off with only C code to work with, so I'll document how I got the display working.
First thing was to just work on the display, so forget about the SD card and the touchscreen.
5V, 0V, 16 data lines and 5 control lines.
Of those control lines, I am not sure which ones you can leave out. I'm pretty sure now that /rd is not needed. But I see that average joe has left out /cs and I don't know about that one.
So let's say 4 control lines, and tie /rd high.
I then coded some spin code to set each of these high and each of these low. Things like ResetHigh, and ChipSelectLow. 8 PUB routines in total. I then tested each of those with a LED on the appropriate pin. Did the code do what it was supposed to?
I then worked on the data lines.
PRI LCD_Writ_Bus(VH,VL) OUTA[7..0] := VL OUTA[15..8] := VH WriteLow ' write pin low WriteHigh ' toggle write pin
Comment out the writelow and writehigh for the moment and put a "repeat" there instead so the program hangs.
Now pass some numbers in VH and VL and see if the pins do what they are supposed to. I used Windows Calculator a lot to convert numbers to binary. Pick a random number, work out its binary, send it out and then check with a logic probe the pins are as they are supposed to be.
Then remove that 'repeat' and put back in the writelow writehigh.
add this code
PRI ILIcmd(c,d) ' instruction in one method Lcd_Write_Com(c >> 8,c & 255) ' split a word into two bytes, send command then data Lcd_Write_Data(d >> 8,d & 255) PRI Lcd_Write_Com(VH,VL) RSLow LCD_Writ_Bus(VH,VL) PRI Lcd_Write_Data(VH,VL) RSHigh LCD_Writ_Bus(VH,VL)
Then try dropping in this startup code.
PUB Start_ILI9325 ' pass orientation true = portrait, false = landscape DisplayPins := %00000000_00000000_00000000_00000000 ' store the status of the display pins ResetHigh wait.pause1ms(5) ResetLow wait.pause1ms(5) ResetHigh ChipSelectHigh ReadHigh WriteHigh wait.pause1ms(5) ChipSelectLow ' ************* Start Initial Sequence ********** ILIcmd($00E5,$78F0) ' set SRAM internal timing ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait ILIcmd($0002,$0700) ' set 1 line inversion ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030 ILIcmd($0004,$0000) ' Resize register ILIcmd($0008,$0207) ' set the back porch and front porch ILIcmd($0009,$0000) ' set non-display area refresh cycle ISC[3:0] ILIcmd($000A,$0000) ' FMARK function ILIcmd($000C,$0000) ' RGB interface setting ILIcmd($000D,$0000) ' Frame marker Position ILIcmd($000F,$0000) ' RGB interface polarity ' *************Power On sequence ****************// ILIcmd($0010,$0000) ' SAP, BT[3:0], AP, DSTB, SLP, STB ILIcmd($0011,$0007) ' DC1[2:0], DC0[2:0], VC[2:0] ILIcmd($0012,$0000) ' VREG1OUT voltage ILIcmd($0013,$0000) ' VDV[4:0] for VCOM amplitude ILIcmd($0007,$0001) wait.pause1ms(50) ' Dis-charge capacitor power voltage ILIcmd($0010,$1090) ' 1490//SAP, BT[3:0], AP, DSTB, SLP, STB ILIcmd($0011,$0227) ' DC1[2:0], DC0[2:0], VC[2:0] wait.pause1ms(50) ' delay ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci; wait.pause1ms(50) ' delay ILIcmd($0013,$1500) ' $1000//1400 Set VDV[4:0] for VCOM amplitude 1A00 ILIcmd($0029,$0027) ' $0012 //001a Set VCM[5:0] for VCOMH //$0025 0034 ILIcmd($002B,$000D) ' Set Frame Rate 000C wait.pause1ms(50) ' delay ILIcmd($0020,$0000) ' GRAM horizontal Address ILIcmd($0021,$0000) ' GRAM Vertical Address ' ----------- Adjust the Gamma Curve ----------// ILIcmd($0030,$0000) ILIcmd($0031,$0707) ILIcmd($0032,$0307) ILIcmd($0035,$0200) ILIcmd($0036,$0008) ILIcmd($0037,$0004) ILIcmd($0038,$0000) ILIcmd($0039,$0707) ILIcmd($003C,$0002) ILIcmd($003D,$1D04) ' ------------------ Set GRAM area ---------------// ILIcmd($0050,$0000) ' Horizontal GRAM Start Address ILIcmd($0051,$00EF) ' Horizontal GRAM End Address ILIcmd($0052,$0000) ' Vertical GRAM Start Address ILIcmd($0053,$013F) ' Vertical GRAM Start Address ILIcmd($0060,$A700) ' Gate Scan Line ILIcmd($0061,$0001) ' NDL,VLE, REV ILIcmd($006A,$0000) ' set scrolling line ' -------------- Partial Display Control ---------/ ILIcmd($0080,$0000) ILIcmd($0081,$0000) ILIcmd($0082,$0000) ILIcmd($0083,$0000) ILIcmd($0084,$0000) ILIcmd($0085,$0000) ' //-------------- Panel Control -------------------// ILIcmd($0090,$0010) ILIcmd($0092,$0600) ILIcmd($0007,$0133) ' 262K color and display ON
Dr A has a good method to get up and running. I actually used his code to develop a template for mine. I changed the initialization values for the display, and then modified his writing method.
PRI LCD_Writ_Bus(V) OUTA[15..0] := V WriteLow ' write pin low WriteHigh ' toggle write pin PRI Lcd_Write_Com(V) RSLow LCD_Writ_Bus(V) PRI Lcd_Write_Data(V) RSHigh LCD_Writ_Bus(V) PRI RSLow 'these are for pullup version, non pullup will be dira[RS] := 1 'outa[RS] := 0 PRI RSHigh 'these are for pullup version, non pullup will be dira[RS] := 0 'outa[RS] := 1 PRI WriteLow 'these are for pullup version, non pullup will be dira[LCD_WR] := 1 'outa[LCD_WR] := 0 ' PRI WriteHigh 'these are for pullup version, non pullup will be dira[LCD_WR] := 0 'outa[LCD_WR] := 1
This could be modified for 8 bit writes if necessary.I've got ASM running good.
*Edit*
Here's version 2! It runs pretty fast and can be optimized further.
Program: 345 Longs
Variable: 17 Longs
not too bad!
For spin, it could be 50cm or more. Pasm might need shorter distances, but spin is slower so distance should not be a problem. My display is 10cm from the prop.
Start with the reset line. Write some code to make that line high, then wait 1ms then low, wait 1ms, then high again. Change the delay to 1 second for debugging. Put a led on that pin, and run the code. That should reset the display which should get something to change on the display.
For pasm, the code I'm going to be writing for the new board will be very different. The design uses a ram chip and was built to transfer data from the ram chip to the display as fast as possible, with the transfer speed between the prop and ram a secondary consideration. So there is a bus between ram and the display, and there are some isolating 245 buffer chips so that bus is independent of the propeller.
If it doesn't work - back to the drawing board. If it does work, well I'm getting 10 boards made so some could be available for others to test out...
So, I my "terminal" object *MAIN* to create an area in main memory, and pass that address to another object *PFW*, which starts the cog that loads the data from main memory.
var Screen_Buffer pub init ...do something long[@Screen_Buffer] := $ffff 'make sure screen buffer does not equal 0 pfw.Start(@Long[@Screen_Buffer]) 'Start Asm Driver, needs to be changed to pass screen buffer from top object ....do more
that's the main object and it's call, the pfw object isvar long screenbufferaddress PUB Start(ScreenBufferAdd) 'Method to Init display, then load a cog with screen driver screenbufferaddress := ScreenBufferAdd 'store buffer address in long Init_SSD1289 'init screen result := cognew(@entry,ScreenBufferAdd ]) 'start write driver and pass it the address of screen buffer PRI Lcd_Write_Asm(V) 'handler for asm writes repeat while (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbuffer long[@screenbufferaddress] := V 'makes screen buffer = v entry mov outa, PinsInit 'set pins to inital state 'mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup mov dira, DirsDisabled 'enables p0 - p15 wrlong zero, bufferaddress 'set par to zero to confirm load done ...do more
what is the RIGHT way to pass this address. I'm lost.VAR long screen PUB null screen := 42 ' start not equal zero [COLOR="orange"]{pfw.}[/COLOR]start(@screen) ' communicate address repeat while screen ' wait until it reached PASM dira[16]~~ repeat !outa[16] waitcnt(clkfreq/2 + cnt) [COLOR="blue"]PUB start(address) cognew(@entry, address) DAT org 0 entry rdlong temp, par ' par == @screen (4n limitation) cmp temp, #42 wz if_e wrlong zero, par ' release caller if ID checks out waitpeq $, #0 ' stop temp res 1 fit CON zero = $1F0 ' par DAT[/COLOR]
[video=youtube_share;_w6VCS-_8X0]
I got some stuff working, but there may be bugs still. It display characters correctly I think. It's a start, I still need to get fifo's working...
TOF object
CON {''Hardware version 2.11 - see diagram. '' } DEV_SPI_EN = 21 ''SPI Enable enumeration DEV_SPI_ADD0 = 22 ''Device address 0 enumeration DEV_SPI_ADD1 = 23 ''Device address 1 enumeration DEV_SPI_LCD_RES = 0 ''Device id for LCD reset _clkmode = xtal1 + pll16x ' use crystal x 16 _xinfreq = 5_000_000 'with 5mhz crystal BGCOLOR = $ffff TXTCOLOR = $0000 Pressed = 1 NotPressed = 0 VAR long Screen_Buffer, CRbuffer long BackgroundColor, ActiveTextColor, stringptr[65] BYTE Fader0[3], Fader1[3], Fader2[3], Fader3[3], faderOrentation, faderpos, faderval, oldfader 'Fader POS, New Fader Value, Old Fader Value, FaderOrentation holds 0 for landscape, portrait not enabled OBJ pfw :"PropFont_asmDone" 'wait : "timing" PUB BOOT | f 'bootstrap, initalizes pins, then starts pst, init display, start asm, clear screen and display hello world dirA[DEV_SPI_ADD0] := 1 'makes address 0 and 1 dirA[DEV_SPI_ADD1] := 1 'outputs dirA[DEV_SPI_EN] := 1 'and enable an output as well OUTA[DEV_SPI_ADD1..DEV_SPI_ADD0] := 3 'OUTA[LCD_WR] := 0 'prime WR pin 'OUTA[LCD_RS] := 0 'and RS pin, probably not needed. OUTA[DEV_SPI_EN] := 1 'Disable - Reset Screen 'wait.pause1s(5) ''PST_Init 'Start Parallax Serial Terminal BackgroundColor := $ffe0 ActiveTextColor := %0000 long[@Screen_Buffer] := $ffff 'make sure screen buffer does not equal 0 pfw.Start(@Long[@Screen_Buffer]) 'Start Asm Driver, needs to be changed to pass screen buffer from top object '' pst.newline ''pst.str(string("Starting Asm")) 'Talk to human ''pst.newline dirA[DEV_SPI_EN] := 1 OUTA[DEV_SPI_EN] := 1 'Disable - Reset Screen pfw.ClearScreen(BackgroundColor) 'Draw White Screen with asm helloworld 'draw hello world {Fader.}FaderTest '{Button.}ButtonTest FaderRun deadend 'hold cog in endless loop PUB HelloWorld pfw.WriteActiveCr("H", 0, 0*16, 0, 0, BackgroundColor, ActiveTextColor) pfw.WriteNextActiveCr("e") pfw.WriteNextActiveCr("l") pfw.WriteNextActiveCr("l") pfw.WriteNextActiveCr("o") pfw.WriteNextActiveCr(" ") pfw.WriteNextActiveCr("W") pfw.WriteNextActiveCr("o") pfw.WriteNextActiveCr("r") pfw.WriteNextActiveCr("l") pfw.WriteNextActiveCr("d") pub deadend 'loop for testing repeat 'endlessly wait repeat waitcnt(2_000 + cnt) PUB FaderTest | F , b Fader0[0] :=255 Fader0[1] := 0 Fader0[2] := 2 Fader1[0] := 0 Fader1[1] := 0 Fader1[2] := 54 Fader2[0] := 126 Fader2[1] := 126 Fader2[2] := 106 Fader3[0] := 192 Fader3[1] := 192 Fader3[2] := 161 REPEAT f from 0 to 3 SetFader(F) DrawFader PUB SetFader(FaderNumber) case FaderNumber 0: faderval := Fader0[0] oldfader := Fader0[1] faderpos := Fader0[2] 1: faderval := Fader1[0] oldfader := Fader1[1] faderpos := Fader1[2] 2: faderval := Fader2[0] oldfader := Fader2[1] faderpos := Fader2[2] 3: faderval := Fader3[0] oldfader := Fader3[1] faderpos := Fader3[2] PUB UpdateFader 'layer 2 if oldfader<> faderval pfw.WriteActiveCr(6, faderpos, 2, 7, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(7, faderpos, 301, 7, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(32, faderpos, oldfader + 24, 4, 3, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(14, faderpos, faderval + 24, 4, 3, BackgroundColor, ActiveTextColor) PUB DrawFader |index 'layer 1 pfw.WriteActiveCr(1, faderpos, 0, 0, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(9, faderpos, 7, 0, 0, BackgroundColor, ActiveTextColor) REPEAT 18 pfw.WriteNextActiveCr(13) pfw.WriteActiveCr(1, faderpos, 297, 0, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(9, faderpos, 304, 0, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(6, faderpos, 2, 7, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(7, faderpos, 301, 7, 0, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(32, faderpos, oldfader + 24, 4, 2, BackgroundColor, ActiveTextColor) pfw.WriteActiveCr(14, faderpos, faderval + 24, 4, 3, BackgroundColor, ActiveTextColor) PUB FaderRun | f repeat REPEAT f from 0 to 3 SetFader(F) UpdateFader Fader0[1] := Fader0[0] Fader0[0] -= 1
This is CrReader, thanks KuronekoCON zero = $1F0 ' par var long command, cog word font[32] PUB null '' This is not a top level object. PUB Start result := cog := cognew(@fillchar, @command) + 1 ' start cog PUB GetChar(c) command := $200|c.byte{0} ' query bitmap repeat ' | while command ' wait for completion return @font{0} DAT org 0 fillchar mov addr, par ' @font[0] :idle rdlong char, par wz if_z jmp #$-1 mov temp, char ' where to begin shr temp, #1 ' 2 chars/long shl temp, #7 ' 32 longs/char test char, #1 wc muxnc shft, #1 ' even/odd mov lcnt, #32 ' 32 rows :loop rdlong char, temp ' read line from ROM shl char, shft ' adjust for even/odd shl char, #2 wc rcl line, #1 ' bit 15 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 12 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 8 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 4 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 0 wrword line, addr ' update hub array add addr, #2 ' advance dst add temp, #4 ' advance src djnz lcnt, #:loop ' repeat wrlong zero, par :chktbl rdword line, addr wz 'get font table and if_nz jmp #:chktbl 'wait till character is printed sub addr, #64 ' rewind jmp #:idle ' initialised data and/or presets addr long 8 shft long 0 ' uninitialised data and/or temporaries temp res 1 char res 1 lcnt res 1 line res 1 fit
Then we have propfont_asmCON ''PINS LCD_RS = 16 ''LCD RS pin LCD_WR = 17 ''LCD WR pin ''LCD REGISTER Enumeration, for SSM1289 REG_OSCILLATOR = $0000 ''Oscillator (R00h) (POR = 0000h) REG_DRIVEROUTPUTCONTROL = $0001 ''Driver Output Control (R01h) (POR = 2B3Fh) REG_LCDDRIVINGWAVFORM = $0002 ''LCD-Driving-Waveform Control (R02h) (POR = 0000h) REG_POWERCONTROL1 = $0003 '' (R03H) REG_DISPLAYCONTROL = $0007 ''Display Control (R07h) (POR = 0000h) REG_FRAMECYCLECONTROL = $000B ''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET REG_POWERCONTROL2 = $000C '' (R0Ch) (POR = 0004) REG_POWERCONTROL3 = $000D '' REG_POWERCONTROL4 = $000E '' REG_GATESCANPOSITION = $000F ''Gate Scan Position (R0Fh) (POR = 0000h) REG_SLEEPMODE = $0010 ''Sleep mode (R10h) (POR = 0001h) REG_ENTRYMODE = $0011 ''Entry Mode (R11h) (POR = 6830h) REG_HPORCH = $0016 '' (R16h) (POR = EF1Ch) REG_VPORCH = $0017 '' (R17h) (POR = 0003h) REG_POWERCONTROL5 = $001E '' REG_RAMDATAWRITE = $0022 '' REG_RAMWRITEDATAMASK1 = $0023 '' (R23h) (POR = 0000h) REG_RAMWRITEDATAMASK2 = $0024 '' (R24h) (POR = 0000h) REG_VERTICALSCROLCONTROL1 = $0041 '' (R41h) (POR = 0000h) REG_VERTICALSCROLCONTROL2 = $0042 '' (R42h) (POR = 0000h) REG_HORIZONTALRAMADDRESSPOS = $0044 '' (R44h) (POR = EF00h) REG_VERTICALRAMADDRESSSTART = $0045 '' (R45h) (POR = 0000h) REG_VERTICALRAMADDRESSEND = $0046 '' (R46h) (POR = 013Fh) REG_FIRSTWINDOWSTART = $0048 '' (R48h) (POR = 0000h) REG_FIRSTWINDOWEND = $0049 '' (R49h) (POR = 013Fh) REG_SECONDWINDOWSTART = $004A '' (R4Ah) (POR = 0000h) REG_SECONDWINDOWEND = $004B '' (R4Bh) (POR = 013Fh) REG_SETGDDRXADDRESSCOUNTER = $004E '' (R4Eh) (POR = 0000h) REG_SETGDDRYADDRESSCOUNTER = $004F '' (R4Fh) (POR = 0000h) FONT_ROM_ADDRESS = $8000 VAR long screenbufferaddress long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2 obj wait : "timing" cr : "crReader" 'pst : "parallax serial terminal" 'used for debugging.. PUB BOOT 'not a standalone object PUB Start(ScreenBufferAdd) 'Method to Init display, then load a cog with screen driver screenbufferaddress := ScreenBufferAdd 'store buffer address in long Init_SSD1289 'init screen long[@screenbufferaddress] := $ffff 'make sure screen buffer does not equal 0 result := cognew(@entry,@long[@screenbufferaddress]) 'start write driver and pass it the address of screen buffer cr.Start PUB WriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress fontaddress := Cr.GetChar(Character) 'odd_even := character & $0001 ' characterpointer := character & $fffe 'characterpointer >>= 1 'characterpointer *= 32 repeat idx from 0 to 31 bitpatern[idx] := word[fontaddress][idx] word[fontaddress] := 0 y1 := Col + ColBorder y2:= (Col + 15) - ColBorder x1 := Row + RowBorder x2:= (Row + 31) - RowBorder SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RowBorder to 31 - RowBorder repeat pxlidx from ColBorder to 15 - ColBorder pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16)) else Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16)) repeat while word[fontaddress] := 0 if (((Col + 16) > 319 ) and ((Row + 32) > 223)) Row := 0 Col := 0 elseif (((Col + 16) > 319 ) and ((Row + 32) < 223)) Row := Row + 32 Col := 0 else Col := Col + 16 ' SetWindow(0, 0, 239, 319) PUB WriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress fontaddress := Cr.GetChar(Character) Row := PosR Col := PosC RowBorder := RBorder ColBorder := CBorder BackgroundColor := BgC ActiveTextColor := Txc repeat idx from 0 to 31 bitpatern[idx] := word[fontaddress][idx] word[fontaddress] := 0 y1 := Col + ColBorder y2:= (Col + 15) - ColBorder x1 := Row + RowBorder x2:= (Row + 31) - RowBorder SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RowBorder to 31 - RowBorder repeat pxlidx from ColBorder to 15 - ColBorder pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16)) else Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16)) repeat while word[fontaddress] := 0 if (((Col + 16) > 319 ) and ((Row + 32) > 223)) Row := 0 Col := 0 elseif (((Col + 16) > 319 ) and ((Row + 32) < 223)) Row := Row + 32 Col := 0 else Col := Col + 16 PUB ClearScreen(color) | idxr, idxc SetWindow(0, 0, 239, 319) SetGAddress(0,0) color += (REG_RAMDATAWRITE << 16) repeat idxr from 0 to 76800 Lcd_Write_Asm(Color) Row := 0 Col := 0 PUB SetWindow(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS 'Set window to draw in WindowX1 := x1 'update draw window in main memory WindowX2 := x2 'update draw window in main memory WindowY1 := y1 'update draw window in main memory WindowY2 := y2 'update draw window in main memory HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) 'combine x1 and x2 values Lcd_Write_Asm ((REG_HORIZONTALRAMADDRESSPOS << 16) + HORIZONTALRAMADDRESSPOS) 'and write to display Lcd_Write_Asm(y1 + (REG_VERTICALRAMADDRESSSTART << 16)) 'send v-address start Lcd_Write_Asm(y2 + (REG_VERTICALRAMADDRESSEND << 16)) 'send v-address end PUB SetGAddress(x,y) 'Set address for gddr writes Lcd_Write_Asm ((REG_SETGDDRXADDRESSCOUNTER << 16) + x) ''max %1111_1111, $FF Lcd_Write_Asm ((REG_SETGDDRYADDRESSCOUNTER << 16) + y) ''max %1_0011_1111, $13f PRI deadend 'loop for testing repeat repeat 'endlessly wait wait.pause1s(1) '' PRI EnableDisplayPins 'enable all pins - DIRA:=%00000000_00000000_11111111_11111111 ''enable p15 - p0 PRI TristateDisplayPins 'tristate all pins - DIRA:=%00000000_00000000_00000000_00000000 ''release p15 - p0 PRI Lcd_Write_Asm(V) 'handler for asm writes repeat while (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbuffer long[@screenbufferaddress] := V 'makes screen buffer = v PRI LCD_Writ_Bus(V) 'write to display OUTA[15..0] := V ' copy V onto pins WriteLow ' write pin low WriteHigh ' toggle write pin PRI Lcd_Write_Com(V) 'write command to display LCD_RSLow 'Sets command LCD_Writ_Bus(V) 'Do write PRI LCD_Write_Data(V) 'write data to display LCD_RSHigh 'Sets data LCD_Writ_Bus(V) 'do write PRI LCD_RSLow outa[LCD_RS] := 0 'controls RS pin with DIR-A dira[LCD_RS] := 1 'see hardware revision PRI LCD_RSHigh 'controls RS pin with DIR-A dira[LCD_RS] := 0 'see hardware revision PRI WriteLow outa[LCD_WR] := 0 'controls WR pin with DIR-A dira[LCD_WR] := 1 'see hardware revision ' PRI WriteHigh 'controls WR pin with DIR-A dira[LCD_WR] := 0 'see hardware revision PRI Init_SSD1289 ''Init Display EnableDisplayPins outa[21] := 1 dira[21] := 1 Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01 Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h) Lcd_Write_Data($0001) ''Turn on oscillator Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11 Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h) Lcd_Write_Data($0000) '' ''exit sleep mode Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11 Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h) Lcd_Write_Data($6838) '' Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) Lcd_Write_Data($1000) '' '' Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000) Lcd_Write_Data($0000) '' '' '' Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F) Lcd_Write_Data($6B3F) '' '' Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308) Lcd_Write_Data($5308) '' ' Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033) Lcd_Write_Data($0033) TristateDisplayPins ''Release pins 'PUB PST_Init | PstCog ''Starts Parallax Serial Terminal for debugging. ' PstCog := (pst.Start(115200) -1) '' returns the cog pst started in ' pst.Str(String("Parallax Serial Terminal started in cog ")) '' talk to human ' pst.Dec(PstCog) '' displays cog on PST '' ' wait.pause1s(1) PUB HelloWorld WriteActiveCr("H", 0, 0*16, 0, 0, $ffff, $0000) WriteNextActiveCr("e") WriteNextActiveCr("l") WriteNextActiveCr("l") WriteNextActiveCr("o") WriteNextActiveCr(" ") WriteNextActiveCr("W") WriteNextActiveCr("o") WriteNextActiveCr("r") WriteNextActiveCr("l") WriteNextActiveCr("d") DAT 'init Display driver 'designed for optimized hardware, pull-up resistors on RS and WR pins. org 0 entry mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup 'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done 'get write command from buffer, and check if it's 0 Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data cmp Lcd_Data, #0 wz 'and check if it's 0 if_z jmp #get 'if it is, try again. 'if not, prepare transfer 'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd data shr LCD_cmd, #16 'move lcd command 16 bit to the right if not gddr write ' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer 'enables p0 - p15 mov pntr, #$8 'set wait period :wait0 djnz pntr, :wait0 'and wait WrCmd mov outa, LCD_Cmd 'place LCD_Cmd on write bus mov pntr, #$8 'set wait period :wait0 djnz pntr, :wait0 'and wait add zero, #0 wz 'prime WZ flag muxz dira, RSpin 'make RS pin low by enabling its DIR REG mov pntr, #$8 'set wait period :wait1 djnz pntr, :wait1 'and wait muxz dira, WritePin 'make Write Pin low by enabling its DIR REG and LCD_Data, lowWordMask 'mask off High word of Lcd_Data mov pntr, #$f 'set wait period :wait2 djnz pntr, :wait2 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$8 'set wait period :wait3 djnz pntr, :wait3 'and wait muxnz dira, RSpin 'make RS pin high by disabling its DIR REG mov pntr, #$8 'set wait period :wait4 djnz pntr, :wait4 'and wait :WrDataPortion mov outa, LCD_Data 'place LCD_Data on write bus wrlong zero, bufferaddress 'wz mov pntr, #$8 'set wait period :wait5 djnz pntr, :wait5 'and wait add zero, #0 wz 'prime WZ flag muxz dira, WritePin 'make Write Pin low by enabling its DIR REG 'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data mov pntr, #$8 'set wait period :wait6 djnz pntr, :wait6 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$8 'set wait period :wait7 djnz pntr, :wait7 'and wait 'mov dira, DirsDisabled 'disables p0 - p15 jmp #Get 'do it all again zero long $0 lowWordMask long $0000_ffff 'pin settings WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 '' (R4Fh) (POR = 0000h) bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1 ForegroundFormat res 1 BackgroundFormat res 1 ForegroundScreen res 1 BackgroundScreen res 1 fit zero long $0 lowWordMask long $0000_ffff 'pin settings WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 '' (R4Fh) (POR = 0000h) bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1 ForegroundFormat res 1 BackgroundFormat res 1 ForegroundScreen res 1 BackgroundScreen res 1 fit
writes WAY faster, and still single character? about 5 or 6 seconds to draw full screen? haven't tested much yet. Still no sd card. I think either the cable I attached *about 3'* is too long, those damn pullup resistors or the cards I have are incompat.PUB WriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress fontaddress := Cr.GetChar(Character) 'odd_even := character & $0001 ' characterpointer := character & $fffe 'characterpointer >>= 1 'characterpointer *= 32 repeat idx from 0 to 31 bitpatern[idx] := word[fontaddress][idx] word[fontaddress] := 0 y1 := Col + ColBorder y2 := (Col + (15 / fontsize ) - ColBorder) x1 := Row + RowBorder x2 := (Row + (31 / fontsize ) - RowBorder) SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RowBorder to 31 - RowBorder step Fontsize repeat pxlidx from ColBorder to 15 - ColBorder step Fontsize pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16)) else Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16)) repeat while word[fontaddress] := 0 if (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) > 223))) Row := 0 Col := 0 elseif (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) < 223))) Row := Row + (32 >> (fontsize -1)) Col := 0 else Col := Col + (16 >> (fontsize - 1)) ' SetWindow(0, 0, 239, 319) PUB WriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC, size) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress fontaddress := Cr.GetChar(Character) Row := PosR Col := PosC RowBorder := RBorder ColBorder := CBorder BackgroundColor := BgC ActiveTextColor := Txc Fontsize := size repeat idx from 0 to 31 bitpatern[idx] := word[fontaddress][idx] word[fontaddress] := 0 y1 := Col + ColBorder y2 := (Col + (15 / fontsize ) - ColBorder) x1 := Row + RowBorder x2 := (Row + (31 / fontsize ) - RowBorder) SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RowBorder to 31 - RowBorder step Fontsize repeat pxlidx from ColBorder to 15 - ColBorder step Fontsize pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16)) else Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16)) repeat while word[fontaddress] := 0 if (((Col + (16 >> fontsize -1)) > 319 ) and ((Row + (32 >> (fontsize -1)) > 223))) Row := 0 Col := 0 elseif (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) < 223))) Row := Row + (32 >> (fontsize -1)) Col := 0 else Col := Col + (16 >> (fontsize - 1))
and of course pix! And another youtube video as soon as it's uploaded.Little slider bars. How cool would it be to make them move when you move your finger along them?!
The call...
Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16))
The method that passes the writePRI Lcd_Write_Asm(V) 'handler for asm writes repeat while (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbuffer long[@screenbufferaddress] := V 'makes screen buffer = v
And the dat blockDAT 'init Display driver 'designed for optimized hardware, pull-up resistors on RS and WR pins. org 0 entry mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup 'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done 'get write command from buffer, and check if it's 0 Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data cmp Lcd_Data, #0 wz 'and check if it's 0 if_z jmp #get 'if it is, try again. 'if not, prepare transfer 'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd data shr LCD_cmd, #16 'move lcd command 16 bit to the right if not gddr write ' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer 'enables p0 - p15 ' mov pntr, #$1 'set wait period ':wait0 djnz pntr, :wait0 'and wait WrCmd mov outa, LCD_Cmd 'place LCD_Cmd on write bus ' mov pntr, #$1 'set wait period ':wait0 djnz pntr, :wait0 'and wait add zero, #0 wz 'prime WZ flag muxz dira, RSpin 'make RS pin low by enabling its DIR REG ' mov pntr, #$1 'set wait period ':wait1 djnz pntr, :wait1 'and wait muxz dira, WritePin 'make Write Pin low by enabling its DIR REG and LCD_Data, lowWordMask 'mask off High word of Lcd_Data ' mov pntr, #1 'set wait period ':wait2 djnz pntr, :wait2 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$1 'set wait period :wait3 djnz pntr, :wait3 'and wait muxnz dira, RSpin 'make RS pin high by disabling its DIR REG mov pntr, #$1 'set wait period :wait4 djnz pntr, :wait4 'and wait :WrDataPortion mov outa, LCD_Data 'place LCD_Data on write bus wrlong zero, bufferaddress 'wz mov pntr, #$1 'set wait period :wait5 djnz pntr, :wait5 'and wait add zero, #0 wz 'prime WZ flag muxz dira, WritePin 'make Write Pin low by enabling its DIR REG 'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data mov pntr, #$2 'set wait period :wait6 djnz pntr, :wait6 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$1 'set wait period :wait7 djnz pntr, :wait7 'and wait 'mov dira, DirsDisabled 'disables p0 - p15 jmp #Get 'do it all again zero long $0 lowWordMask long $0000_ffff 'pin settings WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 '' (R4Fh) (POR = 0000h) bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1
The faders look something like thisPUB FaderInit | F , b Fader0[0] := 1 Fader0[1] := 1 Fader0[2] := 2 Fader1[0] := 1 Fader1[1] := 1 Fader1[2] := 54 Fader2[0] := 1 Fader2[1] := 1 Fader2[2] := 106 Fader3[0] := 1 Fader3[1] := 1 Fader3[2] := 161 PUB SetFader(FaderNumber) case FaderNumber 0: Fader0[0] := NewFaderValue Fader0[1] := OldValue Fader0[2] := faderpos 1: Fader1[0] := NewFaderValue Fader1[1] := OldValue Fader1[2] := faderpos 2: Fader2[0] := NewFaderValue Fader2[1] := OldValue Fader2[2] := faderpos 3: Fader3[0] := NewFaderValue Fader3[1] :=OldValue Fader3[2] := faderpos PUB GetFader(FaderNumber) case FaderNumber 0: NewFaderValue := Fader0[0] OldValue := Fader0[1] faderpos := Fader0[2] 1: NewFaderValue := Fader1[0] OldValue := Fader1[1] faderpos := Fader1[2] 2: NewFaderValue := Fader2[0] OldValue := Fader2[1] faderpos := Fader2[2] 3: NewFaderValue := Fader3[0] OldValue := Fader3[1] faderpos := Fader3[2] PUB updatefader(f) 'layer 2 if OldValue<> NewFaderValue SendPot(F,NewFaderValue) pfw.WriteActiveCr(6, faderpos, 2, 4, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(7, faderpos, 301, 4, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(32, faderpos, OldValue + 24, 4, 3, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(14, faderpos, NewFaderValue + 24, 4, 4, BackgroundColor, ActiveTextColor, 1) oldvalue := NewfaderValue PUB DrawFader |index 'layer 1 pfw.WriteActiveCr(1, faderpos, 0, 0, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(9, faderpos, 7, 0, 0, BackgroundColor, ActiveTextColor, 1) REPEAT 18 pfw.WriteNextActiveCr(13) pfw.WriteActiveCr(1, faderpos, 297, 0, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(9, faderpos, 304, 0, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(6, faderpos, 2, 3, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(7, faderpos, 301, 3, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(32, faderpos, OldValue + 24, 5, 4, BackgroundColor, ActiveTextColor, 1) pfw.WriteActiveCr(14, faderpos, NewFaderValue + 24, 4, 4, BackgroundColor, ActiveTextColor, 1)
These are really buggy right now.Thanks,
Tyler
pfw.WriteActiveCr("F", 0, 8, 0, 0, BackgroundColor, ActiveTextColor, 1) pfw.WriteNextActiveCr("o") pfw.WriteNextActiveCr("n") pfw.WriteNextActiveCr("t")
this writes font to the display starting a row 0 column 8, no borders.if you want, I can help you with the asm modifications. Should not be too hard.
*edited*
I fixed my analog hardware, and now I'm trying to get the HW to bind with the SW values. THIS VERSION IS NOT STABLE!!! I'm working on it
The HW version has optimizations I really recommend. Those pullup resistors on RS and WR are REALLY cool. I was going to pull all lines up or down for a correct init, but address comes out 0 which is screen reset, with enable floating that holds the screen in reset till the prop takes over.
What I'm wondering about now is the best way to regain the eeprom pins after startup. I have lcd_reset line that could be used to indicate a reset status as it is active when spi_en and spi_address lines are inputs. So my thought is to use a `244 to connect the pins to the external devices *midi out and midi in.* Do I need to use both sections of the 244, one for midi active, the other for eeprom active, or can I get away with leaving the eeprom in circuit. I've made enough modifications to the PropRPM that I feel sorry for it. I'm totally willing to cut traces if I have to, but would rather not. I also want to replace the eeprom with the largest one I can, and not sure which part to order. I'm looking at the AT24C512, not sure if this is the best choice.
Another consideration is how to connect my foot controller. I have 18 buttons, 3 digit - 7 segment display, 8 leds and a photo-sensor. I was using my BS2, but would like to free this up so my wife can build the boe-bot. I have a couple of PIC 18F's laying around, but no desire to build a board and develop code for what I consider to be an obsolete and overpriced micro. I will probably end up grabbing a couple more 40pin props and eeproms to match.
I keep saying I'm going to get the SD card working, but have had nothing but failure. I'm wondering if this is because when I'm starting the sd driver, the enable pin is set as an output by the calling cog. I will be conducting more tests later. Fingers crossed.
I also plan on turning the fader code into its own object. I'm trying to wrap my head around the process of this. The idea is to declare multiple instances of the fader object something like
obj fader[4] : "faderObject"
Then update each fader instance, which will hold all necessary information for controlling it. Or something like this?I also received a 16-bit drivers from another member today so I will be looking at those. Anyway, here's some pictures of the progress so far.
SD-MMC File Allocation Table Engine
Version: 2.0 - Special
pst.dec(fat.FATEngineStart(27,26,25,24,-1,-1, -1, -1,-1)) and pst.dec(fat.FATEngineStart(25,26,27,24,-1,-1, -1, -1,-1))
Both calls return -1I have no idea what else to try, other than add the resistors which I will be doing shortly. I will quadruple check my wiring, but doubt that's it. Does anyone have any insight? This is driving me crazy!
*EDIT*
I'm working on a new controller. Here's the initial idea.. I plan on using 2x - 18F452 or 18F4620's. I will be using one of each at first. These use the PSP bus and will be programmable via PROP. Once bootstrap is installed, updates will be handled from sd card, *opcode $F*. Instructions will be 4 bit, 2 bit priority, 2 bits reserved. 8 bit address, 8 or 16 bit data. Prop to PIC transfers will be 1 byte, 2 byte, 3 byte or 4 byte. Still working out all the details, but this will give 2 bidirectional USARTs, 3 SPI busses, 2x8 - bit digital pic bus *B, 2x6 10-bit analog bus. The configuration will be left up to user. There are a ton of built in's that will be very handy. I want to add Dr. Acula's Ram chips on. Any thoughts?
SO, the next task after getting sd cards working was getting Dr. Acula's fonts working. That took about a week. The code needs a ton of work, but it's a start. I'm kinda put off by how the parallax font looks. That 7 is KILLIN me. I still think it looks better than the rom font at half size. Pix to come.
Dr. Acula's font test
CON {''Hardware version 3.11 - see diagram. '' } _clkmode = xtal1 + pll16x ' use crystal x 16 _xinfreq = 5_000_000 'with 5mhz crystal DEV_SD_CLK = 18 DEV_SD_DI = 19 DEV_SD_DO = 20 DEV_SPI_EN = 21 ''SPI Enable enumeration DEV_SPI_ADD0 = 22 ''Device address 0 enumeration DEV_SPI_ADD1 = 23 ''Device address 1 enumeration DEV_SPI_ADD_LE = 24 DEV_SPI_LCD_RES = 0 ''Device id for LCD reset SDC = 1 TSC = 2 EXT = 3 DEV_SPI_EXT_POT_CS = 0 DEV_SPI_EXT_SW_CS = 1 BGCOLOR = $ffff TXTCOLOR = $0000 Pressed = 1 NotPressed = 0 faderUpBtnBound = 499 ''y < 499 faderDnBtnBound = 3700 ''y > 3699 3200, 1600, 320 fadertouchoffset = 320 ''3375 < y < 825 range e cols = 40 rows = 15 screensize = cols * rows lastrow = screensize - cols offset = 8 * 2048 ' the block offset of where we do writes RamText = 169984 VT100 = 202752 FontTable = 206080 VAR long Screen_Buffer, CRbuffer byte FontHeight ' size of the current loaded font (pixels = fontsize *.75) word BackFontColor ' the background color in RRRRRGGG GGGBBBBB format word curx ' current cursor x position in pixels word cury ' current cursor y position in pixels byte Orientation ' true for portrait, false for landscape word ScreenWidth ' either 240 in portrait or 320 in landscape word ScreenHeight ' 320 in portrait or 240 in landscape byte screen[screensize] long col,row,flag 'byte font[13312], sdbuffer[512],buffer2[512] ' 512 byte buffer for sd card interface 'byte tbuf[20] 'byte bigbuf[8192] long BackgroundColor, ActiveTextColor, stringptr[32], maxdur,sr ,speedresults OBJ pfw :"PropFont_asmDone" wait : "timing" 'pst : "parallax serial terminal" spi : "spi_asm" sdfat: "fsrw" 'block: "safe_spi" 'ILI9325:"ILI9325_Dracblade" PUB BOOT | f 'bootstrap, initalizes pins, then starts pst, init display, start asm, clear screen and display hello world WAIT.PAUSE1S(5) initPins SetOrientation(false) BackgroundColor := $ffe0 ActiveTextColor := %0000 long[@Screen_Buffer] := $ffff 'make sure screen buffer does not equal 0 pfw.Start(@Long[@Screen_Buffer]) 'Start Asm Driver, needs to be changed to pass screen buffer from top object pfw.size(1) pfw.setChar(0, 8, 0, 0, BackgroundColor, ActiveTextColor) spi.start(3,0) 'pfw.ClearScreen(BackgroundColor) 'Draw White Screen with asm ' DracFont 'pfw.dec(\SD_speedtest) 'wait.pause1s(5) repeat DracFont Pub DracFont |c 'pfw.clearscreen($FFFF) pfw.size(2) 'pfw.str(string(" setting enable output ")) OUTA[DEV_SPI_EN] := 1 outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC dira[DEV_SPI_EN..DEV_SD_CLK] := 0 dira[DEV_SPI_ADD1..DEV_SPI_ADD0] := 3 'pfw.newline 'pfw.str(string(" setting enable output ok ")) 'pfw.newline 'pfw.str(string(" trying to mount sd card ")) 'pfw.newline 'wait.pause1s(1) if \sdfat.mount(18) < -1 ' pfw.str(string("Mount Failed")) 'wait.pause1s(3) sdfat.unmount else 'pfw.str(string(" Mounting OK ")) \NewFont(string("Par16.ifn")) sdfat.unmount Text_cls 'tswait repeat repeat c from 32 to 125 wait.pause1ms(100) text_out(c) ' ' Text_str(string("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz")) Text_str(string("Basic text display for the ILI9325")) Text_crlf Text_str(string("Print decimal value ")) Text_dec(100) Text_crlf text_str(string("Hex value 500 = ")) Text_hex(500,4) text_crlf 'wait.pause1s(5) PUB Text_Str(rstringptr) '' Print a zero-terminated string repeat strsize(rstringptr) Text_out(byte[rstringptr++]) PUB Text_out(c) | i, k '' Output a character '' '' $08 = backspace '' $09 = tab (8 spaces per) '' $01 = set X position (X follows) '' $0B = set Y position (Y follows) '' $0C = set color (color follows) (not on this simple terminal) '' $0A = line feed '' $0D = carriage return (col = 0) '' others = printable characters case flag $00: case c $08: if col ' not zero so can subtract one col-- Text_print(" ") ' backspace and rubout col-- 'Text_RedrawLine $09: repeat Text_print(" ") while col & 7 $01: flag := c return $0B: flag := c return $0C: flag := c return $0A: Text_newline ' linefeed/new line $0D: col := 0 ' carriage return other: Text_print(c) $0A: col := c // cols $0B: row := c // rows '$0C: color := c & 7 flag := 0 PRI Text_print(c) ' private routine from routine above screen[row * cols + col] := c ' store in the screen text buffer ILIChar(c,col<<3,row <<4) ' print on the screen col*8 and row *16 as this is the font size if ++col == cols Text_newline ' PUB Text_hex(value, digits) {{ Send value as hexadecimal characters up to digits in length. '' '' `Parameters: '' '' `value: byte, word, or long value to send as hexadecimal characters. '' `digits: number of hexadecimal digits to send. Will be zero padded if necessary. '' '' `Return: none. '' '' `Example: pst.Hex(1234, 5) '' '' Output decimal 1234 as five hex digits. Outputs `004D2. '' Next lines, if needed... }} if (digits > 8) repeat digits - 8 Text_out("0") digits := 8 else value <<= (8 - digits) << 2 repeat digits Text_out(lookupz((value <-= 4) & $F : "0".."9", "A".."F")) PUB Text_dec(value) | i '' Print a decimal number if value < 0 -value Text_out("-") i := 1_000_000_000 repeat 10 if value => i Text_out(value / i + "0") value //= i result~~ elseif result or i == 1 Text_out("0") i /= 10 PRI Text_newline | i col := 0 if ++row == rows row-- bytemove(@screen, @screen[cols], lastrow) 'scroll lines bytefill(@screen[lastrow], " ", cols) 'clear new line Text_RedrawScreen ' all lines shuffle up one so need to redraw all the screen PUB Text_RedrawScreen | x,y,i ClearFontBackground(0,0,screenheight,screenwidth) ILIsetcursor(0,0) i := 0 repeat y from 0 to rows -1 repeat x from 0 to cols -1 curx := ILIChar(screen[i],curx,cury) i++ curx :=0 cury +=fontheight PRI Text_RedrawLine | oldcurx,i ' redraw current row, for backspace oldcurx := curx' store ClearFontBackground(0,row <<4 ,screenwidth,row <<4 + FontHeight) ' clear background line to the background color ready to draw curx := 0 cury := row <<4 ' times 16 i := row * cols ' variable row times constant cols repeat cols ' do 40x curx := ILIChar(screen[i],curx,cury) i++ curx := oldcurx ' restore curx PUB ILIChar(ascii,x,y) | jump,size,width,height,ramaddress,xoffset,yoffset,xadvance ' read out a character from a .ifn file stored in ram jump := long[@font + (ascii << 2) + 256]' jump location = ascii *4 plus fonttable + 256 jump += @font size := long[jump] ' size precalculated = width x height x 2 xadvance := long[jump][5] ' ' amount to move to next character offset = 20 which is 5 longs if size > 0 and ascii <> 32 ' no need to print anything if size is zero or read more font data width := long[jump][1] ' width value of offset is 1 long height := long[jump][2] ' height xoffset := long[jump][3] ' xoffset to move yoffset := long[jump][4] ' yoffset to move if (x+width -1 + xoffset) > screenwidth ILIcrlf ' do a new line if it won't fit x :=curx y :=cury pfw.draw( x+xoffset, y+yoffset, x+width-1+xoffset,y+height-1+yoffset) ' draw on screen pfw.hub(jump+32,size) ' move bytes from ram out to the display return x + xadvance PUB SetOrientation(e) ' change orientation true = portrait. Changes global variable 'orientation' and also screen width and height orientation := e pfw.ChangeOrientation(orientation) if orientation screenwidth :=239 screenheight :=319 else screenwidth :=319 screenheight :=239 PUB Text_crlf Text_out(13) Text_out(10) PUB Text_cls bytefill(@screen, " ", screensize) col := row := 0 PUB ILISetCursor(x,y) curx := x cury := y PUB ILIcrlf curx := 0 cury += FontHeight PUB NewFont(nstrpointer) ILIloadfont(nstrpointer) ' only call this routine with the cursor curx at zero 'pfw.newline 'pfw.str(string("calling font clear with curx")) ' pfw.dec(curx) 'pfw.newline 'pfw.str(string("cury")) ' pfw.dec(cury) 'pfw.newline 'pfw.str(string("screenwitdth")) 'pfw.dec(screenwidth) 'pfw.newline ' pfw.str(string("screenheight")) 'pfw.dec(screenheight) 'pfw.newline ''tswait 'pfw.str(string("go")) ClearFontBackground(0,0,screenheight,screenwidth) ' clear an area the same color as the font background 'pfw.str(string("cleared?")) ILIsetcursor(0,0) PUB ILILoadFont(nstringptr)| filesize,i ' hub version ' pass file name in stringptr ' the variable "i" must start on 0,256,512,768 etc for the block move to work i := 0 'pfw.newline 'pfw.str(string("Opening file ")) 'pfw.str(nstringptr) 'pfw.newline sdfat.popen(nstringptr,"r") ' store at the constant 'fonttable' location 'pfw.str(string("Opening file ok ")) 'pfw.newline 'pfw.str(string("Getting filesize")) 'pfw.newline filesize := sdfat.get_filesize 'pfw.str(string("Filesize is ")) 'pfw.dec(filesize) 'pfw.newline 'pfw.str(string("loading font into hub")) 'pfw.newline repeat (filesize >> 8) ' read in this number of 256 byte blocks sdfat.pread(@font+i,256) ' get 256 bytes from sd card i += 256 ' add 256 'pfw.str(string(" read complete ")) 'pfw.newline 'pfw.str(string(" closing filesystem ")) sdfat.pclose 'pfw.str(string(" closed ")) 'pfw.newline 'pfw.str(string("loading font height")) FontHeight := font[251] 'pfw.dec(FontHeight) 'pfw.newline 'pfw.str(string("getting bgcolor")) 'pfw.newline repeat i from 0 to 2 sdbuffer[i] := font[35+i] ' read the 3 RGB bytes 'pfw.str(string("bg color is ")) 'repeat i from 0 to 2 'pfw.dec(sdbuffer[i]) 'pfw.newline 'pfw.str(string("converting colors ")) pfw.convertColors(@sdbuffer,@buffer2,1) 'pfw.str(string("conversion done")) 'tswait 'pfw.clearscreen($4893) 'pfw.str(string("new colors are")) BackFontColor := word[@buffer2] ' background color in ILI two byte format 'pfw.dec(BackFontColor) 'pfw.newline 'pfw.str(string("returing with filesize")) 'pfw.dec(filesize) result := filesize ''tswait PUB ClearFontBackground(x1,y1,x2,y2) | i,size,remainder ' clears an area of the screen to the current font background color size := (x2-x1+1) * (y2 - y1 +1) ' number of pixels remainder := (size & 255) << 1 ' if not a whole number of 256 pixels repeat i from 0 to 510 step 2 ' move the background font colour to the buffer sdbuffer[i] := BackFontColor & 255 ' and replicate for 256 pixels sdbuffer[i+1] := BackFontColor >> 8 pfw.draw(y1,x1,y2,x2) ' set up the area of the screen to draw in repeat size >> 8 ' 512 byte blocks pfw.hub(@sdbuffer,512) ' 2 = 2 bytes which = one pixel *was 512 if remainder <> 0 pfw.hub(@sdbuffer,remainder) ' do the remainder PUB TSWait | yval, xval,x,y OUTA[DEV_SPI_ADD1..DEV_SPI_ADD0] := TSC ''Old format was OUTA[TS_CS] := 0 ' enable the touch screen ' dirA[DEV_SPI_EN] := 1 dirA[DEV_SPI_ADD1] :=1 dirA[DEV_SPI_ADD0] := 1 outa[DEV_SPI_EN] := 1 wait.pause1ms(100) repeat OUTA[DEV_SPI_EN] := 0 SPI.SHIFTOUT(DEV_SD_DI, DEV_SD_CLK, 5, 8 , %1101_0000) ' reads x from 500 to 3700 (off < 500 ) xval := SPI.SHIFTIN(DEV_SD_DO, DEV_SD_CLK,2, 12) SPI.SHIFTOUT(DEV_SD_DI, DEV_SD_CLK, 5, 8 , %1001_0000) ' reads y from 400 to 3800 (off > 3800 ) yval := SPI.SHIFTIN(DEV_SD_DO,DEV_SD_CLK,2, 12) if xval <> 0 result := xval + (yval << 16) OUTA[DEV_SPI_EN] := 1 outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC RETURN ELSE wait.pause1ms(100) PUB StrobeCS OUTA[DEV_SPI_EN] := 0 wait.pause1ms(10) OUTA[DEV_SPI_EN] := 1 pri initPins dirA[DEV_SPI_ADD0] := 1 'makes address 0 and 1 dirA[DEV_SPI_ADD1] := 1 'outputs dirA[DEV_SPI_EN] := 1 'and enable an output as well OUTA[DEV_SPI_ADD1..DEV_SPI_ADD0] := 2 'sd_card is default OUTA[DEV_SPI_EN] := 1 'Disable - Reset Screen 'pri SD_speedtest | r, sta, bytes, CHAR ''works? ' OUTA[DEV_SPI_EN] := 1 ' outa[DEV_SPI_ADD1..DEV_SPI_ADD0] := SDC ' dira[DEV_SPI_EN..DEV_SD_CLK] := 0 ' dira[DEV_SPI_ADD1..DEV_SPI_ADD0] := 3 ' pfw.size(2) ' pfw.clearscreen(0) ' pfw.setColors($0000,$FFFF) ' pfw.Str(string("Starting SD card")) ' helpful message if card is out, better than just a blank screen ' pfw.newline ' Pfw.str(string("Mounting.")) ' pfw.newline ' sdfat.mount(18) ' Pfw.str(string("Mounted.")) ' pfw.newline ' wait.Pause1s(1) ' Pfw.str(string("Dir:")) ' pfw.newline ' sdfat.opendir ' repeat while 0 == sdfat.nextfile(@tbuf) ' Pfw.str(@tbuf) ' Pfw.newline ' Pfw.str(string("That's the dir")) ' sta := cnt ' r := sdfat.popen(string("speed.txt"), "w") ' repeat 256 ' sdfat.pwrite(@bigbuf, 8192) 'r := (cnt - sta) >> 2 ' sdfat.pclose 'pfw.newline 'Pfw.str(string("Writing 2M took ")) ' pfw.dec(r) 'Pfw.newline 'sta := cnt 'r := sdfat.popen(string("speed.txt"), "r") 'repeat 256 ' sdfat.pread(@bigbuf, 8192) 'r := (cnt - sta) >> 2 'sdfat.pclose 'sdfat.release 'sdfat.unmount 'Pfw.str(string("Reading 2M took ")) 'pfw.dec(r) 'Pfw.newline 'Pfw.str(string("That's, all, folks! ")) 'pfw.size(1) 'tswait 'pub deadend 'loop for testing ' repeat 'endlessly wait ' repeat ' waitcnt(2_000 + cnt) DAT sdbuffer byte $0[512] ' 512 byte buffer for sd card interface buffer2 byte $0[512] ' 512 general purpose hub buffer font byte $0[13312]
and the helpers
propFont, now has passthrough functions...
CON ''PINS LCD_RS = 16 ''LCD RS pin LCD_WR = 17 ''LCD WR pin ''LCD REGISTER Enumeration, for SSM1289 REG_OSCILLATOR = $0000 ''Oscillator (R00h) (POR = 0000h) REG_DRIVEROUTPUTCONTROL = $0001 ''Driver Output Control (R01h) (POR = 2B3Fh) REG_LCDDRIVINGWAVFORM = $0002 ''LCD-Driving-Waveform Control (R02h) (POR = 0000h) REG_POWERCONTROL1 = $0003 '' (R03H) REG_DISPLAYCONTROL = $0007 ''Display Control (R07h) (POR = 0000h) REG_FRAMECYCLECONTROL = $000B ''Frame Cycle Control (R0Bh) (POR = 5308h)D308 BY DATASHEET REG_POWERCONTROL2 = $000C '' (R0Ch) (POR = 0004) REG_POWERCONTROL3 = $000D '' REG_POWERCONTROL4 = $000E '' REG_GATESCANPOSITION = $000F ''Gate Scan Position (R0Fh) (POR = 0000h) REG_SLEEPMODE = $0010 ''Sleep mode (R10h) (POR = 0001h) REG_ENTRYMODE = $0011 ''Entry Mode (R11h) (POR = 6830h) REG_HPORCH = $0016 '' (R16h) (POR = EF1Ch) REG_VPORCH = $0017 '' (R17h) (POR = 0003h) REG_POWERCONTROL5 = $001E '' REG_RAMDATAWRITE = $0022 '' REG_RAMWRITEDATAMASK1 = $0023 '' (R23h) (POR = 0000h) REG_RAMWRITEDATAMASK2 = $0024 '' (R24h) (POR = 0000h) REG_VERTICALSCROLCONTROL1 = $0041 '' (R41h) (POR = 0000h) REG_VERTICALSCROLCONTROL2 = $0042 '' (R42h) (POR = 0000h) REG_HORIZONTALRAMADDRESSPOS = $0044 '' (R44h) (POR = EF00h) REG_VERTICALRAMADDRESSSTART = $0045 '' (R45h) (POR = 0000h) REG_VERTICALRAMADDRESSEND = $0046 '' (R46h) (POR = 013Fh) REG_FIRSTWINDOWSTART = $0048 '' (R48h) (POR = 0000h) REG_FIRSTWINDOWEND = $0049 '' (R49h) (POR = 013Fh) REG_SECONDWINDOWSTART = $004A '' (R4Ah) (POR = 0000h) REG_SECONDWINDOWEND = $004B '' (R4Bh) (POR = 013Fh) REG_SETGDDRXADDRESSCOUNTER = $004E '' (R4Eh) (POR = 0000h) REG_SETGDDRYADDRESSCOUNTER = $004F '' (R4Fh) (POR = 0000h) FONT_ROM_ADDRESS = $8000 VAR long screenbufferaddress, Fontsize, pcog long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2 byte orientation word entrymode obj wait : "timing" cr : "crReader" 'pst : "parallax serial terminal" 'used for debugging.. num : "numbers" PUB nul 'not a standalone object PUB draw (x1, y1,x2, y2) 'compatibility passthrough for DRAC SetWindow( y1,x1, y2,x2 ) SetGAddress(y1,x1) col :=0 row :=0 PUB ChangeOrientation(n) ' pass true = portrait or false = landscape, changes global variable orientation in this object ' EnableDisplayPins orientation := n ' if orientation ' Lcd_Write_Com($0001,$0100) ' set SS and SM bit 0001 0100 portrait ' Lcd_Write_Com$0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030 ' else ' Lcd_Write_Com($0001,$0000) ' set SS and SM bit 0001 0000 landscape ' Lcd_Write_Com($0003,$1038) ' landscape $1028 = original but 1038 is correct - not mirror image' pub convertColors(inadd, outadd, len ) |red, green, blue, ilihigh, ililow ' takes a .raw 3 byte RRRRRRRR GGGGGGGG BBBBBBBB and converts to 2 byte RRRRRGGG GGGBBBBB ' pass hubaddr, ramaddr and len ' hubaddr is source location, len is number of pixels ' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklength repeat len red := byte[inadd] inadd++ green := byte[inadd] inadd++ blue := byte[inadd] inadd++ red >>= 3 red <<= 3 green >>= 2 ilihigh:= green ilihigh >>= 3 ilihigh |= red green &=%00000111 green <<= 5 ililow := green blue >>= 3 ililow |= blue word[outadd] := ilihigh +(ililow << 8) outadd++ PUB hub(address,l) | p, pl, ph repeat l / 2 pl := byte[address++] ph := byte[address++] p:= ph +(pl << 8) Lcd_Write_Asm((REG_RAMDATAWRITE << 16)+ p ) 'PUB setEntryModeDefault ' setEntryMode(3,1) pub setEntryMode ' 5..4 3 'entry vs dfm trans- oe wm d0..1 ty id AM LG 'mode Mode 1..0 parent def mode mode 1..0 entrymode := %0110______1000____0000____1000 ' default $6838 Lcd_Write_Asm((REG_ENTRYMODE << 16) + entrymode ) pub setDriverOutputControl | reverse,bgr,tb,rl 'reverse 'bgr 'tb 'rl pub pixel(p) Lcd_Write_Asm((REG_RAMDATAWRITE << 16)+ p ) pub size(s) fontsize := s PUB Str(ptr) | cbuf cbuf := byte[ptr++] WriteActiveCr(cbuf, row, col, 0, 0, BackgroundColor, ActiveTextColor) repeat (strsize(ptr) ) WriteNextActiveCr(byte[ptr++]) PUB dec(n) | t, t2, t3, t4, t5, t6, t7, t8, t9, t10, pl, im str(num.tostr(n, %000_010_001_0_0_000000_01010)) pub newline Row := Row + (32 >> (fontsize -1)) Col := 0 pub setRow(PosR ) Row := PosR pub setCol(PosC) Col := PosC pub setBorders(RBorder, CBorder) RowBorder := RBorder ColBorder := CBorder pub setColors( BgC, TxC) BackgroundColor := BgC ActiveTextColor := Txc PUB setChar(PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress setRow(PosR) setCol(PosC) setBorders(RBorder, CBorder) setColors(BgC, TxC) PUB Start(ScreenBufferAdd) 'Method to Init display, then load a cog with screen driver screenbufferaddress := ScreenBufferAdd 'store buffer address in long Init_SSD1289 'init screen long[@screenbufferaddress] := $ffff 'make sure screen buffer does not equal 0 result := pcog := cognew(@entry,@long[@screenbufferaddress]) 'start write driver and pass it the address of screen buffer cr.Start num.init PUB Stop cogstop(pcog) PUB Char(c) WriteNextActiveCr(c) PUB WriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress fontaddress := Cr.GetChar(Character) repeat idx from 0 to 31 bitpatern[idx] := word[fontaddress][idx] y1 := Col + ColBorder y2 := (Col + (15 / fontsize ) - ColBorder) x1 := Row + RowBorder x2 := (Row + (31 / fontsize ) - RowBorder) SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RowBorder to 31 - RowBorder step Fontsize repeat pxlidx from ColBorder to 15 - ColBorder step Fontsize pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Asm(ActiveTextColor + (REG_RAMDATAWRITE << 16)) else Lcd_Write_Asm(BackgroundColor + (REG_RAMDATAWRITE << 16)) repeat while word[fontaddress] := 0 if (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) > 223))) Row := 0 Col := 0 elseif (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) < 223))) Row := Row + (32 >> (fontsize -1)) Col := 0 else Col := Col + (16 >> (fontsize - 1)) PUB WriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress setChar(PosR, PosC, RBorder, CBorder, BgC, TxC) WriteNextActiveCr(Character) PUB ClearScreen(color) | idxr, idxc SetWindow(0, 0, 239, 319) SetGAddress(0,0) color += (REG_RAMDATAWRITE << 16) repeat idxr from 0 to 76800 Lcd_Write_Asm(Color) Row := 0 Col := 0 'BackgroundColor := color 'ActiveTextColor := $ffff PUB SetWindow(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS 'Set window to draw in WindowX1 := x1 'update draw window in main memory WindowX2 := x2 'update draw window in main memory WindowY1 := y1 'update draw window in main memory WindowY2 := y2 'update draw window in main memory HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) 'combine x1 and x2 values Lcd_Write_Asm ((REG_HORIZONTALRAMADDRESSPOS << 16) + HORIZONTALRAMADDRESSPOS) 'and write to display Lcd_Write_Asm(y1 + (REG_VERTICALRAMADDRESSSTART << 16)) 'send v-address start Lcd_Write_Asm(y2 + (REG_VERTICALRAMADDRESSEND << 16)) 'send v-address end PUB SetGAddress(x,y) 'Set address for gddr writes Lcd_Write_Asm ((REG_SETGDDRXADDRESSCOUNTER << 16) + x) ''max %1111_1111, $FF Lcd_Write_Asm ((REG_SETGDDRYADDRESSCOUNTER << 16) + y) ''max %1_0011_1111, $13f '' PRI EnableDisplayPins 'enable all pins - DIRA:=%00000000_11000000_11111111_11111111 ''enable p15 - p0 PRI TristateDisplayPins 'tristate all pins - DIRA:=%00000000_11000000_00000000_00000000 ''release p15 - p0 PRI Lcd_Write_Asm(V) 'handler for asm writes repeat while (long[@screenbufferaddress] <> 0) 'waits for cog to clear screenbuffer long[@screenbufferaddress] := V 'makes screen buffer = v PRI LCD_Writ_Bus(V) 'write to display OUTA[15..0] := V ' copy V onto pins WriteLow ' write pin low WriteHigh ' toggle write pin PRI Lcd_Write_Com(V) 'write command to display LCD_RSLow 'Sets command LCD_Writ_Bus(V) 'Do write PRI LCD_Write_Data(V) 'write data to display LCD_RSHigh 'Sets data LCD_Writ_Bus(V) 'do write PRI LCD_RSLow outa[LCD_RS] := 0 'controls RS pin with DIR-A dira[LCD_RS] := 1 'see hardware revision PRI LCD_RSHigh 'controls RS pin with DIR-A dira[LCD_RS] := 0 'see hardware revision PRI WriteLow outa[LCD_WR] := 0 'controls WR pin with DIR-A dira[LCD_WR] := 1 'see hardware revision ' PRI WriteHigh 'controls WR pin with DIR-A dira[LCD_WR] := 0 'see hardware revision PRI Init_SSD1289 ''Init Display EnableDisplayPins Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0021) ''GON = 1 DTE = 0 D[1:0] = 01 Lcd_Write_Com (REG_OSCILLATOR) ''Oscillator (R00h) (POR = 0000h) Lcd_Write_Data($0001) ''Turn on oscillator Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0023) ''GON = 1 DTE = 0 D[1:0] = 11 Lcd_Write_Com (REG_SLEEPMODE) ''Sleep mode (R10h) (POR = 0001h) Lcd_Write_Data($0000) '' ''exit sleep mode Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) Lcd_Write_Data($0033) ''GON = 1 DTE = 1 D[1:0] = 11 Lcd_Write_Com (REG_ENTRYMODE) ''Entry Mode (R11h) (POR = 6830h) 6838 Lcd_Write_Data($6838) '' Lcd_Write_Com (REG_LCDDRIVINGWAVFORM) ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) Lcd_Write_Data($1000) '' '' Lcd_Write_Com (REG_GATESCANPOSITION) ''Gate Scan Position (R0Fh) (POR = 0000h) ($0000) Lcd_Write_Data($0000) '' '' '' Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL) ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f ($633F) 6838 Lcd_Write_Data($6B3F) '' '' Bit 14 - Invert Color bit9-TB Lcd_Write_Com (REG_FRAMECYCLECONTROL) ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308) Lcd_Write_Data($5308) '' ' Lcd_Write_Com (REG_DISPLAYCONTROL) ''Display Control (R07h) (POR = 0000h) ($0033) Lcd_Write_Data($0033) TristateDisplayPins ''Release pins PUB HelloWorld WriteActiveCr("H", 0, 0*16, 0, 0, $ffff, $0000) WriteNextActiveCr("e") WriteNextActiveCr("l") WriteNextActiveCr("l") WriteNextActiveCr("o") WriteNextActiveCr(" ") WriteNextActiveCr("W") WriteNextActiveCr("o") WriteNextActiveCr("r") WriteNextActiveCr("l") WriteNextActiveCr("d") DAT 'init Display driver 'designed for optimized hardware, pull-up resistors on RS and WR pins. org 0 entry mov outa, PinsInit 'set pins to inital state mov dira, DirsEnabled 'enables p0 - p15 mov bufferaddress, par 'store par in bufferaddress, par is screen buffer address at startup 'mov dira, DirsDisabled 'disables p0 - p15 if necessary wrlong zero, bufferaddress 'set par to zero to confirm load done 'get write command from buffer, and check if it's 0 Get rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data cmp Lcd_Data, #0 wz 'and check if it's 0 if_z jmp #get 'if it is, try again. 'if not, prepare transfer 'mov dira, DirsEnabled 'set pins if necessary mov LCD_cmd, LCD_Data 'copy lcd command to lcd data shr LCD_cmd, #16 'move lcd command 16 bit to the right if not gddr write ' cmp LCD_cmd, #22 wz 'check to see if this is a gddr write 'if_nz jmp WRcmd 'optimized write to display, for gddr transfer 'enables p0 - p15 ' mov pntr, #$1 'set wait period ':wait0 djnz pntr, :wait0 'and wait WrCmd mov outa, LCD_Cmd 'place LCD_Cmd on write bus ' mov pntr, #$1 'set wait period ':wait0 djnz pntr, :wait0 'and wait add zero, #0 wz 'prime WZ flag muxz dira, RSpin 'make RS pin low by enabling its DIR REG ' mov pntr, #$1 'set wait period ':wait1 djnz pntr, :wait1 'and wait muxz dira, WritePin 'make Write Pin low by enabling its DIR REG and LCD_Data, lowWordMask 'mask off High word of Lcd_Data ' mov pntr, #1 'set wait period ':wait2 djnz pntr, :wait2 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG mov pntr, #$1 'set wait period :wait3 djnz pntr, :wait3 'and wait muxnz dira, RSpin 'make RS pin high by disabling its DIR REG mov pntr, #$2 'set wait period :wait4 djnz pntr, :wait4 'and wait :WrDataPortion mov outa, LCD_Data 'place LCD_Data on write bus mov pntr, #$1 'set wait period :wait5 djnz pntr, :wait5 'and wait add zero, #0 wz 'prime WZ flag muxz dira, WritePin 'make Write Pin low by enabling its DIR REG 'rdlong LCD_Data, bufferaddress 'get long from main memory and put it in ldc command, msW = LCD cmd, LSw = LCD data ' mov pntr, #$2 'set wait period ':wait6 djnz pntr, :wait6 'and wait muxnz dira, WritePin 'make Write Pin high by disabling its DIR REG ' mov pntr, #$1 'set wait period ':wait7 djnz pntr, :wait7 'and wait 'mov dira, DirsDisabled 'disables p0 - p15 wrlong zero, bufferaddress jmp #Get 'do it all again zero long $0 lowWordMask long $0000_ffff 'pin settings WritePin long %00000000_00000010_00000000_00000000 RSPin long %00000000_00000001_00000000_00000000 PinsInit long %00000000_00000000_00000000_00000000 DirsDisabled long %00000000_00000000_00000000_00000000 DirsEnabled long %00000000_00000000_11111111_11111111 '' (R4Fh) (POR = 0000h) bufferaddress res 1 LCD_cmd res 1 LCD_data res 1 Pntr res 1 ForegroundFormat res 1 BackgroundFormat res 1 ForegroundScreen res 1 BackgroundScreen res 1 fit
and my fsrw stuff for good measure{{ ' fsrw 2.6 Copyright 2009 Tomas Rokicki and Jonathan Dummer ' ' See end of file for terms of use. ' ' This object provides FAT16/32 file read/write access on a block device. ' Only one file open at a time. Open modes are 'r' (read), 'a' (append), ' 'w' (write), and 'd' (delete). Only the root directory is supported. ' No long filenames are supported. We also support traversing the ' root directory. ' ' In general, negative return values are errors; positive return ' values are success. Other than -1 on popen when the file does not ' exist, all negative return values will be "aborted" rather than ' returned. ' ' Changes: ' v1.1 28 December 2006 Fixed offset for ctime ' v1.2 29 December 2006 Made default block driver be fast one ' v1.3 6 January 2007 Added some docs, and a faster asm ' v1.4 4 February 2007 Rearranged vars to save memory; ' eliminated need for adjacent pins; ' reduced idle current consumption; added ' sample code with abort code data ' v1.5 7 April 2007 Fixed problem when directory is larger ' than a cluster. ' v1.6 23 September 2008 Fixed a bug found when mixing pputc ' with pwrite. Also made the assembly ' routines a bit more cautious. ' v2.1 12 July 2009 FAT32, SDHC, multiblock, bug fixes ' v2.4 26 September 2009 Added seek support. Added clustersize. ' v2.4a 6 October 2009 modified setdate to explicitly set year/month/etc. ' v2.5 13 November 2009 fixed a bug on releasing the pins, added a "release" pass through function ' v2.6 11 December 2009: faster transfer hub <=> cog, safe_spi.spin uses 1/2 speed reads, is default }} ' ' Constants describing FAT volumes. ' con SECTORSIZE = 512 SECTORSHIFT = 9 DIRSIZE = 32 DIRSHIFT = 5 ' ' The object that provides the block-level access. ' obj 'sdspi : "sdspiqasm" ' old? no release 'sdspi: "mb_spi" nogood 'sdspi: "mb_rawb_spi" noope 'sdspi: "mb_small_spi" 'no work sdspi: "safe_spi" var ' ' ' Variables concerning the open file. ' long fclust ' the current cluster number long filesize ' the total current size of the file long floc ' the seek position of the file long frem ' how many bytes remain in this cluster from this file long bufat ' where in the buffer our current character is long bufend ' the last valid character (read) or free position (write) long direntry ' the byte address of the directory entry (if open for write) long writelink ' the byte offset of the disk location to store a new cluster long fatptr ' the byte address of the most recently written fat entry long firstcluster ' the first cluster of this file ' ' Variables used when mounting to describe the FAT layout of the card ' (moved to the end of the file in the Spin version). ' ' ' Variables controlling the caching. ' ' ' Buffering: two sector buffers. These two buffers must be longword ' aligned! To ensure this, make sure they are the first byte variables ' defined in this object. ' byte buf[SECTORSIZE] ' main data buffer pub release ' ' This is just a pass-through function to allow the block layer ' to tristate the I/O pins to the card. ' sdspi.release pri writeblock2(n, b) ' ' On metadata writes, if we are updating the FAT region, also update ' the second FAT region. ' sdspi.writeblock(n, b) if (n => fat1) if (n < fat1 + sectorsperfat) sdspi.writeblock(n+sectorsperfat, b) pri flushifdirty ' ' If the metadata block is dirty, write it out. ' if (dirty) writeblock2(lastread, @buf2) dirty := 0 pri readblockc(n) ' ' Read a block into the metadata buffer, if that block is not already ' there. ' if (n <> lastread) flushifdirty sdspi.readblock(n, @buf2) lastread := n pri brword(b) ' ' Read a byte-reversed word from a (possibly odd) address. ' return (byte[b]) + ((byte[b][1]) << 8) pri brlong(b) ' ' Read a byte-reversed long from a (possibly odd) address. ' return brword(b) + (brword(b+2) << 16) pri brclust(b) ' ' Read a cluster entry. ' if (filesystem == 1) return brword(b) else return brlong(b) pri brwword(w, v) ' ' Write a byte-reversed word to a (possibly odd) address, and ' mark the metadata buffer as dirty. ' byte[w++] := v byte[w] := v >> 8 dirty := 1 pri brwlong(w, v) ' ' Write a byte-reversed long to a (possibly odd) address, and ' mark the metadata buffer as dirty. ' brwword(w, v) brwword(w+2, v >> 16) pri brwclust(w, v) ' ' Write a cluster entry. if (filesystem == 1) brwword(w, v) else brwlong(w, v) ' ' This may do more complicated stuff later. ' pub unmount pclose sdspi.stop pri getfstype : r if (brlong(@buf+$36) == constant("F" + ("A" << 8) + ("T" << 16) + ("1" << 24)) and buf[$3a]=="6") return 1 if (brlong(@buf+$52) == constant("F" + ("A" << 8) + ("T" << 16) + ("3" << 24)) and buf[$56]=="2") return 2 ' return r (default return) pub mount_explicit(DO, CLK, DI, CS) : r | start, sectorspercluster, reserved, rootentries, sectors {{ ' Mount a volume. The address passed in is passed along to the block ' layer; see the currently used block layer for documentation. If the ' volume mounts, a 0 is returned, else abort is called. }} if (pdate == 0) pdate := constant(((2009-1980) << 25) + (1 << 21) + (27 << 16) + (7 << 11)) unmount sdspi.start_explicit(DO, CLK, DI, CS) lastread := -1 dirty := 0 sdspi.readblock(0, @buf) if (getfstype > 0) start := 0 else start := brlong(@buf+$1c6) sdspi.readblock(start, @buf) filesystem := getfstype if (filesystem == 0) abort(-20) ' not a fat16 or fat32 volume if (brword(@buf+$0b) <> SECTORSIZE) abort(-21) ' bad bytes per sector sectorspercluster := buf[$0d] if (sectorspercluster & (sectorspercluster - 1)) abort(-22) ' bad sectors per cluster clustershift := 0 repeat while (sectorspercluster > 1) clustershift++ sectorspercluster >>= 1 sectorspercluster := 1 << clustershift clustersize := SECTORSIZE << clustershift reserved := brword(@buf+$0e) if (buf[$10] <> 2) abort(-23) ' not two FATs sectors := brword(@buf+$13) if (sectors == 0) sectors := brlong(@buf+$20) fat1 := start + reserved if (filesystem == 2) rootentries := 16 << clustershift sectorsperfat := brlong(@buf+$24) dataregion := (fat1 + 2 * sectorsperfat) - 2 * sectorspercluster rootdir := (dataregion + (brword(@buf+$2c) << clustershift)) << SECTORSHIFT rootdirend := rootdir + (rootentries << DIRSHIFT) endofchain := $ffffff0 else rootentries := brword(@buf+$11) sectorsperfat := brword(@buf+$16) rootdir := (fat1 + 2 * sectorsperfat) << SECTORSHIFT rootdirend := rootdir + (rootentries << DIRSHIFT) dataregion := 1 + ((rootdirend - 1) >> SECTORSHIFT) - 2 * sectorspercluster endofchain := $fff0 if (brword(@buf+$1fe) <> $aa55) abort(-24) ' bad FAT signature totclusters := ((sectors - dataregion + start) >> clustershift) ' return r (default return) ' ' For compatibility, a single pin. ' pub mount(basepin) : r | start, sectorspercluster, reserved, rootentries, sectors return mount_explicit(basepin+2, basepin, basepin+1, basepin+3) pri readbytec(byteloc) ' ' Read a byte address from the disk through the metadata buffer and ' return a pointer to that location. ' readblockc(byteloc >> SECTORSHIFT) return @buf2 + (byteloc & constant(SECTORSIZE - 1)) pri readfat(clust) ' ' Read a fat location and return a pointer to the location of that ' entry. ' fatptr := (fat1 << SECTORSHIFT) + (clust << filesystem) return readbytec(fatptr) pri followchain : r ' ' Follow the fat chain and update the writelink. ' r := brclust(readfat(fclust)) writelink := fatptr ' return r (default return) pri nextcluster : r ' ' Read the next cluster and return it. Set up writelink to ' point to the cluster we just read, for later updating. If the ' cluster number is bad, return a negative number. ' r := followchain if (r < 2 or r => totclusters) abort(-9) ' bad cluster value ' return r (default return) pri freeclusters(clust) | bp ' ' Free an entire cluster chain. Used by remove and by overwrite. ' Assumes the pointer has already been cleared/set to end of chain. ' repeat while (clust < endofchain) if (clust < 2) abort(-26) ' bad cluster number") bp := readfat(clust) clust := brclust(bp) brwclust(bp, 0) flushifdirty pri datablock ' ' Calculate the block address of the current data location. ' return (fclust << clustershift) + dataregion + ((floc >> SECTORSHIFT) & ((1 << clustershift) - 1)) pri uc(c) ' ' Compute the upper case version of a character. ' if ("a" =< c and c =< "z") return c - 32 return c pri pflushbuf(rcnt, metadata) : r | cluststart, newcluster, count, i ' ' Flush the current buffer, if we are open for write. This may ' allocate a new cluster if needed. If metadata is true, the ' metadata is written through to disk including any FAT cluster ' allocations and also the file size in the directory entry. ' if (direntry == 0) abort(-27) ' not open for writing if (rcnt > 0) ' must *not* allocate cluster if flushing an empty buffer if (frem < SECTORSIZE) ' find a new clustercould be anywhere! If possible, stay on the ' same page used for the last cluster. newcluster := -1 cluststart := fclust & (!((SECTORSIZE >> filesystem) - 1)) count := 2 repeat readfat(cluststart) repeat i from 0 to SECTORSIZE - 1<<filesystem step 1<<filesystem if (buf2[i] == 0) if (brclust(@buf2+i) == 0) newcluster := cluststart + (i >> filesystem) if (newcluster => totclusters) newcluster := -1 quit if (newcluster > 1) brwclust(@buf2+i, endofchain+$f) if (writelink == 0) brwword(readbytec(direntry)+$1a, newcluster) writelink := (direntry&(SECTORSIZE-filesystem)) brwlong(@buf2+writelink+$1c, floc+bufat) if (filesystem == 2) brwword(@buf2+writelink+$14, newcluster>>16) else brwclust(readbytec(writelink), newcluster) writelink := fatptr + i fclust := newcluster frem := clustersize quit else cluststart += (SECTORSIZE >> filesystem) if (cluststart => totclusters) cluststart := 0 count-- if (rcnt < 0) rcnt := -5 ' No space left on device quit if (frem => SECTORSIZE) sdspi.writeblock(datablock, @buf) if (rcnt == SECTORSIZE) ' full buffer, clear it floc += rcnt frem -= rcnt bufat := 0 bufend := rcnt if (rcnt < 0 or metadata) ' update metadata even if error readblockc(direntry >> SECTORSHIFT) ' flushes unwritten FAT too brwlong(@buf2+(direntry & (SECTORSIZE-filesystem))+$1c, floc+bufat) flushifdirty if (rcnt < 0) abort(rcnt) return rcnt pub pflush {{ ' Call flush with the current data buffer location, and the flush ' metadata flag set. }} return pflushbuf(bufat, 1) pri pfillbuf : r ' ' Get some data into an empty buffer. If no more data is available, ' return -1. Otherwise return the number of bytes read into the ' buffer. ' if (floc => filesize) return -1 if (frem == 0) fclust := nextcluster frem := (clustersize) <# (filesize - floc) sdspi.readblock(datablock, @buf) r := SECTORSIZE if (floc + r => filesize) r := filesize - floc floc += r frem -= r bufat := 0 bufend := r ' return r (default return) pub pclose : r {{ ' Flush and close the currently open file if any. Also reset the ' pointers to valid values. If there is no error, 0 will be returned. }} if (direntry) r := pflush bufat := 0 bufend := 0 filesize := 0 floc := 0 frem := 0 writelink := 0 direntry := 0 fclust := 0 firstcluster := 0 sdspi.release ' return r (default return) pub setdate(year, month, day, hour, minute, second) {{ ' Set the current date and time, as a long, in the format ' required by FAT16. Various limits are not checked. }} pdate := ((year-1980) << 25) + (month << 21) + (day << 16) pdate += (hour << 11) + (minute << 5) + (second >> 1) pub popen(s, mode) : r | i, sentinel, dirptr, freeentry {{ ' Close any currently open file, and open a new one with the given ' file name and mode. Mode can be "r" "w" "a" or "d" (delete). ' If the file is opened successfully, 0 will be returned. If the ' file did not exist, and the mode was not "w" or "a", -1 will be ' returned. Otherwise abort will be called with a negative error ' code. }} pclose i := 0 repeat while (i<8 and byte[s] and byte[s] <> ".") padname[i++] := uc(byte[s++]) repeat while (i<8) padname[i++] := " " repeat while (byte[s] and byte[s] <> ".") s++ if (byte[s] == ".") s++ repeat while (i<11 and byte[s]) padname[i++] := uc(byte[s++]) repeat while (i < 11) padname[i++] := " " sentinel := 0 freeentry := 0 repeat dirptr from rootdir to rootdirend - DIRSIZE step DIRSIZE s := readbytec(dirptr) if (freeentry == 0 and (byte[s] == 0 or byte[s] == $e5)) freeentry := dirptr if (byte[s] == 0) sentinel := dirptr quit repeat i from 0 to 10 if (padname[i] <> byte[s][i]) quit if (i == 11 and 0 == (byte[s][$0b] & $18)) ' this always returns fclust := brword(s+$1a) if (filesystem == 2) fclust += brword(s+$14) << 16 firstcluster := fclust filesize := brlong(s+$1c) if (mode == "r") frem := (clustersize) <# (filesize) return 0 if (byte[s][11] & $d9) abort(-6) ' no permission to write if (mode == "d") brwword(s, $e5) if (fclust) freeclusters(fclust) flushifdirty return 0 if (mode == "w") brwword(s+$1a, 0) brwword(s+$14, 0) brwlong(s+$1c, 0) writelink := 0 direntry := dirptr if (fclust) freeclusters(fclust) bufend := SECTORSIZE fclust := 0 filesize := 0 frem := 0 return 0 elseif (mode == "a") ' this code will eventually be moved to seek frem := filesize freeentry := clustersize if (fclust => endofchain) fclust := 0 repeat while (frem > freeentry) if (fclust < 2) abort(-7) ' eof repeat while following chain fclust := nextcluster frem -= freeentry floc := filesize & constant(!(SECTORSIZE - 1)) bufend := SECTORSIZE bufat := frem & constant(SECTORSIZE - 1) writelink := 0 direntry := dirptr if (bufat) sdspi.readblock(datablock, @buf) frem := freeentry - (floc & (freeentry - 1)) else if (fclust < 2 or frem == freeentry) frem := 0 else frem := freeentry - (floc & (freeentry - 1)) if (fclust => 2) followchain return 0 else abort(-3) ' bad argument if (mode <> "w" and mode <> "a") return -1 ' not found direntry := freeentry if (direntry == 0) abort(-2) ' no empty directory entry ' write (or new append): create valid directory entry s := readbytec(direntry) bytefill(s, 0, DIRSIZE) bytemove(s, @padname, 11) brwword(s+$1a, 0) brwword(s+$14, 0) i := pdate brwlong(s+$e, i) ' write create time and date brwlong(s+$16, i) ' write last modified date and time if (direntry == sentinel and direntry + DIRSIZE < rootdirend) brwword(readbytec(direntry+DIRSIZE), 0) flushifdirty writelink := 0 fclust := 0 bufend := SECTORSIZE ' return r (default return) pub get_filesize return filesize pub pread(ubuf, count) : r | t {{ ' Read count bytes into the buffer ubuf. Returns the number of bytes ' successfully read, or a negative number if there is an error. ' The buffer may be as large as you want. }} repeat while (count > 0) if (bufat => bufend) t := pfillbuf if (t =< 0) if (r > 0) ' parens below prevent this from being optimized out return (r) return t t := (bufend - bufat) <# (count) if ((t | (ubuf) | bufat) & 3) bytemove(ubuf, @buf+bufat, t) else longmove(ubuf, @buf+bufat, t>>2) bufat += t r += t ubuf += t count -= t ' return r (default return) pub pgetc | t {{ ' Read and return a single character. If the end of file is ' reached, -1 will be returned. If an error occurs, a negative ' number will be returned. }} if (bufat => bufend) t := pfillbuf if (t =< 0) return -1 return (buf[bufat++]) pub pwrite(ubuf, count) : r | t {{ ' Write count bytes from the buffer ubuf. Returns the number of bytes ' successfully written, or a negative number if there is an error. ' The buffer may be as large as you want. }} repeat while (count > 0) if (bufat => bufend) pflushbuf(bufat, 0) t := (bufend - bufat) <# (count) if ((t | (ubuf) | bufat) & 3) bytemove(@buf+bufat, ubuf, t) else longmove(@buf+bufat, ubuf, t>>2) r += t bufat += t ubuf += t count -= t ' return r (default return) {{ ' Write a null-terminated string to the file. }} pub pputs(b) return pwrite(b, strsize(b)) pub pputc(c) : r {{ ' Write a single character into the file open for write. Returns ' 0 if successful, or a negative number if some error occurred. }} if (bufat == SECTORSIZE) if (pflushbuf(SECTORSIZE, 0) < 0) return -1 buf[bufat++] := c ' return r (default return) {{ ' Seek. Right now will only seek within the current cluster. ' Added for PrEdit so he can debug; do not use with files larger ' than one cluster (and make that cluster size 32K please.) ' ' Returns -1 on failure. Make sure to check this return code! ' ' We only support reads right now (but writes won"t be too hard to ' add). }} pub seek(pos) | delta if (direntry or pos < 0 or pos > filesize) return -1 delta := (floc - bufend) & - clustersize if (pos < delta) fclust := firstcluster frem := (clustersize) <# (filesize) floc := 0 bufat := 0 bufend := 0 delta := 0 repeat while (pos => delta + clustersize) fclust := nextcluster floc += clustersize delta += clustersize frem := (clustersize) <# (filesize - floc) bufat := 0 bufend := 0 if (bufend == 0 or pos < floc - bufend or pos => floc - bufend + SECTORSIZE) ' must change buffer delta := floc + frem floc := pos & - SECTORSIZE frem := delta - floc pfillbuf bufat := pos & (SECTORSIZE - 1) return 0 pub tell return floc + bufat - bufend pub opendir | off {{ ' Close the currently open file, and set up the read buffer for ' calls to nextfile. }} pclose off := rootdir - (dataregion << SECTORSHIFT) fclust := off >> (clustershift + SECTORSHIFT) floc := off - (fclust << (clustershift + SECTORSHIFT)) frem := rootdirend - rootdir filesize := floc + frem return 0 pub nextfile(fbuf) | i, t, at, lns {{ ' Find the next file in the root directory and extract its ' (8.3) name into fbuf. Fbuf must be sized to hold at least ' 13 characters (8 + 1 + 3 + 1). If there is no next file, ' -1 will be returned. If there is, 0 will be returned. }} repeat if (bufat => bufend) t := pfillbuf if (t < 0) return t if (((floc >> SECTORSHIFT) & ((1 << clustershift) - 1)) == 0) fclust++ at := @buf + bufat if (byte[at] == 0) return -1 bufat += DIRSIZE if (byte[at] <> $e5 and (byte[at][$0b] & $18) == 0) lns := fbuf repeat i from 0 to 10 byte[fbuf] := byte[at][i] fbuf++ if (byte[at][i] <> " ") lns := fbuf if (i == 7 or i == 10) fbuf := lns if (i == 7) byte[fbuf] := "." fbuf++ byte[fbuf] := 0 return 0 {{ ' Utility routines; may be removed. }} pub getclustersize return clustersize pub getclustercount return totclusters {{ ' Permission is hereby granted, free of charge, to any person obtaining ' a copy of this software and associated documentation files ' (the "Software"), to deal in the Software without restriction, ' including without limitation the rights to use, copy, modify, merge, ' publish, distribute, sublicense, and/or sell copies of the Software, ' and to permit persons to whom the Software is furnished to do so, ' subject to the following conditions: ' ' The above copyright notice and this permission notice shall be included ' in all copies or substantial portions of the Software. ' ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ' EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ' MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ' IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ' CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ' TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ' SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }} DAT filesystem long 0 ' 0 = unmounted, 1 = fat16, 2 = fat32 rootdir long 0 ' the byte address of the start of the root directory rootdirend long 0 ' the byte immediately following the root directory. dataregion long 0 ' the start of the data region, offset by two sectors clustershift long 0 ' log base 2 of blocks per cluster clustersize long 0 ' total size of cluster in bytes fat1 long 0 ' the block address of the fat1 space totclusters long 0 ' how many clusters in the volume sectorsperfat long 0 ' how many sectors per fat endofchain long 0 ' end of chain marker (with a 0 at the end) pdate long 0 ' current date lastread long 0 ' the block address of the buf2 contents dirty long 0 ' nonzero if buf2 is dirty buf2 byte 0[SECTORSIZE] ' main metadata buffer padname byte 0[11] ' filename buffer
I made small changes to fsrw, made the mount command work *sometimes?*
The test code I was having problems with is
[code]
CON
{''Hardware version 3.11 - see diagram.
''
}
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000 'with 5mhz crystal
DEV_SD_CLK = 18
DEV_SD_DI = 19
DEV_SD_DO = 20
DEV_SPI_EN = 21 ''SPI Enable enumeration
DEV_SPI_ADD0 = 22 ''Device address 0 enumeration
DEV_SPI_ADD1 = 23 ''Device address 1 enumeration
DEV_SPI_ADD_LE = 24
DEV_SPI_LCD_RES = 0 ''Device id for LCD reset
SDC = 1
TSC = 2
EXT = 3
DEV_SPI_EXT_POT_CS = 0
DEV_SPI_EXT_SW_CS = 1
BGCOLOR = $ffff
TXTCOLOR = $0000
Pressed = 1
NotPressed = 0
faderUpBtnBound = 499 ''y < 499
faderDnBtnBound = 3700 ''y > 3699 3200, 1600, 320
fadertouchoffset = 320 ''3375 < y < 825 range e
offset = 8 * 2048 ' the block offset of where we do writes
VAR
long Screen_Buffer, CRbuffer
byte tbuf[20]
byte bigbuf[8192]
long BackgroundColor, ActiveTextColor, stringptr[65], maxdur,sr ,speedresults
BYTE Fader0[3], Fader1[3], Fader2[3], Fader3[3], FaderPOS, NewFaderValue, OldValue 'FaderOrentation holds 0 for landscape, portrait not enabled
word Button0[5], Button1[5], Button2[5], Button3[5], Button4[5], Button5[5], ButtonX, ButtonY, ButtonState, OldState
WORD NotPressedBGC,NotPressedATC,PressedBGC,PressedATC, ButtonName, ButtonReg 'ButtonGroup,oldButtonGroup,faderOrentation,
OBJ pfw :"PropFont_asmDone"
wait : "timing"
'pst : "parallax serial terminal"
spi : "spi_asm"
sdfat: "fsrw"
block: "safe_spi"
ILI9325:"ILI9325_Dracblade"
PUB BOOT | f 'bootstrap, initalizes pins, then starts pst, init display, start asm, clear screen and display hello world
WAIT.PAUSE1S(5)
initPins
BackgroundColor := $ffe0
ActiveTextColor := %0000
long[@Screen_Buffer] := $ffff