'**************************************************************** '* Name : ssd1306_I2C.INC * '* Author : richard * '* Notice : * '* : * '* Date : 19/11/2017 * '* Version : 1.0 * '* Notes : * '* :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 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 ERROR STR CONSTANTS ONLY SUPPORTED ON PIC18 ENDIF 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 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 byte glcdCh var byte 'chr DATA glcdData VAR byte 'DATA glcdBC VAR BYTE 'gca var glcdDC VAR BYTE 'gca var glcdFont var word 'font address glcdOffset VAR word 'font 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 glcd_init: #ifdef hwi2c SSPSTAT.7 = 0 'High Speed Filter SSPADD = 6 '2666 kHz @64 MHz SSPCON1 = %00101000 'I2C Master Mode Enable #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] = 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 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 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 :