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.
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 GLCD_E.GLCD_E@, // clk pin
CS As GLCD_CS.GLCD_CS@, // CS pin
DC As GLCD_DC.GLCD_DC@, // DC pin
RW As GLCD_RW.GLCD_RW@, //RW pin
count As Word,
Reset As GLCD_RESET.GLCD_RESET@ // 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)