SSD1306 OLED 128x32 test code

Hemi345

Senior Member
#1
I haven't stumbled across anyone successfully using an SSD1306-based 128x32 OLED display with the PICAXE. So I looked through the Arduino code provided by Adafruit and figure out the different parameters required to make the 128x32 display work. Using the code provided by fellow PICAXE members for the x64 display, I modified it to work with the x32. I've added comments on the various sections that explain what values are required for the 64 pixel and the 32 pixel. It's very important that a delay is programmed in at the start of the program to give the SSD1306 enough time start up, otherwise the display will not work from a 'cold boot'. I also put in an example of some double size (10x16) text in addition to the standard/tiny 5x7 text.

20190415_161918.jpg

Code:
#picaxe 20x2
#no_data
#no_table
#terminal 38400

'This works with the 128x32 OLED!

'Display command constants
Symbol TWI_BUFFER_LENGTH = 32
Symbol LCDWIDTH = 128
Symbol LCDHEIGHT = 32               '64 for 128x64 display, 32 for 128x32 display
Symbol SETCONTRAST =0x81
Symbol contrastVal = 0x8F             '0xCF for 64, 0x8F for 32
Symbol DISPLAYALLON_RESUME =0xA4
Symbol DISPLAYALLON =0xA5
Symbol NORMALDISPLAY =0xA6
Symbol INVERTDISPLAY =0xA7
Symbol DISPLAYOFF =0xAE
Symbol DISPLAYON =0xAF
Symbol SETDISPLAYOFFSET =0xD3
Symbol SETCOMPINS =0xDA
Symbol comPinsVal = 0x02            '0x12 for 64, 0x02 for 32
Symbol SETVCOMDETECT =0xDB
Symbol SETDISPLAYCLOCKDIV =0xD5
Symbol SETPRECHARGE =0xD9
Symbol SETMULTIPLEX =0xA8
Symbol multiplexVal = LCDHEIGHT - 1    '0x3F = 63, 0x1F = 31 (LCDHEIGHT - 1)
Symbol SETLOWColUMN =0x00
Symbol SETHIGHColUMN =0x10
Symbol SETSTARTLINE =0x40
Symbol MEMORYMODE =0x20
Symbol COLUMNADDR =0x21
Symbol PAGEADDR =0x22
Symbol pageEndAddr = 3                '7 for 64, 3 for 32
Symbol COMSCANINC =0xC0
Symbol COMSCANDEC =0xC8
Symbol SEGREMAP =0xA0 | 0x1
Symbol CHARGEPUMP =0x8D
Symbol EXTERNALVCC =0x1
Symbol SWITCHCAPVCC =0x2

symbol RAM_base = 28 ' beginning of upper ram
symbol A_addr = 0 ' beginning of upper case letters in eeprom
symbol N_addr = 130 ' beginning numbers in of upper eeprom
Symbol I2CSpeed = i2cfast_32
Symbol Display = $78 '       $3C << 1  '[$78]

Symbol ch     = b4
Symbol i      = b5
Symbol row    = b6
Symbol col    = b7
symbol eeAdr = b8

pause 2000    'SUPER IMPORTANT - need to give OLED time to start up!
setfreq m32
read A_addr,ch
i = 0x7C ' first of 5 bytes defining pixel pattern for "A"
if ch <> i then ' eeprom not established
  gosub writeEEPROM
else
  sertxd("EEPROM Ok",13,10)
endif
hi2csetup i2cmaster, Display, I2CSpeed, I2cbyte   'Need to initialise I2C
pause 3000

