Anyone working on an SSD1339 based OLED (132x132) module?

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Anyone working on an SSD1339 based OLED (132x132) module?

Post by RadioT » Thu Dec 13, 2007 3:02 pm

Hello,

I've switched over to SF from Proton and have been working on a module for an organic LED display that uses the Solomon SSD1339 chip for about a week now. I'm implementing it using the 8-bit 6800-type interface configuration. Is anyone more experienced with SF working on this type of OLED or interested in collaborating on it?

User avatar
octal
Registered User
Registered User
Posts: 584
Joined: Thu Jan 11, 2007 12:49 pm
Location: Paris IDF
Contact:

Post by octal » Thu Dec 13, 2007 4:04 pm

Hi,
have you got any (ready) documentation about this module? I'll be glad to help you :)

regards
octal

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Thu Dec 13, 2007 4:55 pm

Sure, I have lots of documentation. I am writing a hardware module and also have it going in Proton Plus. However, the Proton code is a kluge, it has a lot of extra small functions since it can't do overloaded subroutines, modules, etc. Which is why I switched to SF.

Note that the SSD1339 has a few unique features. It has built-in functions for drawing lines, circles and rectangles. I use the line drawing feature to put pixels on the screen, just start/stop at the same location. The colour definition is also two bytes, vs. the one byte used by the GLCDs I've seen in the libraries, so I use TColor (which is a byte in graphics.bas) and a second byte for colour, $55 just to fill in the requirement for putting in 2 bytes for colour.

I am using port D for the parallel interface, and B and E for the signals, as noted in the top of the hardware module. I started with the library module for the S1D15G00 by David Barker and made modifications from there.

I have not successfully written directly to RAM in the SSD1339, I'm trying it in the graphic image routine "SetImage", nothing happens.

There's a few manufacturers using the Solomon SSD1339, (they mount the chip on thier own OLED display) including Newtec and Densitron. Densitron has product support, Newtec does not. If you need to see the datasheet for the SSD1339, there's one at:

http://www.densitron.com/Displays/OLED_ ... erica.aspx

You have to register to download the datasheet but it's worth it because it will be the latest version. Or I could email it to you if you like via private message.

So, here is the calling program, the hardware code (SSD1339.bas) module and the top few lines of GLCD.bas module.

I can draw graphics such as squares and circles but the font text comes out as a solid block. Graphic images don't put anything on the screen.

Here is the testing function that calls out the code:


Device = 18F66J16
Clock = 8
Include "GLCD.bas"
Include "Arial.bas"
Config Fosc = intosc

GLCD.SetFont(ArialBold)
GLCD.WriteAt(40,80,"Arial Font")
DelayMS(500)
Rectangle(0,0,120,120)
GLCD.SSD1339.Rectangle(0,0,100,90,119,190,130,9)
Circle(40,40,20)

GLCD.SetImage(49,51,BtnOK)
GLCD.SetImage(89,51,BtnCancel)
GLCD.SetImage(4,2,BatteryImage)

SSD1339.bas:

Code: Select all


Module SSD1339

#define GLCD_PIXEL_08
#define GLCD_COLOR_08
#define GLCD_XY_08
Include "Graphics.bas" 
Include "system.bas" 
 
// default module options - user options can override these values...
// this code uses the 6800 format 8-bit parallel interface
// 6800 8-bit configuration used: BS0 low, BS1 low, BS2 high, BS3 low
// This display is 132x132. The RGB interpretation for 8 bit colour is the same
// as for the S1D15G00 - RRRGGGBB. 
#option GLCD_RESET = PORTE.5     // reset pin, active low-like S1D15G00
#option GLCD_DATA = PORTD        // data port 
#option GLCD_DC = PORTE.6        // Data or Command pin, data when high
#option GLCD_CS = PORTE.7        // Chip Select pin, MCU comms enabled when low-like S1D15G00
#option GLCD_E = PORTB.2        // Enable pin, R/W data latched when pulled high-like S1D15G00
#option GLCD_RW = PORTB.3        // Read-Write pin, write mode when low-like S1D15G00
#option GLCD_ASPECT_RATIO = 100  // aspect ratio
#option GLCD_INIT_DELAY = 100    // initialisation delay (ms)
//#option GLCD_SPI = SW            // use software SPI 

// validate Reset pin...
#if IsOption(GLCD_RESET) And Not IsValidPortPin(GLCD_RESET) 
   #error GLCD_RESET, "Invalid option. RESET must be a valid port pin."
#endif

// validate DATA port...
#if IsOption(GLCD_DATA) And Not IsValidPort(GLCD_DATA) 
   #error GLCD_DATA, "Invalid option. DATA must be a valid port."
#endif  

// validate DC pin...
#if IsOption(GLCD_DC) And Not IsValidPortPin(GLCD_DC) 
   #error GLCD_DC, "Invalid option. DC must be a valid port pin."
#endif

// validate CS pin...
#if IsOption(GLCD_CS) And Not IsValidPortPin(GLCD_CS) 
   #error GLCD_CS, "Invalid option. CS must be a valid port pin."
#endif    

// validate E pin...
#if IsOption(GLCD_E) And Not IsValidPortPin(GLCD_E) 
   #error GLCD_E, "Invalid option. E must be a valid port pin."
#endif  

// validate RW pin...
#if IsOption(GLCD_RW) And Not IsValidPortPin(GLCD_RW) 
   #error GLCD_RW, "Invalid option. RW must be a valid port pin."
#endif  

// validate initialisation delay...
#if IsOption(GLCD_INIT_DELAY)
   #if Not (GLCD_INIT_DELAY in (0 to 1000))
      #error GLCD_INIT_DELAY, "Invalid option. GLCD initialize delay must be between 0 and 1000 (ms)."
   #endif
#endif 

// SSD1339 commands...   
Const
   cmdDisCtl = $CA,     //Display Control
   cmdNOP = $E3,        //NOP - $25 in S1D15G00
   cmdDisOn = $AF,      //Display On, out of sleep
   cmdDisOff = $AE,     //Display Off, in sleep mode
   cmdBlank = $A4,     //Sets diplay mode to All Off-all pixels have GS0 (grayscale level 0), minimum brightness
   cmdAllOn = $A5,     //Sets diplay mode to All On-all pixels have GS63 (grayscale level 63), maximum brightness
   cmdDisNor = $A6,     //Sets display mode to Display Normal
   cmdDisInv = $A7,     //Sets display mode to Display Invert-gray levels swapped-GS0 is GS63, GS7 is GS56, etc
   cmdPaSet = $75,      //Page Address Set
   cmdCaSet = $15,      //Column Address Set
   cmdRamWr = $5C,      //Writing to Memory
   cmdCtrst = $C7,       //Master contrast control
   cmdRemap = $A0,       //$A0 then $34, normal; $A0 then $26 - flips display 180 degrees 
   cmdStLin = $A1,       //sets starting line
   cmdVScrl = $A2,       //set vertical scroll by row from 0-131
   cmdMastC = $AD,       //master configuration, int/ext VCC suppply and int/ext pre-charge V supply
   cmdPwrSa = $B0,       //power save mode, sets int/ext VSL and power save on/off
   cmdResPr = $B1,       //et reset (phase 1) & pre-charge (2) period adjustments-1 is discharge time,2 is charge time
   cmdOscDv = $B3,       //front clock divider and int oscillator freq set      
   cmdPreCV = $BB,       //set the pre-charge colour voltage of each colour
   cmdVCOMH = $BE,       //set VCOMH - should be irrelevant since use ext supply but manuals say set it...
   cmdCoCol = $C1,       //Contrast currents for each colour A, B, C (RGB)
   cmdMuxRa = $CA,       //mux ratio - number of display lines turned on - start & end depends on A2 cmd setting  
   cmdDLine = $83,       //draw line
   cmdDRect = $84,       //draw rectangle
   cmdDcirc = $86,       //draw circle
   cmdCopy  = $8A,       //Copy area
   cmdDimWi = $8C,       //Dim Window
   cmdClWin = $8E,       //Clear Window
   cmdFilED = $92,       //Fill Enable/Disable
   cmdHorSc = $96,       //Horizontal Scroll
   cmdSpHor = $9E,       //Stop horizontal scroll
   cmdStHor = $9F,       //Start horizontal scroll moving  
   GLCDDelay = GLCD_INIT_DELAY     

// port and pin settings, these are brought into
// the program by using the above options...
Dim        
   Data As GLCD_DATA,        // data port 
   TRISData As TRISD, // Data TRIS
   E As [email protected],    // clk pin
   CS As [email protected],   // CS pin
   DC As [email protected],   // DC pin
   RW As [email protected],   //RW pin
   Reset As [email protected]     // reset pin
   
// GLCD width and height...
Public Const
   GLCDWidth = 130,
   GLCDHeight = 130

// x, y position...
Public Dim
   Pos As TPosition
  'Contrast As FContrast   
 {
****************************************************************************
* Name    : StrobeEN (Private)                                             *
* Purpose : Strobe the GLCD EN pin                                         *
****************************************************************************
}    
Inline Sub StrobeEN()
   CS = 0
   E = 1
   DelayUS(1)
   CS = 1
End Sub
{
****************************************************************************
* Name    : GLCDData (PRIVATE)                                             *
* Purpose : Switch To GLCD Data mode                                       *
*           Modified For KS0713                                            *
****************************************************************************
}    
Inline Sub GLCDData()
   DC = 1
End Sub
{
****************************************************************************
* Name    : GLCDInst (PRIVATE)                                             *
* Purpose : Switch To GLCD instruction mode                                *
*           Modified For KS0713                                            *
****************************************************************************
}    
Inline Sub GLCDInst()
   DC = 0	
End Sub
{
****************************************************************************
* Name    : GLCDRead (PRIVATE)                                             *
* Purpose : Set GLCD To Read mode                                          *
****************************************************************************
}    
Inline Sub GLCDRead()
   RW = 1
