Graphic OLED demonstration

cpedw

Senior Member
#1
I was inspired by Hippy's thermometer and used it as the basis of this sine wave plot which was an exercise to familiarise myself with the graphic possibilities of an OLED. This uses the built-in 18M2 of an AXE131Y (8x5 characters) to draw a sine wave that gradually proceeds across the display.

A significant change from Hippy's method is to disable the auto-increment of the Data Register Address. This is achieved by writing $07 instead of $06 in the initialisation sequence, line 168. The program draws the top half and the bottom half of each column before moving to the next column, instead of drawing one complete row then the other row. The Data Register has to be set explicitly for each column, line 75.

The program should be easily adapted for an AXE133Y, 16x2 characters, by changing 47 to 95 (number of columns) in line 65.

Code:
; AXE131y Graph of Sin
; 31/1/19 DW

; .-----------------------------------------------------------------------------.
; |    AXE131Y OLED draw a sin wave                                              |
; `-----------------------------------------------------------------------------'
;  Hippy's program from https://picaxeforum.co.uk/threads/oled-analogue-thermometer.29776/
;  provides the setup and general arrangement
#Picaxe 18M2
#No_Data


; .-----------------------------------------------------------------------------.
; |    Variables                                                                |
; `-----------------------------------------------------------------------------'

Symbol reserveb0 = b0     ; Argument for display commands
Symbol reserveb1 = b1    ; Used to initialise display
Symbol xflag    = bit8; 0 x is Pos that's 0-90. 1 x neg is 91-180 etc
Symbol yflag    = bit9; 0 y is pos
Symbol xflag0    = bit10; xflag at x=0
Symbol yflag0    = bit11; yflag at x=0
Symbol x          = b2
Symbol ang           = b3    ; angle/10 in deg.
Symbol ang0        = b4    ; angle/10 at start of display
Symbol sine       = b5
Symbol angtab    = b6    ; angle pointer in table
Symbol xskip    = b7    ; Test for blank column between characters

; .-----------------------------------------------------------------------------.
; |    LCD connections                                                          |
; `-----------------------------------------------------------------------------'

Symbol pinE  = C.6    : Symbol dirE  = dirC.6   ; 0 = Idle      1 = Active
Symbol pinRS = pinC.7 : Symbol dirRS = dirC.7   ; 0 = Command   1 = Data
Symbol pinD0 = pinB.0 : Symbol dirD0 = dirB.0   ; LCD Data Line 0
Symbol pinD1 = pinB.1 : Symbol dirD1 = dirB.1   ; LCD Data Line 1
Symbol pinD2 = pinB.2 : Symbol dirD2 = dirB.2   ; LCD Data Line 2
Symbol pinD3 = pinB.3 : Symbol dirD3 = dirB.3   ; LCD Data Line 3
Symbol pinD4 = pinB.4 : Symbol dirD4 = dirB.4   ; LCD Data Line 4
Symbol pinD5 = pinB.5 : Symbol dirD5 = dirB.5   ; LCD Data Line 5
Symbol pinD6 = pinB.6 : Symbol dirD6 = dirB.6   ; LCD Data Line 6
Symbol pinD7 = pinB.7 : Symbol dirD7 = dirB.7   ; LCD Data Line 7

; .-----------------------------------------------------------------------------.
; |    Main Program                                                             |
; `-----------------------------------------------------------------------------'

  Gosub InitialiseLcd

  SetFreq M32

  b0 = 1 : GOSUB SendInitCmdByte    ; Clear Display
 
xflag0 = 0
yflag0 = 0
ang0   = 0

DO
    ang   = ang0            ; Set angle at start
    ang0    = ang0 + 1
    xflag = xflag0
    yflag = yflag0
    
    FOR x = 0 TO 47
        IF x=1 THEN            ' Save these flags for next start
            xflag0 = xflag
            yflag0 = yflag
            ang0 = ang
        ENDIF

        xskip = x//6
        IF xskip<>0 THEN            ' Don't write at the between-characters gap
            READTABLE ang, sine    ; ang is angle in deg/10, sine is 8* true sine of angle
            b0 = %10000000 + X : Gosub SendCmdByte; GXA Set the X pixel
            IF yflag=0 THEN         ' Fill in the top row
                b0 = %01000000 : Gosub SendCmdByte  ; GYA 0 
                SELECT CASE sine    ' Define the Y pixel
                CASE 0
                    b0 = 0
                CASE 1
                    b0 = 128
                CASE 2
                    b0 = 64
                CASE 3
                    b0 = 32
                CASE 4
                    b0 = 16
                CASE 5
                    b0 = 8
                CASE 6
                    b0 = 4
                CASE 7
                    b0 = 2
                CASE 8
                    b0 = 1
                ENDSELECT
                Gosub SendDataByte
                 b0 = %01000001 : Gosub SendCmdByte  ; GYA 1    
                b0 = 0 : Gosub SendDataByte        ; Blank in bottom row when yflag=0
            ELSE                            ; Fill in bottom row (yflag=1)
                b0 = %01000001 : Gosub SendCmdByte  ; GYA 1
                SELECT CASE sine    ' Define the Y pixel
                CASE 0
                    b0 = 0
                CASE 1
                    b0 = 1
                CASE 2
                    b0 = 2
                CASE 3
                    b0 = 4
                CASE 4
                    b0 = 8
                CASE 5
                    b0 = 16
                CASE 6
                    b0 = 32
                CASE 7
                    b0 = 64
                CASE 8
                    b0 = 128
                ENDSELECT
                Gosub SendDataByte
                 b0 = %01000000 : Gosub SendCmdByte  ; GYA 0    
                b0 = 0 : Gosub SendDataByte        ; Blank in top row when yflag=1
            ENDIF
        ENDIF

