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) |'' +--------------------------------------------------------------------------+org0
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=goodmovdira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error xwrlong 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_zjmp #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 timesif_zjmp #hubtodisplayCommand
' data format "DoCmd(Y, hub_address, unused, length) cmp cmd, #"Y"wz' Y moves data to the display from hub address, length timesif_zjmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub addressrdlong ramaddr, ramptr ' get ram addressrdlong len, lenptr ' get lengthmov 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 donejmp #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 datardword 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 hubadd 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 movdira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow add zero,#0wz'prime z flagmovdira, DirsEnabled ' set rsHigh by tristate pin muxzdira, 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 movouta, 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 res1
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 GGGBBBBBcon
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 = 32767OBJ
wait : "timing"' thanks to parallax'pst :"Parallax Serial Terminal"Varlong screenbufferaddress
byte pcog
PUBboot
initPins
'Pst.Start(115200)
START_SSD1289
ClearScreenSpin($ffff)
deadend
PUBRequestSDPUBReleaseSDPUBRequestTSPUBReleaseTSPubClearScreenSpin(c)
Draw(0, 0, 240, 320)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat76800
StrobeLcdWr
TristateDisplayPins
pubdeadendrepeatwaitcnt(cnt)
PUBinitPinsouta := %00001001_00000010_00000000_00000000dira := %00001001_11100010_00000000_00000000PUBStart_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
PRIEnableDisplayPinsouta[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111' RS, 16 data lines active outa[p_BusEn] := 0OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRITristateDisplayPins' tristate all pins - DIRA :=%00000000_00000000_00000000_00000000''PRILCD_Writ_Bus(V)OUTA[15..0] := V
StrobeLcdWr ' toggle write pinPRILcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRILcd_Write_Data(V)'RSHigh
LCD_Writ_Bus(V)
PRIRSLowouta[p_RS] := 0PRIRSHighouta[p_RS] := 1'PRIStrobeLcdWr'outa[p_SPIadd2..p_SPIadd0] := LCD_WR outa[p_SPI_En] := 0outa[p_SPI_En] := 1PUBDraw(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 pinsPUBPixel(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 PUBReadRamByte(address)' masks off all but a byte - used often
docmd("R",@result,address,1) ' read just 1 byteresult := result & %00000000_00000000_00000000_11111111' mask off byte so returns a guaranteed byte valuereturnresultPUBWriteRamByte(value,address)' write a byte to ram
docmd("W",@value,address,1)
PUBReadRamLong(address)' read a long, stored LSB first
docmd("R",@result,address,4)
returnresultPUBWriteRamLong(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 driverlong 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)PUBstart_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 cogelserepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codePUBstop_ramif cog
cogstop(cog~ - 1)
PUBDoCmd(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 statusrepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codeDAT'' +--------------------------------------------------------------------------+'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |'' +--------------------------------------------------------------------------+org0
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=goodmovdira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error xwrlong 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_zjmp #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 timesif_zjmp #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 timesif_zjmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub addressrdlong ramaddr, ramptr ' get ram addressrdlong len, lenptr ' get lengthmov 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 displaydjnz len,#:hubdisploop ' loop until donejmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command outputrdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the display call #setRShigh
rdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:hubdisplayloop ' loop until donejmp #init ' set pins to tristate
setRShigh movdira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow add zero,#0wz'prime z flagmovdira, DirsEnabled ' set rsHigh by tristate pin muxzdira, RSpin ' set rsLow by enabling pin
setRslow_ret
ilidisplayword ' pass data out, sends out to the displayadd display, p2dpins wz'this add presets the data for control pins and primes WZ flag for mux operation movouta, display 'then make pins = datamuxnzdira,EnablePin 'make enable pin highadd timeout, #$f
:wait djnz timeout, #:wait
muxzdira, 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 long80' waitcnt delay to reduce power (#80 = 1uS approx)
ctr long0' 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 long0' so code compatability with zicog driver
i long0' general purpose value
j long0' general purpose value
a long0' general purpose value
b long0' general purpose value
r long0' general purpose value
g long0' 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 res1
LCD_data res1'Pntr res 1'ForegroundFormat res 1'BackgroundFormat res 1'ForegroundScreen res 1'BackgroundScreen res 1
timeout res1
Display res1fit
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 GGGBBBBBCON_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 = 16OBJ
wait : "timing"' thanks to parallax'pst :"Parallax Serial Terminal"Varlong screenbufferaddress
long screen[ScreenBufferSize]
byte pcog
PUBboot
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
PUBRequestSDPUBReleaseSDPUBRequestTSPUBReleaseTSPubClearScreenSpin(c)
Draw(0, 0, 239, 319)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat76800
StrobeLcdWr
TristateDisplayPins
pubdeadendrepeatwaitcnt(cnt)
PUBinitPinsouta := %00001001_00000010_00000000_00000000dira := %00001001_11100010_00000000_00000000PUBStart_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
PRIEnableDisplayPinsouta[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111' RS, 16 data lines active outa[p_BusEn] := 0OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRITristateDisplayPins' tristate all pins - DIRA :=%00000000_00000000_00000000_00000000''PRILCD_Writ_Bus(V)OUTA[15..0] := V
StrobeLcdWr ' toggle write pinPRILcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRILcd_Write_Data(V)'RSHigh
LCD_Writ_Bus(V)
PRIRSLowouta[p_RS] := 0PRIRSHighouta[p_RS] := 1'PRIStrobeLcdWr'outa[p_SPIadd2..p_SPIadd0] := LCD_WR outa[p_SPI_En] := 0outa[p_SPI_En] := 1PUBDraw(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 pinsPUBPixel(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 timesVAR' communication params(5) between cog driver code - only "command" and "errx" are modified by the driverlong 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)PUBstart_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 cogelserepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codePUBstop_ramif cog
cogstop(cog~ - 1)
PUBDoCmd(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 statusrepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codeDAT'' +--------------------------------------------------------------------------+'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |'' +--------------------------------------------------------------------------+org0
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=goodmovdira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error xwrlong 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_zjmp #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 timesif_zjmp #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 timesif_zjmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub addressrdlong ramaddr, ramptr ' get ram addressrdlong len, lenptr ' get lengthmov 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 displaydjnz len,#:hubdisploop ' loop until donejmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command outputrdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the display call #setRShigh
rdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:hubdisplayloop ' loop until donejmp #init ' set pins to tristate
setRShigh movdira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow movdira, DirsEnabled wz' set rsHigh by tristate pin muxnzdira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the displayadd display, p2dpins wz'this add presets the data for control pins and primes WZ flag for mux operation movouta, display 'then make pins = datamuxnzdira,EnablePin 'make enable pin highmov timeout, #$8'set wait period
:wait djnz timeout, :wait 'and wait muxzdira, 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 res1
Display res1fit
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 GGGBBBBBCON_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 = 16OBJ
wait : "timing"' thanks to parallax
Cr :"crReader"
num : "numbers"
pst :"Parallax Serial Terminal"Varlong screenbufferaddress
word screen[16], BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2
byte Fontsize, pcog
PUBboot | 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 from0to255
char(x)
deadend
PUBHelloWorld
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")
pubpixel(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))pubsetFontSize(s)
fontsize := s
pubnewline
Row := Row + (32 >> (fontsize -1))
Col := 0pubsetRow(PosR )
Row := PosR
pubsetCol(PosC)
Col := PosC
pubsetBorders(RBorder, CBorder)
RowBorder := RBorder
ColBorder := CBorder
pubsetColors( BgC, TxC)
BackgroundColor := BgC
ActiveTextColor := Txc
PUBsetChar(PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
setRow(PosR)
setCol(PosC)
setBorders(RBorder, CBorder)
setColors(BgC, TxC)
PUBChar(c)
WriteNextActiveCr(c)
PUBWriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
fontaddress := Cr.GetChar(Character)
repeat idx from0to31
bitpatern[idx] := word[fontaddress][idx]
y1 := Col + ColBorder
y2 := (Col + (15 / fontsize ) - ColBorder)
x1 := Row + RowBorder
x2 := (Row + (31 / fontsize ) - RowBorder)
Draw(x1,y1,x2,y2)
'EnableDisplayPinsword[@screen] := $22
DoCmd("Z",@screen, -1,1)
'TristateDisplayPinsrepeat idx from RowBorder to31 - RowBorder step Fontsize
repeat pxlidx from ColBorder to15 - ColBorder step Fontsize
pxlidxdcd := |< pxlidx
if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)
pixel(ActiveTextColor)
else
pixel(BackgroundColor)
'repeat while word[fontaddress] := 0if (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) > 223)))
Row := 0
Col := 0elseif (((Col + (16 >> (fontsize -1))) > 319 ) and ((Row + (32 >> (fontsize -1)) < 223)))
Row := Row + (32 >> (fontsize -1))
Col := 0else
Col := Col + (16 >> (fontsize - 1))
PUBWriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
setChar(PosR, PosC, RBorder, CBorder, BgC, TxC)
WriteNextActiveCr(Character)
PubClearScreenSpin(c)
Draw(0, 0, 239, 319)
EnableDisplayPins
Lcd_Write_Com($22)
OUTA[15..0] := c
repeat76800
StrobeLcdWr
TristateDisplayPins
pubdeadendrepeatwaitcnt(cnt)
PUBinitalizeouta := %00001001_00000010_00000000_00000000dira := %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
PUBStart_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
PUBSpinPixel(p)
EnableDisplayPins
Lcd_Write_Data(p)
TristateDisplayPins
PRIEnableDisplayPinsouta[p_BusDir] := a_PropToRam
DIRA :=%00001001_11100011_11111111_11111111' RS, 16 data lines active outa[p_BusEn] := 0OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr
PRITristateDisplayPins' tristate all pins - DIRA :=%00000000_00000000_00000000_00000000''PRILCD_Writ_Bus(V)OUTA[15..0] := V
StrobeLcdWr ' toggle write pinPRILcd_Write_Com(V)
RSLow
LCD_Writ_Bus(V)
RSHigh
PRILcd_Write_Data(V)'RSHigh
LCD_Writ_Bus(V)
PRIRSLowouta[p_RS] := 0PRIRSHighouta[p_RS] := 1'PRIStrobeLcdWr'outa[p_SPIadd2..p_SPIadd0] := LCD_WR outa[p_SPI_En] := 0outa[p_SPI_En] := 1PUBDrawASM(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)
PUBDraw(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 timesVAR' communication params(5) between cog driver code - only "command" and "errx" are modified by the driverlong 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)PUBstart_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 cogelserepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codePUBstop_ramif cog
cogstop(cog~ - 1)
PUBDoCmd(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 statusrepeatwhile 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) |'' +--------------------------------------------------------------------------+org0
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=goodmovdira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error xwrlong 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_zjmp #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 timesif_zjmp #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 timesif_zjmp #hubtodisplayData
ram_open rdlong hubaddr, hubptr ' get hub addressrdlong ramaddr, ramptr ' get ram addressrdlong len, lenptr ' get lengthmov 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 displaydjnz len,#:hubdisploop ' loop until donejmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command outputrdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:data ' loop until donejmp #init ' set pins to tristate
:data call #setRShigh
rdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word allignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:hubdisplayloop ' loop until donejmp #init ' set pins to tristate
setRShigh movouta, PinsInit
movdira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow movouta, PinsInit
movdira, DirsEnabled wz' set rsHigh by tristate pin muxnzdira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the displayadd Display, p2dpins wz'this add presets the data for control pins and primes WZ flag for mux operation movouta, Display 'then make pins = datamuxzdira,EnablePin 'make enable pin low mov timeout, #$f'set wait period
:wait1 djnz timeout, :wait1 'and wait muxnzdira, 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 long80' waitcnt delay to reduce power (#80 = 1uS approx)
ctr long0' 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 long0' so code compatability with zicog driver
i long0' general purpose value
j long0' general purpose value
a long0' general purpose value
b long0' general purpose value
r long0' general purpose value
g long0' 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 res1
Display res1fit
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 portionPUBDrawASM(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 outputrdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word alignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:data ' loop until donejmp #init ' set pins to tristate
:data call #setRShigh
rdword Display, hubaddr ' copy word from hubadd hubaddr,#2' add 2 to hub address changed for word alignedcall #ilidisplayword ' send these bytes to the displaydjnz len,#:hubdisplayloop ' loop until donejmp #init ' set pins to tristate
setRShigh movouta, PinsInit
movdira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow movouta, PinsInit
movdira, DirsEnabled wz' set rsHigh by tristate pin muxnzdira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the displayadd Display, p2dpins wz'this add presets the data for control pins and primes WZ flag for mux operation movouta, Display 'then make pins = datamuxzdira,EnablePin 'make enable pin low mov timeout, #$f'set wait period
:wait1 djnz timeout, :wait1 'and wait muxnzdira, 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 2012CON_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)OBJVARlong orientation
long curx, cury
long clkcycles ' for the delay routinePUBMain
curx :=0
cury :=0
start_ram ' start the cog driver
MemoryTransfer ' select 138 and set control pins
Start_ILI9325 ' start the display
HelloWorld ' Bootup messagePUBMemoryTransfer
Select138(2) ' enable memory transfer groupDIRA |= %00001110_11111111_11111111_11111111' Pins all as outputsOUTA |= %00000000_11111111_00000000_00000000' all control pins high PUBSelect138(n)' pass n=0 to 7
n := n<<25' shift left so pins 25,26,27DIRA |= %00001110_00000000_00000000_00000000' enable these pins for outputOUTA &= %11110001_11111111_11111111_11111111' mask 3 pins lowOUTA |= n ' send outPUBClearscreen
Draw(0,0,239,319) ' clear the screen - slow spin versionrepeat76800
Pixel($0000)
PUBHelloWorld' use propeller font in the rom for bootup messages when debugging sd cards
Propfont_string(string("Hello World")) ' string to sendPUBPropfont_string(stringptr)'print at curx,curyrepeatstrsize(stringptr)
Propfont_out(byte[stringptr++])
crlf
PUBcrlf
curx := 0
cury += 32' new line at end of stringif cury >319' bottom of screen so new screen
curx:=0
cury:=0PUBPropfont_out(ascii) | address,pixels
Draw(curx,cury,curx+15,cury+31) ' location to start drawing
address := $8000 + (ascii >> 1) << 7' get rom addressrepeat32' 32 rows per character, split in two parts
pixels := long[address] ' get rom font data
pixels := pixels >> (ascii & 1) ' shift for odd charactersrepeat16' 16 columnsif pixels & 1
Pixel(%00000111_11100000) ' foreground color RRRRRGGG_GGGBBBBBelse
Pixel(%00000000_00000000) ' background color
pixels := pixels >> 2' alternate pixels interleaved so shift 2
address += 4
curx +=16if curx >239' new line
crlf
PUBStart_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 portraitPUBChangeOrientation(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 imagePUBDraw(x1, y1, x2, y2)' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixelsifnot orientation ' landscape mode so swap x and yresult :=x1 ' swap x1 and y1
x1 := y1
y1 := resultresult := 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)
PUBPixel(pixelcolor)' send out a pixel, high byte then low byte
Lcd_Write_Data(pixelcolor)
PUBpause1ms(period)'' Pause execution for period (in units of 1 ms).
clkcycles := ((clkfreq / _1ms * period) - 4296) #> 381' Calculate 1 ms time unitwaitcnt(clkcycles + cnt) ' Wait for designated timePUBhex(value, digits)'' Print a hexadecimal number
propfont_out("O")
propfont_out("x")
value <<= (8 - digits) << 2repeat digits
propfont_out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
crlf
PRIILIcmd(c,d)' instruction in one method
Lcd_Write_Com(c) ' send out a word
Lcd_Write_Data(d)
PRILcd_Write_Com(ILIlong)
ILI_RS_low
LCD_Writ_Bus(ILIlong)
PRILcd_Write_Data(ILIlong)
ILI_RS_High
LCD_Writ_Bus(ILIlong)
PRILCD_Writ_Bus(ILILong)'ILILong &= %00000000_00000000_11111111_11111111 ' mask to a word. Not needed if care taken always to send a word valueOUTA &= %11111111_11111111_00000000_00000000' set P0-P15 to zero ready to OROUTA |= ILILong ' merge with the word to output
ILI_WR_Low ' send out the data
ILI_WR_High
PRIILI_RS_LowOUTA &= %11111111_11111011_11111111_11111111' P18 lowPRIILI_RS_HighOUTA |= %00000000_00000100_00000000_00000000' P18 highPRIILI_RD_Low' pulled high in hardware, not used PRIILI_RD_HighPRIILI_WR_LowOUTA &= %11111111_11111101_11111111_11111111' p17 lowPRIILI_WR_HighOUTA |= %00000000_00000010_00000000_00000000' p17 highPRIILI_CS_Low' not used as setting 138 to %010 does thisPRIILI_CS_HighPRIILI_RESET_Low' reset low
Select138(3) ' reset lowPRIILI_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 driverlong 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)PUBstart_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 cogelserepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codePUBstop_ramif cog
cogstop(cog~ - 1)
PUBDoCmd(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 statusrepeatwhile command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error codeDAT'' +--------------------------------------------------------------------------+'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |'' +--------------------------------------------------------------------------+org0
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=goodmovdira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error xwrlong zero, comptr ' command =0 (done)
pause
rdlong cmd, comptr wz' command ?if_zjmp #pause ' not yet' decode commandcmp cmd,#"M"wz' move a block from ram to the displayif_zjmp #moveblock
cmp cmd, #"I"wz' initif_zjmp #init
mov err, cmd ' error = cmd (unknown command)jmp #done
'---------------------------------------------------------------------------------------------------------
ram_open rdlong hubaddr, hubptr ' get hub addressrdlong ramaddr, ramptr ' get ram addressrdlong len, lenptr ' get lengthmov 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 addressmovdira,direction ' set P0-P23 as outputs call #ram_open ' get ramaddr and lenor ramaddr,pin22 ' start with pin 22 high
Moveblock_loop movouta,ramaddr ' send out the address valueandnouta,pin22 ' set pin 22 loworouta,pin22 ' set pin 22 highadd ramaddr,#1' increment ram addressdjnz len,#moveblock_loop
jmp #init
halt jmp #halt
' ************************ Variables ******************************
delay long80' 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_11111111fit496
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.
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.
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.'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!
'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
'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 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.
'' 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
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.