End Sub
{
****************************************************************************
* Name    : GLCDWrite (PRIVATE)                                            *
* Purpose : Set GLCD To write mode                                         *
****************************************************************************
}    
Inline Sub GLCDWrite()
   RW = 0	
End Sub
{
****************************************************************************
* Name    : SetData (PRIVATE)                                              *
* Purpose : Write a Data Byte To GLCD                                      *
****************************************************************************
}     
Sub SetData(pData As Byte) 
   TRISData = $00   // Set Data bus To Output
   GLCDData         // access display RAM Data
   GLCDWrite        // write mode
   Data = pData     // write To the bus
   StrobeEN         // write To GLCD
End Sub
{
****************************************************************************
* Name    : WriteData (PRIVATE)                                            *
* Purpose : Write a series of data bytes to GLCD                           *
****************************************************************************
}     
Compound Sub WriteData(SetData)
{
****************************************************************************
* Name    : GetData (PRIVATE)                                              *
* Purpose : Read Byte from GLCD                                            *
****************************************************************************
}     
Function GetData() As Byte
   TRISData = $FF   // Set Data bus To Input
   GLCDData         // access display RAM Data
   GLCDRead         // Read mode
   StrobeEN         // latch Data
   Result = Data    // get the Data
End Function  
{
****************************************************************************
* Name    : Command (PRIVATE)                                              *
* Purpose : Write a command Byte To GLCD                                   *
****************************************************************************
}     
Public Sub Command(pCommand As Byte) 
   TRISData = $00       // Set Data bus To Output
   GLCDInst             // instruction mode
   GLCDWrite            // write mode
   Data = pCommand      // write To the bus
   StrobeEN             // write To GLCD
End Sub
{
****************************************************************************
* Name    : CommandWithData (PRIVATE)                                      *
* Purpose : Write a command plus extra Data Byte To GLCD                   *
****************************************************************************
}     
Sub CommandWithData(pCommand,pData As Byte) 
   TRISData = $00       // Set Data bus To Output
   GLCDInst             // instruction mode
   GLCDWrite            // write mode
   Data = pCommand      // write To the bus
   StrobeEN             // write To GLCD
   Data = pData
   GLCDData             // instruction mode
   GLCDWrite            // write mode
   StrobeEN
End Sub
{
****************************************************************************
* Name    : WriteCommnad (PRIVATE)                                         *
* Purpose : Use to write a series of command bytes to GLCD when there is   *
*           more than one data byte to write after the command mnemonic    *
****************************************************************************
}     
Compound Sub WriteCommands(Command,SetData)
{
****************************************************************************
* Name    : MoveTo (PRIVATE)                                               *
* Purpose : Move to position x,y on the GLCD                               *
****************************************************************************
}     
Sub MoveTo(pX, pY As Byte)
   //X position start address,X position end address,Y position start address,
   //Y position end address,write to RAM 
   WriteCommands(cmdCaSet,pX,GLCDWidth - 1,cmdCaSet,pY + 2,GLCDHeight + 1,cmdRamWr)     
End Sub
{
****************************************************************************
* Name    : SetPixel                                                       *
* Purpose : Set pixel at pixel location x,y                                *
****************************************************************************
} 
Public Sub SetPixel(pX, pY As Byte)
   'MoveTo(pX, pY)
   'WriteData(Pen.Color,$55)
   WriteCommands(cmdDLine,pX,pY,pX,pY,Pen.Color,$55)
End Sub
{
****************************************************************************
* Name    : GetPixel                                                       *
* Purpose : Return Pixel colour At Pixel position x, y                     *
****************************************************************************
}
Public Function GetPixel(pX, pY As Byte) As TColor
   Dim Pixel As TColor
   Pos.y = pY 
   Pos.x = pX
   WriteCommands(cmdCaSet,Pos.x,Pos.x)
   WriteCommands(cmdPaSet,Pos.y,Pos.y)
   GetData
  'Pixel = GetData >> (pY Mod 8) 
   'Result = Pixel.0  
End Function
{
****************************************************************************
* Name    : SetContrast                                                    *
* Purpose : Set the GLCD contrast                                          *
****************************************************************************
} 
Public Sub SetContrast(pContrast As Byte)
   WriteCommands(cmdCtrst,pContrast) 
End Sub
{
****************************************************************************
* Name    : Cls                                                            *
* Purpose : Clear the GLCD screen                                          *
****************************************************************************
} 
Public Sub Cls(pX,pY,pEndX,pEndY As Byte)
      WriteCommands(cmdClWin,pX,pY,pEndX,pEndY)
End Sub
{
****************************************************************************
* Name    : MakeColor                                                      *
* Purpose : The S1D15G00 8 bit color scheme maps 3 bit R, G values and     *
*         : a 2 bit B value onto a 12 bit RGB. This routine allows you     *
*         : to create a color by specifying RGB values in the range 0..255 *
****************************************************************************
} 
Public Function MakeColor(pR, pG, pB As Byte) As TColor
   'result = (pR / 32 << 5) Or (pG / 32 << 2) Or (pB / 64)  
End Function
{
****************************************************************************
* Name    : PowerOLED                                                      *
* Purpose : Configure the GLCD before Vcc is applied - run this whenever   *
*           the 3.3V bus is started so the display is ready for the high   *
*           voltage Vcc.                                                   *
****************************************************************************
} 
Public Sub PowerOLED()
   Command(cmdDisOff)   //turn off display
   Cls(0,0,132,132)     //clear screen
   DelayMS(GLCDDelay)   //Must be at least 100 mS between this cmd and Vcc 
End Sub
{
****************************************************************************
* Name    : Initialize                                                     *
* Purpose : Configure the GLCD before use.                                 *
****************************************************************************
} 
Public Sub Initialize()        //first section same as PowerOLED
   Command(cmdDisOff)   //turn off display
   Cls(0,0,132,132)     //clear screen
   DelayMS(GLCDDelay)
   
   // set display clock divide ratio and oscillator frequency
   WriteCommands(cmdOscDv,$F0)
   
   //set display offset, = 132 - dummy lines from common 0
   WriteCommands(cmdVScrl,$00) //setting to $01 starts the line off the display
   
   //set multiplex ratio
   WriteCommands(cmdMuxRa, $84) //use 131 lines on the display
   
   //set master configuration
   WriteCommands(cmdMastC, $8F) //use external Vcc & external pre-charge V source ($8E in Densitron manual)
   
   //set display start line
   CommandWithData(cmdStLin, $00) //set start line at 0
   
   //set segment re-map & data format
   CommandWithData(cmdRemap, $60) //$34 sets to normal display, $26 flips display 180 degrees
                                  //$6 = 65K colours (x1xx), and prevent skipping every second row (xx1x)
   //set master contrast current control, user may have to adjust...
   SetContrast(158)
   
   //set contrast control for colours A,B,C (RGB)
   WriteCommands(cmdCoCol,$80,$80,$80)     //confirmed reset values, may change later
   
   //set pre-charge voltage of colours A,B,C (RGB)
   WriteCommands(cmdPreCV,$1C,$1C,$1C)     //confirmed reset values, may change later
   
   //set VCOMH
   CommandWithData(cmdVCOMH, $1F) //use ext VCOMH so should be irrelevant but manuals say to set it...
   
   //Set reset (phase 1) & pre-charge (2) period adjustments-1 is discharge time,2 is charge time -higher 
   //  capacitance displays need more time and thus a higher value
   CommandWithData(cmdResPr, $47) //used $47 out of FF as per defaults-old code used $11
   
   //set power saving mode
   CommandWithData(cmdPwrSa, $1A) //Power saving with external VSL, as per manual
   
   //set display mode - turn display on
   Command(cmdDisOn)
End Sub
{
****************************************************************************
* Name    : SetRegion (PRIVATE)                                            *
* Purpose : Sets the GLCD display boundary setting region                  *
****************************************************************************
} 
Sub SetRegion(pX, pY, pWidth, pHeight As Byte)
   WriteCommands(cmdCaSet,pX,pX + pWidth - 1)
   WriteCommands(cmdPaSet,pY + 2,pY + pHeight + 1)
End Sub
{
****************************************************************************
* Name    : Line                                                           *
* Purpose : Draw Line                                                      *
*         : write start col/row, end col/row,line colour byte 1&2          *
****************************************************************************
} 
Public Sub Line(pX1, pY1, pX2, pY2 As TXY,pColor,pColor2 As Byte)
   WriteCommands(cmdDLine,pX1, pY1, pX2, pY2,pColor,pColor2)
End Sub
{
****************************************************************************
* Name    : Rectangle                                                      *
* Purpose : Draw Rectangle                                                 *
*         : write start col/row, end col/row,line colour byte 1 & 2,fill   *
*           colour bytes 1 & 2                                             *
****************************************************************************
} 
Public Sub Rectangle(pX1, pY1, pX2, pY2 As TXY,pColor,pColor2,pFColor,pFColor2 As Byte)
   WriteCommands(cmdDRect,pX1, pY1, pX2, pY2,pColor,pColor2,pFColor,pFColor2)
End Sub
{
****************************************************************************
* Name    : Circle                                                         *
* Purpose : Draw circle                                                    *
*         : write col/row address of center, radius,line colour byte 1&2,  *
*           fill colour bytes 1 & 2                                        *
****************************************************************************
} 
Public Sub Circle(pX1, pY1, pRadius, pColor,pColor2,pFColor,pFColor2 As Byte)
   WriteCommands(cmdDcirc,pX1, pY1, pRadius, pColor,pColor2,pFColor,pFColor2)
End Sub
{
****************************************************************************
* Name    : Copy                                                           *
* Purpose : Copy one area of the screen to another                         *
*         : Define col/row to start, col/row to end, col/row of new start  *
****************************************************************************
} 
Public Sub Rectangle(pX1, pY1, pX2, pY2 As TXY,CopyCol, RowCol As Byte)
//write start col/row, end col/row,line colour byte 1&2, fill colour byte 1&2
   WriteCommands(cmdCopy,pX1, pY1, pX2, pY2,CopyCol, RowCol)
