Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 16:04 24 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MM2, MM+: SSD1306 OLED loadable drivers updated

     Page 2 of 2    
Author Message
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 10:57am 03 Nov 2021
Copy link to clipboard 
Print this post

Sorry help needed.

When I clean and build I get these errors.





Any ideas please.

Please note,  I had to move Cfunctions.h up a folder level so it could be found otherwise there was a error for that as well.  Also in the code view there is a error that starg.h cannot be found.





Anthony.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8573
Posted: 11:07am 03 Nov 2021
Copy link to clipboard 
Print this post

Replace cfunction.h with attached


CFunctions.zip

Can't help with srdarg.h as that should be standard C
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 12:49pm 03 Nov 2021
Copy link to clipboard 
Print this post

stdarg.h was not a problem in the end.

Thanks for the updated cfunction.h, all has compiled fine.

I can now draw to every pixel on my OLED           using a fast Csub driver.

Step 2 is sending the contrast command and byte value.  With the all-Basic-driver you can access an internal routine of the driver (oled_write_command) to send it but am really not sure how you would get to an internal sub of a csub from MMbasic.  There are some other commands that can be sent that can scroll the screen vertically,  turn it on/off (saving the ram for when it comes back on) and inverse as well.  I'll keep looking but any help appreciated.


Anthony.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8573
Posted: 01:02pm 03 Nov 2021
Copy link to clipboard 
Print this post

  Quote  but am really not sure how you would get to an internal sub of a csub from MMbasic.


Change the main function so it takes an extra parameter. Use this to decide the function you want to use. init, sendcommand, senddata

Below is the main function for the SD CFunction as an example

void main(long *mode, char *p1, long *p2, long *p3, long *p4){
       char fn[16];
       int j,k,l,m,nextsector, loopend;
       DWORD secstart,secoffset;
       FATFS *FatFs;
       DIR *DIRFS;
       FILINFO *fileinfo;
       char *s, *p;
#ifndef useSPI2
       CFuncRam[17]=SPIBRG; //save any user SPI setup
       CFuncRam[18]=SPICON;
       CFuncRam[19]=SPICON2;
#endif
if(ExtCurrentConfig[Option->SDCARD_CS] == EXT_BOOT_RESERVED){
       SPICON=0x8260;
       SPICON2=0xC00;// this is defined in IOPorts.h
       SPIBRG=Option->pins[0];
}
       FatFs=(void*)&CFuncRam[20];
       DIRFS=(void*)&CFuncRam[30];
       fileinfo=(void*)&CFuncRam[40];
       if(*mode==1 || *mode==6 || *mode==7 || *mode==4) {
           for(l=0;l<=p1[0];l++)fn[l]=p1[l];
           fn[p1[0]+1]=0;
           if(*mode==6)ClearProgram();
       }



       if(*mode==1 || *mode==6 || *mode==7 || *mode==4){//initialise and mount the SDcard
           if(ExtCurrentConfig[Option->SDCARD_CS] != EXT_BOOT_RESERVED)errstring(FR_NOT_MOUNTED);
           if(ExtCurrentConfig[SPI_OUT_PIN] != EXT_BOOT_RESERVED) {
               ExtCfg(SPI_OUT_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_OUT_PIN, EXT_RESERVED, 0);
               ExtCfg(SPI_INP_PIN, EXT_DIG_IN, 0); ExtCfg(SPI_INP_PIN, EXT_RESERVED, 0);
               ExtCfg(SPI_CLK_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_CLK_PIN, EXT_RESERVED, 0);
           }
           SPI_PPS_OPEN;
           SPICON=0x8260;
           SPICON2=0xC00;// this is defined in IOPorts.h

           filepos=0;
           errstring(pf_mount(FatFs));
       }
       if(*mode==1){ //open a file
           errstring(pf_open(FatFs,&fn[1]));
       }
       if(*mode==2 ){ //read a file
           if(*p2>=0){
               errstring(pf_lseek(FatFs,*p2));
           }
           if(*p3<256){ //return as a string
               errstring(pf_read(FatFs,p1+1,*p3,&j ));
               p1[0]=j;
           } else {
               errstring(pf_read(FatFs,p1,*p3,&j ));
           }
           *p4=j;

       }
       if(*mode==3){
           if(*p2<0)*p2=filepos;
           filepos+=*p3;
           secstart= *p2 & 0xFFFFFE00; //point to sector start
           secoffset= *p2 & 0x1FF; //offset into the sector
           errstring(pf_lseek(FatFs,secstart));
           s=p1; if(*p3<256) s=p1+1; //move past the length byte if a string
           if(secstart!=*p2){ //not sector aligned
               p=GetTempMemory(512);
               errstring(pf_read(FatFs,p,512,&j ));
               errstring(pf_lseek(FatFs,secstart));
                   //read OK
                   if(512 < *p3+secoffset){
                       loopend=512;
                       nextsector=*p3+secoffset-512;
                   } else {
                       loopend=*p3+secoffset;
                       nextsector=0;
                   }
                   for(k=secoffset;k<  loopend ;k++){
                       p[k]=s[k-secoffset]; //write the new data into the buffer
                   }
                   errstring(pf_write(FatFs,p,j,&j ));
                   *p4=j-secoffset;
                   if(*p4>*p3)*p4=*p3;
                   if(nextsector){
                       errstring(pf_write(FatFs,s+(*p3-nextsector),nextsector,&j ));
                       *p4+=j;
                   }
                   errstring(pf_write(FatFs,0,0,&j )); //finish the write

           } else {
               errstring(pf_write(FatFs,s,*p3,&j ));
               *p4=j;
               errstring(pf_write(FatFs,0,0,&j ));
           }
           
       }
       if(*mode==4){
            errstring(pf_opendir(FatFs,DIRFS,&fn[1]));
       }
       if(*mode==5){
          errstring(pf_readdir(FatFs,DIRFS,fileinfo));
          if(fileinfo->fattrib==22){
              errstring(pf_readdir(FatFs,DIRFS,fileinfo));
          }
          if(fileinfo->fname[0]!=0){
               k=1;
               if(fileinfo->fattrib & 0x10){
                   p1[1]='<';
                   p1[2]='D';
                   p1[3]='i';
                   p1[4]='r';
                   p1[5]='>';
                   k=6;
               }
               for(j=0;j<12;j++)p1[j+k]=fileinfo->fname[j];
               p1[0]=mystrlen(fileinfo->fname)+k-1;
          } else p1[0]=0;
       }
       if(*mode==6){//load program from SDcard
           s=p=GetTempMemory(51200);
           k=1;
           l=0;
           errstring(pf_open(FatFs,&fn[1]));
           errstring(pf_lseek(FatFs,0));
           do {
               errstring(pf_read(FatFs,s,128,&j));
               for(m=0;m<j;m++){
                   if(s[m]==0 && k){
                       j=m;
                       k=0;
                   }
               }
               s+=j;
               l+=j;
           } while(j==128);
           p[l]=0;
           p[l+1]=0;
           SaveProgramToFlash(p,0);
       }
       if(*mode==7){ //save program to SDcard
           errstring(pf_open(FatFs,&fn[1]));
           errstring(pf_lseek(FatFs,0));
           char *b=GetTempMemory(256);
           char *p=(void *)ProgFlash;
           while(!(*p == 0 || *p == 0xff)) {                               // normally a LIST ends at the break so this is a safety precaution
               if(*p == 1) {
                   p = llist(b, p);                                        // otherwise expand the line
                   k=mystrlen(b);
                   b[k++]=13;
                   b[k++]=10;
                   errstring(pf_write(FatFs,b,k,&j ));
                   if(p[0] == 0 && p[1] == 0) break;                       // end of the listing ?
               }
           }
           b[0]=0;
           b[1]=0;
           errstring(pf_write(FatFs,b,2,&j ));
           errstring(pf_write(FatFs,0,0,&j ));
       }
       if(*mode==0){
           Option->SDCARD_CS=*p1;
           if(p2!=NULL){
               Option->pins[0]=*p2;
           } else {
               Option->pins[0]=2;
           }
           if(ExtCurrentConfig[Option->SDCARD_CS] != EXT_BOOT_RESERVED){
               ExtCfg(Option->SDCARD_CS,EXT_DIG_OUT,0); ExtCfg(Option->SDCARD_CS,EXT_BOOT_RESERVED,0);
           }
           PinSetBit(Option->SDCARD_CS, TRISCLR);    
           PinSetBit(Option->SDCARD_CS, LATSET);    
       }

#ifndef useSPI2
       SPIBRG=CFuncRam[17];  //restore user (or my) setup
       SPICON=CFuncRam[18];
       SPICON2=CFuncRam[19];
#endif      
}