gosub InitDisplay
gosub ClearDisplay
'
sertxd("OLED_128x32",cr,lf)
hi2cin 0,(b0)
sertxd("Status of Display ",#b0,13,10)
pause 3000

'//Print [iteration] LINE [linecount] on 4 lines using 5x7 text
b20 = 0
do
  inc b20
  for row = 0 to 3
    col = 0
    sertxd(#row,"/",#col," ")
    gosub SetPosition
    b0 = b20 + "0"    ' display the loop iteration
    Gosub ShowChar
    b1 = 0
    do : LookUp b1, ( " LINE ",0 ), b0
      if b0 <> 0 then : Gosub ShowChar : endif : inc b1
    loop until b0 = 0
    b0 = row + "0" ' display line number
    Gosub ShowChar
    sertxd(cr,lf)
    pause 4000
  next row
  gosub ClearDisplay
  gosub printFan
loop

'//print "FAN" in big double height 10x16 text
printFan:
  'gimme an F:
  row = 1 : col = 2
  gosub SetPosition
  hi2cout (0x40, 0xFE,0xFF,0xFF,0xC7,0xC7,0xC7,0x87,0x7,0x7,0x2, 0)
  row = 2 : col = 2
  gosub SetPosition
  hi2cout (0x40, 0x7F,0xFF,0x7F,0x1,0x1,0x1,0x0,0x0,0x0,0x0, 0)
  'gimme an A:
  row = 1 : col = 15
  gosub SetPosition
  hi2cout (0x40, 0xF8,0xFC,0xFE,0xC7,0xC7,0xC7,0xC7,0xFE,0xFC,0xF8, 0)
  row = 2 : col = 15
  gosub SetPosition
  hi2cout (0x40, 0x7F,0xFF,0x7F,0x1,0x1,0x1,0x1,0x7F,0xFF,0x7F, 0)
  'gimme an N:
  row = 1 : col = 28
  gosub SetPosition
  hi2cout (0x40, 0xFE,0xFF,0xFE,0xF0,0xE0,0x80,0x0,0xFE,0xFF,0xFE, 0)
  row = 2 : col = 28
  gosub SetPosition
  hi2cout (0x40, 0x7F,0xFF,0x7F,0x0,0x1,0x7,0xF,0x7F,0xFF,0x7F, 0) 
pause 16000
return
 
ShowChar: ' A-Z, 0-9, space
  sertxd(b0)
  if b0 >= "A" and b0 <= "Z" then
    bptr = RAM_base ' base of upper ram
    eeAdr = b0 - "A" * 5 + A_addr ' point to 5 unique char bytes in eeprom
    read eeAdr,@bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc ' move from eeprom to ram
    bptr = RAM_base ' base of upper ram
    hi2cout (0x40, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, 0)
  elseif b0 >= "0" and b0 <= "9" then
    bptr = RAM_base ' base of upper ram
    eeAdr = b0 - "0" * 5 + N_addr ' point to 5 unique char bytes in eeprom
    read eeAdr,@bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc ' move from eeprom to ram
    bptr = RAM_base ' base of upper ram
    hi2cout (0x40, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, 0)
  elseif b0 = " " then
    hi2cout (0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0)
  endif
  return

' code below by edmonds: http://www.picaxeforum.co.uk/showthread.php?27651-I2C-OLED-display
  InitDisplay:
  hi2cout (0, DISPLAYOFF)
  hi2cout (0, SETDISPLAYCLOCKDIV)
  hi2cout (0, 0x80)
  hi2cout (0, SETMULTIPLEX)
  hi2cout (0, multiplexVal)
  hi2cout (0, SETDISPLAYOFFSET)
  hi2cout (0, 0x0)
  hi2cout (0, SETSTARTLINE)
  hi2cout (0, CHARGEPUMP)
  hi2cout (0, 0x14)
  hi2cout (0, MEMORYMODE)
  hi2cout (0, 0x00)
  hi2cout (0, SEGREMAP)
  hi2cout (0, COMSCANDEC)
  hi2cout (0, SETCOMPINS)
  hi2cout (0, comPinsVal)
  hi2cout (0, SETCONTRAST)
  hi2cout (0, contrastVal)
  hi2cout (0, SETPRECHARGE)
  hi2cout (0, 0xF1)
  hi2cout (0, SETVCOMDETECT)
  hi2cout (0, 0x40)
  hi2cout (0, DISPLAYALLON_RESUME)
  hi2cout (0, DISPLAYON)
return

SetPosition:
  hi2cout (0, PAGEADDR)
  hi2cout (0, row)
  hi2cout (0, pageEndAddr)
  hi2cout (0, COLUMNADDR)
  hi2cout (0, col)
  hi2cout (0, 127)

return

ClearDisplay:

  row = 0 : col = 0 : gosub SetPosition
    for b0 = 0 to LCDWIDTH
      hi2cout (0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
    next b0

  hi2cout (0, COLUMNADDR)
  hi2cout (0, 0)
  hi2cout (0, 127)
  hi2cout (0, PAGEADDR)
  hi2cout (0, 0)
  hi2cout (0, pageEndAddr)
 
return
'#rem
writeEEPROM:
    pause 32000
    sertxd("invalid check char: ",#ch," not ",0x7c,"; writing eeprom",cr,lf)
    write A_addr, _
            0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, _
            0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, _
            0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, _
            0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, _
            0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, _
            0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, _
            0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, _
            0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, _
            0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, _
            0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, _
            0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, _
            0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, _
            0x03, 0x04, 0x78, 0x04, 0x03, 0x61, 0x59, 0x49, 0x4D, 0x43
' above are 5-byte codes for ABCDEFGHIJKLMNOPQRSTUVWXYZ
    pause 160
    write N_addr, _
            0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, _
            0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, _
            0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, _
            0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, _
            0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E
' above are 5-byte codes for 0123456789
    pause 160
  return
'#endrem
 
Top