'SED1565 LCD DRIVER TEST CODE
'  THIS IS A USER LCDPANEL DRIVER FOR DISPLAYS USING THE EPSON SED1565 AND
'  COMPATIBLE (UC1609).  THESE ARE MONOCHROME LCD DRIVERS.  THE PARTICULAR
'  DISPLAY HERE IS 100 X 64.  THERE IS AN 8X13 FONT EMBEDDED.  ALL SEEMS TO
'  WORK THOUGH IT IS QUITE SLOW.'
'Wettroth 7/1//22
'
'  Started with a ssd1306 OLED driver that has a similar memory layout but
'  different init routine, minor syntax diffs and is SPI vs I2C.  The syntax
'  diff is that the OLED display or'ed data with 40 hex.

'BEGIN

'
'Pins
'Connections Display on SPI- EBLCD Board
'DIN  3 DOUT  <DS PIN 8> SPI OUT
'SCL  7 DOUT  <DS PIN 7> SPI CLK
'CS   5 DOUT  <DS PIN 4> ACT HI
'A0   2 DOUT  <DS PIN 6> GPIO
'RST  4 DOUT  <DS PIN 5> GPIO
'
'ARCHIVED AS REV1
'
'REV 2-
'-----------------------------------------------------------------------------

'Basic Test Code *****************
userdisplayinit       'init display

'insert some adc reading code


'Standard User Display Test

SetPin 24,AIN
SetPin 7,AIN


'Text 0,0,"P1VAL:",LT,8
'Text 0,8,"P2VAL:",LT,8
'CL$=String$(6," ")
'GETDTA:
'Text 38,0,Str$(Pin(24),1,3),LT,8
'Text 38,8,Str$(Pin(7),1,3),LT,8

'Text 38,0,CL$,LT,8,,0,1
'Text 38,8,CL$,LT,8,,0,1


'FONT 8 IS A SMALL FONT
'FONT 1 IS A BIGGER FONT
'DON'T KNOW WHY?

'GoTo GETDTA

Line 0,0,MM.HRes,MM.VRes
Line MM.HRes,0,0,MM.VRes
Box 0,0,MM.HRes,MM.VRes
Text MM.HRes/2,MM.VRes/2,"Fnt1",CM,8


End
'basic end- driver code follows
'-------------------------------------------------------------------
'LCD DRIVER CODE- MMite User LCDPANEL Format
&
' Preliminary- Global
'--------------------------------------------------------------
'init routine - main entry, setup hw and declare vars

Sub userdisplayinit


'Option explicit
Option default none
On error skip
Option LCDPANEL USER, 100,64
On error skip
Erase S$(), tmaskarray(), bmaskarray()
Dim S$(7) length 100 'this is the array that stores the screen image
Dim integer tmaskarray(7)=(255,254,252,248,240,224,192,128) ' mask for writing pixels left to right
Dim integer bmaskarray(7)=(1,3,7,15,31,63,127,255) 'mask for pixels right to left
Local i%


' HW SETUP
'SET DEFAULT PIN STATES BEFORE DDR
Pin(5)=0    'CS LOW, NOTE ACTIVE HIGH
Pin(2)=0    'A0 LOW= CMD, HIGH DATA
Pin(4)=0    'RESET DISPLAY
Pin(24)=0   'LOGIC TRIGGER- DEBUG

'SET DDR'S
SetPin 2,DOUT  'A0 COMMAND/DATA
SetPin 4,DOUT  'RST
SetPin 5,DOUT  'CS
SetPin 24,DOUT 'AUX- DEBUG, LOGIC TRIGGER

'DEBUG
Pin(24)=1   'START RISE- MAIN TRIGGER
Print "MAIN TRIGGER"

SPI OPEN 1000000,0,8    '1M
Pause 5       'WAIT 5 MS WITH RESET HIGH
Pin(4)=1      'RESET INACTIVE

'END HW SETUP- DISPLAY IS RESET, CS IS LOW- INACTIVE
'----
' send the intialisation instructions to the display
'
  Pin(2)=0    'A0 LOW- COMMAND
  Pin(5)=1    'CS ACTIVE
  SPI WRITE 11,&HE2,&HA3,&HA6,&HA1,&HC0,&H23,&H81,&H26,&H2F,&HAF,&H40
  Pin(5)=0
'
'INITIALIZED- create array and clear

' Set the memory image of the display to all zeroes
'
For i% = &h0 To &h7                'PAGES
  s$(i%)=String$(&h64,Chr$(0))     'ZERO OUT
Next i%
'
' Refresh the display with the new blank image
'
update 0, 0, MM.HRes, MM.VRes\8

End Sub
'-----------------------end of userdisplayinit ------------------------------