End Sub
{
****************************************************************************
* Name    : ReadImageByte (PRIVATE)                                        *
* Purpose : Read an image byte                                             *
****************************************************************************
} 
Function ReadImageByte() As Byte
   ASM-
      TBLRD *+
      movff TABLAT, result
   End ASM
End Function    
{
****************************************************************************
* Name    : SetImage (OVERLOAD)                                            *
* Purpose : Overrides the GLCD library native SetImage call with this      *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : pImageAdr is the address of the image to render                *
****************************************************************************
}
#endif // GLCD_PIXEL_01
#endif // GLCD_SETIMAGE  
 
#define GLCD_SETIMAGE // override GLCD SetImage
Public Sub SetImage(pX, pY As TXY, pImageAdr As Word)
   Dim x, xRange As TXY
   Dim TransColor As TColor
   Dim ImageByte1, ImageByte2, ImageByte3 As Byte//for 12 bit colour
   Dim Index, Range As Word
   Dim RLENum As Byte
   Dim LastPenColor As TColor
   Dim Image As TImage
   Dim Ignore As Boolean
   
   // get bitmap ID, width and height...
   TABLEPTR = pImageAdr
   Image.Header = ReadImageByte
   Image.Width = ReadImageByte
   Image.Height = ReadImageByte
   Inc(TABLEPTR)
   
   // last pen color to restore pen, index starts
   // at 4 to account for header size...
   LastPenColor = Pen.Color
   Index = 0

   // 8 bit color is used only to save ROM space...
   If Image.Is8Bit Then
      Range = Image.Height * Image.Width
   
      // is it a transparent image...
      If Image.IsTransparent Then
         Ignore = false
         MoveTo(pX,pY)
         x = pX
         xRange = pX + Image.Width

         // read the transparent pixel...
         If Image.IsRLE Then
            Inc(TABLEPTR)
         EndIf
         TransColor = ReadImageByte
         TABLEPTR = pImageAdr + 4
         
         // repeat for all the pixels in the image...
         Repeat
            RLENum = 1
            If Image.IsRLE Then
               RLENum = ReadImageByte
            EndIf
            Pen.Color = ReadImageByte
            Repeat   
               
               // if it's a transparent pixel, skip...
               If Pen.Color = TransColor Then
                  Ignore = true
               Else 
                  // we have hit a non transparent pixel, so reset x, y
                  If Ignore Then
                     WriteCommands(cmdCaSet,x,pX + Image.Width)
                     Command(cmdRamWr)
                     Ignore = false
                  EndIf  
                  WriteData(Pen.Color,$55) 
               EndIf               
               
               // inc x, if greater than image width then reset
               // x and move to next y
               Inc(x)
               If x >= xRange Then
                  x = pX
                  Inc(pY)
                  MoveTo(pX,pY)
               EndIf
               
               Inc(Index)
               Dec(RLENum)
            Until RLENum = 0   
         Until Index >= Range

      // image is not transparent, fast bit blit...   
      Else
         SetRegion(pX, pY, Image.Width, Image.Height)
         Repeat
            RLENum = 1
            If Image.IsRLE Then
               RLENum = ReadImageByte
            EndIf
            Pen.Color = ReadImageByte
            Repeat
               WriteData(Pen.Color,$55)
               Inc(Index)
               Dec(RLENum)
            Until RLENum = 0
         Until Index >= Range
      EndIf

   // 12 bit, fast bit blit - note that 12 bit images must fall on an even x...
   ElseIf Image.Is12Bit Then
    
    Nop
   EndIf 
   Pen.Color = LastPenColor 
End Sub    
{
****************************************************************************
* Name    : SetImage (OVERLOAD)                                            *
* Purpose : Overrides the GLCD library native SetImage call with this      *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : pImage is a constant array holding the image data to render    *
****************************************************************************
} 
Public Sub SetImage(pX, pY As TXY, ByRefConst pImage() As Byte)
   SetImage(pX, pY, @pImage)
End Sub 
{
****************************************************************************
* Name    : WriteChar                                                      *
* Purpose : Overrides the GLCD library native WriteChar call with this     *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : This routine will only handle xFonts (that is, font files with *
*         : the scan line in the x direction)                              *
****************************************************************************
} 
{ 
#define GLCD_WRITECHAR // override GLCD WriteChar
#define GLCD_XFONT     // force the use of x scanned font
Public Sub WriteChar()
   Dim FontByte As Byte
   Dim x, y, xRange, yRange As Byte
   Dim PenColor As TColor
   Dim Range, Index As Word
   Dim Ignore As Boolean
   
   PenColor = Pen.Color
   Index = 0  
    
   // is the brush style clear... 
   If Brush.Style = bsClear Then
      Ignore = false
      yRange = Pos.y + Font.Height
      y = Pos.y
      
      While y < yRange
         
         MoveTo(Pos.x,y)
         xRange = Pos.x + Font.Width
         x = Pos.x
         While x < xRange
            FontByte = ReadFontByte           
            Index = 8
            Repeat
               // write a font pixel with pen color...  
               If FontByte.7 = 1 Then
                  If Ignore Then
                     'WriteCommands(cmdCaSet,x,Pos.x + Font.Width)
                     'Command(cmdRamWr)
                     Ignore = false
                  EndIf
                  'WriteData(Pen.Color.CB,Pen.Color.BA)
                  'WriteCommands(cmdDLine,x+index,y,x+index,y,Pen.Color.CB,Pen.Color.BA)
                  WriteCommands(cmdDLine,x+Index,y,x+Index,y,56,98)
                  
               // skip transparent pixel...
               Else
                  Ignore = true
               EndIf
               FontByte = FontByte << 1
               Dec(Index)
               Inc(x)
            Until Index = 0
         Wend
         Inc(y)
      Wend
   
   // brush style is not clear, fast bit blit...
   Else
      x = 0
      SetRegion(Pos.x, Pos.y, Font.Width, Font.Height)
      Range = Font.Height * Font.Width
      Repeat
         // grab a font byte...
         If x >= Font.Width Then
            FontByte = ReadFontByte
            x = 0
         ElseIf x Mod 8 = 0 Then
            FontByte = ReadFontByte
         EndIf 
         Inc(x)  
         
         // set either font color or background color...
         If FontByte.7 = 1 Then
            Pen.Color = PenColor
         Else
            Pen.Color = Brush.Color
         EndIf
         'WriteData(Pen.Color.CB,Pen.Color.BA)
         WriteCommands(cmdDLine,x+Index+20,y,x+Index+20,y,$56,$98)
         FontByte = FontByte << 1
         Inc(Index)
      Until Index >= Range

   EndIf
   Pen.Color = PenColor
   Inc(Pos.x,Font.Width)  
End Sub
}
// configure the module
Initialize

GLCD.bas top lines:

Code: Select all

#option GLCD_MODEL = SSD1339
#if Not (GLCD_MODEL in (SSD1339, KS0108, S1D10605, S1D15G00, SED1520, S1D13700))
   #error GLCD_MODEL, "Invalid option. GLCD model not recognized."
#endif

// import SSD1339 driver...
#if GLCD_MODEL = SSD1339
Include "SSD1339.bas"                
Public Dim
   Pos As SSD1339.Pos, 
   Cls As SSD1339.Cls,
   SetPixel As SSD1339.SetPixel,
   WriteByte As SSD1339.SetData,
   ReadByte As SSD1339.GetData,
   SetImage As SSD1339.SetImage,
   GetPixel As SSD1339.GetPixel
#endif

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Post by RangerBob » Thu Dec 13, 2007 5:01 pm

Hello,

I've created a module for use with the Solomon SSD0323 (128 x 64 4-bit greyscale). Looking at the specs, the SSD1339 at least shares common command instructions and data writing structures. My code isn't perfect, and is mostly a modification of the S1D15G00 code, but if you like I could polish it up a bit and release it here for you to at least have a look at.

In fact your task would be easier as the SSD0323 has 4-bit pixel data on a 8 bit bus, whereas the SSD1339 has 3-byte transfers in 262k colour mode. I have to do all sorts of read back crap to make sure that when I change 1 pixel, the adjacent one isn't changed. None of that for you!

The graphics acceleration features look pretty handy too!

Any chance you could point me in the direction of the module you are using btw? I am evaluating other OLED options since the one I originally wrote the module for has now been discontinued.

Regards,

Nathan

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Thu Dec 13, 2007 5:50 pm

Hi Nathan,

Sure, Densitron offers a model with the SSD1339 in the UK. Here's a link to their contact info:

http://www.densitron.com/content.aspx?id=504

as for vendors, you can get it at Spark Fun:

http://www.sparkfun.com/commerce/produc ... cts_id=712

4D systems out of Australia also produces an SSD1339 unit
http://www.4dsystems.com.au

http://www.milinst.com in the UK sells 4D products but I don't see the OLED 128 model, only the models with built-in controllers for 59 pounds Sterling. The "bare" OLED should be no more than about 10 - 15 pounds Sterling.

4D also has a list of other vendors in other countries.

Also, I think your code would be a big help since the problem I am having is in gathering in the array bytes and putting them out the parallel interface in the proper order. Seeing how that is arranged and written would probably bridge the problem I'm stuck on now.

-Tom

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Post by RangerBob » Fri Dec 14, 2007 9:29 am

Ok heres my SSD0323 code. Doesn't seem like it has the same amount of polish as yours! ;) It was knocked up very quickly whilst I was still getting to grips with SF, and I consider it "good enough". Looks like much of it is either the same or very similar though. Hope it helps someone!

Code: Select all

Module SSD0323

// import the graphics module...
#define GLCD_PIXEL_08
#define GLCD_COLOR_08
#define GLCD_XY_08
Include "Graphics.bas"   
Include "system.bas"   

// default module options - user options can override these values...
#option GLCD_DATA = PORTF        // data port
#option GLCD_RS = PORTD.1        // RS pin
#option GLCD_DC = PORTD.2        // Data/Command pin
#option GLCD_RW = PORTD.3        // RW pin
#option GLCD_CS = PORTD.0        // chip select
#option GLCD_RD = PORTD.4        // RD Pin
#option GLCD_INIT_DELAY = 100    // initialisation delay (ms)
#option GLCD_ASPECT_RATIO = 100  // aspect ratio, smaller number will squeeze y for GLCD circles and box
#option GLCD_FLIP = true         // Cable top exit

