Code:
'****************************************************************'* Name : ssd1306_I2C.INC *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 7/5/2018 *
'* Version : 1.1 *
'* Notes : const str added for pic16 *
'* :FOR pic 16/18 SSD1306 *
'****************************************************************
goto overglcd
; adjust to suit and place these in main prg
;use this define for hw i2c
;#define hwi2c 1
;#DEFINE PIC16 1 ;IF PIC 16 USED [USE PIC16 FONT TOO}
' ssdheight con 7 ; 7 = 8 PAGES 64*128 , 3 = 4 pages 32*128
' ssdwidth con 127 ; 128 PIXELS WIDE
' SCL var PortC.3 ' I2C Clock
' SDA var PortC.4 ' I2C Data
' sdd1306_addr con $78
USERCOMMAND "GLCDC" ; X,Y,CHR 0 < X < 127 , 0 < Y < 7 31 < CHR > 127
USERCOMMAND "GLCD_CLR" ;clear area x,y,W,H
USERCOMMAND "GLCDSTR" ;STRING @ X,Y or Constant String
USERCOMMAND "GLCDDHL" ; x,y,L ,bit-patten
USERCOMMAND "GLCDDVL" ; x,y,H
USERCOMMAND "SSDC" ;cmd BYTE TO SSD1306
USERCOMMAND "SSDBM" ;x,y,w,h,label
ASM
;----------------------VERT LINE------------------------------------
GLCDDVL?CCC macro Xin ,Yin , Hin
MOVE?CB Xin ,_gx
MOVE?CB Yin,_gy
MOVE?CB Hin ,_gl
L?CALL _xyy
endm
;----------------------HORIZ LINE------------------------------------
GLCDDHL?CCCC macro Xin ,Yin , Win ,Cin
MOVE?CB Xin ,_gx
MOVE?CB Yin,_gy
MOVE?CB Win ,_gl
MOVE?CB Cin ,_glcdData
L?CALL _xyx
endm
;----[const String]---------------------------------------------------------------
GLCDSTR?CCS macro Xin ,Yin,Cin
IFNDEF TBLPTRL
local TheString, OverStr ; define local labels so you can call macro multiple times
goto OverStr ; goto over string stored in FLASH, so processor can't execute that
TheString ;label to get address of your string
da Cin, 0 ;add string to flash at TheString address and end string with 0
OverStr
MOVE?CW TheString, _glcd_bigaddress
MOVE?CB Xin , _gx
MOVE?CB Yin , _gy
L?GOTO _GlcdUnpackStr
ELSE
local TheString, OverStr ; define local labels so you can call macro multiple times
goto OverStr ; goto over string stored in FLASH, so processor can't execute that
TheString ;label to get address of your string
data Cin, 0 ;add string to flash at TheString address and end string with 0
OverStr
movlw UPPER TheString
movwf TBLPTRU
movlw HIGH TheString
movwf TBLPTRH
movlw LOW TheString
movwf TBLPTRL
MOVE?CB Xin , _gx
MOVE?CB Yin , _gy
L?CALL GLCD_Cstr_out
ENDIF
endm
SSDBM?CCCCL macro Xin ,Yin ,Win,Hin,BMin
IFNDEF TBLPTRL
ERROR BITMAPS ONLY SUPPORTED ON PIC18
ENDIF
MOVE?CB Xin , _gx
MOVE?CB Yin , _gy
MOVE?CB Hin/8-1 , _gy_
MOVE?CB Win+Xin-1 , _gx_
MOVE?CW Win*Hin/8 , _glcd_rad
banksel _glcdbm
movlw low BMin
movwf _glcdbm
movlw high BMin
movwf _glcdbm +1
BANKSEL 0
L?CALL _ssd_bitmap
endm
;----------------------Strings------------------------------------
GLCDSTR?CBB macro Xin ,Yin ,Bin
MOVE?CB Xin , _gx
MOVE?BB Yin , _gy
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
GLCDSTR?CCB macro Xin ,Yin ,Bin
MOVE?CB Xin , _gx
MOVE?CB Yin ,_gy
MOVE?CB high (Bin), FSR1H ;load highbyte
MOVE?CB low (Bin), FSR1L ;load low byte
L?CALL GLCD_str_out
endm
GLCDSTR?BBB macro Xin ,Yin ,Bin
MOVE?B Xin, _gx
MOVE?B Yin, _gy
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
GLCDSTR?WBB macro Xin ,Yin ,Bin
MOVE?WB Xin, _gx
MOVE?BB Yin, _gy
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
GLCDSTR?WWB macro Xin ,Yin ,Bin
MOVE?WB Xin, _gx
MOVE?WB Yin, _gy
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
SSDC?C macro Cin
MOVE?CB Cin , _glcdData
L?CALL _cmd_byte
endm
SSDC?B macro Cin
MOVE?BB Cin , _glcdData
L?CALL _cmd_byte
endm
GLCD_CLR? macro
MOVE?CB 0, _gx
MOVE?CB 0, _gy
MOVE?CB _ssdwidth, _gx_
MOVE?CB _ssdheight, _gy_
L?CALL _glcd_clrxy
endm
GLCD_CLR?CCCC macro Xin ,Yin,X1in ,Y1in
MOVE?CB Xin, _gx
MOVE?CB Yin, _gy
MOVE?CB X1in, _gx_
MOVE?CB Y1in, _gy_
L?CALL _glcd_clrxy
endm
;----------------------Character @ X,Y ------------------------------------
GLCDC?BBB macro Xin ,Yin , Bin
MOVE?BB Xin, _gx
MOVE?BB Yin, _gy
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
GLCDC?WBB macro Xin ,Yin , Bin
MOVE?WB Xin, _gx
MOVE?BB Yin, _gy
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
GLCDC?WWB macro Xin ,Yin , Bin
MOVE?WB Xin, _gx
MOVE?WB Yin, _gy
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
GLCDC?BBC macro Xin ,Yin , Cin
MOVE?BB Xin, _gx
MOVE?BB Yin, _gy
MOVE?CB Cin ,_glcdCh
L?CALL _gcga
endm
GLCDC?WBC macro Xin ,Yin , Cin
MOVE?WB Xin, _gx
MOVE?BB Yin, _gy
MOVE?CB Cin ,_glcdCh
L?CALL _gcga
endm
GLCDC?CCC macro Xin ,Yin ,Cin
MOVE?CB Xin , _gx
MOVE?CB Yin, _gy
MOVE?CB Cin, _glcdCh
L?CALL _gcga
endm
GLCDC?CCB macro Xin ,Yin ,Bin
MOVE?CB Xin , _gx
MOVE?CB Yin, _gy
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
GLetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
movlw High Label ; get high byte
movwf Wout + 1
BANKSEL 0
endm
IFDEF TBLPTRL
GLCD_Cstr_out
tblrd *+
movf TABLAT,w
bz GLCD_exit_Cstr_out ; EXIT ON Null char
CHK?RP _glcdCh
MOVWF _glcdCh
CHK?RP _glcd_bigaddress
movff TBLPTRU,_glcd_bigaddress
movff TBLPTRH,_glcd_bigaddress+1
movff TBLPTRL,_glcd_bigaddress+2
L?CALL _gcga
CHK?RP _glcd_bigaddress
movff _glcd_bigaddress ,TBLPTRU
movff _glcd_bigaddress+1 ,TBLPTRH
movff _glcd_bigaddress+2 ,TBLPTRL
bra GLCD_Cstr_out
GLCD_exit_Cstr_out
BANKSEL 0
return
GLCD_str_out
movf POSTINC1, W ; Get a character
bz GLCD_exit_strout ; EXIT ON Null char
CHK?RP _glcdCh
MOVWF _glcdCh
BANKSEL 0
L?CALL _gcga
bra GLCD_str_out
GLCD_exit_strout
BANKSEL 0
return
ELSE
GLCD_str_out
IFDEF BSR
MOVIW FSR1++ ; Get a character
BTFSC STATUS,Z
BRA GLCD_exit_strout ; EXIT ON Null char
ELSE
movf INDF, W ; Get a character
BTFSC STATUS,Z
GOTO GLCD_exit_strout ; EXIT ON Null char
INCF FSR,F
ENDIF
CHK?RP _glcdCh
MOVWF _glcdCh
MOVE?BB FSR1L,_glcd_bigaddress
MOVE?BB FSR1H,_glcd_bigaddress+1
BANKSEL 0
L?CALL _gcga
MOVE?BB _glcd_bigaddress,FSR1L
MOVE?BB _glcd_bigaddress+1,FSR1H
GOTO GLCD_str_out
GLCD_exit_strout
BANKSEL 0
return
ENDIF
endasm
glcd_bigaddress VAR BYTE[3]
glcd_buff VAR BYTE[32]
BIG_TEXT var byte
glcd_rad var word
glcdCh var byte 'chr DATA
glcdData VAR byte 'DATA
glcdBC VAR word 'gca var
glcdDC VAR BYTE 'gca var
glcdFont var word 'font address
glcdOffset VAR word 'font offset
glcdbm VAR word 'bitmap offset
gl var byte 'width/height
gy var byte 'gca pg address
gy_ var byte 'gca pg address
gx var byte 'gca row address
gx_ var byte 'gca row address
GRX var byte 'DATA
ctemp var word
ctemp1 var word
ssd_add var byte
glcdStrAddr var word ext
@glcdStrAddr = _glcd_bigaddress
GlcdUnpackStr:
readcode glcdStrAddr,CTEMP
glcd_bigaddress[2] = CTEMP&$7f
ctemp=ctemp<<1
glcdCh = CTEMP.HIGHBYTE
glcdStrAddr=glcdStrAddr+1
if glcdCh then
gosub gcga
glcdCh = glcd_bigaddress[2]
else
return
endif
if glcdCh then
gosub gcga
else
return
endif
goto GlcdUnpackStr:
return
glcd_init:
#ifdef hwi2c
SSPSTAT = 0 'High Speed Filter
SSPADD = $13'400 kHz @32 MHz
SSPCON1 = %00101000 'I2C Master Mode Enable
' SSPCON3 = 0
#endif
@ GLetAddress _font7x5,_glcdFont
ssd_add = sdd1306_addr
SSDc $AE ' Display OFF
SSDc $d5
SSDc $80
SSDc $a8 : SSDc $3f
SSDc $D3 : SSDc $00 ; Set Display Offset Mode Set 0
if ssdheight > 3 then
SSDc $40 ' Set display start line 0
else
SSDc $60 ' Set display start line 4
endif
SSDc $8D : SSDc $14 ' Set Charge Pump Internal
SSDc $20 : SSDc $00 ' Adressing mode Horizontal
SSDc $A1 ' set segment remap column 127 as start
SSDc $C8 ' Com Scan Direction, Flip display vertically
SSDc $DA ' set COM pins
if ssdheight > 3 then
SSDc$12 ' set COM pins = 128x64=$12
else
SSDc$02 ' set COM pins = 128x32=$02
endif
SSDc $81 : SSDc$7F ' Set brightness to $01 to $FF ($7F is default, $01 is faint)
SSDc $DB : SSDc$40 ' Set VCOM Deselect Level
SSDc $B0 ' Set Page Address From $B0 to $B7
SSDc $2e ; scroll off
SSDc $A4 ' display ON continue
SSDc $A6 ' $A6=NORMAL MODE; $A7=INVERSE MODE
SSDc $AF ' Display ON
return
xyx: ;draw HORIZ LINE @X,Y for W len 0<X>127 1<W>127
FOR GRX = 0 TO 31
glcd_buff[GRX] = glcdData ;uses this var to set which bit/s is used to generate line
NEXT
gx = gx&ssdwidth
gx_= gx + gl
gy = gy&ssdheight
gy_= gy
gosub setxy
GRX = gl/32
glcd_rad = 32
WHILE GRX
gosub ssd_data
GRX = GRX-1
WEND
glcd_rad = gl//32
IF glcd_rad THEN
gosub ssd_data
ENDIF
return
xyy: ;draw VERT LINE @X,Y for W len @X 0<X>127 1<W>7
FOR GRX = 0 TO ssdheight
glcd_buff[GRX] = 255
NEXT
gx = gx&ssdwidth
gx_= gx
gy = gy&ssdheight
gy_= gy+GL
gosub setxy
glcd_rad = gl
gosub ssd_data
return
glcd_clrxy: ' clear area x1y1 to x2 y2
FOR GRX = 0 TO 31
glcd_buff[GRX] = 0
NEXT
CTEMP = (1 + GX_ - GX)*(1 + GY_ - GY)
gosub setxy
GRX = CTEMP/32
glcd_rad=32
WHILE GRX
gosub ssd_data
GRX = GRX-1
WEND
glcd_rad = CTEMP//32
IF GRX THEN
gosub ssd_data
ENDIF
return
gcga: ;draw a chr
GY = gy&ssdheight
GY_= gy + BIG_TEXT
gx = gx&ssdwidth
#ifdef PIC16
glcdOffset = (glcdch-32)*3 + glcdFont ; point to cga data
#ELSE
glcdOffset = (glcdch-32)*6 + glcdFont ; point to cga data
#ENDIF
gosub unpack
IF BIG_TEXT THEN
GOSUB SSD_BIG
glcd_rad = 24
gx_= gx + 11
ELSE
glcd_rad = 6
gx_= gx + 5
ENDIF
gosub setxy
gosub ssd_data
gx = gx_+ 1 + BIG_TEXT
IF GX > 121 THEN gx=0 ;wrap
return
ssd_data: ;send data block
#ifdef hwi2c
glcdBC=0
SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit
WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
SSPBUF = ssd_add ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPBUF = $40 ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
while glcdBC < glcd_rad
SSPBUF = glcd_buff[glcdBC] ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
glcdBC=glcdBC+1
wend
SSPCON2.2 = 1 ; PEN - send stop bit
While SSPCON2.2 = 1 : Wend ; Wait for SSP to complete
#else
i2Cwrite SDA,SCL,ssd_add,[$40,str glcd_buff\ glcd_rad]
#endif
return
#ifndef PIC16
ssd_bitmap: ;send graphic block from flash
gosub setxy
glcdBC=0
SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit
WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
SSPBUF = ssd_add ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPBUF = $40 ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
while glcdBC < glcd_rad
readcode glcdbm+glcdBC,CTEMP
SSPBUF = ctemp.LOWBYTE ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPBUF = ctemp.highBYTE ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
glcdBC=glcdBC+2
wend
SSPCON2.2 = 1 ; PEN - send stop bit
While SSPCON2.2 = 1 : Wend ; Wait for SSP to complete
return
#endif
SSD_BIG: ;create a big chr from a small one
for glcddc = 5 to 0 STEP -1
ctemp = 0
ctemp1 = 3
gL = glcd_buff[glcddc]
for glcdBc = 0 to 7
IF GL & 1 THEN ctemp = ctemp|ctemp1
ctemp1 = ctemp1<<2
GL = GL>>1
NEXT
gL = glcddc*2
glcd_buff[GL] =ctemp.LOWBYTE
glcd_buff[GL+1] =ctemp.LOWBYTE
glcd_buff[GL+12]=ctemp.HIGHBYTE
glcd_buff[GL+13]=ctemp.HIGHBYTE
NEXT
RETURN
unpack: ;unpack font from flash
for glcddc = 0 to 2
GL = glcddc<<1
readcode glcdOffset,CTEMP
#ifdef PIC16
glcd_buff[gl] = CTEMP&$7f
ctemp=ctemp<<1
glcd_buff[gl+1]= CTEMP.HIGHBYTE
glcdOffset = glcdOffset + 1
#else
glcd_buff[gl] = CTEMP
glcd_buff[gl+1]= CTEMP.HIGHBYTE
glcdOffset = glcdOffset + 2
#endif
next
return
cmd_byte: 'send command sequence "glcdData "
#ifdef hwi2c
;hw i2c
SSPCON2.0 = 1 ; SEN - Start Condition Enable Bit
WHILE SSPCON2.0 = 1 : WEND ; Wait for Start to complete
SSPBUF = ssd_add ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPBUF = 0 ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPBUF = glcdData ; Move data to SSPBUF
WHILE SSPSTAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress
While SSPCON2.6 = 1 : WEND ; Wait for Acknowledge from slave
SSPCON2.2 = 1 ; PEN - send stop bit
While SSPCON2.2 = 1: Wend ; Wait for SSP to complete
#else
;soft i2c
I2Cwrite SDA,SCL,ssd_add,[0,glcdData]
#ENDIF
return
setxy: ;set PAGE WINDOW
SSDc $22
SSDc gy
SSDc gy_
SSDc $21
SSDc gx
SSDc gx_
return
overglcd :
Bookmarks