' standard driver requires two routines-
'  1. output a filled rectangle to display
'  2. output an image

' FILLED RECTANGLE
Sub MM.USER_RECTANGLE(x1%, y1%, x2%, y2%, fcol%)
Local integer i, j, k, l, t, mask, top_row, bottom_row, top_start, bottom_end


'Print X1%,X2%,Y1%,Y2%,FCOL%
'limit checks

If x2% <= x1% Then t = x1% :x1% = x2% :x2% = t    'lim x2>x1 swap
If y2% <= y1% Then t = y1% :y1% = y2% :y2% = t    'lim y2>y1 swap
If x1% < 0 Then x1% = 0
If x1% >= MM.HRes Then x1% = MM.HRes - 1
If x2% < 0 Then x2% = 0
If x2% >= MM.HRes Then x2% = MM.HRes - 1
If y1% < 0 Then y1% = 0
If y1% >= MM.VRes Then y1% = MM.VRes - 1
If y2% < 0 Then y2% = 0
If y2% >= MM.VRes Then y2% = MM.VRes - 1

' establish some useful constants for future calculation
top_row=y1%\8
bottom_row=y2%\8
top_start=y1%-(top_row*8)
bottom_end=y2%-(bottom_row*8)

'
'there are a number of cases that need to be handled
'case1-  vertical pixels in the rectangle are within a single byte
'
If top_row = bottom_row Then
  If fcol% Then 'create a mask to set or clear the requisite pixels
    mask = (tmaskarray(top_start) And bmaskarray(bottom_end))
  Else
    mask = notmask%(tmaskarray(top_start) And bmaskarray(bottom_end))
  EndIf

  For i=x1% To x2% 'loop through the colums and set or clear the required pixels
    l= Peek(var S$(top_row),i+1)
    If (fcol%) Then
      l=l Or mask
    Else
      l=l And mask
    EndIf

    Poke var S$(top_row),i+1, l
  Next i

Else
 ' otherwise deal more generally
  If (top_row+1) <= bottom_row Then
    For i=x1% To x2%
      'first deal with the top byte affected
      l = Peek(var S$(top_row),i+1)
        If (fcol%) Then
          l=l Or tmaskarray(top_start)
        Else
          l = l And (notmask%(tmaskarray(top_start)))
        EndIf

      Poke var S$(top_row),i+1, l
      ' now deal with bottom byte affected
      l= Peek(var S$(bottom_row),i+1)
      If fcol% Then
        l=l Or bmaskarray(bottom_end)
      Else
        l=l And (notmask%(bmaskarray(bottom_end)))
      EndIf

      Poke var S$(bottom_row),i+1, l
    Next i

EndIf
'now deal with bytes in the middle that will be set completely on or completely off
If (top_row+1<bottom_row) Then
  For j=top_row+1 To bottom_row-1
    For i=x1% To x2%
      l= Peek(var S$(j),i+1)
      If fcol% Then
        l=&HFF
      Else
        l=0
      EndIf
      Poke var S$(j),i+1, l
    Next i
  Next j
EndIf
EndIf

update x1%,top_row, x2%, bottom_row

End Sub       'end filled rectangle

'-----------------------------------------
'DISPLAY A BIT MAP CODE
'
' output a bitmap to the screen
' the bitmap is supplied as a pointer to an area of memory so we use
' peek(byte bitmap%+x) to access the x'th byte in the bitmap
' each byte is a horizontal row of pixels starting with the most significant bit
' e.g. for an 8x8 bitmap
' Byte0Bit7, Byte0Bit6, Byte0Bit5, Byte0Bit4, Byte0Bit3, Byte0Bit2, Byte0Bit1, Byte0Bit0
' Byte1Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte2Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte3Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte4Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte5Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte6Bit7, ........., ........., ........., ........., ........., ........., .........
' Byte7Bit7, ........., ........., ........., ........., ........., ........., Byte7bit0
'
Sub MM.USER_BITMAP(x1%, y1%, width%, height%, scale%, fcol%, bcol%, bitmap%)
'Print "userbitmap ", x1%, y1%, width%, height%, scale%, fcol%, bcol%

