Propeller GUI touchscreen and full color display

1111214161724

Comments

  • average joeaverage joe Posts: 795
    edited 2012-05-27 - 17:15:10
    I just wanted to let you know about radiobutton.
    I have everything working now for the most part. I noticed on the music font there is 1 white pixel @ 0,0 that should not be there? I'm going to do some more digging... Building the Logic Analyzer has proven a bigger chore than thought since the tip on my iron is done. Now I must wait till Tuesday to get a new one.
    I was recording a utube video, but the baby woke up. I'll try again during his next nap.
    There's still some exploring to do as to the display issue. I want to port portions over to C so I can experiment with OTHER stuff. *no spoiler alert today :(*

    Also on the to-do list is finish the chiptune player. I have the new transport, now to bind the controls and get a NICE font working instead of the debugging font. Also need to finish the transport buttons. I'm going to do the masking on the BMP so all I have to do is re-draw the button with the correct color bmp. Should be fairly simple and will be compatible with the ILI.
    Gotta run! Thanks again for everything Doc!

    *edit*
    Could you post updated SD file system? I'm missing the HTML bmps. I think we could pull off 16x16 if we used a few cogs ;)

    Another edit, Got my latest demo ready. I need to show some people in the area. I squeezed chiptune player into the last little bit of space. 272 longs free!
  • average joeaverage joe Posts: 795
    edited 2012-05-31 - 16:19:05
    Boards arrived today! Unfortunately I'm too busy to work on them ATM. :(
    I've been watching the "other" post and you guys have done a lot of work! Keep up the good work!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-05-31 - 20:09:46
    So those boards work fine with the smaller ILI9325 displays and no hardware modifications. With your code mods you should be able to get the SSD1289 working - use the display socket on the right as that is the one with the SD card connected.

    When the MCP23008 boards arrive we both will need to rewrite our code. I've been recycling most components off old boards by desoldering. Some components don't desolder very well (ie the ones with many pins) and I tend to abandon sockets, plugs and resistor SIL arrays.

    If you are running out of space we can either move more things into objects and then have separate loadable programs like the standalone movie player, or we can move over to C. The move to C is a little daunting for me as a Basic/Spin programmer but I am starting to get a feel for what -> and :: and * mean. I'm hoping real soon we can have a design where we can get some other builders involved. The /CS thing on the SSD1289 has put things back a few weeks but I think we are back on track now.
  • average joeaverage joe Posts: 795
    edited 2012-06-03 - 17:05:52
    Well, the dual-screen board is 99% built. I'm missing the input cap and need to fudge some of the other vreg caps. The 2- 470uf's are getting 100uf's. The 22uf tant will most likely be replaced with a 10uf EL, maybe 100 uf EL. Should work?
    A revision note for the future, could you use polarized caps on the propeller chip? I usually use tants *a 4.7uf on the PLL side.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-03 - 17:36:05
    Those caps should be fine. If you are running from a wall wart you may not need an input cap - most wall warts I have pulled to bits have 4700uF inside them.

    Re tants vs electrolytics, that could start a long debate! Suffice to say nothing is set in stone and you can solder in different caps if you want as long as the voltage rating is ok and the value is roughly the same.
  • SapiehaSapieha Posts: 2,964
    edited 2012-06-03 - 19:18:00
    Hi.

    I will add some thing to DR_Acula's answer.

    On V-Regs (OutSide-Regulated)--- If Data sheet specifies Tantalum --- Never change them to other type's.

    On Propeller Crystal side Voltage pins ---- Use always Tantalums ---- As electrolytic ones gave to slow response time.


    Well, the dual-screen board is 99% built. I'm missing the input cap and need to fudge some of the other vreg caps. The 2- 470uf's are getting 100uf's. The 22uf tant will most likely be replaced with a 10uf EL, maybe 100 uf EL. Should work?
    A revision note for the future, could you use polarized caps on the propeller chip? I usually use tants *a 4.7uf on the PLL side.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-03 - 19:36:48
    Good points Sapieha.

    Well I suppose I had better go and read the data sheet! For the switchers http://pdf1.alldatasheet.com/datasheet-pdf/view/203238/NSC/LM2575T-5.0.html page 1 for the official values of 100uF on the input and 330uF on the output and scroll down to page 18 for a discussion of the capacitor types and values.

    If you are using linear regulators (this board can have either) then check the data sheet for those.

    Re the propeller caps - yes Sapieha is right, always use a tantalum.
  • average joeaverage joe Posts: 795
    edited 2012-06-03 - 20:04:04
    Very good points! I don't want to start the discussion of what cap is better BUT.
    Propeller chips ALWAYS get .1uf tant and 4.7uf tant on PLL side. *I'm out of 4.7s right now so using stock .1 tant for pll. Should be fine for standard clocked board.* I have also used ceramics in the past but don't recommend. EL's would be a no-no. The large caps are EL of course. The rest of the caps are ceramic, except for audio caps.

    With my "standard" linear regulator design, I use .1 ceramic or tant on the input and output of vregs, right next to the regulator. Input cap will be from 100uf to 470uf. Output is usually a 100uf but I've used 10ufs before with no issues. The regulators I'm using look good with a wide range of caps.

    The 22uf tant is the only one throwing me off. Suck a 10uf in and I'm preparing to pre-power test. Then smoke test!

    *edit*
    OOPS. I guess I loaded the .01uf audio caps with .1uf. I'm out of .01s? Will changing the resistor to 100 ohms hurt anything? Also, I still have no '08 so had to fudge in an '00 again.
  • SapiehaSapieha Posts: 2,964
    edited 2012-06-03 - 20:14:33
    Hi joe.

    I think You have write error --- Else You use bad capacitor with Propeller.
    .1uF shall always be Ceramic capacitor as it have better response to frequencies DECOUPLING capacitor shall answer for.
    And all other decoupling capacitors on all IC's 0.1uF shall be Ceramic ones to.

    4.7uF are to small -- it need's be at least 10uF
    And You need have both ones on this side for all Frequencies --- If You will have stable PLL --- That not burn after some work time
    Very good points! I don't want to start the discussion of what cap is better BUT.
    Propeller chips ALWAYS get .1uf tant and 4.7uf tant on PLL side. *I'm out of 4.7s right now so using stock .1 tant for pll. Should be fine for standard clocked board.* I have also used ceramics in the past but don't recommend. EL's would be a no-no. The large caps are EL of course. The rest of the caps are ceramic, except for audio caps.

    With my "standard" linear regulator design, I use .1 ceramic or tant on the input and output of vregs, right next to the regulator. Input cap will be from 100uf to 470uf. Output is usually a 100uf but I've used 10ufs before with no issues. The regulators I'm using look good with a wide range of caps.

    The 22uf tant is the only one throwing me off. Suck a 10uf in and I'm preparing to pre-power test. Then smoke test!
  • average joeaverage joe Posts: 795
    edited 2012-06-03 - 22:34:05
    Sapieha, thank you for those corrections. I had been using the tant layout I described but will use your recommendations from now on.
    The board is built and just passed 1'st smoke test. Now to load the sockets and try again!


    *edited*

    I'm updating the dual screen driver and have a note:
    PUB TouchXPercent
      if ssd1289
        result := 100 - (TouchValue  & 255)
      else
        result := TouchValue & 255                          ' decode xval 0-100%
    

    X values are swapped. Could also be fixed when starting the D/A conversion?

    ALSO!
    ILIcmd($0001,$4B3F) ' set SS and SM bit 0001 0000 landscape instead of ILIcmd($0001,$6B3F) ' set SS and SM bit 0001 0000 landscape Well I had the board working, now I get nothing... Well it wasn't exactly working, but it was close. Propfont was drawing wrong? FixGlitch no longer works? Scratching my head now![code]
    ILIcmd($0001,$4B3F) ' set SS and SM bit 0001 0000 landscape

    instead of
    ILIcmd($0001,$6B3F) ' set SS and SM bit 0001 0000 landscape


    Well I had the board working, now I get nothing... Well it wasn't exactly working, but it was close. Propfont was drawing wrong? FixGlitch no longer works? Scratching my head now!
  • average joeaverage joe Posts: 795
    edited 2012-06-05 - 22:25:20
    I have revived the ORIGINAL board, this time with a more permanent voltage regulator fix. The reason for this is the original board is stable for the most part and I've been meaning to finish up work on the cache driver. I really like the first board, other than the problem with my display. I've started work on a logic analyzer that plugs in between the board and display. Should help with debugging.

    Now the question that's eating at me, how will the SSD 1963 play with our boards? I've also been wondering about Ray's DVI graphics shield. How cool would it be to have one of the dual-screen boards with a 7" touchscreen and DVI out!

    I'm still working on the cache driver for the original board. Seems to me locks need to be implemented on the bus so cache driver cog and display driver cog don't conflict. So anytime one of the propeller's cogs needs to access the bus, we need to lock the bus first:
    *in asm*
    lck_bus        lockset  lock_id wc
       if_c jmp     #lck_bus    
    
    and then unlock the bus when done
            lockclr lock_id
    
    There's also an optimization you might be interested in:
    '-----------------------------------------------
    ' setups needed for burst read
    '-----------------------------------------------
    _frqa                   long    $1000_0000
    _ctra                   long    4<<26 | 19      ' NCO mode on P19
    _phsa                   long    $0000_0000      ' phsa offset for adjusting clock start
    
    _frqb                   long    2               ' phsb accumulates twice per edge
    _ctrb                   long    $A<<26| 19      ' Edge Accumulate mode on P19
    '----------------------------------------------------------------------------------------------------
    
            mov     frqa, _frqa         ' setup NCO freq
            mov     frqb, _frqb         ' setup EDGE freq
    
    '
    ' rd_cache_line - read a cache line from external memory
    '
    ' vmaddr is the external memory address to read
    ' hubaddr is the hub memory address to write
    ' line_size is the number of bytes to read
    '
    '----------------------------------------------------------------------------------------------------            
    rd_cache_line     ' command T          pasmramtohub
                            call    #load161pasm            ' load the 161 counters with ramaddr
                            call    #memorytransfer         ' set to group 1, enable P16-P20 as outputs and set P16-P20 high                             
                            and     dira,maskP16P31         ' set P0-P15 as inputs
                            andn    outa,maskP16            ' memory /rd low
                            or      outa,maskP19
    
                            mov     phsa, _phsa             ' init counters phsa
                            mov     phsb, ptr               ' save hub ptr to phsb
                            mov     ctrb, _ctrb             ' set ctr be mode
                            andn    outa,maskP19            ' start counters
    
                            rdword  data_16,phsb            ' sync up only
                            mov     ctra, _ctra             ' enable address counter clk
    
    ramtohub_loop           ' 10MB/s read loop uses phsb for hub pointer
                            mov     data_16,ina             ' get first data
                            wrword  data_16,phsb            ' move data to hub
                            djnz    count,#ramtohub_loop
    
                            or      outa,maskP19            ' stop clock
                            mov     ctra, #0                ' stop counter
    
                            or      outa,maskP16            ' memory /rd high  
                            or      dira,maskP0P15          ' %00000000_00000000_11111111_11111111 restore P0-P15as outputs                        
                            and     dira,maskP0P20P22       ' tristates all the common pins
    rd_cache_line_ret       ret
    

    I realize the MPC board will require a re-write of the entire code, I'm just trying to get experience with GCC, SimpleIDE and the like. To be honest, I'm in completely over my head with the C and C++ but gotta start somewhere. I am quite happy with the cache driver numbers, although locking may impact them slightly.

    Work on the chiptune player has begun again. I'm just pondering "skinning" the player. There are also some glaring bugs in the code. Hopefully I will be able to post a utube video soon.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-05 - 22:40:46
    Now the question that's eating at me, how will the SSD 1963 play with our boards? I've also been wondering about Ray's DVI graphics shield. How cool would it be to have one of the dual-screen boards with a 7" touchscreen and DVI out!

    Yes - need to get the SSD1963 working properly. I had it working at one point with a stable picture and I should have saved that as a "restore point" as I can't replicate it again. I'm going to wait until the MCP23008 boards arrive.

    The MCP23008 boards are on the way and that will take things backwards for a bit porting code over but I think it will be worth it as we will have independent control of the /cs lines.
  • average joeaverage joe Posts: 795
    edited 2012-06-05 - 22:58:48
    Um, we have SSD1289's. I'd like to port over to the SSD 1963 as well. I was able to get the dual screen barely working, and then broke it. I will explore this later since getting C fully working is very important.

    Ray's DVI graphics shield is built on the SSD1963, and the 5" and 7" displays I'm interested are as well. I'm hoping the issues we're having with the SSD1289 will not re-appear when transitioning to the 1963. I need to take a closer look at Ray's shield to determine if this will work the way I hope.

    I was hoping to place my parts order today but once again life has interrupted. The kitty I had given away 5 years ago has come home! Sadly there is a growth on his neck that needs medical attention. So parts will need to wait until kitty is taken care of :(
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-06 - 23:15:13
    Yes you are right I got the display numbers muddled.

    I've been experimenting with moving most of the code into an "object". I think it makes it easier to understand. It isn't quite right yet eg the drawing of the icons is done within the object and ideally I'd like to draw them from a .ini file rather than from code.

    Even better, somehow when we compile a program to a .bin or .exe file, create an icon to go with that program. Then the desktop can be rearranged to reflect working programs.

    Jut to flat this line in the begin function of the object
      Start_ILI9325(2)                                       ' start the display 0 = ILI9325 single, 1 = SSD1289 single, 2 ILI9325 double, 3, SSD1289 double         
    

    which sets the display type
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-09 - 00:27:10
    @averagejoe, can you please PM me sometime with your new address so I can send you the next lot of parts and boards.

    I'm in the process of writing some string routines.

    In a roundabout way, I want to store the icon locations and list of programs in a text file on the sd card. To process that, it would be very helpful to be able to easily load text files into string arrays, and vice versa. And to manipulate those string arrays - search for file matches, strip off extensions etc.

    Then I had another idea. Since we have an external ram chip, why not store all strings in external ram? That saves lots of hub space, and as an additional benefit, one does not have to try to conserve string space.

    So - all strings are up to 128 bytes long. And they are in an array and you make that array as big as you like with a DIM command.

    Not finished yet but I think this is a path towards a text editor as well.
    ' ************** string routines stored in external memory so can have arrays and large text files **********************
    
    ' to make things simpler, one array StringArray. any number of entries, each up to 128 characters
    ' pass the source and destination numbers
    ' TextArray(256) = 256 entries for text files etc
    ' first entry is destination, second entrie(s) are the source
    ' Commands are
    ' StringDimTextArray            ' reserves memory 256*128, increments filenumber, adds filesize                                 
    ' StringLoadFile(Name,S)        ' read a .txt file off the SD card and stores in TextArray, new string entry is crlf
    ' StringSaveFile(Name,S,F)      ' save .txt file from TextArray to SD card adding in crlf, Start to Finish
    ' StringClear(Dest)             ' clear a string, pass string number
    ' StringAddChar(Dest,N)         ' adds a character to a string at end
    ' StringSubChar(Dest)           ' remove a character from the end
    ' StringCopy(Dest,Src)          ' copy string from one location to another
    ' StringStore(Dest,Src)         ' convert Prop string("mystring") to string stored in external memory
    ' StringLeft(Dest,Src,N)        ' Basic Left$
    ' StringMid(Dest,Src,L,N)       ' Basic Mid$
    ' StringRight                   ' Basic Right$
    ' StringInstr                   ' Basic Instr
    ' StringUcase(Dest,Src)         ' Basic Ucase$
    ' StringLcase                   ' Basic Lcase$
    ' StringLen                     ' Length
    ' StringStr                     ' string representation of a number
    ' StringHex(Dest,N)             ' number to hex string
    ' StringBin                     ' number to binary string
    ' StringVal                     ' value (add "&H" at beginning if a hex number, "&B" if a binary number)
    ' StringJoin(Dest,Src1,Src2)    ' same as Basic + with strings
    ' StringDebug(n)                ' print using the green propeller font string number n
    
    ' use these routines amongst others.
    
    'integerToDecimal(number, length) '' 5 Stack Longs
    'integerToHexadecimal(number, length) '' 5 Stack Longs
    'integerToBinary(number, length) '' 5 Stack Longs
    'decimalToInteger(characters) | sign '' 10 Stack Longs
    'hexadecimalToInteger(characters) | sign '' 10 Stack Longs
    'binaryToInteger(characters) | sign '' 10 Stack Longs
    
    PUB StringTest ' test all the string routines
       StringDim(10)
       StringStore(5,string("Hello World"))
       StringDebug(5)
       'StringAddChar(5,"s")
       'StringDebug(5)
       'StringSubChar(5)             ' remove one character from the right, useful for backspace etc
       'StringDebug(5)
       'StringCopy(7,5)              ' copy
       'StringDebug(7)
       'StringLeft(7,7,5)            ' source and destination the same or different
       'StringDebug(7)
       'StringMid(8,5,7,3)           ' dest, source, starting byte, number of bytes. first byte is 1
       'StringDebug(8)
       'StringRight(3,5,4)           ' dest, source, number of bytes
       'StringDebug(3)
       'Hex(StringInstr(5,2,"o"),2)  ' find this character starting at 2
       'StringBin(2,255)             ' convert a number to binary
       'StringDebug(2)
       StringHex(4,100)
       StringDebug(4)
       repeat
    
    PUB StringDim(n)                                ' reserve space for a string array, n= number of strings, 128 max bytes per string
       Ramsize[Filenumber] := n << 7                        ' * 128
       StringAddress := NextLocation                          ' get the location of the string array  
       Filenumber += 1
    
    PUB StringStore(StringN,Source)                               ' store a propeller string("test") to array number Dest 
       bytemove(@rambuffer, Source, (strsize(Source) + 1))     ' move to rambuffer array
       StringToRam(StringN)
    
    PUB StringDebug(StringN)                                ' print using the green propeller font
       RamToString(StringN)
       Text(@rambuffer)                                     ' print it out
    
    PUB StringClear(StringN)
       bytefill(@rambuffer,0,128)                            ' only really need to do the first one but may help debugging to completely clear the string
       StringToRam(StringN)
    
    PUB StringAddChar(StringN,c)                            ' add c to the string
       RamToString(StringN)                                 ' get the string
       byte[@rambuffer][strsize(@rambuffer)+1] := 0         ' add in the new zero (can't assume array is cleared)
       byte[@rambuffer][strsize(@rambuffer)] := c
       StringToRam(StringN)                                 ' store back to ram
    
    PUB StringSubChar(StringN)                              ' remove one character from the right same as strings.left(strings.len - 1)   
       RamToString(StringN)
       byte[@rambuffer][strsize(@rambuffer)-1] :=0
       StringToRam(StringN)
    
    PUB StringCopy(Dest,Source)                             ' copy string from source to dest
       RamToString(Source)
       StringToRam(Dest)
    
    PUB StringLeft(Dest,Source,n)                           ' Basic Left$
       RamToString(Source)
       byte[@rambuffer][n] := 0                             ' move the terminator
       StringToRam(Dest)                                    ' move back to ram
    
    PUB StringMid(Dest,Source,start,n) | i                          ' Basic Mid$
       RamToString(Source)
       repeat i from 0 to n-1
         byte[@rambuffer][i] := byte[@rambuffer][i+start-1]       ' possibly could use bytemove here
       byte[@rambuffer][n] := 0                                'add in the new zero terminator  
       StringToRam(Dest)
    
    PUB StringRight(Dest,Source,n) | i,m
       RamToString(Source)
       m := strsize(@rambuffer) - n 
       repeat i from 0 to n                                 ' Basic Right$. include the terminator
         byte[@rambuffer][i] := byte[@rambuffer][i+m]
       StringToRam(Dest)
    
    PUB StringInstr(Source,Start,c) | i                              ' find c in the string starting at start
        RamToString(Source)
        result := 0                                              ' return 0 if not found
        repeat i from (start-1) to strsize(@rambuffer)
          if byte[@rambuffer][i] == c
            result := i+1                                   ' 1 is first character
            quit   
         
    PUB StringBin(Dest,n)                                   ' convert n to a binary value at Dest
        repeat result from 31 to 0
          byte[@rambuffer][result] := ((n & 1) + "0")
          n >>= 1
        byte[@rambuffer][32] := 0                           ' add zero terminator
        StringToRam(Dest)                                   ' store
    
    PUB StringHex(Dest,n)                                   ' number to hex, always 8 characters
      repeat result from 7 to 0
        byte[@rambuffer][result] := lookupz((n & $F): "0".."9", "A".."F")
        n >>= 4
      byte[@rambuffer][8] := 0                              ' zero at end
      StringToRam(Dest)     
    
    PRI StringToRam(StringN)
       HubToRam(StringN<<7 + StringAddress,128)
    
    PRI RamToString(StringN)    
       RamToHub(StringN<<7+StringAddress,128)                             ' moves to rambuffer array    
    
    ' ***************** end string routines *************************  
    
  • average joeaverage joe Posts: 795
    edited 2012-06-09 - 00:51:41
    Great work Doc!
    I've been studying Raymond's DVI board and trying to understand how to interface it with our boards. I think it would be nice to have DVI out as an option. Still stuck on datasheets and such.
    The port of the chiptune player is riddled with bugs I'm working out. It's functional, but there are issues.
    I've spent a few hours working on a C wrapper for low level spin functions. Work is slow due to my lack of C experience. Hopefully I will be able to pick up speed as I go.
    Sending you a PM now!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-13 - 23:28:48
    @averagejoe, the MCP2008 boards have arrived - I'm just waiting on the parts so I can send you both together. I haven't soldered mine up yet as I've been completing a massive rewrite of the code so that now every icon on the screen runs a separate binary program.

    Needed cunning things like a "warm boot" which is faster where we can store some parameters in the external ram as that stays static when the propeller is rebooted.

    I'm also thinking of porting the desktop program to something that reads a file. Or at the very least has the .exe and the icons as the same filename! Need to store four things, exe filename, icon, x position and y position. I think an Excel .csv file might be the easiest.

    Anyway, the desktop loader is called Desktop.spin and this is the code:
    CON
      _clkmode      = xtal1 + pll16x                        ' use crystal x 16
      _xinfreq      = 5_000_000
       
    OBJ
      tch:           "Touch"                                 ' touchscreen driver
    
    PUB Main | wcboot  ' warm or cold boot
      wcboot := tch.Begin(2,true)                                          ' display type 2 = dual ILI9325, true is desktop
      if wcboot == false                             ' erase ram chip, checks if a cold or warm boot, sets some variables
          tch.Clearscreen(tch.RGBtoWord(0,0,0))                         ' clear screen to black - uses the display driver above
          LoadDesktop                                           ' a image 240x320 for the desktop. Load first as there is a ramclear routine that does not delete the first entry
          DrawDesktop
          LoadIcons                                             ' load the mask and icons onto the screen
      else                                                          ' warm boot
          tch.ManualValues                                         ' coming from outside so reset ramsize and ramlocation values for 0 and 1
          DrawDesktop                                           ' quick redraw of desktop if a warm boot
    
      tch.SelectSPIGroup                                        ' selects this group and starts the cog    
      Touchscreen                                           ' wait for input
    
    PUB TouchScreen  | yval, xval,pointer
        repeat
          yval := tch.TouchYPercent                           ' decode yval 0-100%               
          xval := tch.TouchXPercent                          ' decode xval 0-100%
          if (xval <> 255)  and (yval <> 255)
            'tch.SelectMemGroup
            'hex(xval,2)      ' if display any debug messages need to restart the SPI cog as it has been stopped by the debug display
            'hex(yval,2)
            'repeat
            pointer := (yval/20)*4+(xval/25)       ' so can use a case statement 0-19
            if pointer < 20
              tch.SelectMemGroup
            case pointer                                    ' 0 to 19
               0:                   
               1:                   
               2:
               3:
               4:
               5: 
               6:
               7:
               8:  tch.Chain(string("PHOTO.EXE"))
               9:  tch.Chain(string("CALC.EXE"))               ' chain this precompiled program                            
               10: tch.Chain(string("LOREM.EXE")) 
               11: tch.Chain(string("MOVIE.EXE"))              'chain this precompiled program
               12: tch.Chain(string("KEYBOARD.EXE"))
               13: tch.Chain(string("MUSIC.EXE"))
               14: tch.Chain(string("WAVDEMO.EXE"))
               15: tch.Chain(string("BUTTONS.EXE"))  
               16: tch.Chain(string("SYNTHDRC.EXE")) 
               17: tch.Chain(string("HTML.EXE"))
               18: 
               19: 
    
            tch.SetOrientation(true)
            tch.SelectMemGroup                              ' ready for mem out
            DrawDesktop                                 ' redraw the background
            tch.SelectSPIGroup                              ' restart the spi driver
    
    PUB LoadIcons                                           ' load all the icons onto the screen. Possibly use a .ini text file for this
       tch.SDBMPtoRam(string("mask.bmp"))                       ' file number 1
       tch.MergeBackgroundIconRam(string("photos.bmp"),0,120)   ' file number 2 and leaves filenumber as 2 ready for the next one
       tch.MergeBackgroundIconRam(string("calc.bmp"),60,120)        ' draw an icon onto the background    
       tch.MergeBackgroundIconRam(string("facebook.bmp"),120,120)   ' draw an icon
       tch.MergeBackgroundIconRam(string("videos.bmp"),180,120)     ' draw an icon
       tch.MergeBackgroundIconRam(string("notes.bmp"),0,180)        ' draw an icon
       tch.MergeBackgroundIconRam(string("music.bmp"),60,180)       ' draw an icon
       tch.MergeBackgroundIconRam(string("ipod.bmp"),120,180)       ' draw an icon 
       tch.MergeBackgroundIconRam(string("prop.bmp"),180,180)       ' prop icon for a GUI buttons, radio, checkboxes etc
       tch.MergeBackgroundIconRam(string("itunes.bmp"),0,240)       ' play some music
       tch.MergeBackgroundIconRam(string("safari.bmp"),60,240)       ' html (better GUI modelled on Opera rather than Windows)
       DrawDesktop
    
    PUB DrawDesktop
       tch.DrawBMPRam(1,0,0)                                    ' file number 1, location 0,0
    
    PUB LoadDesktop                                         ' first bmp file is not deleted wtih clearramdiskexcludedesktop
       tch.SDBMPtoRam(string("balloon.bmp"))                     ' file number 1 
    

    and as an example, the photo viewer program
    CON
      _clkmode      = xtal1 + pll16x                        ' use crystal x 16
      _xinfreq      = 5_000_000
       
    OBJ
      tch:           "Touch"                                 ' touchscreen driver
    
    PUB Main | touchtest  ' debug value
      tch.Begin(2,false)                                          ' display type 2 = dual ILI9325, false means run a program not the desktop so don't load icons
      PhotoAlbum
      tch.SetWarmBoot                                           ' clears screen, sets a warm boot and reboots
    
    PUB PhotoAlbum | picturenumber
       tch.Clearscreen(%00000000_00000000)                  ' clear the screen
       tch.SetCursor(0,0)
       tch.Text(string("Please wait 8s"))
       tch.ClearRam
       tch.SDBMPtoRam(string("slide1.bmp"))                    ' file 2
       tch.SDBMPtoRam(string("slide2.bmp"))                ' file 3
       tch.SDBMPtoRam(string("slide3.bmp"))                 ' file 4
       tch.SDBMPtoRam(string("slide4.bmp"))                   ' file 5
       tch.SDBMPtoRam(string("slide5.bmp"))                  ' file 6
       picturenumber := 2
       repeat until picturenumber > 6
            tch.DrawBMPRam(Picturenumber,0,0)               ' draw the picture
         result := tch.TouchSwishY                          ' swish left to right or up to down depending on orientation
         if result > 0
           picturenumber --
         else
           picturenumber ++
       tch.Clearscreen(%00000000_00000000)
       tch.pause1ms(1000) ' otherwise still touching the screen
    

    The touch object has all sorts of useful things and I'm sure it will end up being changed and edited.

    I think the important thing is that a typical program, eg the slide viewer above, is only using about half the hub ram. So for a program, and despite all the overheads of driving sd card, touchscreens, displays etc, there are still propeller pins free and half the memory free.

    I'll see if I can get the desktop loading from a .csv file . Hmm - maybe even need an "edit" mode for the desktop so you can move icons around by dragging them with a finger?

    Addit: I see the SSD1963 now comes in a 5" as well http://www.ebay.com.hk/itm/ws/eBayISAPI.dll?ViewItem&item=221044250453&ssPageName=ADME:B:FSEL:HK:1123

    It would be very handy to have software that can handle a variety of screen sizes.
  • average joeaverage joe Posts: 795
    edited 2012-06-14 - 23:09:41
    Hi Doc,
    I finished moving, cleaning, and all the various things that have occupied me for the past 2 weeks. I am by no means unpacked, but I've "found" all the things I need to get working again. With some luck, I'll be able to get the Ez-LCD301 working with the V1 board. It's my current "standard" board as it works for the most part. I've not been able to get the v2 board working yet, although it's fully built. Hopefully the v3 board will work with these dang ssd1289's! If not, I would still like to reference the OTHER ssd. Maybe those will work on all boards? $50 is out of my budget right now for such an experiment, since I still don't have the other 2 displays I ordered. Next week...

    I was able to place a parts order that showed up today, okay well HALF showed up today. I have sockets, hc32's, hc08's as well as some other nice toys. I also ordered more SRAMs since having more than one board running at a time is a plus.. I need to talk to Steve about the board I sent him.

    I could also use some advise about larger EEPROMs. I like the idea of having a larger eeprom that could hold "presets" or such.

    Must run for now. Keep up the awesome work!


    *edit*
    After much thought, I have come up with the name
    "DracBurger Touch"
    Any thoughts?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-16 - 06:23:27
    Re names - no need for the Drac bit - I've already got a series of boards with Drac in the name so you can have the whole name.

    I will get around to soldering the latest board soon. Meanwhile, I have managed to simplify the entire operating system right down to this little bit of code:
    CON
      _clkmode      = xtal1 + pll16x                        ' use crystal x 16
      _xinfreq      = 5_000_000
    OBJ
      tch:           "Touch"                                 ' touchscreen driver
    PUB Main | wcboot  ' warm or cold boot
      wcboot := tch.Begin(2,true)                                          ' display type 2 = dual ILI9325, true is desktop
      if wcboot == false                             ' erase ram chip, checks if a cold or warm boot, sets some variables
          tch.Clearscreen(tch.RGBtoWord(0,0,0))                         ' clear screen to black - uses the display driver above
          tch.SDBMPtoRam(string("desktop.bmp"))                     ' file number 1, a 240x320 file called desktop.bmp     
          DrawDesktop
          LoadDesktopCSV
          DrawIcons 
      else                                                          ' warm boot
          tch.ManualValues                                         ' coming from outside so reset ramsize and ramlocation values for 0 and 1
          DrawDesktop                                           ' quick redraw of desktop if a warm boot
          LoadDesktopCSV
      tch.SelectSPIGroup                                        ' selects this group and starts the cog    
      Touchscreen                                           ' wait for input
    
    PUB TouchScreen  | yval, xval,pointer
        repeat
          yval := tch.TouchYPercent                         ' decode yval 0-100%               
          xval := tch.TouchXPercent                         ' decode xval 0-100%
          if (xval <> 255)  and (yval <> 255)
            pointer := (yval/20)*4+(xval/25)                ' reduce to a value 0-19 so can read the correct string for the file name
            if pointer < 20                                 ' there are spaces for 20 icons on the screen 4 wide 5 high
              tch.SelectMemGroup
            tch.StringJoin(85,pointer+60,81)                ' filename plus .exe
            tch.Chain(tch.stringrambuffer(85))              ' run this filename
    
    PUB DrawDesktop
       tch.DrawBMPRam(1,0,0)                                ' file number 1, location 0,0
    
    PUB LoadDesktopCSV | n                                  ' load the file desktop.csv (Excel csv file with icon locations)
       tch.SDBMPtoRam(string("mask.bmp"))                   ' file 2, load this here - if load after the strings get a white line on the icons  
       tch.StringDim(85)                                    ' file number 3 is all the strings
       tch.StringStore(80,string("desktop.csv"))            ' filename to load
       tch.StringLoadfile(80,0)                             ' load from 0 to 19 (20 lines of text in a desktop.csv file)
       repeat n from 0 to 19
         CutupComma(n)
       tch.StringStore(81,string(".exe"))                   ' store exe extension for later  
       tch.StringStore(82,string(".bmp"))                   ' store .bmp extension
       tch.StringStore(83,string("blank"))                  ' store for later
       ' array 0-19 are raw string, 20-39 are x, 40-59 are y, 60-79 are filename with no extension or "blank"
    
    PUB DrawIcons | n,x,y
       repeat n from 60 to 79                               ' draw the icons - mask alredy loaded in file 2 when loading desktop
         if tch.StringCompare(n,83) == false                ' is this entry "blank"?
           tch.StringJoin(85,n,82)                          ' create filename.bmp
           x := tch.StringVal(n-40)                         ' need to pre-evaluate these, can't put in the mergebackground routine
           y := tch.StringVal(n-20)
           tch.MergeBackgroundIconRam(tch.stringrambuffer(85),x,y,1,2,4)   ' desktop file 1, mask file 2, icons in file 4
           DrawDesktop
    
    PUB CutupComma(Source) | c1,c2,len                      ' pass source 0-19, dest = 20-39 for first group, 40-59 for second group etc
       c1 := tch.StringInstr(Source,1,",")                  ' first comma
       c2 := tch.StringInstr(Source,c1+1,",")               ' second comma
       len := tch.StringLen(Source)                         ' length
       tch.StringLeft(Source+20,Source,c1-1)                ' first value
       tch.StringMid(Source+40,Source,c1+1,c2-c1-1)         ' second value
       tch.StringRight(Source+60,Source,len-c2)             ' third value = filename with no extension
    
    

    It is now super simple. The background is a file called "desktop.bmp". All files that you run (eg calc.exe) have an associated file "calc.bmp" for the icon.

    The locations of the icons and the files are stored in a standard .csv file made with Excel
    0,0,blank
    60,0,blank
    120,0,blank
    180,0,blank
    0,60,blank
    60,60,blank
    120,60,blank
    180,60,blank
    0,120,photo
    60,120,calc
    120,120,lorem
    180,120,movie
    0,180,keyboard
    60,180,music
    120,180,wavdemo
    180,180,buttons
    0,240,synthdrc
    60,240,html
    120,240,blank
    180,240,blank
    

    And that is the entire operating system!

    For any program you want to run you write a new separate program. Use the "touch.spin" library with all sorts of useful routines. Last line in a .exe program is to call a warm boot which loads the desktop out of ram which means it is only about 1 second to chain programs or to go from a program back to the desktop operating system.

    You can pass all sorts of things between chained programs as the external ram stays static.

    There is a huge amount of string space now that strings are in external ram. All strings are fixed length 128 bytes (I've never been a great fan of variable length strings as every now and then you have to clean them up, eg MBASIC used to just freeze at random intervals every 10 mins or so). Who cares about how much space is wasted when strings are in external ram. 8192 strings of 128 bytes each if you want them.

    re bigger eeprom, I am wondering if you can achieve the same effect by using the SD card?


    Addit 20th June - working on porting over to the MCP23008 chip. Got pins going high and low. Need to rewrite all the code that talks to the display next.
    '' Simple I2C MCP23008 demonstration J Moxham
    ''  output to pins (see MCP23016 objects in the Obex for input and other commmands)
    '' Thanks to James Burrows and Michael Green
    '' based on C code http://www.nutsvolts.com/index.php?/blog/post/adding_more_digital_i_o_to_your_16_bit_microcontroller_experiments_part_2_t
    
    CON
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
      SCL = 28          ' pins never change
      SDA = 29
    
    PUB i2c_Demo
        i2c_Initialize                                      ' start the driver
        i2c_writelocation($40,$0,$0)                        ' write to device $40 MCP23008, all pins are outputs  
        repeat
          i2c_writelocation($40,$09,%11111110)  ' device $40, address $09 is output - leds are active low
          waitcnt((clkfreq/2)+cnt)              ' small delay
          i2c_writelocation($40,$09,%11111101)  ' next led on
          waitcnt((clkfreq/2)+cnt)  
          i2c_writelocation($40,$09,%11111011)
          waitcnt((clkfreq/2)+cnt)
          i2c_writelocation($40,$09,%11110111)
          waitcnt((clkfreq/2)+cnt)
          i2c_writelocation($40,$09,%11101111)
          waitcnt((clkfreq/2)+cnt)
          i2c_writelocation($40,$09,%11011111)
          waitcnt((clkfreq/2)+cnt)
          i2c_writelocation($40,$09,%10111111)
          waitcnt((clkfreq/2)+cnt)
          i2c_writelocation($40,$09,%01111111)
          waitcnt((clkfreq/2)+cnt)
    
    PUB i2c_Initialize               ' An I2C device may be left in an
       outa[SCL] := 1                       '   reinitialized.  Drive SCL high.
       dira[SCL] := 1
       dira[SDA] := 0                       ' Set SDA as input
       repeat 9
          outa[SCL] := 0                    ' Put out up to 9 clock pulses
          outa[SCL] := 1
          if ina[SDA]                      ' Repeat if SDA not driven high
             quit                          '  by the EEPROM
    
    PUB i2c_Start                   ' SDA goes HIGH to LOW with SCL HIGH
       outa[SCL]~~                         ' Initially drive SCL HIGH
       dira[SCL]~~
       outa[SDA]~~                         ' Initially drive SDA HIGH
       dira[SDA]~~
       outa[SDA]~                          ' Now drive SDA LOW
       outa[SCL]~                          ' Leave SCL LOW
      
    PUB i2c_Stop                   ' SDA goes LOW to HIGH with SCL High
       outa[SCL]~~                         ' Drive SCL HIGH
       outa[SDA]~~                         '  then SDA HIGH
       dira[SCL]~                          ' Now let them float
       dira[SDA]~                          ' If pullups present, they'll stay HIGH
    
    PUB i2c_Write(data) ': ackbit 
    '' Write i2c data.  Data byte is output MSB first, SDA data line is valid
    '' only while the SCL line is HIGH.  Data is always 8 bits (+ ACK/NAK).
    '' SDA is assumed LOW and SCL and SDA are both left in the LOW state.
       'ackbit := 0                         ' ack bit commented out as this chip always works
       data <<= 24
       repeat 8                            ' Output data to SDA
          outa[SDA] := (data <-= 1) & 1
          outa[SCL]~~                      ' Toggle SCL from LOW to HIGH to LOW
          outa[SCL]~
       dira[SDA]~                          ' Set SDA to input for ACK/NAK
       outa[SCL]~~
       'ackbit := ina[SDA]                  ' Sample SDA when SCL is HIGH
       outa[SCL]~
       outa[SDA]~                          ' Leave SDA driven LOW
       dira[SDA]~~
    
    PUB i2c_writeLocation(device_address, register, value)
      i2c_start                            ' start the chip
      i2c_write(device_address)            ' write to this chip
      i2c_write(register)                  ' write to this register
      i2c_write(value)                     ' write value
      i2c_stop                             ' stop the chip
    
    640 x 480 - 68K
  • Cluso99Cluso99 Posts: 16,955
    edited 2012-06-16 - 09:55:30
    Wow! This sounds really interesting guys :)
  • BitsBits Posts: 414
    edited 2012-06-20 - 11:52:12
    I am considering ordering one of these displays, but how do I know of one that the propeller can run without too much trouble. Is this TFT running 320x480 going to be difficult?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-20 - 19:30:51
    Hi Bits,

    I've been using these http://www.ebay.com/itm/2-4-TFT-LCD-Module-Display-Touch-Panel-PCB-adapter-/190477028273?pt=LH_DefaultDomain_0&hash=item2c5950cbb1

    But I am not sure - they might have changed the driver chip (again!). ILI9325 is the one that is the most reliable. Some other displays seem to require the /CS pin to be toggled when sending data. I'm in the middle of a massive rewrite - new code, new board, no display working at all, back to debugging things with a logic probe. I am hopeful I can get something working soon that is a more universal and where we can plug in a wide range of these displays and just change some code.
  • average joeaverage joe Posts: 795
    edited 2012-06-20 - 23:05:57
    Hi Bits,

    I've been using the 3.2" LCDs with the SSD1289 controller and they seem to be less forgiving than the ILI9325. During the beginning of my personal touchscreen journey, I was able to get the SSD 1289 working directly with the Prop. Screen refreshes were quite slow, but it seemed to work. Then came the V1 board which I am still using with my SSD1289. The ILI displays worked flawlessly, but the SSD has a glitch somewhere. Still can't pin it down exactly.

    Now to answer your question:

    In theory the propeller should be able to drive most of these display driver chips. SOME hardware implementations MAY have issues.

    A bit more about your application and intended hardware would help clarify.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-20 - 23:15:02
    @averagejoe, I'm working on the SSD1289 problem right now.
  • jmgjmg Posts: 14,544
    edited 2012-06-21 - 02:32:00
    Bits wrote: »
    I am considering ordering one of these displays, but how do I know of one that the propeller can run without too much trouble. Is this TFT running 320x480 going to be difficult?

    I note that display has a 'cloned connector' scheme, whilst this series

    http://www.displaytech-us.com/integrated-tft-driver-boards

    somehow missed that obvious answer. It really grates, on the bigger sizes, as you need a huge backing board, just to reach both connectors (or some strange double-crimped ribbon cable..)


    On the plus side, I see ALL the display tech ones 3.5" and up, use the same SSD1963, and Rayman has that jumping thru hoops.

    The smaller 4 all use the RAIO RA8872 LCD controller. Not sure how that goes with the Prop ?

    The RA8872 looks quite capable, it has a simple font built in, and some graphics primitives, so should pair well with resource limited controllers.

    The datasheet includes example code for an 8051, does not look too daunting.

    Be interesting if anyone has that RA8872 working ?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-21 - 05:36:36
    Re displays, many of them come with example C driver code and I've found if you name the functions the same in Spin it makes it fairly easy to translate from C to Spin.

    @average joe, I now have something working. Change one line of code to use the ILI9325 display or the SSD1289 display. Board takes both displays - just power down and swap them over. Now we have full control over all the pins it makes things easier. I put in the /cs low and then /cs high after every data write as that is what the SSD1289 needs and it seems to be ok with the ILI9325 so that makes this code backwards compatible.

    Pictures of both size displays below. The two large ones probably could be another 0.1" closer.

    Only working in spin at the moment so very slow. Will work on porting over to pasm now.

    I have the boards for you at the moment but for some reason futurlec are taking a while with the parts. Do you want me to send the bare boards now we know this works?
  • average joeaverage joe Posts: 795
    edited 2012-06-21 - 16:14:30
    @Doc, please do send the boards. I believe I have all necessary parts, just missing the ADC.

    Very busy trying to catch up with schoolwork, hopefully next week I can post my progress!

    Keep up the great work!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-23 - 00:38:07
    Hi average joe,

    Boards sent 36h ago - they will be winging their way to you now :) Just a thought - take a look at the picture on the right on post #417 - just note around the propeller chip where the resistor arrays go. I noticed when I soldered the board up that it was a bit unclear from the overlay which were the resistors and which were the pins for headers (if you want external headers/access to P0-P23).

    I have done a massive rewrite of the code. Moved lots of "program specific" code out of the common "Touch.spin" object and into individual programs (eg you don't need the checkbox code if you are running the synth program).

    One problem - this MCOP23008 code is slower as there are multiple changes between loading up the 161 chips and then sending to ram. One of the problems is the .bmp files - they start at the end and work to the beginning, but we want them in ram the other way round. So every line of the picture needs a new 161 address. Which means lots of 400khz messages to the I2C port. I'm trying to think of a way of flipping between the 161 and ram access in a quicker way. If only we had one more propeller pin!!

    I am going to try recoding the 161 and I2C into pasm. I tried it yesterday but it didn't work (there are pasm I2C drivers in the obex) but it may not save much time anyway as the 400khz speed is fixed (?)

    I've got one workaround in that the first load of the desktop program is slow, but doing a "warm boot" from a program like the calculator is super fast as it caches the desktop image in ram. Ram to the display is still fast because the .bmp file has already been turned into the right format for fast output to the display. So that is still 30ms.

    Another thing - changing back and forth between the two displays I figured that if we add just one line of code in the desktop program
      wcboot := tch.BeginDesktop("S")                            ' "I" = ILI9325, "S"= SSD1289     
    

    then the "S" or the "I" can be stored in external ram. That means that all the programs you run from icons eg the calculator, synth, can access the type of display from a static location in ram. So no other programs need worry about the display. I've been testing this and it works really well. Saves recompiling eg the calculator program each time you change the display.

    Oh, a minor thing. The x axis is flipped on the SSD1289 display for the touchscreen. But no matter because all programs know which display it is, so that can stay internal to the Touch.Spin object and users don't need to worry about it. So a call to get the x and y position of a finger press is still 0-100% same for both displays.

    It is very handy being able to swap displays. The larger ones almost are as big as the board and we have 480x320 of wonderful touchscreen to use. But the smaller ones have a much better image at oblique angles - almost oled or CRT in that the colors stay the same even when looking at the display very obliquely. So each have their uses.
    640 x 480 - 66K
  • average joeaverage joe Posts: 795
    edited 2012-06-23 - 03:59:07
    @ Doc:

    re: MPC code, I see the 1.7Mhz mode listed on the datasheet, but it looks like 4.5 - 5.5v spec. Other than that, it seems the best way is to use RAW format?
    re: Warm boot, EXCELLENT NEWS. I've had some ideas for "standalone" apps but no time to code.
    re: boards, Thanks again! I will let you know when they arrive!
    re: final stab at a name *it's all in the name* "TouchBurger x" where x is model?

    @Bits, Please keep us updated of the display you choose. If you order something other than the ILI 9325 or SSD 1289 we may be able to spec you a board.

    I must run and try to finish homework. Seems the first week and last week are the worst.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-23 - 04:46:35
    Touchburger sounds fine to me.

    Standalone apps - yes I think that is the way to approach things. eg this is the dual display demo. All the complicated stuff is hidden away in the Touch object. A typical app has about half the hub ram free for code space. And data arrays and strings can be offloaded to the external ram, so there is plenty of space for coding.
    CON
      _clkmode      = xtal1 + pll16x                        ' use crystal x 16
      _xinfreq      = 5_000_000
       
    OBJ
      tch:           "Touch"                                 ' touchscreen driver
    
    PUB Main
      tch.BeginProgram                                          
      DualScreen
      tch.SetWarmBoot                                           ' clears screen, sets a warm boot and reboots
    
    PUB DualScreen |xval, yval
       tch.ClearRam
       tch.SDBMPtoRam(string("KangL.bmp"))                  ' file 2
       tch.DisplayLeft                                      ' left picture
       tch.DrawBMPRam(2,0,0)                                ' draw the picture
       tch.SDBMPtoRam(string("KangR.bmp"))                  ' file 3   
       tch.DisplayRight                                     ' right picture
       tch.DrawBMPRam(3,0,0)                                ' draw the picture   
       tch.SelectSPIGroup                                   ' talk to the spi touchscreen  
       repeat
          yval := tch.TouchYPercent                           ' decode yval 0-100%               
          xval := tch.TouchXPercent                           ' decode xval 0-100%
          if (xval <> 255)  and (yval <> 255)                    ' valid keypress - touch the screen to exit
            return
    
Sign In or Register to comment.