'**************************************************************** '* 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,X1,Y1 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 USERCOMMAND "GLCD_BAR" ;clear/SET area x,y,X1,Y1,COLOUR 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 ;----------------------CLR AND BARS ------------------------------------ GLCD_CLR? macro MOVE?CB 0, _gx MOVE?CB 0, _gy MOVE?CB 0,_glcdData MOVE?CB _ssdwidth, _gx_ MOVE?CB _ssdheight, _gy_ L?CALL _glcd_clrxy endm GLCD_CLR?CCCC macro Xin ,Yin,X1in ,Y1in MOVE?CB 0,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?CB X1in, _gx_ MOVE?CB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCCCC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?CB X1in, _gx_ MOVE?CB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCBBC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?BB X1in, _gx_ MOVE?BB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCWBC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?WB X1in, _gx_ MOVE?BB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCBWC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?BB X1in, _gx_ MOVE?WB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCWWC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?WB X1in, _gx_ MOVE?WB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCCBC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?CB X1in, _gx_ MOVE?BB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCCWC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?CB X1in, _gx_ MOVE?WB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCBCC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?BB X1in, _gx_ MOVE?CB Y1in, _gy_ L?CALL _glcd_clrxy endm GLCD_BAR?CCWCC macro Xin ,Yin,X1in ,Y1in,Cin MOVE?CB Cin ,_glcdData MOVE?CB Xin, _gx MOVE?CB Yin, _gy MOVE?WB X1in, _gx_ MOVE?CB Y1in, _gy_ L?CALL _glcd_clrxy endm 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 0127 1127 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 0127 17 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] = glcdData 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 SSP1STAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress While SSP1CON2.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 SSP1STAT.2 = 1 : WEND ; SSPSTAT = 1 Transmit in progress While SSP1CON2.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 SSP1CON2.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 :