#option GLCD_POWER1 = PORTA.1
#option GLCD_POWER2 = PORTA.2

#option OLED_MODEL = CALGARY
#if Not (OLED_MODEL in (CALGARY, ATLANTA))
   #error OLED_MODEL, "Invalid option. OLED model not recognized."
#endif

// validate data port...
#if IsOption(GLCD_DATA) 
   #if Not IsValidPort(GLCD_DATA)
      #error GLCD_DATA, "Invalid option. DATA must be a valid port name."
   #endif
   #ifdef [email protected] Then
      #error [email protected], "Invalid option. DATA port cannot be a single bit value."
   #endif
#endif

// validate RS pin...
#if IsOption(GLCD_RS) And Not IsValidPortPin(GLCD_RS) 
   #error GLCD_RS, "Invalid option. RS must be a valid port pin."
#endif

// validate DC pin...
#if IsOption(GLCD_DC) And Not IsValidPortPin(GLCD_DC) 
   #error GLCD_DC, "Invalid option. DC must be a valid port pin."
#endif

// validate RW pin...
#if IsOption(GLCD_RW) And Not IsValidPortPin(GLCD_RW) 
   #error GLCD_RW, "Invalid option. RW must be a valid port pin."
#endif

// validate CS pin...
#if IsOption(GLCD_CS) And Not IsValidPortPin(GLCD_CS) 
   #error GLCD_CS, "Invalid option. CS must be a valid port pin."
#endif

// validate RD pin...
#if IsOption(GLCD_RD) And Not IsValidPortPin(GLCD_RD) 
   #error GLCD_CS2, "Invalid option. RD must be a valid port pin."
#endif

// validate initialisation delay...
#if IsOption(GLCD_INIT_DELAY)
   #if Not (GLCD_INIT_DELAY in (0 to 1000))
      #error GLCD_INIT_DELAY, "Invalid option. GLCD initialize delay must be between 0 and 1000 (ms)."
   #endif
#endif 

// now create Data TRIS...
#option _GLCD_DATA_TRIS = GetTRIS(GLCD_DATA)

// GLCD width and height...
#if OLED_MODEL = CALGARY
Public Const
   GLCDWidth = 128,
   GLCDHeight = 64
#endif

// GLCD width and height...
#if OLED_MODEL = ATLANTA
Public Const
   GLCDWidth = 128,
   GLCDHeight = 64
#endif

// x, y position...
Public Dim
   Pos As TPosition

// SSD0323 commands...   
Const
   cmdSetCol            = $15,
   cmdEndCol            = $7F, 
   cmdSetRow            = $75,
   cmdEndRow            = $3F, 
   cmdSetReMap          = $A0,
   cmdOff               = $AE,
   cmdOn                = $AF,
   GLCDDelay = GLCD_INIT_DELAY     

// port and pin settings, these are brought into
// the program by using the above options...
Public Dim        
   Data As GLCD_DATA,           // data in (PORT) 
   TRISData As _GLCD_DATA_TRIS, // data TRIS
   RS As [email protected],      // RS pin (reset pin)
   DC As [email protected],      // DC pin (data or command)
   RW As [email protected],      // RW pin (read or write)
   CS As [email protected],      // chip select
   RD As [email protected],       // Read select
   POWER1 As [email protected],	// VDD power control
   POWER2 As [email protected]   // VCC power control

{
****************************************************************************
* Name    : GLCDData (PRIVATE)                                             *
* Purpose : Switch to GLCD data mode                                       *
****************************************************************************
}    
Inline Sub GLCDData()
	DC = 1
End Sub
{
****************************************************************************
* Name    : GLCDInst (PRIVATE)                                             *
* Purpose : Switch to GLCD instruction mode                                *
****************************************************************************
}    
Inline Sub GLCDInst()
	DC = 0	 
End Sub
{
****************************************************************************
* Name    : GLCDRead (PRIVATE)                                             *
* Purpose : Strobe Read line                                               *
****************************************************************************
}    
Inline Sub Read()
	RD = 0
	RD = 1
End Sub

{
****************************************************************************
* Name    : GLCDWrite (PRIVATE)                                            *
* Purpose : Strobe Write line                                              *
****************************************************************************
}    
Inline Sub Write()
	RW = 0
 	RW = 1
End Sub
{
****************************************************************************
* Name    : SetData (PRIVATE)                                              *
* Purpose : Write a data byte to GLCD                                      *
****************************************************************************
}     
Sub SetData(pData As Byte) 
	DC = 1	        // access display RAM data
	TRISData = $00   // set data bus to output
	Data = pData     // write to the bus
	Write()        // write mode
End Sub
{
****************************************************************************
* Name    : GetData (PRIVATE)                                              *
* Purpose : Read byte from GLCD                                            *
****************************************************************************
}     
Function GetData() As Byte
   CS = 0
   //Dummy Read First
   TRISData = $FF   // set data bus to input   
   GLCDData         // access display RAM data
   
   RD = 0
   DelayUS(1)
   RD = 1

   //Actual Read
   TRISData = $FF   // set data bus to input   
   GLCDData         // access display RAM data
   RD = 0
   DelayUS(1)
   Result = Data    // get the data
   RD = 1
   CS = 1
End Function  
{
****************************************************************************
* Name    : Command (PRIVATE)                                              *
* Purpose : Write a command byte to GLCD                                   *
****************************************************************************
}     

Sub WriteCommand(pCommand As Byte) 
   RD = 1
   DC = 0
   CS = 0
   TRISData = $00   // set data bus to output
   Data = pCommand     // write to the bus
   RW = 0
   RW = 1
   CS = 1
   DelayUS(1)
End Sub

Compound Sub Command(WriteCommand)

{
****************************************************************************
* Name    : SetPosition (PRIVATE)                                          *
* Purpose : Set GLCD x and y positions                                     *
****************************************************************************
}     
Sub SetPosition()
   Command(cmdSetCol,Pos.x,cmdEndCol) // set x position	
   Command(cmdSetRow,Pos.y,cmdEndRow) // set y position
End Sub
{
****************************************************************************
* Name    : SetPixel                                                       *
* Purpose : Set pixel at pixel location x,y                                *
****************************************************************************
} 
Public Sub SetPixel(pX, pY As Byte)
   Dim Pixel As Byte
   Dim Mask As Byte
   Dim Justify As Byte
   
   If (pX < GLCDWidth) And (pY < GLCDHeight) Then

        Justify = pX And 1
	   	pX = (pX >> 1)
        pY = pY
   
		DC = 0
		CS = 0        
		
		TRISData = $00   // set data bus to output
		
		Data = cmdSetCol			'Set position
		Write()
		Data = pX
		Write()
		Data = cmdEndCol
		Write()
		Data = cmdSetRow
		Write()
		Data = pY
		Write()
		Data = cmdEndRow
		Write()

		Data = 255 					'Dummy Read
		DC = 1
		Read()

		TRISData = $FF   // set data bus to Input
				
		RD = 0  					'Read Read
		DelayUS(5)					'let things stabilise before reading
		Pixel = Data
		RD = 1
		DC = 0
		 
		// pen is white...
		If Pen.Color = $00 Then
			'If Pen.Mode = pmCopy Then
				If Justify = 1 Then
					Mask = $F0
				Else
					Mask = $0F
				EndIf   
           	Pixel = Mask And Pixel
         	'EndIf
   
		// pen is black...
		Else
			If Justify = 1 Then 
            	Mask = Pen.Color
        	Else
            	Mask = Pen.Color * 16
        	EndIf
        
         	// pen copy or merge...
         	If Pen.Mode <> pmXOR Then
           		Pixel = Mask Or Pixel 
      
         	// pen XOR
         	Else
            	If (Pixel And Mask) = 0 Then
               		Pixel = Pixel Or Mask
            	Else
               		Mask = Not Mask
               		Pixel = Pixel And Mask
            	EndIf      
         	EndIf
      	EndIf

        TRISData = $00   // set data bus to output
		
		Data = cmdSetCol			'Set position
		Write()
		Data = pX
		Write()
		Data = cmdEndCol
		Write()
		Data = cmdSetRow
		Write()
		Data = pY
		Write()
		Data = cmdEndRow
		Write()
		
		DC = 1
		Data = Pixel
		Write()
		CS = 1		
		
   EndIf
End Sub
{
****************************************************************************
* Name    : GetPixel                                                       *
* Purpose : Return pixel colour at pixel position x, y                     *
****************************************************************************
}
Public Function GetPixel(pX, pY As Byte) As TColor
   Dim Pixel As Byte
   Pos.y = pY / 8
   Pos.x = pX
   SetPosition
   GetData
   Pixel = GetData >> (pY Mod 8) 
   Result = Pixel.0  
End Function

{
********************************************************************************
* Name    : Fill                                                               *
* Purpose : Fill screen area with brush color. 		                           *
*         : Assumes pX1 < pX2 and pY1 < pY2                                    *
********************************************************************************
} 
Public Sub Fill(pX1, pY1, pX2, pY2 As TXY)
	For Pos.x = pX1 To pX2
		For Pos.y = pY1 To pY2
			SetPixel(Pos.x,Pos.y)
		Next
	Next
End Sub

{
****************************************************************************
* Name    : ReadImageByte (PRIVATE)                                        *
* Purpose : Read an image byte                                             *
****************************************************************************
} 
Function ReadImageByte() As Byte
   ASM-
      TBLRD *+
      movff TABLAT, result
   End ASM
End Function