Local INTEGER i, j, k, mask, m, l, ll, t, tt, vCd, hCd, x, y, a%=height% * width%, ln%, c1%, c2%, c3%, c4%
vCd = y1%
If y1% < 0 Then y1% = 0 ' the y coord is above the top of the screen
For i = 0 To height%-1 ' step thru the font scan line by line
  ln%=i * width%
  For j = 0 To scale%-1 ' repeat lines to scale the font in the y axis
    vCd=vCd+1
    If vCd >= 0 Then ' we are above the top of the screen
      y=vCd - 1
      c1%=y \ 8
      mask = 1 << (y Mod 8 )
      c3%=notmask%(mask)
        If vCd > MM.VRes Then GoTo D_UP ' we have extended beyond the bottom of the screen so exit
          hCd = x1%
            For k = 0 To width%-1 ' step through each bit in a scan line
              c2%=ln% + k
              c4%=(a% - c2% - 1) Mod 8
              t=Peek(BYTE bitmap% + c2%\8)
              tt = (t >> c4%) And 1
                For m = 0 To scale% -1 ' repeat pixels to scale in the x axis
                  hCd = hCd +1' we have not reached the left margin
                    If hCd >= 0 Then
                      x=hCd -1
                        If hCd <= MM.HRes Then ' check are we beyond the right margin
                          ll= Peek(var S$(c1%),hCd)
                            If tt Then
                              If fcol% Then ll= ll Or mask Else ll = ll And c3%
                            Else
                              If bcol%<>-1 Then 'transparent text
                                If bcol% Then
                                  ll = ll Or mask Else ll= ll And C3%
                                EndIf
                              EndIf
                            EndIf
                            Poke var S$(c1%), hCd, ll
                        EndIf
                    EndIf
                Next m
            Next k
        EndIf
  Next j
Next i

D_UP:
update x1%, y1% \ 8, x, y\ 8

End Sub
'---------------------------------
'local subs

' Send a command to the display
'
Sub EBLC.SCmd(Comnd%)
  Pin(2)=0    'A0 LOW- COMMAND
  Pin(5)=1    'CS ACTIVE
  SPI WRITE 1,Comnd%
  Pin(5)=0
End Sub
'
' Set the cursor position on the display
'
Sub EBLC.SCz(x%,y%) 'set the cursor position on the display
  Local xn%=x%
    Pin(2)=0  'CMD
    Pin(5)=1  'CS ACTIVE
    SPI WRITE 3,&HB0 Or y%,&H10 Or (XN%>>4 And &H0F),&H00 Or (XN% And &H0F)
    Pin(5)=0  'CS INACTIVE
End Sub
'
'------------------------------------------------------------------------------------------------
' Update the screen between the x coordinates specified and the 8 row block specified
Sub update(x1%, tr%, x2% , br%)
  Local b$, i%
  If x1%< MM.HRes Then
    For i% = tr% To br%
      If i%<MM.VRes\&h8 Then
        EBLC.SCz(x1%,i%)
        b$=Mid$(s$(i%),x1%+1, x2%-x1%+1)
          Pin(2)=&h1    'A0 HI- DATA
          Pin(5)=&h1    'CS ACTIVE
          SPI WRITE Len(B$),B$
          Pin(5)=&h0    'CS INACTIVE
      EndIf
    Next i%
  EndIf
End Sub
'---------------------------------------------------------------------------------------------

' generate the ones complement of a byte
'
Function notmask%(x%)
  notmask% = (-1 Xor x%) And &HFF
End Function
'BIT MAP

DefineFont #8
5C200806
00000000 82200000 00800008 00004551 4F510000 0045F994 2B1CEA21 690000C2
B04C2090 AA104A62 84608046 00000000 40108410 81400081 00841004 A89C8A00
82000080 0080203E 30000000 00000042 0000003E 01000000 21000086 00004208
CAAA2972 82210027 00872008 21842072 42F8800F 00270A04 F824C510 0FFA0041
00270A02 8A3C0831 21F80027 00044108 8A9C2872 28720027 0027089E 61008601
86010080 00846000 40208410 0F000081 0000F880 10028140 20720084 00022084
BA9A2072 28720027 8028FAA2 8ABC28F2 2872002F 00278220 8AA248E2 08FA004E
800F823C 823C08FA 28720008 80278A2E 8ABE288A 82708028 00872008 12044138
4A8A0046 8048A230 82200882 6A8B800F 80288AAA 9AAA2C8A 28728028 00278AA2
82BC28F2 28720008 8046AAA2 A2BC28F2 087A8048 002F081C 200882F8 288A0082
00278AA2 89A2288A 288A0042 00A5AAAA 5208258A 288A8028 00822094 420821F8
0471800F 00074110 A9944AA9 4170804A 00471004 00804821 00000000 800F0000
00008140 07000000 80277A02 8A320B82 0700002F 00278220 8AA62608 07008027
0007FA22 41382431 E8010004 002778A2 8A320B82 06208028 00872008 12040310
09820046 0089C228 20088260 0D000087 8028AA2A 8A320B00 07008028 00278A22
F2220F00 06000008 802078A6 82320B00 07000008 002F7020 41100E41 08000023
80668AA2 89A20800 08000042 00A5AAA2 21940800 08008048 002778A2 21840F00
0400800F 0EE24028
End DefineFont                                                 