'Increment the angle even if there's no drawing at this pixel
        IF xflag = 0 THEN
            ang = ang + 1
            IF ang > 9 THEN
                ang = 8
                xflag = 1
            ENDIF
        ELSE
            ang = ang - 1
            IF ang > 9 THEN
                ang = 1
                xflag = 0
                yflag = yflag + 1
            ENDIF
        ENDIF
        
    NEXT x
LOOP
        
; .-----------------------------------------------------------------------------.
; |    LCD initialisation routine                                               |
; `-----------------------------------------------------------------------------'

InitialiseLcd:

  dirE  = 1             ; Set LCD control lines as outputs
  dirRS = 1
  dirD0 = 1
  dirD1 = 1
  dirD2 = 1
  dirD3 = 1
  dirD4 = 1
  dirD5 = 1
  dirD6 = 1
  dirD7 = 1

  Pause 500

  For b1 = 0 To 7
    LookUp b1, ( $33,$33,$33, $3B,$0C,$07,$1F,$01 ), b0 : Gosub SendInitCmdByte
  Next

  ; Nibble commands - To initialise 8-bit mode
  ;
  ;   $33       %0011----               8-bit
  ;   $33       %0011----               8-bit
  ;   $33       %0011----               8-bit
  ;
  ; Byte commands - To configure the LCD or OLED
  ;
  ;                 LNFff
  ;   $3B       %00111011               Display Format
  ;
  ;               L : 0 = 4-bit Mode    1 = 8-bit Mode
  ;               N : 0 = 1 Line        1 = 2 Lines
  ;               F : 0 = 5x7 Pixels    1 = N/A
  ;
  ;               f : OLED Font table   00 English-Japanese
  ;                                     01 Western European 1
  ;                                     10 English-Russian
  ;                                     11 Western European 2
  ;
  ;                   DCB
  ;   $0C       %00001100               Display Control
  ;
  ;               D : 0 = Display Off   1 = Display On
  ;               C : 0 = Cursor Off    1 = Cursor On
  ;               B : 0 = Cursor Steady 1 = Cursor Flash
  ;
  ;                    IS
  ;   $07       %00000111               Cursor Move
  ;
  ;               I : 0 = Dec Cursor    1 = Inc Cursor
  ;               S : 0 = Cursor Move   1 = Display Shift
  ;
  ;                  GP
  ;   $1F       %00011111               Graphics Mode
  ;
  ;               G : 0 = Text Display  1 = Graphics Mode
  ;               P : 0 = Int Power Off 1 = Int Power On
  ;
  ;   $01       %00000001               Clear Screen
  ;
  ; Additional OLED Graphics commands
  ;
  ;   $80       %1xxxxxxx               GXA
  ;
  ;   $40       %0100000y               GYA 

  Return

; .-----------------------------------------------------------------------------.
; |    LCD interfacing routines                                                 |
; `-----------------------------------------------------------------------------'

SendInitCmdByte:

  Pause 15              ; Delay 15mS

SendCmdByte:

  pinRS = 0             ; Send to Command register

  Gosub SendDataByte

  If b0 <= 3 Then       ; Pause to allow Home or Clear to complete
    Pause 10
  End If

  Return

SendDataByte:
  pinsb=b0
  pulsout pinE,1
  pinRS = 1             ; Send to Data register next
  Return
TABLE 0,(0,1,3,4,5,6,7,8,8,8)        ; Sin at 10deg intervals scaled x8   
; .-----------------------------------------------------------------------------.
; |    End of program                                                           |
; `-----------------------------------------------------------------------------'
Derek
 
Top