{
****************************************************************************
* Name    : SetImage (OVERLOAD)                                            *
* Purpose : Overrides the GLCD library native SetImage call with this      *
*         : routine which is better suited for rendering to the SSD0323    *
*         : pImageAdr is the address of the image to render.               *
*		  : Each databyte holds 2 adjactent pixels. Image must be even 	   *
*		  : sized horizontally and placed in an even location.			   *
*		  : *To Be Looked At*											   *							
****************************************************************************
} 
#define GLCD_SETIMAGE // override GLCD SetImage
Public Sub SetImage(pX, pY As TXY, pImageAdr As Word)
   Dim x, y As Byte
   Dim Image As TImage
   
   // get bitmap ID, width and height...
   TABLEPTR = pImageAdr
   Image.Width = ReadImageByte
   Image.Width = (Image.Width / 2)
   Image.Height = ReadImageByte

    For y = pY To (pY + (image.Height - 1))
    	
		Command(cmdSetCol,pX,cmdEndCol)
	    Command(cmdSetRow,y,cmdEndRow)
	    
	    DC = 1
    	CS = 0
	    TRISData = $00   // set data bus to output
	    		
		For x = 0 To (Image.Width - 1)
			Data = ReadImageByte
			DelayUS(1)
			Write()
			DelayUS(1)
		Next
    
    	CS = 1
    	
    	DelayUS(1)
    	
	Next   

End Sub    	

{
********************************************************************************
* Name    : SetImage                                                           *
* Purpose : BitBlit image To GLCD at pixel location x, y.                      *
*         : NOTE - This subroutine only supports Greyscale bitmaps.            *
*         : It requires images drawn with bytes in the x-direction.            *
********************************************************************************
} 
Public Sub SetImage(pX, pY As TXY, ByRefConst pImage() As Byte, pMode As Byte = cmCopy)
   SetImage(pX, pY, @pImage)
End Sub 

{
****************************************************************************
* Name    : Cls                                                            *
* Purpose : Clear the GLCD screen                                          *
****************************************************************************
} 
Public Sub Cls()
   Dim x As Word
   
    Command(cmdSetCol,$00,cmdEndCol)
    Command(cmdSetRow,$00,cmdEndRow)
 
 	DC = 1
    CS = 0
    TRISData = $00   // set data bus to output
    Data = $00
    
    For x = 0 To 4096
		Write()
    Next
    
    CS = 1
End Sub

{
****************************************************************************
* Name    : BlankScreen                                                    *
* Purpose : Blanks the display, but preserves data                         *
****************************************************************************
} 
Public Sub BlankScreen(x As Boolean)
  
    If x = true Then
		Command($A6)		'All Pixels blank (data untouched)
    Else
	   Command($A4)			'Normal Mode (data untouched)
	EndIf

End Sub

{
****************************************************************************
* Name    : OLEDoff                                                        *
* Purpose : Shuts off oled display safely                                  *
****************************************************************************
} 
Public Sub OLEDoff()
	Command(cmdOff)      // Turn display off
   	Low(POWER2)
   	DelayMS(100)
   	Low(POWER1)
End Sub
{
****************************************************************************
* Name    : Initialize                                                     *
* Purpose : Configure the GLCD before use                                  *
****************************************************************************
} 
Sub Initialize()

	High(POWER1)		// VDD on

	Output(RS)
	RS = 0
	DelayMS(100)
   
	RS = 1

	Pos.x = 0
	Pos.y = 0  
	DelayMS(GLCDDelay)   // start up delay, allow GLCD to settle
	High(DC)          
	High(RW)
	High(CS)
	High(RD)
   
	Command(cmdOff)      // Turn display off

	High(POWER2)		// VCC on

	DelayMS(GLCDDelay)

#if OLED_MODEL = CALGARY   
	Command($86,$86)		'Set Current Range
	Command($81,$66)		'Set Contrast Control
   
	#if GLCD_FLIP = FALSE	'Cable Bottom Exit     
		Command($A0,$52)	'Set Remap
		Command($A2,$4C)	'Set Display Offset		
	#else                   'Cable Top Exit
		Command($A0,$41)	'Set Remap
		Command($A2,$44)	'Set Disply Offset	
	#endif
   
	Command($A1,$00)		'Set Display Start Line
	Command($A4)			'Set Display Mode
	Command($AD,$02)		'Set DC-DC converter off
	Command($A8,$3F)		'Set Multiplex Ratio
	Command($B2,$46)		'Set Row Period
	Command($B0,$28)		'Set Pre-Charge compensation
	Command($B4,$07)
	Command($B3,$91)		'Set Clock Divide  was $F1
	Command($B1,$22)		'Set Phase Length
 	Command($BF,$0D)		'Set VSL
	Command($BE,$02)		'Set VCOMH
	Command($BC,$10)		'Set VPrecharge
   
   // Set Grey Scale Table
	Command($B8)
	Command($00)
	Command($11)
	Command($21)
	Command($32)
	Command($43)
	Command($54)
	Command($65)
	Command($76)
#endif

#if OLED_MODEL = ATLANTA   
	Command($86,$86)		'Set Current Range
	Command($81,$35)		'Set Contrast Control
   
	#if GLCD_FLIP = FALSE	'Cable Bottom Exit     
		Command($A0,$52)	'Set Remap
		Command($A2,$40)	'Set Display Offset		
	#else                   'Cable Top Exit
		Command($A0,$41)	'Set Remap
		Command($A2,$44)	'Set Disply Offset	
	#endif
   
	Command($A1,$00)		'Set Display Start Line
	Command($A4)			'Set Display Mode
	Command($AD,$02)		'Set DC-DC converter off
	Command($A8,$3F)		'Set Multiplex Ratio
	Command($B2,$46)		'Set Row Period
	Command($B0,$28)		'Set Pre-Charge compensation
	Command($B4,$07)
	Command($B3,$21)		'Set Clock Divide  was $F1
	Command($B1,$22)		'Set Phase Length
 	Command($BF,$0B)		'Set VSL
	Command($BE,$0B)		'Set VCOMH
	Command($BC,$10)		'Set VPrecharge
   
   // Set Grey Scale Table
	Command($B8)
	Command($00)
	Command($11)
	Command($21)
	Command($32)
	Command($43)
	Command($54)
	Command($65)
	Command($76)
#endif

   Cls()
      
   // Display On
   Command(cmdOn)

   // Set Row & Column Address
   Command(cmdSetCol,$00,cmdEndCol)
   Command(cmdSetRow,$00,cmdEndRow)
      
End Sub 

// configure the module
Initialize
Added to GLCD:

Code: Select all

// validate model...
#option GLCD_MODEL = SSD0323
#if Not (GLCD_MODEL in (SSD0323, SSD0323DF, KS0108, S1D10605, S1D15G00, SED1520, S1D13700))
   #error GLCD_MODEL, "Invalid option. GLCD model not recognized."
#endif

#if GLCD_MODEL = SSD0323
Include "SSD0323.bas"                
Public Dim
   Pos As SSD0323.Pos, 
   Cls As SSD0323.Cls,
   SetPixel As SSD0323.SetPixel,
   SetImage As SSD0323.SetImage,
   Fill As SSD0323.Fill
#endif

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Fri Dec 14, 2007 10:36 am

Thanks for posting it! I'll go through our respective functions and see what I can do to get something working. This ain't rocket science, it should be a straightforward case of "fetch the font byte, then write it the way the hardware wants it". Once it works I'll repost for any and all to critique/test/etc.

-Tom

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Fri Dec 14, 2007 1:20 pm

I can already see some things to work on:

1. I didn't put in the dummy read before the actual read. This will have to be done before the function can be used for reading back bytes from the SSD1330 chip.

2. Looking at the SSD1339 datasheet, it's not entirely clear whether it's the CS line or the E line or possibly even the RW line or all these lines that optimally need to be toggled for each read or write. The Solomon Systech SSD1339 datasheet did not provide more than a single read/write cycle in the parallel data example. The datasheet is written in a very terse manner with grammatical errors, so I'm not surprised to see your code uses the R/W line to latch data and I use CS. It seems both methods "work" but I have to wonder if this will lead to "surprise" faults under conditions of stress such as temperature extremes.

3. Need to add a fill command.

4. SetImage() is key to this working, there's a big difference between them in the different code variants. WriteChar() sort of works as-is with David's original GLCD code but I need to get the MPlab debugger working with this code so I can see what is being written. My code won't compile for the MPLab software debugger for some reason, I really really hope SF will incorporate it's own debugger in the future. Writing code without decent visibility is why I'm having problems getting this routine going in the first place. I suppose I could wire up an 18F66J16 with in-circuit hardware debug but that's another week or more to get running...the idea of using BASIC instead of C, C##, etc. is to avoid long learning/implemenation curves.

-Tom

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Sun Dec 16, 2007 1:53 am

OK, after some work, here's code that uses USART port 2 for debugging and will correctly print fonts and graphics. Note the initialization strings, they are critical. I also need to clean up the line strobe functions, I put them in explicitly to make sure it worked. I'll clean it up and try to get larger sized fonts to work, they are not there yet. Also, for some reason, TBLRD*+ didn't increment the pointer - I had so add a parallel index function called count.

-Tom

Code: Select all

Module SSD1339
Device = 18F66J16
#define GLCD_PIXEL_08
#define GLCD_COLOR_08
#define GLCD_XY_08
Include "Graphics.bas" 
Include "system.bas" 
Include "usart2.bas"
Include "convert.bas"
 
// default module options - user options can override these values...
// this code uses the 6800 format 8-bit parallel interface
// 6800 8-bit configuration used: BS0 low, BS1 low, BS2 high, BS3 low
// This display is 132x132. The RGB interpretation for 8 bit colour is the same
// as for the S1D15G00 - RRRGGGBB. 
#option GLCD_RESET = PORTE.5     // reset pin, active low-like S1D15G00
#option GLCD_DATA = PORTD        // data port 
#option GLCD_DC = PORTE.6        // Data or Command pin, data when high
#option GLCD_CS = PORTE.7        // Chip Select pin, MCU comms enabled when low-like S1D15G00
#option GLCD_E = PORTB.2        // Enable pin, R/W data latched when pulled high-like S1D15G00
#option GLCD_RW = PORTB.3        // Read-Write pin, write mode when low-like S1D15G00
#option GLCD_ASPECT_RATIO = 100  // aspect ratio
#option GLCD_INIT_DELAY = 100    // initialisation delay (ms)
//#option GLCD_SPI = SW            // use software SPI 

