WAIT, er... don't get me wrong, my wife is THE BEST. I'm pretty sure she was just teasing, but there's only one way to find out She's just annoyed because it's going to cost another 20 bucks to get the boe-bot going after spending 50 bucks to start. I don't blame her. I think the real moral of the story is TEST YER OL STUFF B4 ORDERING THE NEW! or something like that.
I tried to get SD3.01_FATEngine working, but had no luck. I'm working on re-writing the demo with FSRW? because it works for me? I've gotten to
filesize := 'fat.filesize
I'm not seeing an easy way to do this so I guess i'll just hardwire it for now?
WAIT, er... don't get me wrong, my wife is THE BEST
It was not my intent to suggest otherwise... I am sure she is. I am just saying, protect your hobby and get it in righting before saying I do, and before she says you don't. Of course I am just teasing.
Scroll test. Dump out the entire memory (filled with random data and some black lines) and scroll up 10 lines each screen. Refresh is 30x a second so this should make for a very responsive text scroll when moving a finger on the touchscreen. Plus animated GIFs will be very smooth.
Just saw this post ... as I already said I also have such a kind of display with another display-controller, but most controllers have similar functions. So, you should maybe read the specs again if your display supports scrolling. Mine does. You simply define where the controller should start with reading lines. This makes scrolling really fast, as you simple redefine screen-start and then update some lines.
My prenup has worked fine after 32 years. I just agree whats mine is hers and hers is hers. Then I say I have ordered whatever. Apart from an external stresser, we have had only 2 serious arguments, and the second (forget the first) was over our then teenage kids swearing in the house. They are now just over and under 30 and very close. Just be honest!
I'm still trying to re-write Dr. Acula's font demo for my hardware and ready to bang my head against the wall. The sd card DO line is interfering with the touchscreen operation, as well as other issues. I don't understand the difference between fsrw and kye's sd card object. Fsrw works, kye's does not.. ?
We must find a workaround. Hmm - there is nothing wrong with older memory chips. They should all work fine and even a 32k one will be enough to hold a couple of fonts. Maybe you might need a few NOPs if they are slower.
Can you post the Kye SD card that is not working? Also, when in doubt, use Windows to reformat the SD card. I presume you are using a FAT32 reformat?
Addit : playing around with a larger board format for the Gadget Gangster. This is a "eurocard" 160x100 mm size which is a default size in Eagle as well.
With DIP chips the boards can get large fairly quickly, especially if you have double memory chips. I'm testing the idea you can have 224 I/O pins on a propeller. So each board can be placed in HiZ. I probably take this a bit too far - there are a few examples in these boards where there are 10k pullups on pins, and I even isolate those so that each board truly can't interfere with another.
The motherboard has the standard GG footprint. You could even use this board completely unpopulated and just use it to expand to the larger size.
The 32 prop pins are brought out to 4 groups of 8 and these are in the corners of the board for mechanical stability when stacking. 4 pins for power. And another group of 8 to select each board (these could have been deleted and each board decoded locally but it adds more components and another stackable header is cheaper).
The motherboard had lots of spare space on it so I filled that up with diagnostic leds but these are not really needed except when debugging circuits.
The Touchscreen board has 1 megabyte of ram and a faster access than previous dracblade designs.
The Dracblade board has 512k of ram and can run independently of the touchscreen. This can be handy for debugging to TV and VGA, but it is mainly there to show this concept is backwards compatible with other designs. There is no reason you could not add a C3 board to the stack, or a Propeller demoboard.
I'm sure with surface mount this could be shrunk down to the smaller GG footprint, and this could well be useful once designs are debugged.
This is all a bit experimental at the moment and there are chips on the board I've never even worked with such as the HC137 and 74HC4316 but hopefully it will all work as designed.
Thanks idbruce. I've been thinking about how to select each board and I think there are some startup conditions where an I2C expander might be better. Also if you use one of the I2C lines to control which board to select, it may conflict with existing I2C chips. So I think it might be better to use a MCP23008.
I'm liking the idea more and more of being able to complete deselect boards and make all the pins HiZ on that board. It means you can mix and match all sorts of previously incompatible boards and code.
Hey Doc, got a question for you. I can't test JDlcd yet, got Cour16 loaded partially. Only lowercase work, no numbers. Have not played with it fully. When I tried using the program you attached, once again no dice. It gives me an io error. I can find it if need be. I'm on win7 but tried compatibility, run as admin. The usual suspects. Any hints?
How about a tap n' drag function that zooms relative to the center of the screen?
E.G.: Touch screen->Raise finger->Touch screen->Drag closer to center to zoom out, farther to zoom in.
Of course it's probably too early in dev to start thinking too much about UI...
What a great idea!
I don't own any apple products but my kids do and I see them using two fingers to shrink and expand things. But the way resistive touchscreens work, you can't look for two presses at the same time. So your tap n drag would work very nicely.
Values are 0-100 x and y. So, thinking this through, you detect the tap, then set a delay loop that maybe times out after a second or two while it looks for the second press.
Then work out if the direction is moving towards or away from the centre. So if the centre is 50,50, then thinking just in the x direction for the moment, you get the x value, subtract 50, take the absolute value to remove the minus sign if it is 0-49, then work out if it is higher or lower than the previous value. Take a few readings and that can work out if the finger is moving. For x and y, distance is the square root of x squared plus y squared. This might be a fun way to use the log and antilog tables that are in the propeller ROM. Actually, that distance formula removes the negative sign so you don't need to to get the absolute value.
So you just take the value, subtract 50 from x and y which moves the coords to a 0,0 centre, then d = (x^2 +y^2) ^0.5 and work out if d is changing.
I *knew* that year 11 math would come in handy one day!
Hey Doc, got a question for you. I can't test JDlcd yet, got Cour16 loaded partially. Only lowercase work, no numbers.
That might be my fault, I think I changed the format of the font files a few times. I can post the latest vb.net code. Or is this the code that you can't get to run?
Not sure which version I am running. I've been wondering about more documentation on font stuffs... I've been playing around for a while and finally got a font to work. Now to check that I didn't break anything. A full pack of SW would be real nice. I've been looking through the different versions. I keep hoping to get up to speed, but you keep leaving me behind.
So you just take the value, subtract 50 from x and y which moves the coords to a 0,0 centre, then d = (x^2 +y^2) ^0.5 and work out if d is changing.
The vast majority of touch-screen gestures use a single axis to function. People have come to expect a single motion to affect the screen in a single way, so 2 axes would seem alien, and could quickly become unwieldy / confusing... Maybe it wasn't as good an idea as I thought it was. :frown: Unless this is just for the hobby community, it's probably not a very good idea to use in your product.
EDIT: If you do use my idea and are going for an Apple product kind of interface, it could zoom relative to the initial tap location.
Dr. Acula,
I love the new board design. I have been working up my own design based off your current design. I'm making some changes due to component availability, and overall system design. The first change I'd be forced to make is to use 373's instead of 573's. This should not affect operation, as they are compatible devices with different pinouts? I have also been thinking about replacing the address latches with 161's. I know I have a couple, but I'm not sure if I have the 4 that I would need for my 256k chips. The SRAM's I have coming are 15ns. I think the limiting factor here will be the interface chips. I will also be using a different option for the ili control latch. Not sure of that yet. I also be using an inverter to control we/RD of the display as well as the we/OE of the ram chip. CS for Ram and Display will be controlled directly by micro, I think.
Any thoughts or advice? Especially about using the 161's for address buffers.
Can I ask about you're use of 244s to isolate the sd and touch? I have them multiplexed together directly and they seem to work ok.
One last thing, about the displays. I am a bit unsure if there is a way to send pixel data without addressing the GRAM write register every time. I have not played with this too much. The datasheet is a bit hard to understand. Any advice about getting a grasp on that?
*edit*
It turns out I have 2x 74ls161a's in inventory. I also have 1x 74hc245 and 1x 74ls245. I'm looking at ordering 2x 74hc245's, and debating picking up 4x 74hc161's. The datasheet I looked @ clocked the ls161A's @ min 20mhz. typ 32mhz. Is this going to be a huge limitation or is it acceptable? Is there a better parallel-load binary counter you can think of?
This is the design I finally sent off to BatchPCB. I also sent off a motherboard, dracblade and a board with a real Z80 on it. I want a stack of boards to test the concept of being able to put a board into HiZ so you can talk to multiple boards with one propeller.
1) I changed 573s to 373s too as I have lots of 373s. 573s are easier to work with on a breadboard but an autorouter doesn't really care.
2) Your sram chips are very fast. Which ones are you using?
3) 161s should work. I used them for a graphics board once. For clocking out a picture a counter is fine but I'd like to use some of the memory for true random access at some point down the track for things like C++ and Catalina.
4) You probably can share lines with the SD and touch as these generally won't be used at the same time. Good thinking.
5) re "I am a bit unsure if there is a way to send pixel data without addressing the GRAM write register every time." - you mean for random pixels? One thing we ought to do is translate the "Draw" routine into pasm for setting up pixels.
6) 161s at 20Mhz should be fine. Isn't that the max propeller frequency anyway?
6) 161s at 20Mhz should be fine. Isn't that the max propeller frequency anyway?
Re, 6. Very true, but I've had thoughts of tying the 161's clk with the Display CE, and OC them somehow...Still.
RE. #2. http://search.digikey.com/us/en/products/CY7C199CN-15PXC/428-2158-5-ND/1206029 @ $1.78? Grabbed these since they were way cheap.
Re. #3. I though about this too. This is why I've set up my 161 clock / Load Enable the way I have. From what I understand, Set Ram load Enable low, Make databus = address, clock low to high, and low.
RE. 5, translating draw into pasm would be fairly easy I think. Same thing with a clear screen. I'm thinking about using LCD COMMAND layer on top of the ram. Make $FF clearscreen and $FE draw? This way, 1 hub address can hold 1- 16 bit command and, 16 bit data?
Thanks for the bump. It ended up "on hold" because average joe above came up with such a clever redesign of the circuit that we needed to start again. He has saved lots of chips (which means more cool stuff can fit on the board) and come up with a design that is going to be around 300x faster than the first design. Refresh a full screen in 30 milliseconds. And it fits on one board instead of a stack of three. So the status as of today is that some new boards are being made and just got an email now saying they started making them. Schematics on average joe's thread. Life is good
Dr_Acula
I am new to propeller chips and wanted to make a project with a TFT. It is nowhere near as complicated as yours but I have no idea where to start. I like the size of the display you're using and have found it online, but the only thing my TFT will be used for is displaying a single (big) character at a time, and no touch interaction or animations. Is the propeller capable of doing this on its own or will the peripheral devices you've used be necessary? Would I be able to do it all in Spin or does the display require programming? My task seems simple (especially compared to your work!) but I know nothing about video drivers or display controllers. Thanks for any advice you might have.
-Brian
For a big single character the TV display might be the best. Three propeller pins, three resistors and code is already written in spin. There are many TV displays sold as "car reversing" screens.
The touchscreen would work but it is more complicated and a lot of the code is too slow at the moment. Hope this helps.
Hey Doc,
Just wanted to give this thread a *BUMP* and see if you've got boards yet. I also wanted to see if you have more recent code. I've downloaded several of the backups you've posted, but only glanced at them. The code I was initially working off was the ILI demo.
Hey Doc, any word on those boards yet?After initial tests of screen and ram passed with flying colors, I started working on writing data AND COMMANDS to the display in ASM from hub address *I think I would like to DIRECTLY be able to pass these, but still deciding how to do that.* I would like the screen working before I start fussing with the ram. I'm hoping to use the screen to debug ram if necessary. I hope it doesn't come to that, but...
Here's what I've got so far. The H/W is slightly different from yours, but pretty close. I believe it's on the previous post of my thread.
DAT
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
' wait for a command (pause short time to reduce power)
pause
' mov ctr, delay wz ' if =0 no pause
' if_nz add ctr, cnt
' if_nz waitcnt ctr, #0 ' wait for a short time (reduces power)
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
' command format "DoCmd(Z,hub_address, unused, length)
cmp cmd, #"Z" wz ' Z moves command to the display from hub address, length times
if_z jmp #hubtodisplayCommand
' data format "DoCmd(Y, hub_address, unused, length)
cmp cmd, #"Y" wz ' Y moves data to the display from hub address, length times
if_z jmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
hubtodisplayData ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
call #ram_open ' gets hubaddr and len (ignores ramaddress) <-----To write from HUB_ADD to screen DIRECTLY, we could pass data by using hubadd to hold the
call #setRShigh ' set pins for data output data,
:hubdisploop rdword Display, hubaddr ' copy word from hub and save a hub instruction here, call the display jump next, and return to start
add hubaddr,#2 ' add 2 to hub address changed for word aligned saving a few instructions?
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisploop ' loop until done
jmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output <-----This would benefit from having a direct passing command, holding 2 words with command and data
rdword Display, hubaddr ' copy word from hub so read long here instead, split high and low words and pass to screen.
add hubaddr,#2 ' add 2 to hub address changed for word aligned saving a few instructions for passing only 1 command.
call #ilidisplayword ' send these bytes to the display
call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word aligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow add zero,#0 wz 'prime z flag
mov dira, DirsEnabled ' set rsHigh by tristate pin
muxz dira, RSpin ' set rsLow by enabling pin
setRslow_ret
ilidisplayword ' pass data out, sends out to the display
add display, p2dpins 'this add presets the data for control pins
mov outa, display 'then make pins = data
'missing strobe LCD WR
ilidisplayword_ret ret
Zero long %00000000_00000000_00000000_00000000 ' for tristating all pins
EnablePin long %00000000_00000010_00000000_00000000
RSPin long %00000000_00000001_00000000_00000000
p2dpins long %00001000_01100010_00000000_00000000 ' propToDisplay $0CE2_0000
PinsInit long %00001001_01100010_00000000_00000000 'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled
DirsDisabled long %00000000_00000000_00000000_00000000
DirsEnabled long %00001001_11100000_11111111_11111111
Display res 1
The original was taken from ILIDemo *I'm pretty sure* I have some other code changed too, but it's all commented out for the most part. Am I heading in the right direction? Any advice? Right about now, I feel like an idiot savant, stumbling my way through something that ?should? be simple.
Glad to hear boards arrived.I have not tested code as it is not quite ready. I believe I'm close but need to run through the loops a few times to make sure things are right, which I'm pretty sure they are not yet. Concentrating on writing to the LCD as it should help with debugging if necessary.
'Starting rewrite for counters using 32k SRAM Breadboard Hardware *see schematic for more info*
' Originally
' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
' and also contains the dracblade ram driver for fast block moves from ram to the display
' Methods:
' .Start = start the driver
' .Draw = start drawing at x1,y1 and continue until x2,y2
' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
con
p_RS = 16 ''PINS FOR CS - TO KEEP FROM FLOATING
p_SPI_EN = 17 'LCD_WR = 17 ''and sd card defs
p_SDataCk = 18 'DEV_SD_CLK = 18
p_SDataIn = 19 'DEV_SD_DI = 19
p_SdataOut = 20 'DEV_SD_DO = 20
p_SPIadd0 = 21 'DEV_SPI_EN = 21
p_SPIadd1 = 22 'DEV_SPI_ADD0 = 22
p_SPIadd2 = 23 'DEV_SPI_ADD1 = 23
p_BusEn = 24 'DEV_SPI_ADD_LE = 24
p_RamRD = 26
p_BusDir = 27
a_SPI_RAM_WR = 0
a_SPI_Load = 1
a_SPI_Count = 2
a_SPI_LCD_WR = 3
a_SPI_TS_CS = 4
a_SPI_SD_CS = 5
a_SPI_EXT_CS = 7
p_unused = 25
a_SPI_unused = 6
a_RamToProp = 0
a_PropToRam = 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
'Ram Allocation table here
RamStart = 0
RamEnd = 32767
OBJ
wait : "timing" ' thanks to parallax
'pst :"Parallax Serial Terminal"
Var
long screenbufferaddress
byte pcog
PUB boot
initPins
'Pst.Start(115200)
START_SSD1289
ClearScreenSpin($ffff)
deadend
PUB RequestSD
PUB ReleaseSD
PUB RequestTS
PUB ReleaseTS
Pub ClearScreenSpin(c)
Draw(0, 0, 240, 320)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat 76800
StrobeLcdWr
TristateDisplayPins
pub deadend
repeat
waitcnt(cnt)
PUB initPins
outa := %00001001_00000010_00000000_00000000
dira := %00001001_11100010_00000000_00000000
PUB Start_SSD1289 ''Init Display
EnableDisplayPins ''enable pins 0 to 15
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
PRI EnableDisplayPins
outa[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111 ' RS, 16 data lines active
outa[p_BusEn] := 0
OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRI TristateDisplayPins ' tristate all pins -
DIRA :=%00000000_00000000_00000000_00000000 ''
PRI LCD_Writ_Bus(V)
OUTA[15..0] := V
StrobeLcdWr ' toggle write pin
PRI Lcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRI Lcd_Write_Data(V)
'RSHigh
LCD_Writ_Bus(V)
PRI RSLow
outa[p_RS] := 0
PRI RSHigh
outa[p_RS] := 1
'
PRI StrobeLcdWr
'outa[p_SPIadd2..p_SPIadd0] := LCD_WR
outa[p_SPI_En] := 0
outa[p_SPI_En] := 1
PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
EnableDisplayPins ' enable pins 0-11
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
Lcd_Write_Data(y1)
Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
Lcd_Write_Data(y2)
Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
Lcd_Write_Data(x1 )
Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
Lcd_Write_Data( y1)
TristateDisplayPins ' tristate pins 0-11 so other drivers can use these pins
PUB Pixel(pixelcolor) ' send out a pixel, high byte then low byte
EnableDisplayPins
Lcd_Write_Com($22) ' enable pins 0-11
Lcd_Write_Data(pixelcolor)
TristateDisplayPins ' tristate pins 0-11 so other drivers can use these pins
PUB ReadRamByte(address) ' masks off all but a byte - used often
docmd("R",@result,address,1) ' read just 1 byte
result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
return result
PUB WriteRamByte(value,address) ' write a byte to ram
docmd("W",@value,address,1)
PUB ReadRamLong(address) ' read a long, stored LSB first
docmd("R",@result,address,4)
return result
PUB WriteRamLong(value,address) ' write a long to ram
docmd("W",@value,address,4)
CON
''Dracblade driver for talking to a ram chip via three latches
'' Modified code from Cluso's triblade
''also includes commands to move blocks of data to the ILI9325 touchscreen display
''Modified for counters by Joe
' DoCmd (command_, hub_address, ram_address, block_length)
' I - initialise
' W - Move block_length bytes from hub_address to ram_address
' R - Move block_length bytes from ram_address to hub_address
' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256)
' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
' E - Set Draw(E, H,Vs,Ve)
' F - Clear Screen(F, color,NA,NA )
VAR
' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
long command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
' command = R, W, H I,D etc =0 when operation completed by cog
' hubaddrs = hub address for data buffer
' ramaddrs = ram address for data ($0000 to $FFFF)
' blocklen = ram buffer length for data transfer
' errx = returns =0 (false=good), else <>0 (true & error code)
' cog = cog no of driver (set by spin start routine)
PUB start_ram : err_
' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
command := "I"
cog := 1 + cognew(@tbp2_start, @command)
if cog == 0
err_ := $FF ' error = no cog
else
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
PUB stop_ram
if cog
cogstop(cog~ - 1)
PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
' Do the command: R, W, N, F, H,I,D
hubaddrs := hub_address ' hub address start
ramaddrs := ram_address ' ram address start
blocklen := block_length ' block length
command := command_ ' must be last !!
' Wait for command to complete and get status
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
DAT
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
' wait for a command (pause short time to reduce power)
pause
' mov ctr, delay wz ' if =0 no pause
' if_nz add ctr, cnt
' if_nz waitcnt ctr, #0 ' wait for a short time (reduces power)
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
' single raw command format "DoCmd(Z,hub_address, unused, length)
cmp cmd, #"Z" wz ' Z moves command to the display from hub address, length times
if_z jmp #hubtodisplayCommand
' single raw command format "DoCmd(Y, hub_address, unused, length)
cmp cmd, #"Y" wz ' Y moves data to the display from hub address, length times
if_z jmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
hubtodisplayData ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
call #ram_open ' gets hubaddr and len (ignores ramaddress)
call #setRShigh ' set pins for data output
:hubdisploop rdword Display, hubaddr ' copy word from hub, not needed ?
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisploop ' loop until done
jmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow add zero,#0 wz 'prime z flag
mov dira, DirsEnabled ' set rsHigh by tristate pin
muxz dira, RSpin ' set rsLow by enabling pin
setRslow_ret
ilidisplayword ' pass data out, sends out to the display
add display, p2dpins wz 'this add presets the data for control pins and primes WZ flag for mux operation
mov outa, display 'then make pins = data
muxnz dira,EnablePin 'make enable pin high
add timeout, #$f
:wait djnz timeout, #:wait
muxz dira, EnablePin
'missing strobe lcd enable
ilidisplayword_ret ret
' cmp cmd, #"E" wz
' if_z jmp #SetDraw
' cmp cmd, #"F" wz
' if_z jmp #ClearScreen
' cmp cmd, #"R" wz ' R = read block from external ram to hub
' if_z jmp #rdblock
' cmp cmd, #"W" wz ' W = write block from hub to external ram
' if_z jmp #wrblock
' cmp cmd, #"C" wz ' C moves a block of data from ram to the display
' if_z jmp #extramtodisplay
'
' cmp cmd, #"A" wz ' A moves 256 bytes from hub to external ram
' if_z jmp #blockhubtoram
' cmp cmd, #"B" wz ' B moves 256 bytes from external ram to hub
' if_z jmp #blockramtohub
' cmp cmd, #"E" wz ' convert 3 byte .raw format to 2 byte .ili format - hub to hub
' if_z jmp #rawtoiliformat
' cmp cmd, #"F" wz ' draw a transparent icon, pass two locations in hub ram and len = number of pixels
' if_z jmp #drawicon
' cmp cmd, #"I" wz ' init
' if_z jmp #init
' mov err, cmd ' error = cmd (unknown command)
' jmp #done
SetDraw
ret
ClearScreen
ret
' set all latches (replaces H command), pass value in third variable of the DoCmd
'setlatches call #ram_open ' gets address value in 'address'
' call #lowmiddlehighlatch ' set all the latches
' jmp #init
'---------------------------------------------------------------------------------------------------------
'Memory Access Functions
' read block from external ram to hub
'rdblock call #ram_open ' get variables from hub variables
'rdloop call #read_byte ' read byte from address into data_8
' wrbyte data_8,hubaddr ' write data_8 to hubaddr ie copy byte to hub
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' djnz len,#rdloop ' loop until done
' jmp #init ' reinitialise
' write block from hub to external ram
'wrblock call #ram_open
'wrloop rdbyte data_8, hubaddr ' copy byte from hub
' call #write_byte ' write byte from data_8 to address
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' djnz len,#wrloop ' loop until done
' jmp #init ' reinitialise
'read_byte call #lowmiddlehighlatch ' set up latches
' call #read_memory_byte ' read a byte into data_8
'read_byte_ret ret
'________________________________________TODO
'read_memory_byte mov dira,LatchDirection2 ' for reads so P0-P7 tristate till do read
' mov outa,GateHigh ' actually ReadEnable but they are the same
' andn outa,GateHigh ' set gate low
' nop ' short delay to stabilise
' nop
' mov data_8, ina ' read SRAM
' and data_8, #$FF ' extract 8 bits
' or outa,GateHigh ' set the gate high again
'read_memory_byte_ret ret
'write_byte call #lowmiddlehighlatch ' set up latches
' call #write_memory_byte
'write_byte_ret ret
'
'write_memory_byte mov outx,data_8 ' get the byte to output
' and outx, #$FF ' ensure upper bytes=0
' or outx,WriteEnable ' or with correct 138 address
' mov outa,outx ' send it out
' andn outa,GateHigh ' set gate low
' nop ' no nop doesn't work, one does, so put in two to be sure
' nop ' another NOP
' or outa,GateHigh ' set it high again
'write_memory_byte_ret ret
'LowMiddleHighLatch ' sets up the ram latches.
' call #lowlatchout
' call #middlelatchout
' call #highlatchout
'LowMiddleHighLatch_ret ret
' write to low, middle and high latches as subroutines. Pass 'ramaddr' which is a long. Extract xxxxxxxx_HHHHHHHH_MMMMMMMM_LLLLLLLL
'LowLatchOut mov outx,ramaddr ' get the address into a temp variable
' and outx,#$FF ' mask the low byte
' or outx,LowAddress ' or with 138 low address
' call #LatchOutput
'LowLatchOut_ret ret
'MiddleLatchOut mov outx,ramaddr ' middle byte get the address into a temp variable
' shr outx,#8 ' shift right by 8 places
' and outx,#$FF ' mask the low byte
' or outx,MiddleAddress ' or with 138 middle address
' call #LatchOutput
'MiddleLatchOut_ret ret
'HighLatchOut mov outx,ramaddr ' middle byte get the address into a temp variable
' shr outx,#16 ' shift right by 16 places
' and outx,#$FF ' mask the low byte
' or outx,HighAddress ' or with 138 high address
' call #LatchOutput
'HighLatchOut_ret ret
'LatchOutput mov dira,LatchDirection ' set up the pins for programming latch chips
' mov outa,outx ' send it out
' andn outa,GateHigh ' set gate low nop not needed
' or outa,GateHigh ' set it high again
'LatchOutput_ret ret
'
' ** move a block of 256 bytes from hub to external ram **
'Blockhubtoram call #ram_open ' get variables from hub variables
' call #lowmiddlehighlatch ' set all three latches
' mov len,#256 ' do 256 times
'Blockhubtoram_loop
' rdbyte data_8, hubaddr ' copy byte from hub
' call #write_memory_byte ' send out to the ram
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' call #lowlatchout ' update the low latch
' djnz len,#blockhubtoram_loop ' loop until done
' jmp #init ' restart
' ** move a block of 256 bytes from external ram to hub **
'Blockramtohub call #ram_open ' get variables from hub variables
' call #lowmiddlehighlatch ' set all three latches
' mov len,#256 ' do 256 times
'Blockramtohub_loop
' call #read_memory_byte ' read byte from address into data_8
' wrbyte data_8,hubaddr ' write data_8 to hubaddr ie copy byte to hub
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' call #lowlatchout ' update the low latch
' djnz len,#blockramtohub_loop ' loop until done
' jmp #init ' restart
'
'extramtodisplay ' send a block of data blocklen from external memory ramaddress to the ILI9325 display
' call #ram_open ' gets ramaddr and len (ignore hubaddr)
' shr len,#1 ' len /2 as 2 bytes per pixel
' call #setRShigh ' set pins for data output
'ililoop call #readiliword ' read ilihigh, ililow, increments ramaddr by 2
' call #ilidisplayword ' sends ilihigh ililow to the display
' djnz len,#ililoop ' loop until done
' jmp #init ' set pins to tristate
'readiliword ' read ilihigh and ililow from ramaddr, increments ramaddr by 2
' call #read_byte ' read byte from ramaddr into data_8
' mov dira,latchdirection ' enable for output (readmemorybyte leaves P0-P7 as inputs)
' mov ilihigh,data_8
' add ramaddr,#1 ' add 1 to ram address
' call #read_byte ' read second byte from address into data_8
' mov dira,latchdirection ' enable for output (readmemorybyte leaves P0-P7 as inputs)
' mov ililow,data_8
' add ramaddr,#1 ' add 1 to ram address
'readiliword_ret ret
'
'RawtoILIformat ' 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
' call #ram_open ' gets hubaddress, ramaddress and len (ignores ramaddress)
'rawloop
' rdbyte red,hubaddr
' add hubaddr,#1
' rdbyte green,hubaddr
' add hubaddr,#1
' rdbyte blue,hubaddr
' add hubaddr,#1
' call #rgbtoili
' wrbyte ilihigh,ramaddr
' add ramaddr,#1
' wrbyte ililow,ramaddr
' add ramaddr,#1
' djnz len,#rawloop ' loop until done
' jmp #init ' set pins to tristate
'RGBtoILI ' pass red,green, blue, returns ililow and ilihigh
' shr red,#3 ' 000RRRRR
' shl red,#3 ' RRRRR000
' shr green,#2 ' 00GGGGGG
' mov ilihigh,green ' ilihigh = 00GGGGGG
' shr ilihigh,#3 ' ilihigh = 00000GGG
' or ilihigh,red ' ilihigh = RRRRRGGG
' and green,#%00000111 ' 00000GGG
' shl green,#5 ' GGG00000
' mov ililow,green ' ililow = GGG00000
' shr blue,#3 ' blue = 000BBBBB
' or ililow,blue ' ililow = GGGBBBBB
'RGBtoILI_ret ret
'ILItoRGB ' pass ilihigh RRRRRGGG and ililow GGGBBBBB returns RRRRR000 GGGGGG00 BBBBB000
' mov red,ilihigh ' red = RRRRRGGG
' and red,#%11111000 ' red = RRRRR000
' mov green,ilihigh ' green = RRRRRGGG
' shl green,#5 ' green = GGG00000
' mov i,ililow ' i = GGGBBBBB
' and i,#%11100000 ' i = GGG00000
' shr i,#3 ' i = 000GGG00
' or green,i ' green = GGGGGG00
' mov blue,ililow ' blue = GGGBBBBB
' shl blue,#3 ' blue = BBBBB000
'ILItoRGB_ret ret
'DrawIcon ' pass hubaddr, ramaddr and len.
' hubaddr is location in ram of the picture (messy naming of the variable)
' ramaddr is the location in ram of the mask (both sources are ram, not hub)
' format of the picture is 2 bytes RRRRRGGG GGGBBBBB
' ' format of the icon is R G B A and A = 0 for transparent and 255 for full opaque (transparent usually round the edges)
' call #ram_open ' gets hubaddr, ramaddr and len
' mov backgroundcount,hubaddr ' backgroundcount is the picture
' mov iconcount,ramaddr ' iconcount is the icon
'drawiconloop mov ramaddr,backgroundcount ' address for reading the picture
' call #readiliword ' get ilihigh and ililow RRRRRGGG GGGBBBBB
' mov backgroundcount,ramaddr ' store new picture counter
' call #ilitoRGB ' convert to red green blue
' mov ramaddr,iconcount ' get icon location
' call #readiliword ' returns ilihigh and ililow which are actually red and green
' mov r,ilihigh ' get red
' mov g,ililow ' get green
' call #readiliword ' returns ilihigh and ililow which are actually blue and alpha
' mov b,ilihigh ' get blue
' mov a,ililow ' get alpha
' mov iconcount,ramaddr ' restore the icon pointer
' cmp a,#128 wc ' test if background or foreground
' if_c jmp #drawiconfinish ' if carry then this is background
' mov red,r ' move icon to foreground
' mov green,g
' mov blue,b
'drawiconfinish call #rgbtoili ' convert to ililow and ilihigh
' call #ilidisplayword ' send out to the display
' djnz len,#drawiconloop ' loop len times until finished
' jmp #init ' set pins to tristate
delay long 80 ' waitcnt delay to reduce power (#80 = 1uS approx)
ctr long 0 ' used to pause execution (lower power use) & byte counter
'GateHigh long %00000000_00000000_00000001_00000000 ' HC138 gate high, all others must be low
'Outx long 0 ' for temp use, same as n in the spin code
'LatchDirection long %00000000_00000000_00001111_11111111 ' 138 active, gate active and 8 data lines active
'LatchDirection2 long %00000000_00000000_00001111_00000000 ' for reads so data lines are tristate till the read
'LowAddress long %00000000_00000000_00000101_00000000 ' low address latch = xxxx010x and gate high xxxxxxx1
'MiddleAddress long %00000000_00000000_00000111_00000000 ' middle address latch = xxxx011x and gate high xxxxxxx1
'HighAddress long %00000000_00000000_00001001_00000000 ' high address latch = xxxx100x and gate high xxxxxxx1
'ReadEnable long %00000000_00000000_00000001_00000000 ' /RD = xxxx000x and gate high xxxxxxx1
' commented out as the same as GateHigh
Zero long %00000000_00000000_00000000_00000000 ' for tristating all pins
data_8 long 0 ' so code compatability with zicog driver
i long 0 ' general purpose value
j long 0 ' general purpose value
a long 0 ' general purpose value
b long 0 ' general purpose value
r long 0 ' general purpose value
g long 0 ' general purpose value
' variables and constants for the ILI9325 display
'Latch5address long %00000000_00000000_00001011_00000000 ' latch5 address
'Latch6address long %00000000_00000000_00001101_00000000 ' latch6 address
'Latch7data long %00000000_00000000_00001111_00010111 ' latch7 address 111x and gate high, reset high, cs low, read high, write high, rs high for data output, combines rshigh in spin into one line
'Latch7WriteLow long %00000000_00000000_00001111_00010101 ' cs low, write low
'ililow long 0 ' low data byte latch5
'ilihigh long 0 ' high data byte latch6
'red long 0 ' red, green blue variables
'green long 0
'blue long 0
'backgroundcount long 0
'iconcount long 0
lowWordMask long $0000_ffff
'pin settings
EnablePin long %00000000_00000010_00000000_00000000
RSPin long %00000000_00000001_00000000_00000000
p2dpins long %00001000_01100000_00000000_00000000 ' propToDisplay enable pin low, but tristate, primed for lcd transfer
PinsInit long %00001001_01100010_00000000_00000000 'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high
DirsDisabled long %00000000_00000000_00000000_00000000
DirsEnabled long %00001001_11100000_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
timeout res 1
Display res 1
fit
This is where I'm at so far. Notice large portions of the code are commented out. I believe the spin portion should still work. The rest is a work in progress. I'll keep you updated as i go.
*edit*
Please remember I am using DIRA to control RS pin and ENABLE pin in ASM since I have pullup resistors on these pins!
I got it! ASM now transfers data from hub to display. It's VERY quick using a 16 block buffer.
'Starting rewrite for counters using 32k SRAM Breadboard Hardware *see schematic for more info*
' Originally
' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
' and also contains the dracblade ram driver for fast block moves from ram to the display
' Methods:
' .Start = start the driver
' .Draw = start drawing at x1,y1 and continue until x2,y2
' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
CON
_xinfreq = 5_000_000
_clkmode = xtal1 + pll16x
p_RS = 16 ''PINS FOR CS - TO KEEP FROM FLOATING
p_SPI_EN = 17 'LCD_WR = 17 ''and sd card defs
p_SDataCk = 18 'DEV_SD_CLK = 18
p_SDataIn = 19 'DEV_SD_DI = 19
p_SdataOut = 20 'DEV_SD_DO = 20
p_SPIadd0 = 21 'DEV_SPI_EN = 21
p_SPIadd1 = 22 'DEV_SPI_ADD0 = 22
p_SPIadd2 = 23 'DEV_SPI_ADD1 = 23
p_BusEn = 24 'DEV_SPI_ADD_LE = 24
p_RamRD = 26
p_BusDir = 27
a_SPI_RAM_WR = 0
a_SPI_Load = 1
a_SPI_Count = 2
a_SPI_LCD_WR = 3
a_SPI_TS_CS = 4
a_SPI_SD_CS = 5
a_SPI_EXT_CS = 7
p_unused = 25
a_SPI_unused = 6
a_RamToProp = 0
a_PropToRam = 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
'Ram Allocation table here
RamStart = 0
RamEnd = 32767
ScreenBufferSize = 16
OBJ
wait : "timing" ' thanks to parallax
'pst :"Parallax Serial Terminal"
Var
long screenbufferaddress
long screen[ScreenBufferSize]
byte pcog
PUB boot
initPins
'Pst.Start(115200)
START_SSD1289
ClearScreenSpin($ffff)
start_ram
longfill(@screen, 0, 16)
repeat (76800 / 16)
DoCmd("Y", @screen,-1, 16)
'wait.pause10us(100)
deadend
PUB RequestSD
PUB ReleaseSD
PUB RequestTS
PUB ReleaseTS
Pub ClearScreenSpin(c)
Draw(0, 0, 239, 319)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat 76800
StrobeLcdWr
TristateDisplayPins
pub deadend
repeat
waitcnt(cnt)
PUB initPins
outa := %00001001_00000010_00000000_00000000
dira := %00001001_11100010_00000000_00000000
PUB Start_SSD1289 ''Init Display
EnableDisplayPins ''enable pins 0 to 15
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
PRI EnableDisplayPins
outa[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111 ' RS, 16 data lines active
outa[p_BusEn] := 0
OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRI TristateDisplayPins ' tristate all pins -
DIRA :=%00000000_00000000_00000000_00000000 ''
PRI LCD_Writ_Bus(V)
OUTA[15..0] := V
StrobeLcdWr ' toggle write pin
PRI Lcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRI Lcd_Write_Data(V)
'RSHigh
LCD_Writ_Bus(V)
PRI RSLow
outa[p_RS] := 0
PRI RSHigh
outa[p_RS] := 1
'
PRI StrobeLcdWr
'outa[p_SPIadd2..p_SPIadd0] := LCD_WR
outa[p_SPI_En] := 0
outa[p_SPI_En] := 1
PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
EnableDisplayPins ' enable pins 0-11
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
Lcd_Write_Data(y1)
Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
Lcd_Write_Data(y2)
Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
Lcd_Write_Data(x1 )
Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
Lcd_Write_Data( y1)
TristateDisplayPins ' tristate pins 0-11 so other drivers can use these pins
PUB Pixel(pixelcolor) ' send out a pixel, high byte then low byte
EnableDisplayPins
Lcd_Write_Com($22) ' enable pins 0-11
Lcd_Write_Data(pixelcolor)
TristateDisplayPins ' tristate pins 0-11 so other drivers can use these pins
'PUB ReadRamByte(address) ' masks off all but a byte - used often
' docmd("R",@result,address,1) ' read just 1 byte
' result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
' return result
'PUB WriteRamByte(value,address) ' write a byte to ram
' docmd("W",@value,address,1)
'
'PUB ReadRamLong(address) ' read a long, stored LSB first
' docmd("R",@result,address,4)
' return result
'
'PUB WriteRamLong(value,address) ' write a long to ram
' docmd("W",@value,address,4)
'
'
CON
''Dracblade driver for talking to a ram chip via three latches
'' Modified code from Cluso's triblade
''also includes commands to move blocks of data to the ILI9325 touchscreen display
''Modified for counters by Joe
' DoCmd (command_, hub_address, ram_address, block_length)
' I - initialise
' W - Move block_length bytes from hub_address to ram_address
' R - Move block_length bytes from ram_address to hub_address
' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256)
' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
' E - Set Draw(E, H,Vs,Ve)
' F - Clear Screen(F, color,NA,NA )
' Y - moves data to the display from hub address, length times
' Z - moves command to the display from hub address, length times
VAR
' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
long command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
' command = R, W, H I,D etc =0 when operation completed by cog
' hubaddrs = hub address for data buffer
' ramaddrs = ram address for data ($0000 to $FFFF)
' blocklen = ram buffer length for data transfer
' errx = returns =0 (false=good), else <>0 (true & error code)
' cog = cog no of driver (set by spin start routine)
PUB start_ram : err_
' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
command := "I"
cog := 1 + cognew(@tbp2_start, @command)
if cog == 0
err_ := $FF ' error = no cog
else
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
PUB stop_ram
if cog
cogstop(cog~ - 1)
PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
' Do the command: R, W, N, F, H,I,D
hubaddrs := hub_address ' hub address start
ramaddrs := ram_address ' ram address start
blocklen := block_length ' block length
command := command_ ' must be last !!
' Wait for command to complete and get status
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
DAT
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
' wait for a command (pause short time to reduce power)
pause
' mov ctr, delay wz ' if =0 no pause
' if_nz add ctr, cnt
' if_nz waitcnt ctr, #0 ' wait for a short time (reduces power)
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
' single raw command format "DoCmd(Z,hub_address, unused, length)
cmp cmd, #"Z" wz ' Z moves command to the display from hub address, length times
if_z jmp #hubtodisplayCommand
' single raw command format "DoCmd(Y, hub_address, unused, length)
cmp cmd, #"Y" wz ' Y moves data to the display from hub address, length times
if_z jmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
hubtodisplayData ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
call #ram_open ' gets hubaddr and len (ignores ramaddress)
call #setRShigh ' set pins for data output
:hubdisploop rdword Display, hubaddr ' copy word from hub, not needed ?
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisploop ' loop until done
jmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow mov dira, DirsEnabled wz ' set rsHigh by tristate pin
muxnz dira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the display
add display, p2dpins wz 'this add presets the data for control pins and primes WZ flag for mux operation
mov outa, display 'then make pins = data
muxnz dira,EnablePin 'make enable pin high
mov timeout, #$8 'set wait period
:wait djnz timeout, :wait 'and wait
muxz dira, EnablePin
ilidisplayword_ret ret
Zero long %00000000_00000000_00000000_00000000
EnablePin long %00000000_00000010_00000000_00000000
RSPin long %00000000_00000001_00000000_00000000
p2dpins long %00001000_01100000_00000000_00000000 ' propToDisplay enable pin low, but tristate, primed for lcd transfer
PinsInit long %00001001_01100010_00000000_00000000 'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high
DirsDisabled long %00000000_00000000_00000000_00000000
DirsEnabled long %00001001_11100000_11111111_11111111
timeout res 1
Display res 1
fit
I will be working on command passing, and then get the RAM up. Should not be as hard as I'm making it.
*edit*
I plan on ordering your display in the near future. I will also be ordering your SRAM's and more 161s. I'm trying to decide if I should just order 2, and get some sockets, or get 6 and not worry about the sockets right now. RAM, Prop, EEPROM and 3232 will get sockets. Still up in the air about the counters.
*edited again!*
Something is wrong with this code. IT DOES NOT fill the screen? Even the SPIN code doesn't completely fill the screen? Must have something set wrong some where.
And I figured it out. Had draw set to 320*240.... DUH fixed in post
I've done some more work, and imported my propFont reader for debugging.
'Starting rewrite for counters using 32k SRAM Breadboard Hardware *see schematic for more info*
' Originally
' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
' and also contains the dracblade ram driver for fast block moves from ram to the display
' Methods:
' .Start = start the driver
' .Draw = start drawing at x1,y1 and continue until x2,y2
' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
CON
_xinfreq = 5_000_000
_clkmode = xtal1 + pll16x
p_RS = 16 ''PINS FOR CS - TO KEEP FROM FLOATING
p_SPI_EN = 17 'LCD_WR = 17 ''and sd card defs
p_SDataCk = 18 'DEV_SD_CLK = 18
p_SDataIn = 19 'DEV_SD_DI = 19
p_SdataOut = 20 'DEV_SD_DO = 20
p_SPIadd0 = 21 'DEV_SPI_EN = 21
p_SPIadd1 = 22 'DEV_SPI_ADD0 = 22
p_SPIadd2 = 23 'DEV_SPI_ADD1 = 23
p_BusEn = 24 'DEV_SPI_ADD_LE = 24
p_RamRD = 26
p_BusDir = 27
a_SPI_RAM_WR = 0
a_SPI_Load = 1
a_SPI_Count = 2
a_SPI_LCD_WR = 3
a_SPI_TS_CS = 4
a_SPI_SD_CS = 5
a_SPI_EXT_CS = 7
p_unused = 25
a_SPI_unused = 6
a_RamToProp = 0
a_PropToRam = 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
'Ram Allocation table here
RamStart = 0
RamEnd = 32767
ScreenBufferSize = 16
OBJ
wait : "timing" ' thanks to parallax
Cr :"crReader"
num : "numbers"
pst :"Parallax Serial Terminal"
Var
long screenbufferaddress
word screen[16], BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2
byte Fontsize, pcog
PUB boot | x
initalize
'HelloWorld
'enableDisplayPins
' lcd_write_com($22)
'TristateDisplayPins
' repeat x from 0 to $FFFF
' pixel(x)
setChar(0, 0, 0, 0,$FFFF, 0)
setfontsize(1)
repeat x from 0 to 255
char(x)
deadend
PUB HelloWorld
setfontsize(1)
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")
pub pixel(p)
word[@screen] := p
DoCmd("Y", @screen,-1, 1)
'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 setFontSize(s)
fontsize := s
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 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)
Draw(x1,y1,x2,y2)
'EnableDisplayPins
word[@screen] := $22
DoCmd("Z",@screen, -1,1)
'TristateDisplayPins
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)
pixel(ActiveTextColor)
else
pixel(BackgroundColor)
'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 ClearScreenSpin(c)
Draw(0, 0, 239, 319)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat 76800
StrobeLcdWr
TristateDisplayPins
pub deadend
repeat
waitcnt(cnt)
PUB initalize
outa := %00001001_00000010_00000000_00000000
dira := %00001001_11100010_00000000_00000000
Pst.Start(115200)
START_SSD1289
ClearScreenSpin($ffff)
start_ram
wordfill(@screen, 0, 16)
repeat (76800 / 16)
DoCmd("Y", @screen,-1, 16)
'PUB StartPF 'Method to Init display, then load a cog with screen driver
cr.Start
num.init
PUB Start_SSD1289 ''Init Display
EnableDisplayPins ''enable pins 0 to 15
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
PUB SpinPixel(p)
EnableDisplayPins
Lcd_Write_Data(p)
TristateDisplayPins
PRI EnableDisplayPins
outa[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111 ' RS, 16 data lines active
outa[p_BusEn] := 0
OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRI TristateDisplayPins ' tristate all pins -
DIRA :=%00000000_00000000_00000000_00000000 ''
PRI LCD_Writ_Bus(V)
OUTA[15..0] := V
StrobeLcdWr ' toggle write pin
PRI Lcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRI Lcd_Write_Data(V)
'RSHigh
LCD_Writ_Bus(V)
PRI RSLow
outa[p_RS] := 0
PRI RSHigh
outa[p_RS] := 1
'
PRI StrobeLcdWr
'outa[p_SPIadd2..p_SPIadd0] := LCD_WR
outa[p_SPI_En] := 0
outa[p_SPI_En] := 1
PUB DrawASM(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
word[@screen][0] := REG_HORIZONTALRAMADDRESSPOS
word[@screen][1] := HORIZONTALRAMADDRESSPOS
word[@screen][2] := REG_VERTICALRAMADDRESSSTART
word[@screen][3] := y1
word[@screen][4] := REG_VERTICALRAMADDRESSEND
word[@screen][5] := y2
word[@screen][6] := REG_SETGDDRxADDRESSCOUNTER
word[@screen][7] := x1
word[@screen][8] := REG_SETGDDRyADDRESSCOUNTER
word[@screen][9] := y1
DoCmd("Z", @screen, -1, 10)
PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
EnableDisplayPins ' enable pins 0-11
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
Lcd_Write_Data(y1)
Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
Lcd_Write_Data(y2)
Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
Lcd_Write_Data(x1 )
Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
Lcd_Write_Data(y1)
TristateDisplayPins ' tristate pins 0-11 so other drivers can use these pins
'PUB ReadRamByte(address) ' masks off all but a byte - used often
' docmd("R",@result,address,1) ' read just 1 byte
' result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
' return result
'PUB WriteRamByte(value,address) ' write a byte to ram
' docmd("W",@value,address,1)
'
'PUB ReadRamLong(address) ' read a long, stored LSB first
' docmd("R",@result,address,4)
' return result
'
'PUB WriteRamLong(value,address) ' write a long to ram
' docmd("W",@value,address,4)
'
'
CON
''Dracblade driver for talking to a ram chip via three latches
'' Modified code from Cluso's triblade
''also includes commands to move blocks of data to the ILI9325 touchscreen display
''Modified for counters by Joe
' DoCmd (command_, hub_address, ram_address, block_length)
' I - initialise
' W - Move block_length bytes from hub_address to ram_address
' R - Move block_length bytes from ram_address to hub_address
' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256)
' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
' E - Set Draw(E, H,Vs,Ve)
' F - Clear Screen(F, color,NA,NA )
' Y - moves data to the display from hub address, length times
' Z - moves command to the display from hub address, length times
VAR
' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
long command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
' command = R, W, H I,D etc =0 when operation completed by cog
' hubaddrs = hub address for data buffer
' ramaddrs = ram address for data ($0000 to $FFFF)
' blocklen = ram buffer length for data transfer
' errx = returns =0 (false=good), else <>0 (true & error code)
' cog = cog no of driver (set by spin start routine)
PUB start_ram : err_
' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
command := "I"
cog := 1 + cognew(@tbp2_start, @command)
if cog == 0
err_ := $FF ' error = no cog
else
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
PUB stop_ram
if cog
cogstop(cog~ - 1)
PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
' Do the command: R, W, N, F, H,I,D
hubaddrs := hub_address ' hub address start
ramaddrs := ram_address ' ram address start
blocklen := block_length ' block length
command := command_ ' must be last !!
' Wait for command to complete and get status
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
' wait for a command (pause short time to reduce power)
pause
' mov ctr, delay wz ' if =0 no pause
' if_nz add ctr, cnt
' if_nz waitcnt ctr, #0 ' wait for a short time (reduces power)
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
' single raw command format "DoCmd(Z,hub_address, unused, length)
cmp cmd, #"Z" wz ' Z moves command to the display from hub address, length times
if_z jmp #hubtodisplayCommand
' single raw command format "DoCmd(Y, hub_address, unused, length)
cmp cmd, #"Y" wz ' Y moves data to the display from hub address, length times
if_z jmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
hubtodisplayData ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
call #ram_open ' gets hubaddr and len (ignores ramaddress)
call #setRShigh ' set pins for data output
:hubdisploop rdword Display, hubaddr ' copy word from hub, not needed ?
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisploop ' loop until done
jmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:data ' loop until done
jmp #init ' set pins to tristate
:data call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov outa, PinsInit
mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow mov outa, PinsInit
mov dira, DirsEnabled wz ' set rsHigh by tristate pin
muxnz dira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the display
add Display, p2dpins wz 'this add presets the data for control pins and primes WZ flag for mux operation
mov outa, Display 'then make pins = data
muxz dira,EnablePin 'make enable pin low
mov timeout, #$f 'set wait period
:wait1 djnz timeout, :wait1 'and wait
muxnz dira, EnablePin 'make enable pin high
ilidisplayword_ret ret
' cmp cmd, #"E" wz
' if_z jmp #SetDraw
' cmp cmd, #"F" wz
' if_z jmp #ClearScreen
' cmp cmd, #"R" wz ' R = read block from external ram to hub
' if_z jmp #rdblock
' cmp cmd, #"W" wz ' W = write block from hub to external ram
' if_z jmp #wrblock
' cmp cmd, #"C" wz ' C moves a block of data from ram to the display
' if_z jmp #extramtodisplay
'
' cmp cmd, #"A" wz ' A moves 256 bytes from hub to external ram
' if_z jmp #blockhubtoram
' cmp cmd, #"B" wz ' B moves 256 bytes from external ram to hub
' if_z jmp #blockramtohub
' cmp cmd, #"E" wz ' convert 3 byte .raw format to 2 byte .ili format - hub to hub
' if_z jmp #rawtoiliformat
' cmp cmd, #"F" wz ' draw a transparent icon, pass two locations in hub ram and len = number of pixels
' if_z jmp #drawicon
' cmp cmd, #"I" wz ' init
' if_z jmp #init
' mov err, cmd ' error = cmd (unknown command)
' jmp #done
SetDraw
ret
ClearScreen
ret
' set all latches (replaces H command), pass value in third variable of the DoCmd
'setlatches call #ram_open ' gets address value in 'address'
' call #lowmiddlehighlatch ' set all the latches
' jmp #init
'---------------------------------------------------------------------------------------------------------
'Memory Access Functions
' read block from external ram to hub
'rdblock call #ram_open ' get variables from hub variables
'rdloop call #read_byte ' read byte from address into data_8
' wrbyte data_8,hubaddr ' write data_8 to hubaddr ie copy byte to hub
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' djnz len,#rdloop ' loop until done
' jmp #init ' reinitialise
' write block from hub to external ram
'wrblock call #ram_open
'wrloop rdbyte data_8, hubaddr ' copy byte from hub
' call #write_byte ' write byte from data_8 to address
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' djnz len,#wrloop ' loop until done
' jmp #init ' reinitialise
'read_byte call #lowmiddlehighlatch ' set up latches
' call #read_memory_byte ' read a byte into data_8
'read_byte_ret ret
'________________________________________TODO
'read_memory_byte mov dira,LatchDirection2 ' for reads so P0-P7 tristate till do read
' mov outa,GateHigh ' actually ReadEnable but they are the same
' andn outa,GateHigh ' set gate low
' nop ' short delay to stabilise
' nop
' mov data_8, ina ' read SRAM
' and data_8, #$FF ' extract 8 bits
' or outa,GateHigh ' set the gate high again
'read_memory_byte_ret ret
'write_byte call #lowmiddlehighlatch ' set up latches
' call #write_memory_byte
'write_byte_ret ret
'
'write_memory_byte mov outx,data_8 ' get the byte to output
' and outx, #$FF ' ensure upper bytes=0
' or outx,WriteEnable ' or with correct 138 address
' mov outa,outx ' send it out
' andn outa,GateHigh ' set gate low
' nop ' no nop doesn't work, one does, so put in two to be sure
' nop ' another NOP
' or outa,GateHigh ' set it high again
'write_memory_byte_ret ret
'LowMiddleHighLatch ' sets up the ram latches.
' call #lowlatchout
' call #middlelatchout
' call #highlatchout
'LowMiddleHighLatch_ret ret
' write to low, middle and high latches as subroutines. Pass 'ramaddr' which is a long. Extract xxxxxxxx_HHHHHHHH_MMMMMMMM_LLLLLLLL
'LowLatchOut mov outx,ramaddr ' get the address into a temp variable
' and outx,#$FF ' mask the low byte
' or outx,LowAddress ' or with 138 low address
' call #LatchOutput
'LowLatchOut_ret ret
'MiddleLatchOut mov outx,ramaddr ' middle byte get the address into a temp variable
' shr outx,#8 ' shift right by 8 places
' and outx,#$FF ' mask the low byte
' or outx,MiddleAddress ' or with 138 middle address
' call #LatchOutput
'MiddleLatchOut_ret ret
'HighLatchOut mov outx,ramaddr ' middle byte get the address into a temp variable
' shr outx,#16 ' shift right by 16 places
' and outx,#$FF ' mask the low byte
' or outx,HighAddress ' or with 138 high address
' call #LatchOutput
'HighLatchOut_ret ret
'LatchOutput mov dira,LatchDirection ' set up the pins for programming latch chips
' mov outa,outx ' send it out
' andn outa,GateHigh ' set gate low nop not needed
' or outa,GateHigh ' set it high again
'LatchOutput_ret ret
'
' ** move a block of 256 bytes from hub to external ram **
'Blockhubtoram call #ram_open ' get variables from hub variables
' call #lowmiddlehighlatch ' set all three latches
' mov len,#256 ' do 256 times
'Blockhubtoram_loop
' rdbyte data_8, hubaddr ' copy byte from hub
' call #write_memory_byte ' send out to the ram
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' call #lowlatchout ' update the low latch
' djnz len,#blockhubtoram_loop ' loop until done
' jmp #init ' restart
' ** move a block of 256 bytes from external ram to hub **
'Blockramtohub call #ram_open ' get variables from hub variables
' call #lowmiddlehighlatch ' set all three latches
' mov len,#256 ' do 256 times
'Blockramtohub_loop
' call #read_memory_byte ' read byte from address into data_8
' wrbyte data_8,hubaddr ' write data_8 to hubaddr ie copy byte to hub
' add hubaddr,#1 ' add 1 to hub address
' add ramaddr,#1 ' add 1 to ram address
' call #lowlatchout ' update the low latch
' djnz len,#blockramtohub_loop ' loop until done
' jmp #init ' restart
'
'extramtodisplay ' send a block of data blocklen from external memory ramaddress to the ILI9325 display
' call #ram_open ' gets ramaddr and len (ignore hubaddr)
' shr len,#1 ' len /2 as 2 bytes per pixel
' call #setRShigh ' set pins for data output
'ililoop call #readiliword ' read ilihigh, ililow, increments ramaddr by 2
' call #ilidisplayword ' sends ilihigh ililow to the display
' djnz len,#ililoop ' loop until done
' jmp #init ' set pins to tristate
'readiliword ' read ilihigh and ililow from ramaddr, increments ramaddr by 2
' call #read_byte ' read byte from ramaddr into data_8
' mov dira,latchdirection ' enable for output (readmemorybyte leaves P0-P7 as inputs)
' mov ilihigh,data_8
' add ramaddr,#1 ' add 1 to ram address
' call #read_byte ' read second byte from address into data_8
' mov dira,latchdirection ' enable for output (readmemorybyte leaves P0-P7 as inputs)
' mov ililow,data_8
' add ramaddr,#1 ' add 1 to ram address
'readiliword_ret ret
'
'RawtoILIformat ' 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
' call #ram_open ' gets hubaddress, ramaddress and len (ignores ramaddress)
'rawloop
' rdbyte red,hubaddr
' add hubaddr,#1
' rdbyte green,hubaddr
' add hubaddr,#1
' rdbyte blue,hubaddr
' add hubaddr,#1
' call #rgbtoili
' wrbyte ilihigh,ramaddr
' add ramaddr,#1
' wrbyte ililow,ramaddr
' add ramaddr,#1
' djnz len,#rawloop ' loop until done
' jmp #init ' set pins to tristate
'RGBtoILI ' pass red,green, blue, returns ililow and ilihigh
' shr red,#3 ' 000RRRRR
' shl red,#3 ' RRRRR000
' shr green,#2 ' 00GGGGGG
' mov ilihigh,green ' ilihigh = 00GGGGGG
' shr ilihigh,#3 ' ilihigh = 00000GGG
' or ilihigh,red ' ilihigh = RRRRRGGG
' and green,#%00000111 ' 00000GGG
' shl green,#5 ' GGG00000
' mov ililow,green ' ililow = GGG00000
' shr blue,#3 ' blue = 000BBBBB
' or ililow,blue ' ililow = GGGBBBBB
'RGBtoILI_ret ret
'ILItoRGB ' pass ilihigh RRRRRGGG and ililow GGGBBBBB returns RRRRR000 GGGGGG00 BBBBB000
' mov red,ilihigh ' red = RRRRRGGG
' and red,#%11111000 ' red = RRRRR000
' mov green,ilihigh ' green = RRRRRGGG
' shl green,#5 ' green = GGG00000
' mov i,ililow ' i = GGGBBBBB
' and i,#%11100000 ' i = GGG00000
' shr i,#3 ' i = 000GGG00
' or green,i ' green = GGGGGG00
' mov blue,ililow ' blue = GGGBBBBB
' shl blue,#3 ' blue = BBBBB000
'ILItoRGB_ret ret
'DrawIcon ' pass hubaddr, ramaddr and len.
' hubaddr is location in ram of the picture (messy naming of the variable)
' ramaddr is the location in ram of the mask (both sources are ram, not hub)
' format of the picture is 2 bytes RRRRRGGG GGGBBBBB
' ' format of the icon is R G B A and A = 0 for transparent and 255 for full opaque (transparent usually round the edges)
' call #ram_open ' gets hubaddr, ramaddr and len
' mov backgroundcount,hubaddr ' backgroundcount is the picture
' mov iconcount,ramaddr ' iconcount is the icon
'drawiconloop mov ramaddr,backgroundcount ' address for reading the picture
' call #readiliword ' get ilihigh and ililow RRRRRGGG GGGBBBBB
' mov backgroundcount,ramaddr ' store new picture counter
' call #ilitoRGB ' convert to red green blue
' mov ramaddr,iconcount ' get icon location
' call #readiliword ' returns ilihigh and ililow which are actually red and green
' mov r,ilihigh ' get red
' mov g,ililow ' get green
' call #readiliword ' returns ilihigh and ililow which are actually blue and alpha
' mov b,ilihigh ' get blue
' mov a,ililow ' get alpha
' mov iconcount,ramaddr ' restore the icon pointer
' cmp a,#128 wc ' test if background or foreground
' if_c jmp #drawiconfinish ' if carry then this is background
' mov red,r ' move icon to foreground
' mov green,g
' mov blue,b
'drawiconfinish call #rgbtoili ' convert to ililow and ilihigh
' call #ilidisplayword ' send out to the display
' djnz len,#drawiconloop ' loop len times until finished
' jmp #init ' set pins to tristate
delay long 80 ' waitcnt delay to reduce power (#80 = 1uS approx)
ctr long 0 ' used to pause execution (lower power use) & byte counter
'GateHigh long %00000000_00000000_00000001_00000000 ' HC138 gate high, all others must be low
'Outx long 0 ' for temp use, same as n in the spin code
'LatchDirection long %00000000_00000000_00001111_11111111 ' 138 active, gate active and 8 data lines active
'LatchDirection2 long %00000000_00000000_00001111_00000000 ' for reads so data lines are tristate till the read
'LowAddress long %00000000_00000000_00000101_00000000 ' low address latch = xxxx010x and gate high xxxxxxx1
'MiddleAddress long %00000000_00000000_00000111_00000000 ' middle address latch = xxxx011x and gate high xxxxxxx1
'HighAddress long %00000000_00000000_00001001_00000000 ' high address latch = xxxx100x and gate high xxxxxxx1
'ReadEnable long %00000000_00000000_00000001_00000000 ' /RD = xxxx000x and gate high xxxxxxx1
' commented out as the same as GateHigh
Zero long %00000000_00000000_00000000_00000000 ' for tristating all pins
data_8 long 0 ' so code compatability with zicog driver
i long 0 ' general purpose value
j long 0 ' general purpose value
a long 0 ' general purpose value
b long 0 ' general purpose value
r long 0 ' general purpose value
g long 0 ' general purpose value
' variables and constants for the ILI9325 display
'Latch5address long %00000000_00000000_00001011_00000000 ' latch5 address
'Latch6address long %00000000_00000000_00001101_00000000 ' latch6 address
'Latch7data long %00000000_00000000_00001111_00010111 ' latch7 address 111x and gate high, reset high, cs low, read high, write high, rs high for data output, combines rshigh in spin into one line
'Latch7WriteLow long %00000000_00000000_00001111_00010101 ' cs low, write low
'ililow long 0 ' low data byte latch5
'ilihigh long 0 ' high data byte latch6
'red long 0 ' red, green blue variables
'green long 0
'blue long 0
'backgroundcount long 0
'iconcount long 0
lowWordMask long $0000_ffff
'pin settings
EnablePin long %00000000_00000010_00000000_00000000
RSPin long %00000000_00000001_00000000_00000000
p2dpins long %00001000_01100000_00000000_00000000 ' propToDisplay enable pin low, but tristate, primed for lcd transfer
PinsInit long %00001001_01100010_00000000_00000000 'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high
DirsDisabled long %00000000_00000000_00000000_00000000
DirsEnabled long %00001001_11100000_11111111_11111111 '' (R4Fh) (POR = 0000h)
'bufferaddress res 1
'Pntr res 1
'ForegroundFormat res 1
'BackgroundFormat res 1
'ForegroundScreen res 1
'BackgroundScreen res 1
timeout res 1
Display res 1
fit
There is still issues with this code, and large portions untested. I have been trying to get ASM to write commands to the screen, but having problems. The draw command does not work properly when using asm. The problem is somewhere in this chunk of code, I THINK.
'spin portion
PUB DrawASM(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
word[@screen][0] := REG_HORIZONTALRAMADDRESSPOS
word[@screen][1] := HORIZONTALRAMADDRESSPOS
word[@screen][2] := REG_VERTICALRAMADDRESSSTART
word[@screen][3] := y1
word[@screen][4] := REG_VERTICALRAMADDRESSEND
word[@screen][5] := y2
word[@screen][6] := REG_SETGDDRxADDRESSCOUNTER
word[@screen][7] := x1
word[@screen][8] := REG_SETGDDRyADDRESSCOUNTER
word[@screen][9] := y1
DoCmd("Z", @screen, -1, 10)
'asm portion
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word aligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:data ' loop until done
jmp #init ' set pins to tristate
:data call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word aligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov outa, PinsInit
mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow mov outa, PinsInit
mov dira, DirsEnabled wz ' set rsHigh by tristate pin
muxnz dira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the display
add Display, p2dpins wz 'this add presets the data for control pins and primes WZ flag for mux operation
mov outa, Display 'then make pins = data
muxz dira,EnablePin 'make enable pin low
mov timeout, #$f 'set wait period
:wait1 djnz timeout, :wait1 'and wait
muxnz dira, EnablePin 'make enable pin high
ilidisplayword_ret ret
I'm taking a break from trying to make this work and I'm going to start on getting the RAM working. It would be nice to have commands writing in ASM, but I can do this in spin for now.
*edit* I figured it out. I just needed to make the wait time a bit longer. I edited this to match what I have working.
I plan on ordering your display in the near future. I will also be ordering your SRAM's and more 161s. I'm trying to decide if I should just order 2, and get some sockets, or get 6 and not worry about the sockets right now. RAM, Prop, EEPROM and 3232 will get sockets. Still up in the air about the counters.
I always use sockets for everything. Then you can recycle chips between boards. Almost everything *except* the sockets on the board below was desoldered and recycled from a previous board. Much cheaper that way.
It is always nice when a lot of things work first up on a new board!
Haven't tested the ram yet or the SD card but no reason it should not work as this design is simpler than previous ones with most things being controlled directly by propeller pins. The cunning thing is the groupings of pins - eg you want the SD card and the ram chips and the display to be grouped together for fast transfers. Once something is on the display, select another group to do keyboard and detect when something touches the display.
So really it is just a 138, five 161 counters, two ram chips and the display module.
Simple demo code below. I need to catch up with averagejoe's 161 code.
BTW averagejoe, can you PM me your address and I'll send you a couple of these boards.
'' ILI9325 driver using the Touchblade161 design for faster ram to display transfers
'' James Moxham 2012
CON
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000
_1ms = 1_000_000 / 1_000 ' Divisor for 1 ms
' pins
' P24 = audio out
' 25,26,27 138 one of 8 decoded, active low
' 0=000 = SPI touchscreen input, keyboard, TV VGA enabled
' 1=001 = Load counter
' 2=010 = Memory transfer - P0-P15=bus, P16=161_clk, P17 = ILI_WR, P18=ILI_RS, P19= Ram_RD, P20=Ram_WR,P21-23 = SD card
' 3=011 = ILI Reset
' 4=100 = Digital output (8 bits to a 574 latch)
' 5=101 = spare
' 6=110 = spare
' 7=111 = startup (all above deselected)
OBJ
VAR
long orientation
long curx, cury
long clkcycles ' for the delay routine
PUB Main
curx :=0
cury :=0
start_ram ' start the cog driver
MemoryTransfer ' select 138 and set control pins
Start_ILI9325 ' start the display
HelloWorld ' Bootup message
PUB MemoryTransfer
Select138(2) ' enable memory transfer group
DIRA |= %00001110_11111111_11111111_11111111 ' Pins all as outputs
OUTA |= %00000000_11111111_00000000_00000000 ' all control pins high
PUB Select138(n) ' pass n=0 to 7
n := n<<25 ' shift left so pins 25,26,27
DIRA |= %00001110_00000000_00000000_00000000 ' enable these pins for output
OUTA &= %11110001_11111111_11111111_11111111 ' mask 3 pins low
OUTA |= n ' send out
PUB Clearscreen
Draw(0,0,239,319) ' clear the screen - slow spin version
repeat 76800
Pixel($0000)
PUB HelloWorld ' use propeller font in the rom for bootup messages when debugging sd cards
Propfont_string(string("Hello World")) ' string to send
PUB Propfont_string(stringptr) 'print at curx,cury
repeat strsize(stringptr)
Propfont_out(byte[stringptr++])
crlf
PUB crlf
curx := 0
cury += 32 ' new line at end of string
if cury >319 ' bottom of screen so new screen
curx:=0
cury:=0
PUB Propfont_out(ascii) | address,pixels
Draw(curx,cury,curx+15,cury+31) ' location to start drawing
address := $8000 + (ascii >> 1) << 7 ' get rom address
repeat 32 ' 32 rows per character, split in two parts
pixels := long[address] ' get rom font data
pixels := pixels >> (ascii & 1) ' shift for odd characters
repeat 16 ' 16 columns
if pixels & 1
Pixel(%00000111_11100000) ' foreground color RRRRRGGG_GGGBBBBB
else
Pixel(%00000000_00000000) ' background color
pixels := pixels >> 2 ' alternate pixels interleaved so shift 2
address += 4
curx +=16
if curx >239 ' new line
crlf
PUB Start_ILI9325 ' pass orientation true = portrait, false = landscape
ILI_Reset_High
pause1ms(5)
ILI_Reset_Low
pause1ms(5)
ILI_Reset_High
ILI_CS_High
ILI_RD_High
ILI_WR_High
pause1ms(5)
ILI_CS_Low
' ************* 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)
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]
pause1ms(50) ' delay
ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci;
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
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
ChangeOrientation(true) ' default to portrait
PUB ChangeOrientation(n) ' pass true = portrait or false = landscape, changes global variable orientation in this object
orientation := n
if orientation
ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait
ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030
else
ILIcmd($0001,$0000) ' set SS and SM bit 0001 0000 landscape
ILIcmd($0003,$1038) ' landscape $1028 = original but 1038 is correct - not mirror image
PUB Draw(x1, y1, x2, y2) ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
ifnot orientation ' landscape mode so swap x and y
result :=x1 ' swap x1 and y1
x1 := y1
y1 := result
result := x2 ' swap x2 and y2
x2 :=y2
y2 := result
ILIcmd($0050,x1)
ILIcmd($0052,y1)
ILIcmd($0051,x2)
ILIcmd($0053,y2)
ILIcmd($0020,x1)
ILIcmd($0021,y1)
Lcd_Write_Com($0022)
PUB Pixel(pixelcolor) ' send out a pixel, high byte then low byte
Lcd_Write_Data(pixelcolor)
PUB pause1ms(period)
'' Pause execution for period (in units of 1 ms).
clkcycles := ((clkfreq / _1ms * period) - 4296) #> 381 ' Calculate 1 ms time unit
waitcnt(clkcycles + cnt) ' Wait for designated time
PUB hex(value, digits)
'' Print a hexadecimal number
propfont_out("O")
propfont_out("x")
value <<= (8 - digits) << 2
repeat digits
propfont_out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
crlf
PRI ILIcmd(c,d) ' instruction in one method
Lcd_Write_Com(c) ' send out a word
Lcd_Write_Data(d)
PRI Lcd_Write_Com(ILIlong)
ILI_RS_low
LCD_Writ_Bus(ILIlong)
PRI Lcd_Write_Data(ILIlong)
ILI_RS_High
LCD_Writ_Bus(ILIlong)
PRI LCD_Writ_Bus(ILILong)
'ILILong &= %00000000_00000000_11111111_11111111 ' mask to a word. Not needed if care taken always to send a word value
OUTA &= %11111111_11111111_00000000_00000000 ' set P0-P15 to zero ready to OR
OUTA |= ILILong ' merge with the word to output
ILI_WR_Low ' send out the data
ILI_WR_High
PRI ILI_RS_Low
OUTA &= %11111111_11111011_11111111_11111111 ' P18 low
PRI ILI_RS_High
OUTA |= %00000000_00000100_00000000_00000000 ' P18 high
PRI ILI_RD_Low ' pulled high in hardware, not used
PRI ILI_RD_High
PRI ILI_WR_Low
OUTA &= %11111111_11111101_11111111_11111111 ' p17 low
PRI ILI_WR_High
OUTA |= %00000000_00000010_00000000_00000000 ' p17 high
PRI ILI_CS_Low ' not used as setting 138 to %010 does this
PRI ILI_CS_High
PRI ILI_RESET_Low ' reset low
Select138(3) ' reset low
PRI ILI_RESET_High
Select138(2) ' 138 back to memselect
DAT
sdbuffer byte $0[512] ' 512 byte buffer for sd card interface
'************************** Cog driver for the 16 bit ILI9325 screen *********************
VAR
' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
long command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
' command = R, W, H I,D etc =0 when operation completed by cog
' hubaddrs = hub address for data buffer
' ramaddrs = ram address for data ($0000 to $FFFF)
' blocklen = ram buffer length for data transfer
' errx = returns =0 (false=good), else <>0 (true & error code)
' cog = cog no of driver (set by spin start routine)
PUB start_ram : err_
' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
command := "I"
cog := 1 + cognew(@tbp2_start, @command)
if cog == 0
err_ := $FF ' error = no cog
else
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
PUB stop_ram
if cog
cogstop(cog~ - 1)
PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
' Do the command: R, W, N, F, H,I,D
hubaddrs := hub_address ' hub address start
ramaddrs := ram_address ' ram address start
blocklen := block_length ' block length
command := command_ ' must be last !!
' Wait for command to complete and get status
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
DAT
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
pause
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
cmp cmd,#"M" wz ' move a block from ram to the display
if_z jmp #moveblock
cmp cmd, #"I" wz ' init
if_z jmp #init
mov err, cmd ' error = cmd (unknown command)
jmp #done
'---------------------------------------------------------------------------------------------------------
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
Moveblock ' uses ramaddr and len
' OUTA := address ' address is not latched - this is where the speed is
' OUTA &= %11111111_10111111_11111111_11111111 ' ILI write low
' OUTA |= %00000000_01000000_00000000_00000000 ' ILI write high
' address++ ' increment address
mov dira,direction ' set P0-P23 as outputs
call #ram_open ' get ramaddr and len
or ramaddr,pin22 ' start with pin 22 high
Moveblock_loop mov outa,ramaddr ' send out the address value
andn outa,pin22 ' set pin 22 low
or outa,pin22 ' set pin 22 high
add ramaddr,#1 ' increment ram address
djnz len,#moveblock_loop
jmp #init
halt jmp #halt
' ************************ Variables ******************************
delay long 80 ' waitcnt delay to reduce power (#80 = 1uS approx)
Zero long %00000000_00000000_00000000_00000000 ' for tristating all pins
pin22 long %00000000_01000000_00000000_00000000
direction long %00000000_11111111_11111111_11111111
fit 496
That board looks great! I'm ordering parts right now. Not sure if I will buy the screen right now, or wait a bit.
To be honest, 99% of my parts stock is from old electronics. I've been making trips to the local recycling place and have become buddies with "the guy." He lets me look through boards they're going to send to China, and have my choice. I always throw him $20 and grab maybe 5 or 10 small boards. Found the MAX232 that's going in the test bed that way
*edit*
I'm putting together a parts order, and realizing we need a Bill of Materials. This includes optional components. I'm currently ordering @Mouser, since they have the ram chips you're using.
Edited again. Still working on a parts order. Mouser doesn't seem to have the 3.3 vreg. I have not looked @ substitution yet. I'm also wondering about those inductors. Mouser has these http://www.mouser.com/ProductDetail/Pulse/PE-52647NL/?qs=1CGoW%2f3pMwqX4Nj3HGoSjfhVp1UWNjObw3LB8spey6I%3d @ $2.58 a piece. Not sure how critical they are to the regulator. I have several 5V, 2a regulated wall warts so I will probably bypass the 5v reg entirely.
Comments
I tried to get SD3.01_FATEngine working, but had no luck. I'm working on re-writing the demo with FSRW? because it works for me? I've gotten to I'm not seeing an easy way to do this so I guess i'll just hardwire it for now?
It was not my intent to suggest otherwise... I am sure she is. I am just saying, protect your hobby and get it in righting before saying I do, and before she says you don't. Of course I am just teasing.
Bruce
Just saw this post ... as I already said I also have such a kind of display with another display-controller, but most controllers have similar functions. So, you should maybe read the specs again if your display supports scrolling. Mine does. You simply define where the controller should start with reading lines. This makes scrolling really fast, as you simple redefine screen-start and then update some lines.
Goodness me, that is terrible news!
We must find a workaround. Hmm - there is nothing wrong with older memory chips. They should all work fine and even a 32k one will be enough to hold a couple of fonts. Maybe you might need a few NOPs if they are slower.
Can you post the Kye SD card that is not working? Also, when in doubt, use Windows to reformat the SD card. I presume you are using a FAT32 reformat?
Addit : playing around with a larger board format for the Gadget Gangster. This is a "eurocard" 160x100 mm size which is a default size in Eagle as well.
With DIP chips the boards can get large fairly quickly, especially if you have double memory chips. I'm testing the idea you can have 224 I/O pins on a propeller. So each board can be placed in HiZ. I probably take this a bit too far - there are a few examples in these boards where there are 10k pullups on pins, and I even isolate those so that each board truly can't interfere with another.
The motherboard has the standard GG footprint. You could even use this board completely unpopulated and just use it to expand to the larger size.
The 32 prop pins are brought out to 4 groups of 8 and these are in the corners of the board for mechanical stability when stacking. 4 pins for power. And another group of 8 to select each board (these could have been deleted and each board decoded locally but it adds more components and another stackable header is cheaper).
The motherboard had lots of spare space on it so I filled that up with diagnostic leds but these are not really needed except when debugging circuits.
The Touchscreen board has 1 megabyte of ram and a faster access than previous dracblade designs.
The Dracblade board has 512k of ram and can run independently of the touchscreen. This can be handy for debugging to TV and VGA, but it is mainly there to show this concept is backwards compatible with other designs. There is no reason you could not add a C3 board to the stack, or a Propeller demoboard.
I'm sure with surface mount this could be shrunk down to the smaller GG footprint, and this could well be useful once designs are debugged.
This is all a bit experimental at the moment and there are chips on the board I've never even worked with such as the HC137 and 74HC4316 but hopefully it will all work as designed.
WOW! That is some very serious design work. Nice job.
You still have my vote for most interesting and impressive thread.
Bruce
I'm liking the idea more and more of being able to complete deselect boards and make all the pins HiZ on that board. It means you can mix and match all sorts of previously incompatible boards and code.
E.G.: Touch screen->Raise finger->Touch screen->Drag closer to center to zoom out, farther to zoom in.
Of course it's probably too early in dev to start thinking too much about UI...
What a great idea!
I don't own any apple products but my kids do and I see them using two fingers to shrink and expand things. But the way resistive touchscreens work, you can't look for two presses at the same time. So your tap n drag would work very nicely.
Values are 0-100 x and y. So, thinking this through, you detect the tap, then set a delay loop that maybe times out after a second or two while it looks for the second press.
Then work out if the direction is moving towards or away from the centre. So if the centre is 50,50, then thinking just in the x direction for the moment, you get the x value, subtract 50, take the absolute value to remove the minus sign if it is 0-49, then work out if it is higher or lower than the previous value. Take a few readings and that can work out if the finger is moving. For x and y, distance is the square root of x squared plus y squared. This might be a fun way to use the log and antilog tables that are in the propeller ROM. Actually, that distance formula removes the negative sign so you don't need to to get the absolute value.
So you just take the value, subtract 50 from x and y which moves the coords to a 0,0 centre, then d = (x^2 +y^2) ^0.5 and work out if d is changing.
I *knew* that year 11 math would come in handy one day!
That might be my fault, I think I changed the format of the font files a few times. I can post the latest vb.net code. Or is this the code that you can't get to run?
Thank you!
The vast majority of touch-screen gestures use a single axis to function. People have come to expect a single motion to affect the screen in a single way, so 2 axes would seem alien, and could quickly become unwieldy / confusing... Maybe it wasn't as good an idea as I thought it was. :frown: Unless this is just for the hobby community, it's probably not a very good idea to use in your product.
EDIT: If you do use my idea and are going for an Apple product kind of interface, it could zoom relative to the initial tap location.
I love the new board design. I have been working up my own design based off your current design. I'm making some changes due to component availability, and overall system design. The first change I'd be forced to make is to use 373's instead of 573's. This should not affect operation, as they are compatible devices with different pinouts? I have also been thinking about replacing the address latches with 161's. I know I have a couple, but I'm not sure if I have the 4 that I would need for my 256k chips. The SRAM's I have coming are 15ns. I think the limiting factor here will be the interface chips. I will also be using a different option for the ili control latch. Not sure of that yet. I also be using an inverter to control we/RD of the display as well as the we/OE of the ram chip. CS for Ram and Display will be controlled directly by micro, I think.
Any thoughts or advice? Especially about using the 161's for address buffers.
Can I ask about you're use of 244s to isolate the sd and touch? I have them multiplexed together directly and they seem to work ok.
One last thing, about the displays. I am a bit unsure if there is a way to send pixel data without addressing the GRAM write register every time. I have not played with this too much. The datasheet is a bit hard to understand. Any advice about getting a grasp on that?
*edit*
It turns out I have 2x 74ls161a's in inventory. I also have 1x 74hc245 and 1x 74ls245. I'm looking at ordering 2x 74hc245's, and debating picking up 4x 74hc161's. The datasheet I looked @ clocked the ls161A's @ min 20mhz. typ 32mhz. Is this going to be a huge limitation or is it acceptable? Is there a better parallel-load binary counter you can think of?
1) I changed 573s to 373s too as I have lots of 373s. 573s are easier to work with on a breadboard but an autorouter doesn't really care.
2) Your sram chips are very fast. Which ones are you using?
3) 161s should work. I used them for a graphics board once. For clocking out a picture a counter is fine but I'd like to use some of the memory for true random access at some point down the track for things like C++ and Catalina.
4) You probably can share lines with the SD and touch as these generally won't be used at the same time. Good thinking.
5) re "I am a bit unsure if there is a way to send pixel data without addressing the GRAM write register every time." - you mean for random pixels? One thing we ought to do is translate the "Draw" routine into pasm for setting up pixels.
6) 161s at 20Mhz should be fine. Isn't that the max propeller frequency anyway?
Re, 6. Very true, but I've had thoughts of tying the 161's clk with the Display CE, and OC them somehow...Still.
RE. #2. http://search.digikey.com/us/en/products/CY7C199CN-15PXC/428-2158-5-ND/1206029 @ $1.78? Grabbed these since they were way cheap.
Re. #3. I though about this too. This is why I've set up my 161 clock / Load Enable the way I have. From what I understand, Set Ram load Enable low, Make databus = address, clock low to high, and low.
RE. 5, translating draw into pasm would be fairly easy I think. Same thing with a clear screen. I'm thinking about using LCD COMMAND layer on top of the ram. Make $FF clearscreen and $FE draw? This way, 1 hub address can hold 1- 16 bit command and, 16 bit data?
Just thought your thread needed a little friendly bump. I went looking for it and found it was getting buried.
So what's new on this project? Is it on hold while you figure out your IO stuff?
Bruce
I am new to propeller chips and wanted to make a project with a TFT. It is nowhere near as complicated as yours but I have no idea where to start. I like the size of the display you're using and have found it online, but the only thing my TFT will be used for is displaying a single (big) character at a time, and no touch interaction or animations. Is the propeller capable of doing this on its own or will the peripheral devices you've used be necessary? Would I be able to do it all in Spin or does the display require programming? My task seems simple (especially compared to your work!) but I know nothing about video drivers or display controllers. Thanks for any advice you might have.
-Brian
The touchscreen would work but it is more complicated and a lot of the code is too slow at the moment. Hope this helps.
Just wanted to give this thread a *BUMP* and see if you've got boards yet. I also wanted to see if you have more recent code. I've downloaded several of the backups you've posted, but only glanced at them. The code I was initially working off was the ILI demo.
Hey Doc, any word on those boards yet?After initial tests of screen and ram passed with flying colors, I started working on writing data AND COMMANDS to the display in ASM from hub address *I think I would like to DIRECTLY be able to pass these, but still deciding how to do that.* I would like the screen working before I start fussing with the ram. I'm hoping to use the screen to debug ram if necessary. I hope it doesn't come to that, but...
Here's what I've got so far. The H/W is slightly different from yours, but pretty close. I believe it's on the previous post of my thread.
The original was taken from ILIDemo *I'm pretty sure* I have some other code changed too, but it's all commented out for the most part. Am I heading in the right direction? Any advice? Right about now, I feel like an idiot savant, stumbling my way through something that ?should? be simple.
*edit*
Please remember I am using DIRA to control RS pin and ENABLE pin in ASM since I have pullup resistors on these pins!
I will be working on command passing, and then get the RAM up. Should not be as hard as I'm making it.
*edit*
I plan on ordering your display in the near future. I will also be ordering your SRAM's and more 161s. I'm trying to decide if I should just order 2, and get some sockets, or get 6 and not worry about the sockets right now. RAM, Prop, EEPROM and 3232 will get sockets. Still up in the air about the counters.
*edited again!*
Something is wrong with this code. IT DOES NOT fill the screen? Even the SPIN code doesn't completely fill the screen? Must have something set wrong some where.
And I figured it out. Had draw set to 320*240.... DUH fixed in post
There is still issues with this code, and large portions untested. I have been trying to get ASM to write commands to the screen, but having problems. The draw command does not work properly when using asm. The problem is somewhere in this chunk of code, I THINK.
I'm taking a break from trying to make this work and I'm going to start on getting the RAM working. It would be nice to have commands writing in ASM, but I can do this in spin for now.
*edit* I figured it out. I just needed to make the wait time a bit longer. I edited this to match what I have working.
I always use sockets for everything. Then you can recycle chips between boards. Almost everything *except* the sockets on the board below was desoldered and recycled from a previous board. Much cheaper that way.
It is always nice when a lot of things work first up on a new board!
Haven't tested the ram yet or the SD card but no reason it should not work as this design is simpler than previous ones with most things being controlled directly by propeller pins. The cunning thing is the groupings of pins - eg you want the SD card and the ram chips and the display to be grouped together for fast transfers. Once something is on the display, select another group to do keyboard and detect when something touches the display.
Optional components: TV, VGA, Keyboard, 74HC244, 74HC574, 74HC4316, audio.
So really it is just a 138, five 161 counters, two ram chips and the display module.
Simple demo code below. I need to catch up with averagejoe's 161 code.
BTW averagejoe, can you PM me your address and I'll send you a couple of these boards.
To be honest, 99% of my parts stock is from old electronics. I've been making trips to the local recycling place and have become buddies with "the guy." He lets me look through boards they're going to send to China, and have my choice. I always throw him $20 and grab maybe 5 or 10 small boards. Found the MAX232 that's going in the test bed that way
*edit*
I'm putting together a parts order, and realizing we need a Bill of Materials. This includes optional components. I'm currently ordering @Mouser, since they have the ram chips you're using.
Edited again. Still working on a parts order. Mouser doesn't seem to have the 3.3 vreg. I have not looked @ substitution yet. I'm also wondering about those inductors. Mouser has these http://www.mouser.com/ProductDetail/Pulse/PE-52647NL/?qs=1CGoW%2f3pMwqX4Nj3HGoSjfhVp1UWNjObw3LB8spey6I%3d @ $2.58 a piece. Not sure how critical they are to the regulator. I have several 5V, 2a regulated wall warts so I will probably bypass the 5v reg entirely.