Shop Learn
Propeller GUI touchscreen and full color display - Page 5 — Parallax Forums

Propeller GUI touchscreen and full color display

1235724

Comments

  • average joeaverage joe Posts: 795
    edited 2012-03-09 08:13
    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 :D 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?
  • idbruceidbruce Posts: 6,173
    edited 2012-03-09 08:25
    average joe
    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.

    Bruce
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-03-09 11:59
    Dr_Acula wrote: »
    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.
  • Cluso99Cluso99 Posts: 17,970
    edited 2012-03-09 16:58
    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!
  • average joeaverage joe Posts: 795
    edited 2012-03-09 20:40
    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.. ?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-10 03:20
    my wife has told me no more ordering parts

    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.
    948 x 597 - 202K
    939 x 594 - 200K
    945 x 588 - 252K
  • idbruceidbruce Posts: 6,173
    edited 2012-03-10 06:51
    Hey Doc

    WOW! That is some very serious design work. Nice job.

    You still have my vote for most interesting and impressive thread.

    Bruce
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-11 04:39
    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.

    mcp23008.jpg
    694 x 522 - 47K
  • the-new-guythe-new-guy Posts: 16
    edited 2012-03-11 06:50
    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...
  • average joeaverage joe Posts: 795
    edited 2012-03-12 08:30
    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?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-12 16:28
    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?
  • average joeaverage joe Posts: 795
    edited 2012-03-12 16:39
    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.
  • the-new-guythe-new-guy Posts: 16
    edited 2012-03-12 18:27
    Dr_Acula wrote: »
    What a great idea!

    Thank you!
    Dr_Acula wrote: »
    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.
  • average joeaverage joe Posts: 795
    edited 2012-03-13 18:07
    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?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-14 01:56
    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?
  • average joeaverage joe Posts: 795
    edited 2012-03-14 02:13
    Dr_Acula wrote: »
    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?
  • idbruceidbruce Posts: 6,173
    edited 2012-03-20 02:54
    Okay Doc

    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
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-20 03:56
    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 :)
  • egenrietheregenriether Posts: 29
    edited 2012-03-20 07:41
    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
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-20 14:33
    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.
  • average joeaverage joe Posts: 795
    edited 2012-03-25 03:22
    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.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-25 03:50
    No sorry still waiting on boards. It will need a complete rewrite of the code for the counter version. Hopefully some time later this week?
  • average joeaverage joe Posts: 795
    edited 2012-03-25 04:44
    Ok, sounds good. I should be testing sometime today!
  • average joeaverage joe Posts: 795
    edited 2012-03-29 23:37
    *BUMP*

    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.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-30 01:15
    Boards arrived two hours ago - woot! Hopefully I'll be able to test your code out soon on a real board.
  • average joeaverage joe Posts: 795
    edited 2012-03-30 01:26
    Glad to hear boards arrived.I have not tested code as it is not quite ready. I believe I'm close but need to run through the loops a few times to make sure things are right, which I'm pretty sure they are not yet. Concentrating on writing to the LCD as it should help with debugging if necessary.
    'Starting rewrite for counters using 32k SRAM           Breadboard Hardware *see schematic for more info*
    ' Originally
    ' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
    ' and also contains the dracblade ram driver for fast block moves from ram to the display
    ' Methods:
    ' .Start = start the driver
    ' .Draw  = start drawing at x1,y1 and continue until x2,y2
    ' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
    con
      p_RS                = 16            ''PINS FOR CS - TO KEEP FROM FLOATING 
      p_SPI_EN            = 17                    'LCD_WR            = 17                         ''and sd card defs
      p_SDataCk           = 18                    'DEV_SD_CLK        = 18
      p_SDataIn           = 19                    'DEV_SD_DI         = 19
      p_SdataOut          = 20                    'DEV_SD_DO         = 20    
      p_SPIadd0           = 21                    'DEV_SPI_EN        = 21
      p_SPIadd1           = 22                    'DEV_SPI_ADD0      = 22
      p_SPIadd2           = 23                    'DEV_SPI_ADD1      = 23
      p_BusEn             = 24                    'DEV_SPI_ADD_LE    = 24
      p_RamRD             = 26
      p_BusDir            = 27
    
     a_SPI_RAM_WR      = 0
     a_SPI_Load        = 1
     a_SPI_Count       = 2
     a_SPI_LCD_WR      = 3
     a_SPI_TS_CS       = 4
     a_SPI_SD_CS       = 5
     a_SPI_EXT_CS      = 7
    
      p_unused         = 25
      a_SPI_unused     = 6        
    
      a_RamToProp     = 0
      a_PropToRam     = 1            
    
      
    ''LCD REGISTERS   
      REG_OSCILLATOR                = $0000                               ''Oscillator                                (R00h) (POR = 0000h)
      REG_DRIVEROUTPUTCONTROL       = $0001                               ''Driver Output Control                     (R01h) (POR = 2B3Fh)
      REG_LCDDRIVINGWAVFORM         = $0002                               ''LCD-Driving-Waveform Control              (R02h) (POR = 0000h)
      REG_POWERCONTROL1             = $0003                               ''                                          (R03H)
      REG_DISPLAYCONTROL            = $0007                               ''Display Control                           (R07h) (POR = 0000h)
      REG_FRAMECYCLECONTROL         = $000B                               ''Frame Cycle Control                       (R0Bh) (POR = 5308h)D308 BY DATASHEET
      REG_POWERCONTROL2             = $000C                               ''                                          (R0Ch) (POR = 0004)
      REG_POWERCONTROL3             = $000D                               ''                                          
      REG_POWERCONTROL4             = $000E                               ''
      REG_GATESCANPOSITION          = $000F                               ''Gate Scan Position                        (R0Fh) (POR = 0000h)
      REG_SLEEPMODE                 = $0010                               ''Sleep mode                                (R10h) (POR = 0001h)
      REG_ENTRYMODE                 = $0011                               ''Entry Mode                                (R11h) (POR = 6830h)             
      REG_HPORCH                    = $0016                               ''                                          (R16h) (POR = EF1Ch)
      REG_VPORCH                    = $0017                               ''                                          (R17h) (POR = 0003h)
      REG_POWERCONTROL5             = $001E                               ''                                          
      REG_RAMDATAWRITE              = $0022                               ''
      REG_RAMWRITEDATAMASK1         = $0023                               ''                                          (R23h) (POR = 0000h)
      REG_RAMWRITEDATAMASK2         = $0024                               ''                                          (R24h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL1     = $0041                               ''                                          (R41h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL2     = $0042                               ''                                          (R42h) (POR = 0000h)
      REG_HORIZONTALRAMADDRESSPOS   = $0044                               ''                                          (R44h) (POR = EF00h)
      REG_VERTICALRAMADDRESSSTART   = $0045                               ''                                          (R45h) (POR = 0000h)
      REG_VERTICALRAMADDRESSEND     = $0046                               ''                                          (R46h) (POR = 013Fh)
      REG_FIRSTWINDOWSTART          = $0048                               ''                                          (R48h) (POR = 0000h)
      REG_FIRSTWINDOWEND            = $0049                               ''                                          (R49h) (POR = 013Fh)
      REG_SECONDWINDOWSTART         = $004A                               ''                                          (R4Ah) (POR = 0000h)
      REG_SECONDWINDOWEND           = $004B                               ''                                          (R4Bh) (POR = 013Fh)
      REG_SETGDDRXADDRESSCOUNTER    = $004E                               ''                                          (R4Eh) (POR = 0000h)
      REG_SETGDDRYADDRESSCOUNTER    = $004F
    
      'Ram Allocation table here
      RamStart      =   0
      RamEnd        = 32767
    OBJ  
        wait    : "timing"                                    ' thanks to parallax
        'pst :"Parallax Serial Terminal"
    Var
     long screenbufferaddress
     byte pcog
    PUB boot
        initPins
        'Pst.Start(115200)
        START_SSD1289
        ClearScreenSpin($ffff)                              
      deadend
                                   
    PUB RequestSD
    PUB ReleaseSD
    PUB RequestTS
    PUB ReleaseTS
    
    Pub ClearScreenSpin(c)
       
         Draw(0, 0, 240, 320)
          EnableDisplayPins
         Lcd_Write_Com($22)
         OUTA[15..0]  := c   
       repeat 76800
         StrobeLcdWr
     TristateDisplayPins
          
    pub deadend
    repeat
     waitcnt(cnt)
     
    PUB initPins
    
      outa := %00001001_00000010_00000000_00000000
      dira := %00001001_11100010_00000000_00000000
    
    PUB Start_SSD1289                                        ''Init Display
      EnableDisplayPins                                   ''enable pins 0 to 15
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) 
        Lcd_Write_Data($0021)                               ''GON = 1 DTE = 0 D[1:0] = 01 
        Lcd_Write_Com (REG_OSCILLATOR)                      ''Oscillator (R00h) (POR = 0000h)
        Lcd_Write_Data($0001)                               ''Turn on oscillator
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0023)                               ''GON = 1 DTE = 0 D[1:0] = 11
        Lcd_Write_Com (REG_SLEEPMODE)                       ''Sleep mode (R10h) (POR = 0001h)
        Lcd_Write_Data($0000)     ''                        ''exit sleep mode         
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11
        Lcd_Write_Com (REG_ENTRYMODE)                       ''Entry Mode (R11h) (POR = 6830h)
        Lcd_Write_Data($6838)                               ''
        Lcd_Write_Com (REG_LCDDRIVINGWAVFORM)               ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) 
        Lcd_Write_Data($1000)     ''                        ''
        Lcd_Write_Com (REG_GATESCANPOSITION)                ''Gate Scan Position (R0Fh) (POR = 0000h)  ($0000)
        Lcd_Write_Data($0000)     ''                        ''                                                        ''
        Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL)             ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f    ($633F) 
        Lcd_Write_Data($6B3F) ''                            ''                                                      
        Lcd_Write_Com (REG_FRAMECYCLECONTROL)               ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
        Lcd_Write_Data($5308)                               ''                           '
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) ($0033)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11   
      TristateDisplayPins
        
    PRI EnableDisplayPins
        outa[p_BusDir] := a_PropToRam 
        DIRA :=%00001001_11100011_11111111_11111111 '  RS, 16 data lines active   
        outa[p_BusEn] := 0
        OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr 
    PRI TristateDisplayPins ' tristate all pins -                                                 
        DIRA :=%00000000_00000000_00000000_00000000 ''
        
    PRI LCD_Writ_Bus(V) 
        OUTA[15..0]  := V
        StrobeLcdWr                                           ' toggle write pin
        
    PRI Lcd_Write_Com(V)
        RSLow
        LCD_Writ_Bus(V)
        RSHigh
        
    PRI Lcd_Write_Data(V)
        'RSHigh
        LCD_Writ_Bus(V)
        
    PRI RSLow                                    
        outa[p_RS] := 0    
    PRI RSHigh
        outa[p_RS] := 1
                       '
    PRI StrobeLcdWr
       'outa[p_SPIadd2..p_SPIadd0] := LCD_WR                          
       outa[p_SPI_En] := 0
       outa[p_SPI_En] := 1
     
    PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
        EnableDisplayPins                       ' enable pins 0-11
      HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)     
        Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
        Lcd_Write_Data(y1) 
        Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
        Lcd_Write_Data(y2)
        Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
        Lcd_Write_Data(x1 )
        Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
        Lcd_Write_Data( y1)    
        TristateDisplayPins                                   ' tristate pins 0-11 so other drivers can use these pins
    
    PUB Pixel(pixelcolor)               ' send out a pixel, high byte then low byte
        EnableDisplayPins
        Lcd_Write_Com($22)               ' enable pins 0-11    
        Lcd_Write_Data(pixelcolor)                        
        TristateDisplayPins                                   ' tristate pins 0-11 so other drivers can use these pins               
    
    
    
    PUB ReadRamByte(address)                                ' masks off all but a byte - used often
        docmd("R",@result,address,1)                        ' read just 1 byte
        result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
        return result
    
    PUB WriteRamByte(value,address)                         ' write a byte to ram
        docmd("W",@value,address,1)
    
    PUB ReadRamLong(address)                             ' read a long, stored LSB first
        docmd("R",@result,address,4)
        return result
    
    PUB WriteRamLong(value,address)                         ' write a long to ram
        docmd("W",@value,address,4) 
          
    
    CON
    ''Dracblade driver for talking to a ram chip via three latches
    '' Modified code from Cluso's triblade
    ''also includes commands to move blocks of data to the ILI9325 touchscreen display
    ''Modified for counters by Joe
    ' DoCmd (command_, hub_address, ram_address, block_length)                                                         
    
    ' I - initialise     
    ' W - Move block_length bytes from hub_address to ram_address
    ' R - Move block_length bytes from ram_address to hub_address
    ' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256) 
    ' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
    ' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
    ' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
    ' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
    
    '  E - Set Draw(E, H,Vs,Ve)
    '  F - Clear Screen(F, color,NA,NA )
    VAR
    
    ' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
       long  command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
    '        command  = R, W, H I,D etc =0 when operation completed by cog
    '        hubaddrs = hub address for data buffer
    '        ramaddrs = ram address for data ($0000 to $FFFF)
    '        blocklen = ram buffer length for data transfer
    '        errx     = returns =0 (false=good), else <>0 (true & error code)
    '        cog      = cog no of driver (set by spin start routine)
       
    PUB start_ram : err_
    ' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
      command := "I"
      cog := 1 + cognew(@tbp2_start, @command)
      if cog == 0
        err_ := $FF                 ' error = no cog
      else
        repeat while command        ' driver cog sets =0 when done
        err_ := errx                ' driver cog sets =0 if no error, else xx = error code
    
    PUB stop_ram
       if cog
          cogstop(cog~ - 1)      
    
    PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
    ' Do the command: R, W, N, F, H,I,D
      hubaddrs := hub_address       ' hub address start
      ramaddrs := ram_address       ' ram address start
      blocklen := block_length      ' block length
      command  := command_          ' must be last !!
    ' Wait for command to complete and get status
      repeat while command          ' driver cog sets =0 when done
      err_ := errx                  ' driver cog sets =0 if no error, else xx = error code
    
    
    DAT
    '' +--------------------------------------------------------------------------+
    '' | Dracblade Ram Driver (with grateful acknowlegements to Cluso)            |
    '' +--------------------------------------------------------------------------+
                            org     0
    tbp2_start    ' setup the pointers to the hub command interface (saves execution time later
                                          '  +-- These instructions are overwritten as variables after start
    comptr                  mov     comptr, par     ' -|  hub pointer to command                
    hubptr                  mov     hubptr, par     '  |  hub pointer to hub address            
    ramptr                  add     hubptr, #4      '  |  hub pointer to ram address            
    lenptr                  mov     ramptr, par     '  |  hub pointer to length                 
    errptr                  add     ramptr, #8      '  |  hub pointer to error status           
    cmd                     mov     lenptr, par     '  |  command  I/R/W/G/P/Q                  
    hubaddr                 add     lenptr, #12     '  |  hub address                           
    ramaddr                 mov     errptr, par     '  |  ram address                           
    len                     add     errptr, #16     '  |  length                                
    err                     nop                     ' -+  error status returned (=0=false=good) 
    
    
    ' Initialise hardware tristates everything and read/write set the pins
    init                    mov     err, #0                  ' reset err=false=good
                            mov     dira,zero                ' tristate the pins
    
    done                    wrlong  err, errptr             ' status  =0=false=good, else error x
                            wrlong  zero, comptr            ' command =0 (done)
    ' wait for a command (pause short time to reduce power)
    pause
    '                        mov     ctr, delay      wz      ' if =0 no pause
    '              if_nz     add     ctr, cnt
    '              if_nz     waitcnt ctr, #0                 ' wait for a short time (reduces power)
                            rdlong  cmd, comptr     wz      ' command ?
                  if_z      jmp     #pause                  ' not yet
    ' decode command
    '                       single raw command format "DoCmd(Z,hub_address, unused, length)
                            cmp     cmd, #"Z"       wz      ' Z moves command to the display from hub address, length times
                  if_z      jmp     #hubtodisplayCommand
    '                       single raw command format "DoCmd(Y, hub_address, unused, length)                                     
                            cmp     cmd, #"Y"       wz      ' Y moves data to the display from hub address, length times
                  if_z      jmp     #hubtodisplayData
                  
    ram_open                rdlong  hubaddr, hubptr         ' get hub address
                            rdlong  ramaddr, ramptr         ' get ram address
                            rdlong  len, lenptr             ' get length
                            mov     err, #5                 ' err=5
    ram_open_ret            ret
    
    hubtodisplayData        ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
                            call    #ram_open               ' gets hubaddr and len (ignores ramaddress)                        
                            call    #setRShigh              ' set pins for data output
    :hubdisploop            rdword  Display, hubaddr        ' copy word from hub, not needed ?
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned                        
                            call    #ilidisplayword         ' send these bytes to the display
                            djnz    len,#:hubdisploop       ' loop until done
                            jmp     #init                   ' set pins to tristate
    
                            
    hubtodisplayCommand     call    #ram_open               ' gets hubaddr and len (ignores ramaddress)
    
    :hubdisplayloop         call    #setRSlow                ' set pins for Command output
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display       
                            call    #setRShigh
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display
    
                            djnz    len,#:hubdisplayloop       ' loop until done
                            jmp     #init                   ' set pins to tristate                                                                                   
    
    
    
    setRShigh               mov     dira, DirsEnabled      ' set rsHigh by tristate pin                  
    setRShigh_ret           ret
    
    
    setRSlow                 add   zero,#0                   wz     'prime z flag
                             mov   dira, DirsEnabled                ' set rsHigh by tristate pin       
                             muxz  dira, RSpin                      ' set rsLow by enabling pin
    setRslow_ret
    
    
    ilidisplayword            ' pass data out, sends out to the display
                            add display, p2dpins       wz                'this add presets the data for control pins and primes WZ flag for mux operation 
                            mov outa,    display                         'then make pins = data
    
                            muxnz dira,EnablePin                          'make enable pin high
                            add timeout, #$f                               
    :wait                   djnz timeout, #:wait
                            muxz dira, EnablePin
                                             'missing strobe lcd enable
    ilidisplayword_ret      ret
    
    
    
    
    
    
                 '          cmp     cmd, #"E"       wz
                 ' if_z     jmp     #SetDraw
                 '          cmp     cmd, #"F"       wz
                 ' if_z     jmp     #ClearScreen
                  
    '                       cmp     cmd, #"R"       wz      ' R = read block from external ram to hub
    '             if_z      jmp     #rdblock
    '                       cmp     cmd, #"W"       wz      ' W = write block from hub to external ram
    '             if_z      jmp     #wrblock
    '                       cmp     cmd, #"C"       wz      ' C moves a block of data from ram to the display
    '             if_z      jmp     #extramtodisplay
    '
    '                       cmp     cmd, #"A"       wz      ' A moves 256 bytes from hub to external ram
    '             if_z      jmp     #blockhubtoram
    '                       cmp     cmd, #"B"       wz      ' B moves 256 bytes from external ram to hub
    '             if_z      jmp     #blockramtohub
    '                       cmp     cmd, #"E"       wz      ' convert 3 byte .raw format to 2 byte .ili format - hub to hub
    '             if_z      jmp     #rawtoiliformat
    '                       cmp     cmd, #"F"       wz      ' draw a transparent icon, pass two locations in hub ram and len = number of pixels
    '             if_z      jmp     #drawicon
    '                       cmp     cmd, #"I"       wz      ' init
    '             if_z      jmp     #init     
    '                       mov     err, cmd                ' error = cmd (unknown command)
    '                       jmp     #done
    
    
    
    SetDraw
     ret
    ClearScreen
     ret
     
    ' set all latches (replaces H command), pass value in third variable of the DoCmd
    
    'setlatches              call #ram_open                  ' gets address value in 'address'
    '                        call #lowmiddlehighlatch        ' set all the latches
    '                        jmp  #init
    
    '---------------------------------------------------------------------------------------------------------
    'Memory Access Functions
                            ' read block from external ram to hub
    'rdblock                call    #ram_open               ' get variables from hub variables
    'rdloop                 call    #read_byte              ' read byte from address into data_8
    '                       wrbyte  data_8,hubaddr          ' write data_8 to hubaddr ie copy byte to hub
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       djnz    len,#rdloop             ' loop until done
    '                       jmp     #init                   ' reinitialise
    
    
                            ' write block from hub to external ram
    'wrblock                call    #ram_open
    'wrloop                 rdbyte  data_8, hubaddr         ' copy byte from hub
    '                       call    #write_byte             ' write byte from data_8 to address
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       djnz    len,#wrloop             ' loop until done
    '                       jmp     #init                   ' reinitialise
    
    
                            
    
    'read_byte              call #lowmiddlehighlatch        ' set up latches 
    '                       call #read_memory_byte          ' read a byte into data_8
    'read_byte_ret          ret                        
    
    
    '________________________________________TODO
    'read_memory_byte       mov dira,LatchDirection2        ' for reads so P0-P7 tristate till do read
    '                       mov outa,GateHigh               ' actually ReadEnable but they are the same
    '                       andn outa,GateHigh              ' set gate low
    '                       nop                             ' short delay to stabilise
    '                       nop
    '                       mov data_8, ina                 ' read SRAM
    '                       and data_8, #$FF                ' extract 8 bits
    '                       or  outa,GateHigh               ' set the gate high again
    'read_memory_byte_ret   ret
    
    
    
    'write_byte             call #lowmiddlehighlatch        ' set up latches
    '                       call #write_memory_byte
    'write_byte_ret         ret
    '
    'write_memory_byte      mov outx,data_8                 ' get the byte to output
    '                       and outx, #$FF                  ' ensure upper bytes=0
    '                       or outx,WriteEnable             ' or with correct 138 address
    '                       mov outa,outx                   ' send it out
    '                       andn outa,GateHigh              ' set gate low
    '                       nop                             ' no nop doesn't work, one does, so put in two to be sure
    '                       nop                             ' another NOP
    '                       or outa,GateHigh                ' set it high again
    'write_memory_byte_ret  ret
    
    'LowMiddleHighLatch ' sets up the ram latches.
    '                       call #lowlatchout
    '                       call #middlelatchout
    '                       call #highlatchout
    'LowMiddleHighLatch_ret ret
    
    ' write to low, middle and high latches as subroutines. Pass 'ramaddr' which is a long. Extract xxxxxxxx_HHHHHHHH_MMMMMMMM_LLLLLLLL
    
    'LowLatchOut            mov outx,ramaddr                ' get the address into a temp variable
     '                      and outx,#$FF                   ' mask the low byte
    '                       or  outx,LowAddress             ' or with 138 low address
      '                     call #LatchOutput
    'LowLatchOut_ret        ret                        
    
    'MiddleLatchOut         mov outx,ramaddr                ' middle byte get the address into a temp variable
    '                       shr outx,#8                     ' shift right by 8 places
    '                       and outx,#$FF                   ' mask the low byte
    '                       or  outx,MiddleAddress          ' or with 138 middle address
    '                       call #LatchOutput
    'MiddleLatchOut_ret     ret                        
    
    'HighLatchOut           mov outx,ramaddr                ' middle byte get the address into a temp variable
    '                       shr outx,#16                    ' shift right by 16 places
    '                       and outx,#$FF                   ' mask the low byte
    '                       or  outx,HighAddress            ' or with 138 high address
    '                       call #LatchOutput                        
    'HighLatchOut_ret       ret
    
    'LatchOutput            mov dira,LatchDirection         ' set up the pins for programming latch chips
    '                       mov outa,outx                   ' send it out
    '                       andn outa,GateHigh              ' set gate low  nop not needed
    '                       or outa,GateHigh                ' set it high again 
    'LatchOutput_ret        ret
    '
    ' ** move a block of 256 bytes from hub to external ram **
    
    'Blockhubtoram          call    #ram_open               ' get variables from hub variables
    '                       call    #lowmiddlehighlatch     ' set all three latches
    '                       mov     len,#256                ' do 256 times
    'Blockhubtoram_loop                          
     '                      rdbyte  data_8, hubaddr         ' copy byte from hub
     '                      call    #write_memory_byte      ' send out to the ram 
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       call    #lowlatchout            ' update the low latch
    '                       djnz    len,#blockhubtoram_loop ' loop until done
    '                       jmp     #init                    ' restart
    
    ' ** move a block of 256 bytes from external ram to hub **
    
    'Blockramtohub          call    #ram_open               ' get variables from hub variables
    '                       call    #lowmiddlehighlatch     ' set all three latches
    '                       mov     len,#256                ' do 256 times
    'Blockramtohub_loop                          
    '                       call    #read_memory_byte       ' read byte from address into data_8
    '                       wrbyte  data_8,hubaddr          ' write data_8 to hubaddr ie copy byte to hub
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       call    #lowlatchout            ' update the low latch
    '                       djnz    len,#blockramtohub_loop ' loop until done
    '                       jmp     #init                    ' restart
    '
    
    
    
    
    'extramtodisplay ' send a block of data blocklen from external memory ramaddress to the ILI9325 display
    '                       call    #ram_open               ' gets ramaddr and len (ignore hubaddr)
    '                       shr     len,#1                  ' len /2 as 2 bytes per pixel   
    '                       call    #setRShigh              ' set pins for data output 
    'ililoop                call    #readiliword            ' read ilihigh, ililow, increments ramaddr by 2
    '                       call    #ilidisplayword         ' sends ilihigh ililow to the display
    '                       djnz    len,#ililoop            ' loop until done
    '                       jmp     #init                   ' set pins to tristate
    
    'readiliword            ' read ilihigh and ililow from ramaddr, increments ramaddr by 2
    '                       call    #read_byte              ' read byte from ramaddr into data_8
    '                       mov     dira,latchdirection     ' enable for output (readmemorybyte leaves P0-P7 as inputs) 
    '                       mov     ilihigh,data_8
    '                       add     ramaddr,#1              ' add 1 to ram address 
    '                       call    #read_byte              ' read second byte from address into data_8
    '                       mov     dira,latchdirection     ' enable for output (readmemorybyte leaves P0-P7 as inputs) 
    '                       mov     ililow,data_8
    '                       add     ramaddr,#1              ' add 1 to ram address
    'readiliword_ret        ret                        
    
    
    '                                               
    'RawtoILIformat         ' takes a .raw 3 byte RRRRRRRR GGGGGGGG BBBBBBBB and converts to 2 byte RRRRRGGG GGGBBBBB
    '                       ' pass hubaddr, ramaddr and len
    '                       ' hubaddr is source location, len is number of pixels
    '                       ' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklength
    '                       call    #ram_open ' gets hubaddress, ramaddress and len (ignores ramaddress)
    'rawloop
    '                       rdbyte red,hubaddr
    '                       add hubaddr,#1
    '                       rdbyte green,hubaddr
    '                       add hubaddr,#1
    '                       rdbyte blue,hubaddr
    '                       add hubaddr,#1
    '                       call #rgbtoili
    '                       wrbyte ilihigh,ramaddr
    '                       add ramaddr,#1
    '                       wrbyte ililow,ramaddr
    '                       add ramaddr,#1
    '                       djnz    len,#rawloop            ' loop until done 
    '                       jmp     #init                   ' set pins to tristate
    
    'RGBtoILI               ' pass red,green, blue, returns ililow and ilihigh
    '                       shr     red,#3                  ' 000RRRRR 
    '                       shl     red,#3                  ' RRRRR000 
    '                       shr     green,#2                ' 00GGGGGG
    '                       mov     ilihigh,green           ' ilihigh = 00GGGGGG
    '                       shr     ilihigh,#3              ' ilihigh = 00000GGG
    '                       or      ilihigh,red             ' ilihigh = RRRRRGGG
    '                       and     green,#%00000111        ' 00000GGG
    '                       shl     green,#5                ' GGG00000
    '                       mov     ililow,green            ' ililow = GGG00000
    '                       shr     blue,#3                 ' blue = 000BBBBB
    '                       or      ililow,blue             ' ililow = GGGBBBBB
    'RGBtoILI_ret           ret
    
    'ILItoRGB               ' pass ilihigh RRRRRGGG and ililow GGGBBBBB returns RRRRR000 GGGGGG00 BBBBB000
    '                       mov     red,ilihigh             ' red = RRRRRGGG
    '                       and     red,#%11111000          ' red = RRRRR000
    '                       mov     green,ilihigh           ' green = RRRRRGGG
    '                       shl     green,#5                ' green = GGG00000
    '                       mov     i,ililow                ' i = GGGBBBBB
    '                       and     i,#%11100000            ' i = GGG00000
    '                       shr     i,#3                    ' i = 000GGG00
    '                       or      green,i                 ' green = GGGGGG00
    '                       mov     blue,ililow             ' blue = GGGBBBBB
    '                       shl     blue,#3                 ' blue = BBBBB000
    'ILItoRGB_ret           ret
    
                           
    
    'DrawIcon               ' pass hubaddr, ramaddr and len. 
                            ' hubaddr is location in ram of the picture (messy naming of the variable)
                            ' ramaddr is the location in ram of the mask (both sources are ram, not hub)
                            ' format of the picture is 2 bytes RRRRRGGG GGGBBBBB
    '                       ' format of the icon is R G B A and A = 0 for transparent and 255 for full opaque (transparent usually round the edges)
    '                       call    #ram_open ' gets hubaddr, ramaddr and len
    '                       mov     backgroundcount,hubaddr ' backgroundcount is the picture
    '                       mov     iconcount,ramaddr       ' iconcount is the icon
    'drawiconloop           mov     ramaddr,backgroundcount ' address for reading the picture
    '                       call    #readiliword            ' get ilihigh and ililow RRRRRGGG GGGBBBBB
    '                       mov     backgroundcount,ramaddr ' store new picture counter
    '                       call    #ilitoRGB               ' convert to red green blue
     '                      mov     ramaddr,iconcount       ' get icon location
    '                       call    #readiliword            ' returns ilihigh and ililow which are actually red and green
    '                       mov     r,ilihigh               ' get red
    '                       mov     g,ililow                ' get green
    '                       call    #readiliword            ' returns ilihigh and ililow which are actually blue and alpha             
    '                       mov     b,ilihigh               ' get blue
    '                       mov     a,ililow                ' get alpha
    '                       mov     iconcount,ramaddr       ' restore the icon pointer
    '                       cmp     a,#128          wc      ' test if background or foreground
    '             if_c      jmp     #drawiconfinish         ' if carry then this is background
    '                       mov     red,r                   ' move icon to foreground
    '                       mov     green,g
    '                       mov     blue,b
    'drawiconfinish         call    #rgbtoili               ' convert to ililow and ilihigh
    '                       call    #ilidisplayword         ' send out to the display
    '                       djnz    len,#drawiconloop       ' loop len times until finished
    '                       jmp     #init                   ' set pins to tristate
    
    
    
    
    
    delay                   long    80                                    ' waitcnt delay to reduce power (#80 = 1uS approx)
    ctr                     long    0                                     ' used to pause execution (lower power use) & byte counter
    
    'GateHigh               long    %00000000_00000000_00000001_00000000  ' HC138 gate high, all others must be low
    
    'Outx                   long    0                                     ' for temp use, same as n in the spin code
    'LatchDirection         long    %00000000_00000000_00001111_11111111 ' 138 active, gate active and 8 data lines active
    'LatchDirection2        long    %00000000_00000000_00001111_00000000 ' for reads so data lines are tristate till the read
    
    'LowAddress             long    %00000000_00000000_00000101_00000000 ' low address latch = xxxx010x and gate high xxxxxxx1
    'MiddleAddress          long    %00000000_00000000_00000111_00000000 ' middle address latch = xxxx011x and gate high xxxxxxx1
    'HighAddress            long    %00000000_00000000_00001001_00000000 ' high address latch = xxxx100x and gate high xxxxxxx1
    'ReadEnable long    %00000000_00000000_00000001_00000000 ' /RD = xxxx000x and gate high xxxxxxx1
                                                            ' commented out as the same as GateHigh
    
    Zero                    long    %00000000_00000000_00000000_00000000 ' for tristating all pins
    data_8                  long    0                                    ' so code compatability with zicog driver
    i                       long    0                                    ' general purpose value
    j                       long    0                                    ' general purpose value
    a                       long    0                                    ' general purpose value
    b                       long    0                                    ' general purpose value
    r                       long    0                                    ' general purpose value
    g                       long    0                                    ' general purpose value
                                     
    ' variables and constants for the ILI9325 display
    'Latch5address          long    %00000000_00000000_00001011_00000000 ' latch5 address
    'Latch6address          long    %00000000_00000000_00001101_00000000 ' latch6 address
    'Latch7data             long    %00000000_00000000_00001111_00010111 ' latch7 address 111x and gate high, reset high, cs low, read high, write high, rs high for data output, combines rshigh in spin into one line                   
    'Latch7WriteLow         long    %00000000_00000000_00001111_00010101 ' cs low, write low
    'ililow                 long    0                                    ' low data byte latch5
    'ilihigh                long    0                                    ' high data byte latch6
    'red                    long    0                                    ' red, green blue variables
    'green                  long    0
    'blue                   long    0
    'backgroundcount        long    0
    'iconcount              long    0
    
    
    
    
    lowWordMask                       long $0000_ffff
                                          'pin settings
    EnablePin                         long   %00000000_00000010_00000000_00000000
    RSPin                             long   %00000000_00000001_00000000_00000000
    
    p2dpins                           long   %00001000_01100000_00000000_00000000      ' propToDisplay    enable pin low, but tristate, primed for lcd transfer                                               
    PinsInit                          long   %00001001_01100010_00000000_00000000      'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high 
    
    DirsDisabled                      long   %00000000_00000000_00000000_00000000
    DirsEnabled                       long   %00001001_11100000_11111111_11111111                                                                           ''                                          (R4Fh) (POR = 0000h)
    
    
    
    'bufferaddress          res 1
    LCD_cmd                 res 1
    LCD_data                res 1
    'Pntr                   res 1
    
    'ForegroundFormat       res 1
    'BackgroundFormat       res 1
    'ForegroundScreen       res 1
    'BackgroundScreen       res 1
    
    timeout                 res 1
    Display                 res 1
    fit
    
    This is where I'm at so far. Notice large portions of the code are commented out. I believe the spin portion should still work. The rest is a work in progress. I'll keep you updated as i go.


    *edit*
    Please remember I am using DIRA to control RS pin and ENABLE pin in ASM since I have pullup resistors on these pins!
  • average joeaverage joe Posts: 795
    edited 2012-03-30 03:38
    I got it! ASM now transfers data from hub to display. It's VERY quick using a 16 block buffer.
    'Starting rewrite for counters using 32k SRAM           Breadboard Hardware *see schematic for more info*
    ' Originally
    ' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
    ' and also contains the dracblade ram driver for fast block moves from ram to the display
    ' Methods:
    ' .Start = start the driver
    ' .Draw  = start drawing at x1,y1 and continue until x2,y2
    ' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
    CON
     _xinfreq = 5_000_000
     _clkmode = xtal1 + pll16x
    
      p_RS                = 16            ''PINS FOR CS - TO KEEP FROM FLOATING 
      p_SPI_EN            = 17                    'LCD_WR            = 17                         ''and sd card defs
      p_SDataCk           = 18                    'DEV_SD_CLK        = 18
      p_SDataIn           = 19                    'DEV_SD_DI         = 19
      p_SdataOut          = 20                    'DEV_SD_DO         = 20    
      p_SPIadd0           = 21                    'DEV_SPI_EN        = 21
      p_SPIadd1           = 22                    'DEV_SPI_ADD0      = 22
      p_SPIadd2           = 23                    'DEV_SPI_ADD1      = 23
      p_BusEn             = 24                    'DEV_SPI_ADD_LE    = 24
      p_RamRD             = 26
      p_BusDir            = 27
    
     a_SPI_RAM_WR      = 0
     a_SPI_Load        = 1
     a_SPI_Count       = 2
     a_SPI_LCD_WR      = 3
     a_SPI_TS_CS       = 4
     a_SPI_SD_CS       = 5
     a_SPI_EXT_CS      = 7
    
      p_unused         = 25
      a_SPI_unused     = 6        
    
      a_RamToProp     = 0
      a_PropToRam     = 1            
    
      
    ''LCD REGISTERS   
      REG_OSCILLATOR                = $0000                               ''Oscillator                                (R00h) (POR = 0000h)
      REG_DRIVEROUTPUTCONTROL       = $0001                               ''Driver Output Control                     (R01h) (POR = 2B3Fh)
      REG_LCDDRIVINGWAVFORM         = $0002                               ''LCD-Driving-Waveform Control              (R02h) (POR = 0000h)
      REG_POWERCONTROL1             = $0003                               ''                                          (R03H)
      REG_DISPLAYCONTROL            = $0007                               ''Display Control                           (R07h) (POR = 0000h)
      REG_FRAMECYCLECONTROL         = $000B                               ''Frame Cycle Control                       (R0Bh) (POR = 5308h)D308 BY DATASHEET
      REG_POWERCONTROL2             = $000C                               ''                                          (R0Ch) (POR = 0004)
      REG_POWERCONTROL3             = $000D                               ''                                          
      REG_POWERCONTROL4             = $000E                               ''
      REG_GATESCANPOSITION          = $000F                               ''Gate Scan Position                        (R0Fh) (POR = 0000h)
      REG_SLEEPMODE                 = $0010                               ''Sleep mode                                (R10h) (POR = 0001h)
      REG_ENTRYMODE                 = $0011                               ''Entry Mode                                (R11h) (POR = 6830h)             
      REG_HPORCH                    = $0016                               ''                                          (R16h) (POR = EF1Ch)
      REG_VPORCH                    = $0017                               ''                                          (R17h) (POR = 0003h)
      REG_POWERCONTROL5             = $001E                               ''                                          
      REG_RAMDATAWRITE              = $0022                               ''
      REG_RAMWRITEDATAMASK1         = $0023                               ''                                          (R23h) (POR = 0000h)
      REG_RAMWRITEDATAMASK2         = $0024                               ''                                          (R24h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL1     = $0041                               ''                                          (R41h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL2     = $0042                               ''                                          (R42h) (POR = 0000h)
      REG_HORIZONTALRAMADDRESSPOS   = $0044                               ''                                          (R44h) (POR = EF00h)
      REG_VERTICALRAMADDRESSSTART   = $0045                               ''                                          (R45h) (POR = 0000h)
      REG_VERTICALRAMADDRESSEND     = $0046                               ''                                          (R46h) (POR = 013Fh)
      REG_FIRSTWINDOWSTART          = $0048                               ''                                          (R48h) (POR = 0000h)
      REG_FIRSTWINDOWEND            = $0049                               ''                                          (R49h) (POR = 013Fh)
      REG_SECONDWINDOWSTART         = $004A                               ''                                          (R4Ah) (POR = 0000h)
      REG_SECONDWINDOWEND           = $004B                               ''                                          (R4Bh) (POR = 013Fh)
      REG_SETGDDRXADDRESSCOUNTER    = $004E                               ''                                          (R4Eh) (POR = 0000h)
      REG_SETGDDRYADDRESSCOUNTER    = $004F
    
      'Ram Allocation table here
      RamStart      =   0
      RamEnd        = 32767
    
      ScreenBufferSize = 16
      
    OBJ  
        wait    : "timing"                                    ' thanks to parallax
        'pst :"Parallax Serial Terminal"
    Var
     long screenbufferaddress
     long screen[ScreenBufferSize]
     byte pcog
    PUB boot
        initPins
        'Pst.Start(115200)
        START_SSD1289
        ClearScreenSpin($ffff)
        start_ram
        longfill(@screen, 0, 16)
        repeat (76800 / 16)
          DoCmd("Y", @screen,-1, 16)
         'wait.pause10us(100)                  
      deadend
                                   
    PUB RequestSD
    PUB ReleaseSD
    PUB RequestTS
    PUB ReleaseTS
    
    Pub ClearScreenSpin(c)
                                   
         Draw(0, 0, 239, 319)
          EnableDisplayPins
         Lcd_Write_Com($22)
         OUTA[15..0]  := c   
       repeat 76800
         StrobeLcdWr
     TristateDisplayPins
          
    pub deadend
    repeat
     waitcnt(cnt)
     
    PUB initPins
    
      outa := %00001001_00000010_00000000_00000000
      dira := %00001001_11100010_00000000_00000000
    
    PUB Start_SSD1289                                        ''Init Display
      EnableDisplayPins                                   ''enable pins 0 to 15
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) 
        Lcd_Write_Data($0021)                               ''GON = 1 DTE = 0 D[1:0] = 01 
        Lcd_Write_Com (REG_OSCILLATOR)                      ''Oscillator (R00h) (POR = 0000h)
        Lcd_Write_Data($0001)                               ''Turn on oscillator
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0023)                               ''GON = 1 DTE = 0 D[1:0] = 11
        Lcd_Write_Com (REG_SLEEPMODE)                       ''Sleep mode (R10h) (POR = 0001h)
        Lcd_Write_Data($0000)     ''                        ''exit sleep mode         
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11
        Lcd_Write_Com (REG_ENTRYMODE)                       ''Entry Mode (R11h) (POR = 6830h)
        Lcd_Write_Data($6838)                               ''
        Lcd_Write_Com (REG_LCDDRIVINGWAVFORM)               ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) 
        Lcd_Write_Data($1000)     ''                        ''
        Lcd_Write_Com (REG_GATESCANPOSITION)                ''Gate Scan Position (R0Fh) (POR = 0000h)  ($0000)
        Lcd_Write_Data($0000)     ''                        ''                                                        ''
        Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL)             ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f    ($633F) 
        Lcd_Write_Data($6B3F) ''                            ''                                                      
        Lcd_Write_Com (REG_FRAMECYCLECONTROL)               ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
        Lcd_Write_Data($5308)                               ''                           '
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) ($0033)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11   
      TristateDisplayPins
        
    PRI EnableDisplayPins
        outa[p_BusDir] := a_PropToRam 
        DIRA :=%00001001_11100011_11111111_11111111 '  RS, 16 data lines active   
        outa[p_BusEn] := 0
        OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr 
    PRI TristateDisplayPins ' tristate all pins -                                                 
        DIRA :=%00000000_00000000_00000000_00000000 ''
        
    PRI LCD_Writ_Bus(V) 
        OUTA[15..0]  := V
        StrobeLcdWr                                           ' toggle write pin
        
    PRI Lcd_Write_Com(V)
        RSLow
        LCD_Writ_Bus(V)
        RSHigh
        
    PRI Lcd_Write_Data(V)
        'RSHigh
        LCD_Writ_Bus(V)
        
    PRI RSLow                                    
        outa[p_RS] := 0    
    PRI RSHigh
        outa[p_RS] := 1
                       '
    PRI StrobeLcdWr
       'outa[p_SPIadd2..p_SPIadd0] := LCD_WR                          
       outa[p_SPI_En] := 0
       outa[p_SPI_En] := 1
     
    PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
        EnableDisplayPins                       ' enable pins 0-11
      HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)     
        Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
        Lcd_Write_Data(y1) 
        Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
        Lcd_Write_Data(y2)
        Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
        Lcd_Write_Data(x1 )
        Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
        Lcd_Write_Data( y1)    
        TristateDisplayPins                                   ' tristate pins 0-11 so other drivers can use these pins
    
    PUB Pixel(pixelcolor)               ' send out a pixel, high byte then low byte
        EnableDisplayPins
        Lcd_Write_Com($22)               ' enable pins 0-11    
        Lcd_Write_Data(pixelcolor)                        
        TristateDisplayPins                                   ' tristate pins 0-11 so other drivers can use these pins               
    
    
    
    'PUB ReadRamByte(address)                                ' masks off all but a byte - used often
    '    docmd("R",@result,address,1)                        ' read just 1 byte
    '    result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
    '    return result
    
    'PUB WriteRamByte(value,address)                         ' write a byte to ram
    '    docmd("W",@value,address,1)
    '
    'PUB ReadRamLong(address)                             ' read a long, stored LSB first
    '    docmd("R",@result,address,4)
    '    return result
    '
    'PUB WriteRamLong(value,address)                         ' write a long to ram
    '    docmd("W",@value,address,4) 
    '      
    '
    CON
    ''Dracblade driver for talking to a ram chip via three latches
    '' Modified code from Cluso's triblade
    ''also includes commands to move blocks of data to the ILI9325 touchscreen display
    ''Modified for counters by Joe
    ' DoCmd (command_, hub_address, ram_address, block_length)                                                         
    
    ' I - initialise     
    ' W - Move block_length bytes from hub_address to ram_address
    ' R - Move block_length bytes from ram_address to hub_address
    ' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256) 
    ' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
    ' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
    ' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
    ' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
    
    '  E - Set Draw(E, H,Vs,Ve)
    '  F - Clear Screen(F, color,NA,NA )
    
    '  Y - moves data to the display from hub address, length times
    '  Z - moves command to the display from hub address, length times
    
    VAR
    
    ' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
       long  command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
    '        command  = R, W, H I,D etc =0 when operation completed by cog
    '        hubaddrs = hub address for data buffer
    '        ramaddrs = ram address for data ($0000 to $FFFF)
    '        blocklen = ram buffer length for data transfer
    '        errx     = returns =0 (false=good), else <>0 (true & error code)
    '        cog      = cog no of driver (set by spin start routine)
       
    PUB start_ram : err_
    ' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
      command := "I"
      cog := 1 + cognew(@tbp2_start, @command)
      if cog == 0
        err_ := $FF                 ' error = no cog
      else
        repeat while command        ' driver cog sets =0 when done
        err_ := errx                ' driver cog sets =0 if no error, else xx = error code
    
    PUB stop_ram
       if cog
          cogstop(cog~ - 1)      
    
    PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
    ' Do the command: R, W, N, F, H,I,D
      hubaddrs := hub_address       ' hub address start
      ramaddrs := ram_address       ' ram address start
      blocklen := block_length      ' block length
      command  := command_          ' must be last !!
    ' Wait for command to complete and get status
      repeat while command          ' driver cog sets =0 when done
      err_ := errx                  ' driver cog sets =0 if no error, else xx = error code
    
    
    DAT
    '' +--------------------------------------------------------------------------+
    '' | Dracblade Ram Driver (with grateful acknowlegements to Cluso)            |
    '' +--------------------------------------------------------------------------+
                            org     0
    tbp2_start    ' setup the pointers to the hub command interface (saves execution time later
                                          '  +-- These instructions are overwritten as variables after start
    comptr                  mov     comptr, par     ' -|  hub pointer to command                
    hubptr                  mov     hubptr, par     '  |  hub pointer to hub address            
    ramptr                  add     hubptr, #4      '  |  hub pointer to ram address            
    lenptr                  mov     ramptr, par     '  |  hub pointer to length                 
    errptr                  add     ramptr, #8      '  |  hub pointer to error status           
    cmd                     mov     lenptr, par     '  |  command  I/R/W/G/P/Q                  
    hubaddr                 add     lenptr, #12     '  |  hub address                           
    ramaddr                 mov     errptr, par     '  |  ram address                           
    len                     add     errptr, #16     '  |  length                                
    err                     nop                     ' -+  error status returned (=0=false=good) 
    
    
    ' Initialise hardware tristates everything and read/write set the pins
    init                    mov     err, #0                  ' reset err=false=good
                            mov     dira,zero                ' tristate the pins
    
    done                    wrlong  err, errptr             ' status  =0=false=good, else error x
                            wrlong  zero, comptr            ' command =0 (done)
    ' wait for a command (pause short time to reduce power)
    pause
    '                        mov     ctr, delay      wz      ' if =0 no pause
    '              if_nz     add     ctr, cnt
    '              if_nz     waitcnt ctr, #0                 ' wait for a short time (reduces power)
                            rdlong  cmd, comptr     wz      ' command ?
                  if_z      jmp     #pause                  ' not yet
    ' decode command
    '                       single raw command format "DoCmd(Z,hub_address, unused, length)
                            cmp     cmd, #"Z"       wz      ' Z moves command to the display from hub address, length times
                  if_z      jmp     #hubtodisplayCommand
    '                       single raw command format "DoCmd(Y, hub_address, unused, length)                                     
                            cmp     cmd, #"Y"       wz      ' Y moves data to the display from hub address, length times
                  if_z      jmp     #hubtodisplayData
                  
    ram_open                rdlong  hubaddr, hubptr         ' get hub address
                            rdlong  ramaddr, ramptr         ' get ram address
                            rdlong  len, lenptr             ' get length
                            mov     err, #5                 ' err=5
    ram_open_ret            ret
    
    hubtodisplayData        ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
                            call    #ram_open               ' gets hubaddr and len (ignores ramaddress)                        
                            call    #setRShigh              ' set pins for data output
    :hubdisploop            rdword  Display, hubaddr        ' copy word from hub, not needed ?
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned                        
                            call    #ilidisplayword         ' send these bytes to the display
                            djnz    len,#:hubdisploop       ' loop until done
                            jmp     #init                   ' set pins to tristate
                            
    hubtodisplayCommand     call    #ram_open               ' gets hubaddr and len (ignores ramaddress)
    
    :hubdisplayloop         call    #setRSlow                ' set pins for Command output
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display       
                            call    #setRShigh
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display
    
                            djnz    len,#:hubdisplayloop       ' loop until done
                            jmp     #init                   ' set pins to tristate                                                                                   
    
    
    
    setRShigh               mov     dira, DirsEnabled      ' set rsHigh by tristate pin                  
    setRShigh_ret           ret
    
    
    setRSlow                 mov   dira, DirsEnabled   wz           ' set rsHigh by tristate pin                             
                             muxnz dira, RSpin                      ' set rsLow by enabling pin
    setRslow_ret             ret
    
    
    ilidisplayword            ' pass data out, sends out to the display
                            add display, p2dpins       wz                'this add presets the data for control pins and primes WZ flag for mux operation 
                            mov outa,    display                         'then make pins = data
                            muxnz dira,EnablePin                          'make enable pin high
                              mov    timeout, #$8                        'set wait period
    :wait                    djnz   timeout, :wait                     'and wait  
                            muxz dira, EnablePin
    ilidisplayword_ret      ret
    
    Zero                    long    %00000000_00000000_00000000_00000000
    EnablePin                         long   %00000000_00000010_00000000_00000000
    RSPin                             long   %00000000_00000001_00000000_00000000
    
    p2dpins                           long   %00001000_01100000_00000000_00000000      ' propToDisplay    enable pin low, but tristate, primed for lcd transfer                                               
    PinsInit                          long   %00001001_01100010_00000000_00000000      'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high 
    
    DirsDisabled                      long   %00000000_00000000_00000000_00000000
    DirsEnabled                       long   %00001001_11100000_11111111_11111111
    timeout                 res 1
    Display                 res 1
    fit                                     
    
    I will be working on command passing, and then get the RAM up. Should not be as hard as I'm making it.
    *edit*
    I plan on ordering your display in the near future. I will also be ordering your SRAM's and more 161s. I'm trying to decide if I should just order 2, and get some sockets, or get 6 and not worry about the sockets right now. RAM, Prop, EEPROM and 3232 will get sockets. Still up in the air about the counters.


    *edited again!*
    Something is wrong with this code. IT DOES NOT fill the screen? Even the SPIN code doesn't completely fill the screen? Must have something set wrong some where.
    And I figured it out. Had draw set to 320*240.... DUH fixed in post
  • average joeaverage joe Posts: 795
    edited 2012-03-30 18:12
    I've done some more work, and imported my propFont reader for debugging.
    'Starting rewrite for counters using 32k SRAM           Breadboard Hardware *see schematic for more info*
    ' Originally
    ' ILI9325 Driver using Dracblade P0 - P11 pins and three latches
    ' and also contains the dracblade ram driver for fast block moves from ram to the display
    ' Methods:
    ' .Start = start the driver
    ' .Draw  = start drawing at x1,y1 and continue until x2,y2
    ' .Pixel = a pixel in 2 bytes RRRRRGGG GGGBBBBB
    CON
     _xinfreq = 5_000_000
     _clkmode = xtal1 + pll16x
    
      p_RS                = 16            ''PINS FOR CS - TO KEEP FROM FLOATING 
      p_SPI_EN            = 17                    'LCD_WR            = 17                         ''and sd card defs
      p_SDataCk           = 18                    'DEV_SD_CLK        = 18
      p_SDataIn           = 19                    'DEV_SD_DI         = 19
      p_SdataOut          = 20                    'DEV_SD_DO         = 20    
      p_SPIadd0           = 21                    'DEV_SPI_EN        = 21
      p_SPIadd1           = 22                    'DEV_SPI_ADD0      = 22
      p_SPIadd2           = 23                    'DEV_SPI_ADD1      = 23
      p_BusEn             = 24                    'DEV_SPI_ADD_LE    = 24
      p_RamRD             = 26
      p_BusDir            = 27
    
     a_SPI_RAM_WR      = 0
     a_SPI_Load        = 1
     a_SPI_Count       = 2
     a_SPI_LCD_WR      = 3
     a_SPI_TS_CS       = 4
     a_SPI_SD_CS       = 5
     a_SPI_EXT_CS      = 7
    
      p_unused         = 25
      a_SPI_unused     = 6        
    
      a_RamToProp     = 0
      a_PropToRam     = 1            
    
      
    ''LCD REGISTERS   
      REG_OSCILLATOR                = $0000                               ''Oscillator                                (R00h) (POR = 0000h)
      REG_DRIVEROUTPUTCONTROL       = $0001                               ''Driver Output Control                     (R01h) (POR = 2B3Fh)
      REG_LCDDRIVINGWAVFORM         = $0002                               ''LCD-Driving-Waveform Control              (R02h) (POR = 0000h)
      REG_POWERCONTROL1             = $0003                               ''                                          (R03H)
      REG_DISPLAYCONTROL            = $0007                               ''Display Control                           (R07h) (POR = 0000h)
      REG_FRAMECYCLECONTROL         = $000B                               ''Frame Cycle Control                       (R0Bh) (POR = 5308h)D308 BY DATASHEET
      REG_POWERCONTROL2             = $000C                               ''                                          (R0Ch) (POR = 0004)
      REG_POWERCONTROL3             = $000D                               ''                                          
      REG_POWERCONTROL4             = $000E                               ''
      REG_GATESCANPOSITION          = $000F                               ''Gate Scan Position                        (R0Fh) (POR = 0000h)
      REG_SLEEPMODE                 = $0010                               ''Sleep mode                                (R10h) (POR = 0001h)
      REG_ENTRYMODE                 = $0011                               ''Entry Mode                                (R11h) (POR = 6830h)             
      REG_HPORCH                    = $0016                               ''                                          (R16h) (POR = EF1Ch)
      REG_VPORCH                    = $0017                               ''                                          (R17h) (POR = 0003h)
      REG_POWERCONTROL5             = $001E                               ''                                          
      REG_RAMDATAWRITE              = $0022                               ''
      REG_RAMWRITEDATAMASK1         = $0023                               ''                                          (R23h) (POR = 0000h)
      REG_RAMWRITEDATAMASK2         = $0024                               ''                                          (R24h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL1     = $0041                               ''                                          (R41h) (POR = 0000h)
      REG_VERTICALSCROLCONTROL2     = $0042                               ''                                          (R42h) (POR = 0000h)
      REG_HORIZONTALRAMADDRESSPOS   = $0044                               ''                                          (R44h) (POR = EF00h)
      REG_VERTICALRAMADDRESSSTART   = $0045                               ''                                          (R45h) (POR = 0000h)
      REG_VERTICALRAMADDRESSEND     = $0046                               ''                                          (R46h) (POR = 013Fh)
      REG_FIRSTWINDOWSTART          = $0048                               ''                                          (R48h) (POR = 0000h)
      REG_FIRSTWINDOWEND            = $0049                               ''                                          (R49h) (POR = 013Fh)
      REG_SECONDWINDOWSTART         = $004A                               ''                                          (R4Ah) (POR = 0000h)
      REG_SECONDWINDOWEND           = $004B                               ''                                          (R4Bh) (POR = 013Fh)
      REG_SETGDDRXADDRESSCOUNTER    = $004E                               ''                                          (R4Eh) (POR = 0000h)
      REG_SETGDDRYADDRESSCOUNTER    = $004F
    
      'Ram Allocation table here
      RamStart      =   0
      RamEnd        = 32767
    
      ScreenBufferSize = 16
      
    OBJ  
        wait    : "timing"                                    ' thanks to parallax
        Cr     :"crReader"
        num : "numbers"
        pst :"Parallax Serial Terminal"
    Var
     long screenbufferaddress
     word screen[16], BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2                    
     byte Fontsize, pcog                                   
    PUB boot    | x
        initalize
        
      'HelloWorld
     
      
    
    'enableDisplayPins    
    ' lcd_write_com($22)   
    'TristateDisplayPins
    ' repeat x from 0 to $FFFF 
    '   pixel(x)
        
     setChar(0, 0, 0, 0,$FFFF, 0)
     setfontsize(1)
      repeat x from 0 to 255
        char(x)                            
      deadend
    
                         
    
    PUB HelloWorld
    setfontsize(1)
    
       WriteActiveCr("H", 0, 0*16, 0, 0, $ffff, $0000)       
       WriteNextActiveCr("e")
       WriteNextActiveCr("l")
       WriteNextActiveCr("l")
       WriteNextActiveCr("o")
       WriteNextActiveCr(" ")
       WriteNextActiveCr("W")
       WriteNextActiveCr("o")
       WriteNextActiveCr("r")
       WriteNextActiveCr("l")
       WriteNextActiveCr("d")
    
    
    
    
    
    
    
    
    pub pixel(p)
    word[@screen] := p    
      DoCmd("Y", @screen,-1, 1)
    
    'pub size(s)
    ' fontsize := s
     
    'PUB Str(ptr) | cbuf
    ' cbuf := byte[ptr++]
    ' WriteActiveCr(cbuf, row, col, 0, 0, BackgroundColor, ActiveTextColor)   
    ' repeat (strsize(ptr) )
    '   WriteNextActiveCr(byte[ptr++])
    '
    'PUB dec(n) | t, t2, t3, t4, t5, t6, t7, t8, t9, t10, pl, im
    'str(num.tostr(n, %000_010_001_0_0_000000_01010))
    
    pub setFontSize(s)
    fontsize := s
                     
    pub newline
       Row := Row + (32 >> (fontsize -1))
       Col := 0
       
    pub setRow(PosR )
       Row := PosR
       
    pub setCol(PosC)
       Col := PosC
       
    pub setBorders(RBorder, CBorder)
       RowBorder := RBorder
       ColBorder := CBorder
       
    pub setColors( BgC, TxC)
      BackgroundColor  := BgC
      ActiveTextColor  := Txc
    
    PUB setChar(PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
     setRow(PosR)
     setCol(PosC)
     setBorders(RBorder, CBorder)
     setColors(BgC, TxC)
    
    
    PUB Char(c)
    WriteNextActiveCr(c)
    
    PUB WriteNextActiveCr(Character) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
    
     fontaddress := Cr.GetChar(Character)
    
      repeat idx from 0 to 31 
       bitpatern[idx] := word[fontaddress][idx]
      
     y1 :=   Col + ColBorder  
     y2 :=  (Col + (15 / fontsize ) - ColBorder)      
      x1 :=   Row + RowBorder
      x2 :=  (Row + (31 / fontsize )  - RowBorder)
    
        Draw(x1,y1,x2,y2)
    
        'EnableDisplayPins
        word[@screen] := $22
        DoCmd("Z",@screen, -1,1)
        'TristateDisplayPins
        
      repeat idx from RowBorder to 31 - RowBorder step Fontsize       
        repeat pxlidx from ColBorder to  15 - ColBorder step Fontsize 
          pxlidxdcd := |< pxlidx
          if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd)  
            pixel(ActiveTextColor)
          else
            pixel(BackgroundColor)                
        'repeat while word[fontaddress] := 0
    
    if (((Col + (16 >> (fontsize -1))) > 319 ) and  ((Row + (32 >> (fontsize -1)) > 223)))
       Row := 0
       Col := 0                         
    elseif (((Col + (16 >> (fontsize -1))) > 319 ) and  ((Row + (32 >> (fontsize -1)) < 223))) 
       Row := Row + (32 >> (fontsize -1))
       Col := 0
    else
       Col := Col + (16 >> (fontsize - 1))
    
    PUB WriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2, fontaddress
     setChar(PosR, PosC, RBorder, CBorder,  BgC, TxC)
     WriteNextActiveCr(Character)
    
    
    
    
    
    
    
    
    
    
    
    
    
    Pub ClearScreenSpin(c)                               
         Draw(0, 0, 239, 319)
          EnableDisplayPins
         Lcd_Write_Com($22)
         OUTA[15..0]  := c   
       repeat 76800
         StrobeLcdWr
     TristateDisplayPins
          
    pub deadend
    repeat
     waitcnt(cnt)
     
    PUB initalize
      outa := %00001001_00000010_00000000_00000000
      dira := %00001001_11100010_00000000_00000000
     Pst.Start(115200)
        START_SSD1289
        ClearScreenSpin($ffff)
        start_ram
        wordfill(@screen, 0, 16)
        repeat (76800 / 16)
            DoCmd("Y", @screen,-1, 16)
                
    'PUB StartPF             'Method to Init display, then load a cog with screen driver
     cr.Start
     num.init
      
    PUB Start_SSD1289                                        ''Init Display
      EnableDisplayPins                                   ''enable pins 0 to 15
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) 
        Lcd_Write_Data($0021)                               ''GON = 1 DTE = 0 D[1:0] = 01 
        Lcd_Write_Com (REG_OSCILLATOR)                      ''Oscillator (R00h) (POR = 0000h)
        Lcd_Write_Data($0001)                               ''Turn on oscillator
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0023)                               ''GON = 1 DTE = 0 D[1:0] = 11
        Lcd_Write_Com (REG_SLEEPMODE)                       ''Sleep mode (R10h) (POR = 0001h)
        Lcd_Write_Data($0000)     ''                        ''exit sleep mode         
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11
        Lcd_Write_Com (REG_ENTRYMODE)                       ''Entry Mode (R11h) (POR = 6830h)
        Lcd_Write_Data($6838)                               ''
        Lcd_Write_Com (REG_LCDDRIVINGWAVFORM)               ''LCD-Driving-Waveform Control (R02h) (POR = 0000h)($1000) 
        Lcd_Write_Data($1000)     ''                        ''
        Lcd_Write_Com (REG_GATESCANPOSITION)                ''Gate Scan Position (R0Fh) (POR = 0000h)  ($0000)
        Lcd_Write_Data($0000)     ''                        ''                                                        ''
        Lcd_Write_Com (REG_DRIVEROUTPUTCONTROL)             ''Driver Output Control (R01h) (POR = [0XXXX0X1]3Fh) 433f    ($633F) 
        Lcd_Write_Data($6B3F) ''                            ''                                                      
        Lcd_Write_Com (REG_FRAMECYCLECONTROL)               ''Frame Cycle Control (R0Bh) (POR = 5308h) ($5308)
        Lcd_Write_Data($5308)                               ''                           '
        Lcd_Write_Com (REG_DISPLAYCONTROL)                  ''Display Control (R07h) (POR = 0000h) ($0033)
        Lcd_Write_Data($0033)                               ''GON = 1 DTE = 1 D[1:0] = 11   
      TristateDisplayPins
      
    PUB SpinPixel(p)
    EnableDisplayPins
     Lcd_Write_Data(p)
    TristateDisplayPins
    
    PRI EnableDisplayPins
        outa[p_BusDir] := a_PropToRam 
        DIRA :=%00001001_11100011_11111111_11111111 '  RS, 16 data lines active   
        outa[p_BusEn] := 0
        OUTA[p_SPIadd2..p_SPIadd0] := a_SPI_LCD_Wr 
    PRI TristateDisplayPins ' tristate all pins -                                                 
        DIRA :=%00000000_00000000_00000000_00000000 ''
        
    PRI LCD_Writ_Bus(V) 
        OUTA[15..0]  := V
        StrobeLcdWr                                           ' toggle write pin
        
    PRI Lcd_Write_Com(V)
        RSLow
        LCD_Writ_Bus(V)
        RSHigh
        
    PRI Lcd_Write_Data(V)
        'RSHigh
        LCD_Writ_Bus(V)
        
    PRI RSLow                                    
        outa[p_RS] := 0    
    PRI RSHigh
        outa[p_RS] := 1
                       '
    PRI StrobeLcdWr
       'outa[p_SPIadd2..p_SPIadd0] := LCD_WR                          
       outa[p_SPI_En] := 0
       outa[p_SPI_En] := 1
    
    PUB DrawASM(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels 
      HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
      word[@screen][0] := REG_HORIZONTALRAMADDRESSPOS
      word[@screen][1] := HORIZONTALRAMADDRESSPOS
      word[@screen][2] := REG_VERTICALRAMADDRESSSTART
      word[@screen][3] := y1 
      word[@screen][4] := REG_VERTICALRAMADDRESSEND
      word[@screen][5] := y2
      word[@screen][6] := REG_SETGDDRxADDRESSCOUNTER
      word[@screen][7] := x1 
      word[@screen][8] := REG_SETGDDRyADDRESSCOUNTER
      word[@screen][9] := y1    
      DoCmd("Z", @screen, -1, 10)  
    
    
    
     
    PUB Draw(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
        EnableDisplayPins                       ' enable pins 0-11
      HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)     
        Lcd_Write_Com(REG_HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Data(HORIZONTALRAMADDRESSPOS)
        Lcd_Write_Com(REG_VERTICALRAMADDRESSSTART)
        Lcd_Write_Data(y1) 
        Lcd_Write_Com(REG_VERTICALRAMADDRESSEND)
        Lcd_Write_Data(y2)
        Lcd_Write_Com(REG_SETGDDRxADDRESSCOUNTER)
        Lcd_Write_Data(x1 )
        Lcd_Write_Com(REG_SETGDDRyADDRESSCOUNTER)
        Lcd_Write_Data(y1)    
        TristateDisplayPins                                   ' tristate pins 0-11 so other drivers can use these pins                                                                                                                                 
    
    
    
    'PUB ReadRamByte(address)                                ' masks off all but a byte - used often
    '    docmd("R",@result,address,1)                        ' read just 1 byte
    '    result := result & %00000000_00000000_00000000_11111111 ' mask off byte so returns a guaranteed byte value
    '    return result
    
    'PUB WriteRamByte(value,address)                         ' write a byte to ram
    '    docmd("W",@value,address,1)
    '
    'PUB ReadRamLong(address)                             ' read a long, stored LSB first
    '    docmd("R",@result,address,4)
    '    return result
    '
    'PUB WriteRamLong(value,address)                         ' write a long to ram
    '    docmd("W",@value,address,4) 
    '      
    '
    CON
    ''Dracblade driver for talking to a ram chip via three latches
    '' Modified code from Cluso's triblade
    ''also includes commands to move blocks of data to the ILI9325 touchscreen display
    ''Modified for counters by Joe
    ' DoCmd (command_, hub_address, ram_address, block_length)                                                         
    
    ' I - initialise     
    ' W - Move block_length bytes from hub_address to ram_address
    ' R - Move block_length bytes from ram_address to hub_address
    ' A - Move block of 256 bytes from hub to external ram. Faster than W as middle latch not changing each byte. block_length ignored (always 256) 
    ' *** command A and B must start on 0,256,512,768 etc so only the lower 8 bytes change ***
    ' B - Move a block of 256 bytes from external ram to hub. Faster than R as middle latch not changing each byte
    ' C - move a block of data (block_length) from ram_address to the ILI9325 display (assumes Draw has been called in spin first)
    ' D - move a block of data (block_length) from hub_address to the ILI9325 display (assumes Draw has been called in spin first)
    
    '  E - Set Draw(E, H,Vs,Ve)
    '  F - Clear Screen(F, color,NA,NA )
    
    '  Y - moves data to the display from hub address, length times
    '  Z - moves command to the display from hub address, length times
    
    VAR
    
    ' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
       long  command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
    '        command  = R, W, H I,D etc =0 when operation completed by cog
    '        hubaddrs = hub address for data buffer
    '        ramaddrs = ram address for data ($0000 to $FFFF)
    '        blocklen = ram buffer length for data transfer
    '        errx     = returns =0 (false=good), else <>0 (true & error code)
    '        cog      = cog no of driver (set by spin start routine)
       
    PUB start_ram : err_
    ' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
      command := "I"
      cog := 1 + cognew(@tbp2_start, @command)
      if cog == 0
        err_ := $FF                 ' error = no cog
      else
        repeat while command        ' driver cog sets =0 when done
        err_ := errx                ' driver cog sets =0 if no error, else xx = error code
    
    PUB stop_ram
       if cog
          cogstop(cog~ - 1)      
    
    PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
    ' Do the command: R, W, N, F, H,I,D
      hubaddrs := hub_address       ' hub address start
      ramaddrs := ram_address       ' ram address start
      blocklen := block_length      ' block length
      command  := command_          ' must be last !!
    ' Wait for command to complete and get status
      repeat while command          ' driver cog sets =0 when done
      err_ := errx                  ' driver cog sets =0 if no error, else xx = error code
    
    
    '' +--------------------------------------------------------------------------+
    '' | Dracblade Ram Driver (with grateful acknowlegements to Cluso)            |
    '' +--------------------------------------------------------------------------+
                            org     0
    tbp2_start    ' setup the pointers to the hub command interface (saves execution time later
                                          '  +-- These instructions are overwritten as variables after start
    comptr                  mov     comptr, par     ' -|  hub pointer to command                
    hubptr                  mov     hubptr, par     '  |  hub pointer to hub address            
    ramptr                  add     hubptr, #4      '  |  hub pointer to ram address            
    lenptr                  mov     ramptr, par     '  |  hub pointer to length                 
    errptr                  add     ramptr, #8      '  |  hub pointer to error status           
    cmd                     mov     lenptr, par     '  |  command  I/R/W/G/P/Q                  
    hubaddr                 add     lenptr, #12     '  |  hub address                           
    ramaddr                 mov     errptr, par     '  |  ram address                           
    len                     add     errptr, #16     '  |  length                                
    err                     nop                     ' -+  error status returned (=0=false=good) 
    
    
    ' Initialise hardware tristates everything and read/write set the pins
    init                    mov     err, #0                  ' reset err=false=good
                            mov     dira,zero                ' tristate the pins
    
    done                    wrlong  err, errptr             ' status  =0=false=good, else error x
                            wrlong  zero, comptr            ' command =0 (done)
    ' wait for a command (pause short time to reduce power)
    pause
    '                        mov     ctr, delay      wz      ' if =0 no pause
    '              if_nz     add     ctr, cnt
    '              if_nz     waitcnt ctr, #0                 ' wait for a short time (reduces power)
                            rdlong  cmd, comptr     wz      ' command ?
                  if_z      jmp     #pause                  ' not yet
    ' decode command
    '                       single raw command format "DoCmd(Z,hub_address, unused, length)
                            cmp     cmd, #"Z"       wz      ' Z moves command to the display from hub address, length times
                  if_z      jmp     #hubtodisplayCommand
    '                       single raw command format "DoCmd(Y, hub_address, unused, length)                                     
                            cmp     cmd, #"Y"       wz      ' Y moves data to the display from hub address, length times
                  if_z      jmp     #hubtodisplayData
                  
    ram_open                rdlong  hubaddr, hubptr         ' get hub address
                            rdlong  ramaddr, ramptr         ' get ram address
                            rdlong  len, lenptr             ' get length
                            mov     err, #5                 ' err=5
    ram_open_ret            ret
    
    hubtodisplayData        ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
                            call    #ram_open               ' gets hubaddr and len (ignores ramaddress)                        
                            call    #setRShigh              ' set pins for data output
    :hubdisploop            rdword  Display, hubaddr        ' copy word from hub, not needed ?
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned                        
                            call    #ilidisplayword         ' send these bytes to the display
                            djnz    len,#:hubdisploop       ' loop until done
                            jmp     #init                   ' set pins to tristate
                            
    hubtodisplayCommand     call    #ram_open               ' gets hubaddr and len (ignores ramaddress)
    
    :hubdisplayloop         call    #setRSlow                ' set pins for Command output
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display
                            
                            djnz    len,#:data       ' loop until done
                            jmp     #init                   ' set pins to tristate                                                                                   
          
    :data                   call    #setRShigh
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word alligned
                            call    #ilidisplayword         ' send these bytes to the display
    
                            djnz    len,#:hubdisplayloop       ' loop until done
                            jmp     #init                   ' set pins to tristate                                                                                   
    
    
    
    setRShigh               mov     outa, PinsInit
                            mov     dira, DirsEnabled      ' set rsHigh by tristate pin                  
    setRShigh_ret           ret
    
    
    setRSlow                 mov   outa, PinsInit
                             mov   dira, DirsEnabled   wz           ' set rsHigh by tristate pin                             
                             muxnz dira, RSpin                      ' set rsLow by enabling pin
    setRslow_ret             ret
    
    
    ilidisplayword            ' pass data out, sends out to the display
                            add Display, p2dpins       wz                'this add presets the data for control pins and primes WZ flag for mux operation                      
                            mov outa, Display 'then make pins = data
                              muxz dira,EnablePin                          'make enable pin low                       
                              mov    timeout, #$f                        'set wait period
    :wait1                    djnz   timeout, :wait1                     'and wait  
                              muxnz dira, EnablePin                      'make enable pin high                        
     
    ilidisplayword_ret      ret
                 '          cmp     cmd, #"E"       wz
                 ' if_z     jmp     #SetDraw
                 '          cmp     cmd, #"F"       wz
                 ' if_z     jmp     #ClearScreen
                  
    '                       cmp     cmd, #"R"       wz      ' R = read block from external ram to hub
    '             if_z      jmp     #rdblock
    '                       cmp     cmd, #"W"       wz      ' W = write block from hub to external ram
    '             if_z      jmp     #wrblock
    '                       cmp     cmd, #"C"       wz      ' C moves a block of data from ram to the display
    '             if_z      jmp     #extramtodisplay
    '
    '                       cmp     cmd, #"A"       wz      ' A moves 256 bytes from hub to external ram
    '             if_z      jmp     #blockhubtoram
    '                       cmp     cmd, #"B"       wz      ' B moves 256 bytes from external ram to hub
    '             if_z      jmp     #blockramtohub
    '                       cmp     cmd, #"E"       wz      ' convert 3 byte .raw format to 2 byte .ili format - hub to hub
    '             if_z      jmp     #rawtoiliformat
    '                       cmp     cmd, #"F"       wz      ' draw a transparent icon, pass two locations in hub ram and len = number of pixels
    '             if_z      jmp     #drawicon
    '                       cmp     cmd, #"I"       wz      ' init
    '             if_z      jmp     #init     
    '                       mov     err, cmd                ' error = cmd (unknown command)
    '                       jmp     #done
    
    
    
    SetDraw
     ret
    ClearScreen
     ret
     
    ' set all latches (replaces H command), pass value in third variable of the DoCmd
    
    'setlatches              call #ram_open                  ' gets address value in 'address'
    '                        call #lowmiddlehighlatch        ' set all the latches
    '                        jmp  #init
    
    '---------------------------------------------------------------------------------------------------------
    'Memory Access Functions
                            ' read block from external ram to hub
    'rdblock                call    #ram_open               ' get variables from hub variables
    'rdloop                 call    #read_byte              ' read byte from address into data_8
    '                       wrbyte  data_8,hubaddr          ' write data_8 to hubaddr ie copy byte to hub
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       djnz    len,#rdloop             ' loop until done
    '                       jmp     #init                   ' reinitialise
    
    
                            ' write block from hub to external ram
    'wrblock                call    #ram_open
    'wrloop                 rdbyte  data_8, hubaddr         ' copy byte from hub
    '                       call    #write_byte             ' write byte from data_8 to address
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       djnz    len,#wrloop             ' loop until done
    '                       jmp     #init                   ' reinitialise
    
    
                            
    
    'read_byte              call #lowmiddlehighlatch        ' set up latches 
    '                       call #read_memory_byte          ' read a byte into data_8
    'read_byte_ret          ret                        
    
    
    '________________________________________TODO
    'read_memory_byte       mov dira,LatchDirection2        ' for reads so P0-P7 tristate till do read
    '                       mov outa,GateHigh               ' actually ReadEnable but they are the same
    '                       andn outa,GateHigh              ' set gate low
    '                       nop                             ' short delay to stabilise
    '                       nop
    '                       mov data_8, ina                 ' read SRAM
    '                       and data_8, #$FF                ' extract 8 bits
    '                       or  outa,GateHigh               ' set the gate high again
    'read_memory_byte_ret   ret
    
    
    
    'write_byte             call #lowmiddlehighlatch        ' set up latches
    '                       call #write_memory_byte
    'write_byte_ret         ret
    '
    'write_memory_byte      mov outx,data_8                 ' get the byte to output
    '                       and outx, #$FF                  ' ensure upper bytes=0
    '                       or outx,WriteEnable             ' or with correct 138 address
    '                       mov outa,outx                   ' send it out
    '                       andn outa,GateHigh              ' set gate low
    '                       nop                             ' no nop doesn't work, one does, so put in two to be sure
    '                       nop                             ' another NOP
    '                       or outa,GateHigh                ' set it high again
    'write_memory_byte_ret  ret
    
    'LowMiddleHighLatch ' sets up the ram latches.
    '                       call #lowlatchout
    '                       call #middlelatchout
    '                       call #highlatchout
    'LowMiddleHighLatch_ret ret
    
    ' write to low, middle and high latches as subroutines. Pass 'ramaddr' which is a long. Extract xxxxxxxx_HHHHHHHH_MMMMMMMM_LLLLLLLL
    
    'LowLatchOut            mov outx,ramaddr                ' get the address into a temp variable
     '                      and outx,#$FF                   ' mask the low byte
    '                       or  outx,LowAddress             ' or with 138 low address
      '                     call #LatchOutput
    'LowLatchOut_ret        ret                        
    
    'MiddleLatchOut         mov outx,ramaddr                ' middle byte get the address into a temp variable
    '                       shr outx,#8                     ' shift right by 8 places
    '                       and outx,#$FF                   ' mask the low byte
    '                       or  outx,MiddleAddress          ' or with 138 middle address
    '                       call #LatchOutput
    'MiddleLatchOut_ret     ret                        
    
    'HighLatchOut           mov outx,ramaddr                ' middle byte get the address into a temp variable
    '                       shr outx,#16                    ' shift right by 16 places
    '                       and outx,#$FF                   ' mask the low byte
    '                       or  outx,HighAddress            ' or with 138 high address
    '                       call #LatchOutput                        
    'HighLatchOut_ret       ret
    
    'LatchOutput            mov dira,LatchDirection         ' set up the pins for programming latch chips
    '                       mov outa,outx                   ' send it out
    '                       andn outa,GateHigh              ' set gate low  nop not needed
    '                       or outa,GateHigh                ' set it high again 
    'LatchOutput_ret        ret
    '
    ' ** move a block of 256 bytes from hub to external ram **
    
    'Blockhubtoram          call    #ram_open               ' get variables from hub variables
    '                       call    #lowmiddlehighlatch     ' set all three latches
    '                       mov     len,#256                ' do 256 times
    'Blockhubtoram_loop                          
     '                      rdbyte  data_8, hubaddr         ' copy byte from hub
     '                      call    #write_memory_byte      ' send out to the ram 
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       call    #lowlatchout            ' update the low latch
    '                       djnz    len,#blockhubtoram_loop ' loop until done
    '                       jmp     #init                    ' restart
    
    ' ** move a block of 256 bytes from external ram to hub **
    
    'Blockramtohub          call    #ram_open               ' get variables from hub variables
    '                       call    #lowmiddlehighlatch     ' set all three latches
    '                       mov     len,#256                ' do 256 times
    'Blockramtohub_loop                          
    '                       call    #read_memory_byte       ' read byte from address into data_8
    '                       wrbyte  data_8,hubaddr          ' write data_8 to hubaddr ie copy byte to hub
    '                       add     hubaddr,#1              ' add 1 to hub address
    '                       add     ramaddr,#1              ' add 1 to ram address
    '                       call    #lowlatchout            ' update the low latch
    '                       djnz    len,#blockramtohub_loop ' loop until done
    '                       jmp     #init                    ' restart
    '
    
    
    
    
    'extramtodisplay ' send a block of data blocklen from external memory ramaddress to the ILI9325 display
    '                       call    #ram_open               ' gets ramaddr and len (ignore hubaddr)
    '                       shr     len,#1                  ' len /2 as 2 bytes per pixel   
    '                       call    #setRShigh              ' set pins for data output 
    'ililoop                call    #readiliword            ' read ilihigh, ililow, increments ramaddr by 2
    '                       call    #ilidisplayword         ' sends ilihigh ililow to the display
    '                       djnz    len,#ililoop            ' loop until done
    '                       jmp     #init                   ' set pins to tristate
    
    'readiliword            ' read ilihigh and ililow from ramaddr, increments ramaddr by 2
    '                       call    #read_byte              ' read byte from ramaddr into data_8
    '                       mov     dira,latchdirection     ' enable for output (readmemorybyte leaves P0-P7 as inputs) 
    '                       mov     ilihigh,data_8
    '                       add     ramaddr,#1              ' add 1 to ram address 
    '                       call    #read_byte              ' read second byte from address into data_8
    '                       mov     dira,latchdirection     ' enable for output (readmemorybyte leaves P0-P7 as inputs) 
    '                       mov     ililow,data_8
    '                       add     ramaddr,#1              ' add 1 to ram address
    'readiliword_ret        ret                        
    
    
    '                                               
    'RawtoILIformat         ' takes a .raw 3 byte RRRRRRRR GGGGGGGG BBBBBBBB and converts to 2 byte RRRRRGGG GGGBBBBB
    '                       ' pass hubaddr, ramaddr and len
    '                       ' hubaddr is source location, len is number of pixels
    '                       ' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklength
    '                       call    #ram_open ' gets hubaddress, ramaddress and len (ignores ramaddress)
    'rawloop
    '                       rdbyte red,hubaddr
    '                       add hubaddr,#1
    '                       rdbyte green,hubaddr
    '                       add hubaddr,#1
    '                       rdbyte blue,hubaddr
    '                       add hubaddr,#1
    '                       call #rgbtoili
    '                       wrbyte ilihigh,ramaddr
    '                       add ramaddr,#1
    '                       wrbyte ililow,ramaddr
    '                       add ramaddr,#1
    '                       djnz    len,#rawloop            ' loop until done 
    '                       jmp     #init                   ' set pins to tristate
    
    'RGBtoILI               ' pass red,green, blue, returns ililow and ilihigh
    '                       shr     red,#3                  ' 000RRRRR 
    '                       shl     red,#3                  ' RRRRR000 
    '                       shr     green,#2                ' 00GGGGGG
    '                       mov     ilihigh,green           ' ilihigh = 00GGGGGG
    '                       shr     ilihigh,#3              ' ilihigh = 00000GGG
    '                       or      ilihigh,red             ' ilihigh = RRRRRGGG
    '                       and     green,#%00000111        ' 00000GGG
    '                       shl     green,#5                ' GGG00000
    '                       mov     ililow,green            ' ililow = GGG00000
    '                       shr     blue,#3                 ' blue = 000BBBBB
    '                       or      ililow,blue             ' ililow = GGGBBBBB
    'RGBtoILI_ret           ret
    
    'ILItoRGB               ' pass ilihigh RRRRRGGG and ililow GGGBBBBB returns RRRRR000 GGGGGG00 BBBBB000
    '                       mov     red,ilihigh             ' red = RRRRRGGG
    '                       and     red,#%11111000          ' red = RRRRR000
    '                       mov     green,ilihigh           ' green = RRRRRGGG
    '                       shl     green,#5                ' green = GGG00000
    '                       mov     i,ililow                ' i = GGGBBBBB
    '                       and     i,#%11100000            ' i = GGG00000
    '                       shr     i,#3                    ' i = 000GGG00
    '                       or      green,i                 ' green = GGGGGG00
    '                       mov     blue,ililow             ' blue = GGGBBBBB
    '                       shl     blue,#3                 ' blue = BBBBB000
    'ILItoRGB_ret           ret
    
                           
    
    'DrawIcon               ' pass hubaddr, ramaddr and len. 
                            ' hubaddr is location in ram of the picture (messy naming of the variable)
                            ' ramaddr is the location in ram of the mask (both sources are ram, not hub)
                            ' format of the picture is 2 bytes RRRRRGGG GGGBBBBB
    '                       ' format of the icon is R G B A and A = 0 for transparent and 255 for full opaque (transparent usually round the edges)
    '                       call    #ram_open ' gets hubaddr, ramaddr and len
    '                       mov     backgroundcount,hubaddr ' backgroundcount is the picture
    '                       mov     iconcount,ramaddr       ' iconcount is the icon
    'drawiconloop           mov     ramaddr,backgroundcount ' address for reading the picture
    '                       call    #readiliword            ' get ilihigh and ililow RRRRRGGG GGGBBBBB
    '                       mov     backgroundcount,ramaddr ' store new picture counter
    '                       call    #ilitoRGB               ' convert to red green blue
     '                      mov     ramaddr,iconcount       ' get icon location
    '                       call    #readiliword            ' returns ilihigh and ililow which are actually red and green
    '                       mov     r,ilihigh               ' get red
    '                       mov     g,ililow                ' get green
    '                       call    #readiliword            ' returns ilihigh and ililow which are actually blue and alpha             
    '                       mov     b,ilihigh               ' get blue
    '                       mov     a,ililow                ' get alpha
    '                       mov     iconcount,ramaddr       ' restore the icon pointer
    '                       cmp     a,#128          wc      ' test if background or foreground
    '             if_c      jmp     #drawiconfinish         ' if carry then this is background
    '                       mov     red,r                   ' move icon to foreground
    '                       mov     green,g
    '                       mov     blue,b
    'drawiconfinish         call    #rgbtoili               ' convert to ililow and ilihigh
    '                       call    #ilidisplayword         ' send out to the display
    '                       djnz    len,#drawiconloop       ' loop len times until finished
    '                       jmp     #init                   ' set pins to tristate
    
    delay                   long    80                                    ' waitcnt delay to reduce power (#80 = 1uS approx)
    ctr                     long    0                                     ' used to pause execution (lower power use) & byte counter
    
    'GateHigh               long    %00000000_00000000_00000001_00000000  ' HC138 gate high, all others must be low
    
    'Outx                   long    0                                     ' for temp use, same as n in the spin code
    'LatchDirection         long    %00000000_00000000_00001111_11111111 ' 138 active, gate active and 8 data lines active
    'LatchDirection2        long    %00000000_00000000_00001111_00000000 ' for reads so data lines are tristate till the read
    
    'LowAddress             long    %00000000_00000000_00000101_00000000 ' low address latch = xxxx010x and gate high xxxxxxx1
    'MiddleAddress          long    %00000000_00000000_00000111_00000000 ' middle address latch = xxxx011x and gate high xxxxxxx1
    'HighAddress            long    %00000000_00000000_00001001_00000000 ' high address latch = xxxx100x and gate high xxxxxxx1
    'ReadEnable long    %00000000_00000000_00000001_00000000 ' /RD = xxxx000x and gate high xxxxxxx1
                                                            ' commented out as the same as GateHigh
    
    Zero                    long    %00000000_00000000_00000000_00000000 ' for tristating all pins
    data_8                  long    0                                    ' so code compatability with zicog driver
    i                       long    0                                    ' general purpose value
    j                       long    0                                    ' general purpose value
    a                       long    0                                    ' general purpose value
    b                       long    0                                    ' general purpose value
    r                       long    0                                    ' general purpose value
    g                       long    0                                    ' general purpose value
                                     
    ' variables and constants for the ILI9325 display
    'Latch5address          long    %00000000_00000000_00001011_00000000 ' latch5 address
    'Latch6address          long    %00000000_00000000_00001101_00000000 ' latch6 address
    'Latch7data             long    %00000000_00000000_00001111_00010111 ' latch7 address 111x and gate high, reset high, cs low, read high, write high, rs high for data output, combines rshigh in spin into one line                   
    'Latch7WriteLow         long    %00000000_00000000_00001111_00010101 ' cs low, write low
    'ililow                 long    0                                    ' low data byte latch5
    'ilihigh                long    0                                    ' high data byte latch6
    'red                    long    0                                    ' red, green blue variables
    'green                  long    0
    'blue                   long    0
    'backgroundcount        long    0
    'iconcount              long    0
    
    
    
    
    lowWordMask                       long $0000_ffff
                                          'pin settings
    EnablePin                         long   %00000000_00000010_00000000_00000000
    RSPin                             long   %00000000_00000001_00000000_00000000
    
    p2dpins                           long   %00001000_01100000_00000000_00000000      ' propToDisplay    enable pin low, but tristate, primed for lcd transfer                                               
    PinsInit                          long   %00001001_01100010_00000000_00000000      'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high 
    
    DirsDisabled                      long   %00000000_00000000_00000000_00000000
    DirsEnabled                       long   %00001001_11100000_11111111_11111111                                                                           ''                                          (R4Fh) (POR = 0000h)
    
    
    
    'bufferaddress          res 1
    'Pntr                   res 1
    'ForegroundFormat       res 1
    'BackgroundFormat       res 1
    'ForegroundScreen       res 1
    'BackgroundScreen       res 1
    
    timeout                 res 1
    Display                 res 1
    fit                                      
    

    There is still issues with this code, and large portions untested. I have been trying to get ASM to write commands to the screen, but having problems. The draw command does not work properly when using asm. The problem is somewhere in this chunk of code, I THINK.
    'spin portion
    
    
    PUB DrawASM(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels 
      HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8)
      word[@screen][0] := REG_HORIZONTALRAMADDRESSPOS
      word[@screen][1] := HORIZONTALRAMADDRESSPOS
      word[@screen][2] := REG_VERTICALRAMADDRESSSTART
      word[@screen][3] := y1 
      word[@screen][4] := REG_VERTICALRAMADDRESSEND
      word[@screen][5] := y2
      word[@screen][6] := REG_SETGDDRxADDRESSCOUNTER
      word[@screen][7] := x1 
      word[@screen][8] := REG_SETGDDRyADDRESSCOUNTER
      word[@screen][9] := y1    
      DoCmd("Z", @screen, -1, 10)  
    
    
    'asm portion
    hubtodisplayCommand     call    #ram_open               ' gets hubaddr and len (ignores ramaddress)
    
    :hubdisplayloop         call    #setRSlow                ' set pins for Command output
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word aligned
                            call    #ilidisplayword         ' send these bytes to the display
                            
                            djnz    len,#:data       ' loop until done
                            jmp     #init                   ' set pins to tristate                                                                                   
          
    :data                   call    #setRShigh
                            rdword  Display, hubaddr        ' copy word from hub
                            add     hubaddr,#2              ' add 2 to hub address changed for word aligned
                            call    #ilidisplayword         ' send these bytes to the display
    
                            djnz    len,#:hubdisplayloop       ' loop until done
                            jmp     #init                   ' set pins to tristate
    
    
    setRShigh               mov     outa, PinsInit
                            mov     dira, DirsEnabled      ' set rsHigh by tristate pin                  
    setRShigh_ret           ret
    
    
    setRSlow                 mov   outa, PinsInit
                             mov   dira, DirsEnabled   wz           ' set rsHigh by tristate pin                             
                             muxnz dira, RSpin                      ' set rsLow by enabling pin
    setRslow_ret             ret
    
    
    ilidisplayword            ' pass data out, sends out to the display
                            add Display, p2dpins       wz                'this add presets the data for control pins and primes WZ flag for mux operation                      
                            mov outa, Display 'then make pins = data
                              muxz dira,EnablePin                          'make enable pin low                       
                              mov    timeout, #$f                        'set wait period
    :wait1                    djnz   timeout, :wait1                     'and wait  
                              muxnz dira, EnablePin                      'make enable pin high                        
     
    ilidisplayword_ret      ret
    
    I'm taking a break from trying to make this work and I'm going to start on getting the RAM working. It would be nice to have commands writing in ASM, but I can do this in spin for now.

    *edit* I figured it out. I just needed to make the wait time a bit longer. I edited this to match what I have working.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-03-30 19:50
    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.

    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      
    
  • average joeaverage joe Posts: 795
    edited 2012-03-30 21:01
    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.
Sign In or Register to comment.