// validate Reset pin...
#if IsOption(GLCD_RESET) And Not IsValidPortPin(GLCD_RESET) 
   #error GLCD_RESET, "Invalid option. RESET must be a valid port pin."
#endif

// validate DATA port...
#if IsOption(GLCD_DATA) And Not IsValidPort(GLCD_DATA) 
   #error GLCD_DATA, "Invalid option. DATA must be a valid port."
#endif  

// validate DC pin...
#if IsOption(GLCD_DC) And Not IsValidPortPin(GLCD_DC) 
   #error GLCD_DC, "Invalid option. DC must be a valid port pin."
#endif

// validate CS pin...
#if IsOption(GLCD_CS) And Not IsValidPortPin(GLCD_CS) 
   #error GLCD_CS, "Invalid option. CS must be a valid port pin."
#endif    

// validate E pin...
#if IsOption(GLCD_E) And Not IsValidPortPin(GLCD_E) 
   #error GLCD_E, "Invalid option. E must be a valid port pin."
#endif  

// validate RW pin...
#if IsOption(GLCD_RW) And Not IsValidPortPin(GLCD_RW) 
   #error GLCD_RW, "Invalid option. RW must be a valid port pin."
#endif  

// validate initialisation delay...
#if IsOption(GLCD_INIT_DELAY)
   #if Not (GLCD_INIT_DELAY in (0 to 1000))
      #error GLCD_INIT_DELAY, "Invalid option. GLCD initialize delay must be between 0 and 1000 (ms)."
   #endif
#endif 

// SSD1339 commands...   
Const
   cmdDisCtl = $CA,     //Display Control
   cmdNOP = $E3,        //NOP - $25 in S1D15G00
   cmdDisOn = $AF,      //Display On, out of sleep
   cmdDisOff = $AE,     //Display Off, in sleep mode
   cmdBlank = $A4,     //Sets diplay mode to All Off-all pixels have GS0 (grayscale level 0), minimum brightness
   cmdAllOn = $A5,     //Sets diplay mode to All On-all pixels have GS63 (grayscale level 63), maximum brightness
   cmdDisNor = $A6,     //Sets display mode to Display Normal
   cmdDisInv = $A7,     //Sets display mode to Display Invert-gray levels swapped-GS0 is GS63, GS7 is GS56, etc
   cmdPaSet = $75,      //Page Address Set
   cmdCaSet = $15,      //Column Address Set
   cmdRamWr = $5C,      //Writing to Memory
   cmdCtrst = $C7,       //Master contrast control
   cmdRemap = $A0,       //$A0 then $34, normal; $A0 then $26 - flips display 180 degrees 
   cmdStLin = $A1,       //sets starting line
   cmdVScrl = $A2,       //set vertical scroll by row from 0-131
   cmdMastC = $AD,       //master configuration, int/ext VCC suppply and int/ext pre-charge V supply
   cmdPwrSa = $B0,       //power save mode, sets int/ext VSL and power save on/off
   cmdResPr = $B1,       //et reset (phase 1) & pre-charge (2) period adjustments-1 is discharge time,2 is charge time
   cmdOscDv = $B3,       //front clock divider and int oscillator freq set      
   cmdPreCV = $BB,       //set the pre-charge colour voltage of each colour
   cmdVCOMH = $BE,       //set VCOMH - should be irrelevant since use ext supply but manuals say set it...
   cmdCoCol = $C1,       //Contrast currents for each colour A, B, C (RGB)
   cmdMuxRa = $CA,       //mux ratio - number of display lines turned on - start & end depends on A2 cmd setting  
   cmdDLine = $83,       //draw line
   cmdDRect = $84,       //draw rectangle
   cmdDcirc = $86,       //draw circle
   cmdCopy  = $8A,       //Copy area
   cmdDimWi = $8C,       //Dim Window
   cmdClWin = $8E,       //Clear Window
   cmdFilED = $92,       //Fill Enable/Disable
   cmdHorSc = $96,       //Horizontal Scroll
   cmdSpHor = $9E,       //Stop horizontal scroll
   cmdStHor = $9F,       //Start horizontal scroll moving  
   GLCDDelay = GLCD_INIT_DELAY     

// port and pin settings, these are brought into
// the program by using the above options...
Dim        
   Data As GLCD_DATA,        // data port 
   TRISData As TRISD, // Data TRIS
   E As [email protected],    // clk pin
   CS As [email protected],   // CS pin
   DC As [email protected],   // DC pin
   RW As [email protected],   //RW pin
   count As Word,
   Reset As [email protected]     // reset pin

   
// GLCD width and height...
Public Const
   GLCDWidth = 130,
   GLCDHeight = 130

// x, y position...
Public Dim
   Pos As TPosition,
   tempdata As Byte

  'Contrast As FContrast   
 {
****************************************************************************
* Name    : StrobeEN (Private)                                             *
* Purpose : Strobe the GLCD EN pin                                         *
****************************************************************************
}    
Inline Sub StrobeEN()
   CS = 0
   E = 1
   DelayUS(1)
   CS = 1
End Sub

  
{
****************************************************************************
* Name    : GLCDData (PRIVATE)                                             *
* Purpose : Switch To GLCD Data mode                                       *
*           Modified For KS0713                                            *
****************************************************************************
}    
Inline Sub GLCDData()
   DC = 1
End Sub
{
****************************************************************************
* Name    : GLCDInst (PRIVATE)                                             *
* Purpose : Switch To GLCD instruction mode                                *
*           Modified For KS0713                                            *
****************************************************************************
}    
Inline Sub GLCDInst()
   DC = 0	
End Sub
{
****************************************************************************
* Name    : GLCDRead (PRIVATE)                                             *
* Purpose : Set GLCD To Read mode                                          *
****************************************************************************
}    
Inline Sub GLCDRead()
   RW = 1
End Sub
{
****************************************************************************
* Name    : GLCDWrite (PRIVATE)                                            *
* Purpose : Set GLCD To write mode                                         *
****************************************************************************
}    
Inline Sub GLCDWrite()
   RW = 0	
End Sub
{
****************************************************************************
* Name    : SetData (PRIVATE)                                              *
* Purpose : Write a Data Byte To GLCD                                      *
****************************************************************************
}     
Sub SetData(pData As Byte) 
   TRISData = $00   // Set Data bus To Output
   GLCDData         // access display RAM Data
   GLCDWrite        // write mode
   Data = pData     // write To the bus
   StrobeEN         // write To GLCD
End Sub
{
****************************************************************************
* Name    : WriteData (PRIVATE)                                            *
* Purpose : Write a series of data bytes to GLCD                           *
****************************************************************************
}     
Compound Sub WriteData(SetData)
{
****************************************************************************
* Name    : GetData (PRIVATE)                                              *
* Purpose : Read Byte from GLCD                                            *
****************************************************************************
}     
Function GetData() As Byte
   TRISData = $FF   // Set Data bus To Input
   GLCDData         // access display RAM Data
   GLCDRead         // Read mode
   StrobeEN         // latch Data
   Result = Data    // get the Data
End Function  
{
****************************************************************************
* Name    : Command (PRIVATE)                                              *
* Purpose : Write a command Byte To GLCD                                   *
****************************************************************************
}     
Public Sub Command(pCommand As Byte) 
   TRISData = $00       // Set Data bus To Output
   GLCDInst             // instruction mode
   GLCDWrite            // write mode
   Data = pCommand      // write To the bus
   StrobeEN             // write To GLCD
End Sub
{
****************************************************************************
* Name    : CommandWithData (PRIVATE)                                      *
* Purpose : Write a command plus extra Data Byte To GLCD                   *
****************************************************************************
}     
Sub CommandWithData(pCommand,pData As Byte) 
   TRISData = $00       // Set Data bus To Output
   GLCDInst             // instruction mode
   GLCDWrite            // write mode
   Data = pCommand      // write To the bus
   StrobeEN             // write To GLCD
   Data = pData
   GLCDData             // instruction mode
   GLCDWrite            // write mode
   StrobeEN
End Sub
{
****************************************************************************
* Name    : WriteCommnad (PRIVATE)                                         *
* Purpose : Use to write a series of command bytes to GLCD when there is   *
*           more than one data byte to write after the command mnemonic    *
****************************************************************************
}     
Public Compound Sub WriteCommands(Command,SetData)
{
****************************************************************************
* Name    : MoveTo (PRIVATE)                                               *
* Purpose : Move to position x,y on the GLCD                               *
****************************************************************************
}     
Sub MoveTo(pX, pY As Byte)
   //X position start address,X position end address,Y position start address,
   //Y position end address,write to RAM 
   WriteCommands(cmdCaSet,pX,GLCDWidth - 1,cmdCaSet,pY + 2,GLCDHeight + 1,cmdRamWr)     
End Sub
{
****************************************************************************
* Name    : SetPixel                                                       *
* Purpose : Set pixel at pixel location x,y                                *
****************************************************************************
} 
Public Sub SetPixel(pX, pY As Byte)
   'MoveTo(pX, pY)
     'WriteCommands(cmdCaSet,pX,pX) 
     'WriteCommands(cmdPaSet,pY,pY) 
     Command($5C)
     TRISData = $00   // set data bus to output 
            DC = 1         //indicate it's data
            RW = 0        //indicate it's a read
            E = 1         //initiate a write
            CS = 0        //start operation
            Data = Pen.Color 
            CS = 1       //end operation
            E = 0        //end initiation  
     
   'WriteData(Pen.Color,$55)
   'WriteCommands(cmdDLine,pX,pY,pX,pY,Pen.Color,$55)