Edited 2021-11-03 23:02 by matherp
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 08:21am 04 Nov 2021
Copy link to clipboard 
Print this post

Thanks again Peter.

I can now send a command byte, and associated data byte where required, to my 1.3" 12C SH1106 from mmbasic via the loadable driver.

In this video mmbasic only draws the initial Hello World screen and then the rest is done via commands to the OLED.

You can change the
Contrast (0 - 256 but 0 is not black)
Turn screen off/on (preserving the ram memory for instant on)
Inverse the display
and
Scroll vertically up or down.  The screen wraps around.

Particularly with the contrast and on/off functions I will now be able to significantly reduce the burn-in that I have experienced with these screens.  

Cheers,
Anthony.

Video is a link to a MS One drive file.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8573
Posted: 08:25am 04 Nov 2021
Copy link to clipboard 
Print this post

Nice job - always great to see someone getting to grips with CFunctions so effectively. Please do post your code for others to see and use
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 08:58am 04 Nov 2021
Copy link to clipboard 
Print this post

I don't know if I have fully got to grips with cfunctions however I was able to make some changes and managed to compile them.  Works for me but I have had a couple of CPU exceptions from MMbasic particularly when first copying a new version of the driver.  Seems to settle.  Probably can be done better, hope it works for somebody else - no guarantee or warranty.

I have added a parameter that is passed to the driver to control its mode.
sh1106ext(x,i2c addr,pin,pin,height,rot)
0  intialise lcd, eg sh1106ext(0,&h3c,15,16,64,1)
1  write 1 byte to Oled  eg sh1106ext(1,&h3c,&hae) - turn off
2  write 2 bytes to Oled  eg sh1106ext(2,&h3c,&h81,&h7f) - set contrast

AE/AF Screen on / off
81 is contrast with data of 00 - FF or 0 -255
40-7F is screen offset
A6/A7 is Normal/Inverse




Previously to solve the 2 pixel offset I had I simply added 2 to x in this sub.

void OLED_setxy(int x,int y){
 x+=2 ; //move right 2 bytes
 oled_write_command(0xB0+y)        ; //set page address
 oled_write_command(0x10 | ((x>>4) & 0x0F))  ; //set high col address
 oled_write_command(x & 0x0f)     ; //set low col address


Library save it,  you can get CPU Exceptions if used in normal program memory.
SH1106ext.zip

Let me know if it works for you.
Anthony.
Edited 2021-11-06 17:24 by ajkw
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024