End Sub
{
****************************************************************************
* Name    : GetPixel                                                       *
* Purpose : Return Pixel colour At Pixel position x, y                     *
****************************************************************************
}
Public Function GetPixel(pX, pY As Byte) As TColor
   Dim Pixel As TColor
   Pos.y = pY 
   Pos.x = pX
   WriteCommands(cmdCaSet,Pos.x,Pos.x)
   WriteCommands(cmdPaSet,Pos.y,Pos.y)
   GetData
  'Pixel = GetData >> (pY Mod 8) 
   'Result = Pixel.0  
End Function
{
****************************************************************************
* Name    : SetContrast                                                    *
* Purpose : Set the GLCD contrast                                          *
****************************************************************************
} 
Public Sub SetContrast(pContrast As Byte)
   WriteCommands(cmdCtrst,pContrast) 
End Sub
{
****************************************************************************
* Name    : Cls                                                            *
* Purpose : Clear the GLCD screen                                          *
****************************************************************************
} 
Public Sub Cls(pX,pY,pEndX,pEndY As Byte)
      WriteCommands(cmdClWin,pX,pY,pEndX,pEndY)
End Sub
{
****************************************************************************
* Name    : MakeColor                                                      *
* Purpose : The S1D15G00 8 bit color scheme maps 3 bit R, G values and     *
*         : a 2 bit B value onto a 12 bit RGB. This routine allows you     *
*         : to create a color by specifying RGB values in the range 0..255 *
****************************************************************************
} 
Public Function MakeColor(pR, pG, pB As Byte) As TColor
   'result = (pR / 32 << 5) Or (pG / 32 << 2) Or (pB / 64)  
End Function
{
****************************************************************************
* Name    : PowerOLED                                                      *
* Purpose : Configure the GLCD before Vcc is applied - run this whenever   *
*           the 3.3V bus is started so the display is ready for the high   *
*           voltage Vcc.                                                   *
****************************************************************************
} 
Public Sub PowerOLED()
   Command(cmdDisOff)   //turn off display
   Cls(0,0,132,132)     //clear screen
   DelayMS(GLCDDelay)   //Must be at least 100 mS between this cmd and Vcc 
End Sub
{
****************************************************************************
* Name    : Initialize                                                     *
* Purpose : Configure the GLCD before use.                                 *
****************************************************************************
} 
Public Sub Initialize()        //first section same as PowerOLED
   Command(cmdDisOff)   //turn off display
   Cls(0,0,132,132)     //clear screen
   DelayMS(GLCDDelay)
   
   // set display clock divide ratio and oscillator frequency
   WriteCommands(cmdOscDv,$F0)
   
   //set display offset, = 132 - dummy lines from common 0
   WriteCommands(cmdVScrl,$00) //setting to $01 starts the line off the display
   
   //set multiplex ratio
   WriteCommands(cmdMuxRa, $84) //use 131 lines on the display
   
   //set master configuration
   WriteCommands(cmdMastC, $8F) //use external Vcc & external pre-charge V source ($8E in Densitron manual)
   
   //set display start line
   CommandWithData(cmdStLin, $00) //set start line at 0
   
   //set segment re-map & data format
   CommandWithData(cmdRemap, $34) //$34 sets to normal display, $26 flips display 180 degrees. Notes:
        //$xxxx xxx0 = X1, horizontal (xxx0), or vertical (xxx1)address pointer movement
        //$xxxx xx0x = X2, column addresses mapped left to right (xx0x), or right to left (xx1x)
        //$xxxx x0xx = X4, colour remap, colour sequence is ABC (x0xx), or CBA (x1xx)
        //$xxxx 0xxx = X8, MCU interface 8/16 or 9/18 bit, 8/16 (0xxx), or 9/18 (1xxx)
        //$xxx0 xxxx = 1X, scan remap, up to down (xxx0), or down to up (xxx1)
        //$xx0x xxxx = 2X, disable com split odd even (xx0x), or enable...just try it to see it, too hard to explain (xx1x)
        //$x0xx xxxx = 4X, 256 colours (00xx) or 65K colours (01xx)
        //$0xxx xxxx = 8X, 262K colours with 8/9/16 bit MCU interface, or 262K colours with 16 bit MCU interface (11xx)
   
   //set master contrast current control, user may have to adjust...
   SetContrast(158)
   
   //set contrast control for colours A,B,C (RGB)
   WriteCommands(cmdCoCol,$80,$80,$80)     //confirmed reset values, may change later
   
   //set pre-charge voltage of colours A,B,C (RGB)
   WriteCommands(cmdPreCV,$1C,$1C,$1C)     //confirmed reset values, may change later
   
   //set VCOMH
   CommandWithData(cmdVCOMH, $1F) //use ext VCOMH so should be irrelevant but manuals say to set it...
   
   //Set reset (phase 1) & pre-charge (2) period adjustments-1 is discharge time,2 is charge time -higher 
   //  capacitance displays need more time and thus a higher value
   CommandWithData(cmdResPr, $47) //used $47 out of FF as per defaults-old code used $11
   
   //set power saving mode
   CommandWithData(cmdPwrSa, $1A) //Power saving with external VSL, as per manual
   
   //set display mode - turn display on
   Command(cmdDisOn)
End Sub
{
****************************************************************************
* Name    : SetRegion (PRIVATE)                                            *
* Purpose : Sets the GLCD display boundary setting region                  *
****************************************************************************
} 
Sub SetRegion(pX, pY, pWidth, pHeight As Byte)
   WriteCommands(cmdCaSet,pX,pX + pWidth - 1)
   WriteCommands(cmdPaSet,pY + 2,pY + pHeight + 1)
End Sub
{
****************************************************************************
* Name    : Line                                                           *
* Purpose : Draw Line                                                      *
*         : write start col/row, end col/row,line colour byte 1&2          *
****************************************************************************
} 
Public Sub Line(pX1, pY1, pX2, pY2 As TXY,pColor,pColor2 As Byte)
   WriteCommands(cmdDLine,pX1, pY1, pX2, pY2,pColor,pColor2)
End Sub
{
****************************************************************************
* Name    : Rectangle                                                      *
* Purpose : Draw Rectangle                                                 *
*         : write start col/row, end col/row,line colour byte 1 & 2,fill   *
*           colour bytes 1 & 2                                             *
****************************************************************************
} 
Public Sub Rectangle(pX1, pY1, pX2, pY2 As TXY,pColor,pColor2,pFColor,pFColor2 As Byte)
   WriteCommands(cmdDRect,pX1, pY1, pX2, pY2,pColor,pColor2,pFColor,pFColor2)
End Sub
{
****************************************************************************
* Name    : Circle                                                         *
* Purpose : Draw circle                                                    *
*         : write col/row address of center, radius,line colour byte 1&2,  *
*           fill colour bytes 1 & 2                                        *
****************************************************************************
} 
Public Sub Circle(pX1, pY1, pRadius, pColor,pColor2,pFColor,pFColor2 As Byte)
   WriteCommands(cmdDcirc,pX1, pY1, pRadius, pColor,pColor2,pFColor,pFColor2)
End Sub
{
****************************************************************************
* Name    : Copy                                                           *
* Purpose : Copy one area of the screen to another                         *
*         : Define col/row to start, col/row to end, col/row of new start  *
****************************************************************************
} 
Public Sub Rectangle(pX1, pY1, pX2, pY2 As TXY,CopyCol, RowCol As Byte)
//write start col/row, end col/row,line colour byte 1&2, fill colour byte 1&2
   WriteCommands(cmdCopy,pX1, pY1, pX2, pY2,CopyCol, RowCol)
End Sub
{
****************************************************************************
* Name    : ReadImageByte (PRIVATE)                                        *
* Purpose : Read an image byte                                             *
****************************************************************************
} 
Function ReadImageByte() As Byte
   ASM-
      TBLRD*+
      movff TABLAT, result
   End ASM
End Function    
{
****************************************************************************
* Name    : SetImage (OVERLOAD)                                            *
* Purpose : Overrides the GLCD library native SetImage call with this      *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : pImageAdr is the address of the image to render                *
****************************************************************************
}
#define GLCD_SETIMAGE // override GLCD SetImage
Public Sub SetImage(pX, pY As TXY, pImageAdr As Word)
   Dim x, y As Byte 
   Dim Image As TImage 
   'Dim count As Word
   Dim Index, Range As Word
   Dim RLENum As Byte
   Dim LastPenColor As Byte
   count = 0
   LastPenColor = Pen.Color
   Index = 0
    
   // get bitmap ID, width and height... 
   TABLEPTR = pImageAdr
   Image.Header = ReadImageByte 
   Image.Width = ReadImageByte 
   //Image.Width = (Image.Width / 2) 
   Image.Height = ReadImageByte 
   'USART2.Write("Width/height,x,y,header: ", HexToStr(Image.Width),",",HexToStr(Image.Height),",",HexToStr(pX),",",HexToStr(pY),",",HexToStr(Image.Header), 13, 10)
   Range = Image.Height * Image.Width
   

   'DelayMS(10000)
    'For y = pY To (pY + (image.Height - 1)) 
     WriteCommands(cmdCaSet,pX+2,Image.Width+1) 
     WriteCommands(cmdPaSet,pY+6,Image.Height+10) 
     Command($5C)  
       DC = 1 
       CS = 0 
       TRISData = $00   // set data bus to output 
       Repeat       
        RLENum = 1
            If Image.IsRLE Then            
                TABLEPTR = pImageAdr + 4 + count 
                Inc(count)
                    RLENum = ReadImageByte 
            EndIf  
          'USART2.Write("RLENum first loop check: ",HexToStr(RLENum),13, 10)  
        Repeat  
            'Inc(pImageAdr)
            TABLEPTR = pImageAdr + 4 + count 
            DC = 1         //indicate it's data
            RW = 0        //indicate it's a read
            E = 1         //initiate a write
            CS = 0        //start operation
            Data = ReadImageByte 
            CS = 1       //end operation
            E = 0        //end initiation  
            Dec(RLENum)
            Inc(Index)
            'USART2.Write("RLENum: ",HexToStr(RLENum),13, 10)
        Until RLENum = 0
        Inc(count)
      Until Index >= Range           
      'Next 

   'Next 
   Pen.Color = LastPenColor
End Sub    
{
****************************************************************************
* Name    : SetImage (OVERLOAD)                                            *
* Purpose : Overrides the GLCD library native SetImage call with this      *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : pImage is a constant array holding the image data to render    *
****************************************************************************
} 
Public Sub SetImage(pX, pY As TXY, ByRefConst pImage() As Byte)
   SetImage(pX, pY, @pImage)
End Sub 
{
****************************************************************************
* Name    : WriteChar                                                      *
* Purpose : Overrides the GLCD library native WriteChar call with this     *
*         : routine which is better suited for rendering to the S1D15G00   *
*         : This routine will only handle xFonts (that is, font files with *
*         : the scan line in the x direction)                              *
****************************************************************************
} 
 
#define GLCD_WRITECHAR // override GLCD WriteChar
#define GLCD_XFONT     // force the use of x scanned font
Public Sub WriteChar()
   Dim FontByte As Byte
   Dim x, y, xRange, yRange As Byte
   Dim PenColor As TColor
   Dim Range, Index As Word
   Dim Ignore As Boolean
   'count = 0
   
   'count = count + TABLEPTR
   'USART2.Write("TABLEPTR, count:",HexToStr(TABLEPTR),",",HexToStr(TABLEPTR),13, 10)
   PenColor = Pen.Color
   Index = 0  

   // is the brush style clear... 
   If Brush.Style = bsClear Then
      Ignore = false
      yRange = Pos.y + Font.Height
      y = Pos.y
      While y < yRange

         MoveTo(Pos.x,y)
         xRange = Pos.x + Font.Width
         x = Pos.x
         While x < xRange
            FontByte = ReadFontByte
            
            Index = 8
            Repeat
               // write a font pixel with pen color...  
               If FontByte.7 = 1 Then
                  If Ignore Then
                     WriteCommands($15,x,Pos.x + Font.Width)
                      Command($5C)
                     Ignore = false
                  EndIf
         Command($5C)
        TRISData = $00   // set data bus to output 
            DC = 1         //indicate it's data
            RW = 0        //indicate it's a read
            E = 1         //initiate a write
            CS = 0        //start operation
            Data = Pen.Color 
            CS = 1       //end operation
            E = 0        //end initiation  
            
               // skip transparent pixel...
               Else
                  Ignore = true
               EndIf
               FontByte = FontByte << 1
               Dec(Index)
               Inc(x)
            Until Index = 0
         Wend
         Inc(y)
      Wend
   
   // brush style is not clear, fast bit blit...
   Else

x = 0
      SetRegion(Pos.x, Pos.y, Font.Width, Font.Height)
      Range = Font.Height * Font.Width
      Repeat
         // grab a font byte...
         If x >= Font.Width Then
            FontByte = ReadFontByte
            x = 0
         ElseIf x Mod 8 = 0 Then
            FontByte = ReadFontByte
         EndIf 
         Inc(x)  
         
         // set either font color or background color...
         If FontByte.7 = 1 Then
            Pen.Color = PenColor
         Else
            Pen.Color = Brush.Color
         EndIf
         Command($5C)
        TRISData = $00   // set data bus to output 
            DC = 1         //indicate it's data
            RW = 0        //indicate it's a read
            E = 1         //initiate a write
            CS = 0        //start operation
            Data = Pen.Color 
            CS = 1       //end operation
            E = 0        //end initiation  
     
         FontByte = FontByte << 1
         Inc(Index)
      Until Index >= Range

   EndIf
   Pen.Color = PenColor
   Inc(Pos.x,Font.Width)  
End Sub

// configure the module
Initialize
 SetBaudrate(br19200)

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Post by RangerBob » Mon Dec 17, 2007 11:41 am

RadioT wrote:I can already see some things to work on:

1. I didn't put in the dummy read before the actual read. This will have to be done before the function can be used for reading back bytes from the SSD1330 chip.

2. Looking at the SSD1339 datasheet, it's not entirely clear whether it's the CS line or the E line or possibly even the RW line or all these lines that optimally need to be toggled for each read or write. The Solomon Systech SSD1339 datasheet did not provide more than a single read/write cycle in the parallel data example. The datasheet is written in a very terse manner with grammatical errors, so I'm not surprised to see your code uses the R/W line to latch data and I use CS. It seems both methods "work" but I have to wonder if this will lead to "surprise" faults under conditions of stress such as temperature extremes.

3. Need to add a fill command.

4. SetImage() is key to this working, there's a big difference between them in the different code variants. WriteChar() sort of works as-is with David's original GLCD code but I need to get the MPlab debugger working with this code so I can see what is being written. My code won't compile for the MPLab software debugger for some reason, I really really hope SF will incorporate it's own debugger in the future. Writing code without decent visibility is why I'm having problems getting this routine going in the first place. I suppose I could wire up an 18F66J16 with in-circuit hardware debug but that's another week or more to get running...the idea of using BASIC instead of C, C##, etc. is to avoid long learning/implemenation curves.

-Tom
Glad you got something working!

1. Yeah, the dummy read is important. I think some of the SF routines pull back data from the controller so this is pretty important.

2. The CS / R/W thing is do do with which parallel mode you have selected. I believe mine runs in 8080 mode. Is yours set to 6800 mode? The Pins behave differently depending on which is set. It might just be I misnamed my pins though, that bit of the datasheet was a bit of a mess!

You're right that the Solomon datasheets leave something to be desired. Most of my work came from the OSRAM Pictivia datasheets which helpfully explained a lot that the Solomon stuff left out.

4. Be warned - my setimage routine is a very quick and dirty hack. Because of the 2 pixels per byte addressing scheme my display has, I couldn't be bothered to process it properly on the PIC, plus it produces nicely packed datatables. I modified someone elses code to do the dirty work on the PC for me.

It is a bit frustrating running without debug, but I understand David is working hard at it as we speak. I find a few well placed Serial print routines can usually work wonders anyway!

Looks like good work to me so far! Perhaps it might stir me into properly tidying up my code!

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Mon Dec 17, 2007 12:29 pm

2. The CS / R/W thing is do do with which parallel mode you have selected. I believe mine runs in 8080 mode. Is yours set to 6800 mode? The Pins behave differently depending on which is set. It might just be I misnamed my pins though, that bit of the datasheet was a bit of a mess!
Right, sorry, I didn't state that I am using 6800 mode. Thus, the E pin references.

Glad to hear David is planning on a built-in debug facility. Nothing like being able to just pick variables to watch and set breakpoints instead of having to set up print statements and delays!

-Tom

Doj
Posts: 362
Joined: Wed Apr 11, 2007 10:18 pm
Location: East Sussex

Post by Doj » Mon Dec 17, 2007 1:29 pm

Hello both,
I have written a completely bespoke driver for my little 128*160 TFT and thy VB conversion software for BMP conversion(developed over the last year).
The main things I was interested in was speed of refresh and compact data tables.
Both were achieved by splitting the high and low data bytes of the display packet into seperate data tables and then the subsequent read loop requires only one increment of the loop per pixel read as the location in the two data tables is the same, this makes a very large improvement in speed, some 30% if memory serves.
Another speed improvement in the order of 10-15% was to have two byte sized loops to count the word sized table address, the pic does not like to throw words around as much as it likes bytes.

My final throw of the dice was to do a little compression in the VB code which is quite simply counting consecutive bytes of the same value in the data tables and producing a third table which is used as a loop counter for the values in the main data tables.
Allthough there is a penalty in terms of execution time within the PIC as it requires an extra read an loop, this is usually outweighed by the fact that the stred data tables can be 25% to 95% smaller!

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Mon Jan 14, 2008 12:28 pm

Hi Mark,

Since the last posts, I've done some more work with this module. I'm using it in 256 colour mode so am directly writing 8 bits as the total data packet size but I'll keep your array ideas in mind should I go to a higher colour count, since they require a 2 byte write.

The compression you mention sounds to me like a modified form of RLE (run-length encoding) except with putting the "number of bytes of X" in a separate array. I am using the GLCD graphic plug-in to compress the image for my logo splash screen with RLE. Since the image is only a few colours, I am getting about 4 to 1 compression, quite nice.

One note about the SSD1339 controller. I was getting strange scrambling on all of the font bits on reset or power-up when running clock speeds above 4 MHz. Later font data writes often worked. After some testing, I realized the issue was not related to pin strobe timing but to synchronization of the PIC output data lines of the port (I am using Port D) to the OLED's input. I now write a line of data to appear on the screen and then immediately re-run the initialization sequence. Perhaps running the entire initialization is over-doing it, but now it always comes up perfectly. Note that I always write some data to the screen between the initializations; if I do not, I have seen where the screen comes up blank. Note the low voltage power supply is always brought up before the high-voltage supply prior to initialization. If done in the opposite sequence, I have seen where the screen comes up blank.

For example, instead of running:

Code: Select all

 InitializeOLED         // initialize OLED
 Cls(0,0,132,132)       //clear entire screen
 GLCD.SetFont(VerdanaBold)
 GLCD.WriteAt(0,2,"Powered Up")
I now run:

Code: Select all

 InitializeOLED         // initialize OLED
 Cls(0,0,132,132)       //clear entire screen
 GLCD.SetFont(VerdanaBold)
 GLCD.WriteAt(0,2,"Powered Up")
 DelayUS(1)
 InitializeOLED
 GLCD.WriteAt(0,2,"Powered Up")
in my testing and it always comes up correctly.

73's,
de Tom

Doj
Posts: 362
Joined: Wed Apr 11, 2007 10:18 pm
Location: East Sussex

Post by Doj » Mon Jan 14, 2008 3:05 pm

Hello Tom,
All these drivers have their little quirks, 256 colour mode should be more than enough for most uses.

The only thing left to say is SHOW US THE PICTURE!

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Thu Jan 17, 2008 12:34 pm

OK,here's a graphic with my company's logo and some text! Now I need to make this into a proper user module once I'm done this project.....

73's,
de Tom
Image
Image

Post Reply