No announcement yet.

Help with Custom Images AND Fonts with uOLED-128G2

  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with Custom Images AND Fonts with uOLED-128G2

    Hello! I currently have my uOLED-128G2 display configured in serial mode paired with an Arduino Uno. I have a set of images on the SD card that I'm using. I've decided I also want to include a third party font. The instructions on 4D-AN-00084 demonstrate copying the font using Visi which appears to overwrite the contents of my SD card. I used the Graphics Composer to copy the images (RAW) to the SD card.

    Can someone point me in the right direction to get my images and necessary files for fonts to the SD card?

    Thanks in advance.

  • #2
    Hi tdub,

    These application notes might help you with copying the images you want in the SD card (RAW) for Goldelox.

    Serial Displaying Images from the uSD Card RAW

    ViSi Displaying Images from the uSD Card - WYSIWYG RAW

    Designer Displaying Images from the uSD Card - RAW

    You might want to try and use those App Notes in conjunction with the 'Font' App note to be able to copy both of the type of files you need.

    Best Regards,


    • #3
      Regarding AN-00061 ViSi Displaying Images from the uSD Card – WYSIWYG RAW....

      How can I control the order of the image files written to the SD card? I’m using uOLED-160-G2

      I have a series of six images that I would like to have stored on the SD card three times sequentially and in the same order. The first series will be images at full brightness, then second series will be identical except slight darkening with 85% transparent black mask, then third series identical to first with 70% transparent black mask.

      The reason is to allow for use in very low light with gfx_Contrast(3) since (2) and below is essentially screen off.

      So when I set my brightness variable to 2 or 1, I want to make my software keep
      gfx_Contrast(3), but then just add to the first series image location offset so that either the second or third series image is picked instead of the first series full brightness ones.

      Basically I want to treat the images like a 6x3 array.

      Since my image files are all identical size I'm hoping to have simple additional offset to access either the 85% or 70% bright image as needed.

      However I cannot do this unless I can control the exact order they are written to the SDcard.

      Hopefully the logic of workshop image writing is known and can be controlled! Thanks
      Last edited by db2wings; 7 October 2019, 08:05 PM.


      • #4

        How can I control the order of the image files written to the SD card? I’m using uOLED-160-G2
        To show the image, you only need to specify the address where it is located. As you can see on the application note, it is located on the file.

        If you are using the 'Image Widget', select the image and click paste code. This will allow you to display the image on the display.

        However, you can also use the 'User Images' widget and store the six images you have. Select the image and click the 'Paste' code.
        Change the 'frame' to navigate which picture did you want to show.

        I hope this helps.

        Best Regards,


        • #5
          Thanks for the reply, but I think you misunderstood my question. Maybe I need to clarify that I’m running the uOLED-160-G2 display in serial mode using an Arduino board. I don’t think it matters to our discussion though.

          I need to be able to control what ORDER the images are written to the SDcard by Workshop when I create and compile my Visi project.

          Why? For discussion say I have 9 identically sized images called: A1, B1, C1, A2, B2, C2, A3, B3, & C3.

          The _3 images are unmasked full bright A,B &C images. The _2 images are 15% masked with black to darken them. Then finally the _1 images are 30% masked with black to darken them even further.

          Now If they are written on the SDcard in that exact order listed above then I can figure out the relative offset from A1 to A2 and that it should be the same as the offset from B2 to B3 etc for each of similar “paired” images. I would assign that relative address offset to constant variable called ”RAO”.

          This would then allow me to have six variables (HiA, LoA, HiB, LoB, HiC & LoC) that I initially load with the HIword & LOword addressees of A3, B3, C3, the brightest images from the

          Then if the user selects a brightness level of 3 or more, the program will set gfx_Contrast(3) or higher and use
          combinations of:

          media_SetAdd(HiA, LoA);
          media_Image(x, y);

          to show the unmasked images.

          Then if the user selects a brightness level of 2, the program will set gfx_Contrast(3) as the lowest contrast level it will set, but then
          go to a lower brightness level by decrementing the HiA, LoA, HiB, LoB, HiC & LoC variables by subtracting RAO from them.

          then whenever the
          media_SetAdd(HiA, LoA);
          media_Image(x, y);

          is called the screen stays at contrast level 3, but now
          the media_SetAdd(HiA, LoA); points to the A2 image which is 15% darker than the A3 image.

          If the user sets brightness to 1, then we subtract RAO from the HiA, LoA, HiB, LoB, HiC & LoC variables once again
          to set the pointers to the _1 images which are 30% darker than the A3 images.

          Conversely when brightness level is set back up to higher levels, the HiA, LoA, HiB, LoB, HiC & LoC variables are incremented by RAO each time until the full brightness _3 images are used once again.

          To accomplish this procedure above, I need to understand how the image order on the SDcard is set by the workshop app so I can control what ORDER they are written

          Is it such that when you start a new project that the image files are written to the SDcard in the order that the widgets are created, or is it reverse, or is it alphanumeric by name, or alphanumeric order by alias, or sorted by file size or something else?

          I know I could do this another way, most likely with an array of the actual adreeses being assigned to the HiA, LoA, HiB, LoB, HiC & LoC variables but I thought this might be an efficient way if I could get the files written in the needed order.

          Thanks again for the help!
          Last edited by db2wings; 9 October 2019, 05:59 PM.


          • #6

            Thank you for the detailed explanation.

            Can I ask, how is the image placed on the screen? Does the 9 pictures placed on top of each other? Or it is grouped by three's (A, B, C) ?
            If you are using the User Image, you will only need to change the framenumber to navigate to the image on the widget. You can do it like this:
            media_Init(); // initialize the uSD card
            media_SetAdd(iUserimages1H, iUserimages1L); // set the address - the constants
            media_VideoFrame(x, y, [B]framenumber[/B])// change the videoframe
            However, to answer the question the order in which they are placed on the uSD card, depends on the 'Image' widget, as it is indexed from 1 to x (iImage1, iImage2 ...). So the picture placed on the 'iImage1' will be the first in order.

            Best Regards,


            • #7
              Ok thanks for the answer I think that gives me enough to work with, I’ve been changing the name and the aliases of each image to make things more sensical to me, but I’ll let them stay with default names and see what order comes out. Assuming I’m understanding what your wrote of course.

              Click image for larger version

Name:	88F8ADF0-EFBB-49FD-B6AE-4E061D899B3F.jpeg
Views:	202
Size:	768.1 KB
ID:	69896
              Last edited by db2wings; 10 October 2019, 01:35 PM.


              • John Kevin
                John Kevin commented
                Editing a comment
                Basically yes. Even if you rename the Image Widget, the first Image object that you put in the WYSIWYG area will be the first on order. You could also test this, compile the project and check the file

            • #8
              I eventually found a better way to accomplish what I was trying to do by putting all the SD card image offsets into a two dimensional array. I figured I had to have all those offsets in memory might as well have them arranged in usable order. Its a lot of editing work to create the array and not allow typos to ruin it, and its a pain to make changes to the visi file because re-write of the SDcard triggers a totally new array needing to be built. But otherwise it works great!

              I also created an array of image locations to enable easier placement of images on the screen where needed.

              // Eventually I plan to run two screens, so in the following
              // code example I have declared my first screen for
              // software serial as follows:
              // pin 2 = TX of display, pin 3 = RX // create instance of SoftwareSerial called "DisplaySerial1"
              SoftwareSerial DisplaySerial1(TX_PIN_SCREEN1,RX_PIN_SCREEN1);
              //Create instance of Goldelox_Serial_4DLib class called "Display1" using pointer to DisplaySerial1
              Goldelox_Serial_4DLib Display1(&DisplaySerial1);
              // OLED contrast level controls screen brightness. 0 is off, 1-2 is too dark
              // to see and essentially off also. Thus useable levels are 3-15 for brightness level.
              // I need to have a dimmer display than contrast level 3 which is still quite bright.
              // To accomplish this have global variable called brite_level.For brite_levels from 3-15
              // I just use Display1.gfx_Contrast(brite_level);
              // but brite_level or 2 or 1 I set gfx_Contrast(3); I then use dimmer images
              // that have been masked with 20% black and 40% black.
              // The following is scheme is used to manage and display images at the proper masking level:
              // brite_level 3-15 = Display1.gfx_Contrast(brite_level); using full bright non-masked image
              // brite_level 2    = Display1.gfx_Contrast(3); using 20% black masked image
              // brite_level 1    = Display1.gfx_Contrast(3); using 40% black masked image
              int  brite_level = 6;   // initial contrast level
              // Image array package - array of word variables, for SDcard image offsets
              // images as follows where the dimmest version of an image 40% black
              // mask has the location of its HIGH address as the 0 first item in that row
              // the second dimmest with 20% black mask is the 1 second entry
              // and full brite image with no mask is 2 or third entry.
              // Thus offsets are ordered as follows for each image:
              // 40black_H, 20black_H, Noblack_H, 40black_L, 20black_L, Noblack_L
              word img_pkg[16][6]=
                  {0x0004,0x0003,0x0003,0x3000,0x3000,0x3000}, // 0    splash
                  {0x0001,0x0001,0x0001,0x5C00,0x7A00,0x9800}, // 1    n2tail
                  {0x0001,0x0001,0x0001,0xB600,0xD400,0xF200}, // 2    n6tail
                  {0x0002,0x0002,0x0002,0x1000,0x2000,0x3000}, // 3    cautionflash
                  {0x0002,0x0002,0x0002,0x4000,0x5000,0x6000}, // 4    caution
                  {0x0002,0x0002,0x0002,0x7000,0x8000,0x9000}, // 5    warnflash
                  {0x0002,0x0002,0x0002,0xD000,0xE000,0xF000}, // 6    warn
                  {0x0002,0x0002,0x0002,0xA000,0xB000,0xC000}, // 7    hydpump
                  {0x0003,0x0003,0x0003,0x0000,0x1000,0x2000}, // 8    geardown
                  {0x0003,0x0003,0x0003,0xD200,0xE200,0xF200}, // 9    gearnup
                  {0x0003,0x0004,0x0004,0x0200,0x4200,0x5200}, // 10    hivolts
                  {0x0004,0x0004,0x0004,0x1200,0x2200,0x3200}, // 11    lovolts
                  {0x0005,0x0004,0x0004,0x2200,0xC200,0x6200}, // 12    bigwarnflash
                  {0x0005,0x0005,0x0006,0x8200,0xE200,0x4200}, // 13    bigwarn
                  {0x0006,0x0007,0x0007,0xA200,0x0200,0x6200}, // 14    bigcautionflash
                  {0x0007,0x0008,0x0008,0xC200,0x2200,0x8200}  // 15    bigcaution
              // image locations - two dimensional array of ints for image display location
              // format is coordinates to display at and size of image. x, y, w, h
              int img_loc[10][4] =
              {0,0,160,128}, //0 whole screen
              {0,0,160,23},  //1 Top_banner
              {0,25,78,24},  //2 One_L
              {82,25,78,24}, //3 One_R
              {0,51,78,24},  //4 Two_L
              {82,51,78,24}, //5 Two_R
              {0,77,78,24},  //6 Three_L
              {82,77,78,24}, //7 Three_R
              {0,103,160,24},//8 Bottom_banner
              {0,25,160,76}  //9 Alert
              // heres function to display images
              void Pop_Message(int img_num,int loc_num)
                  int c =  brite_level; if (brite_level>=3) c = 3; // possible c values are now 1,2 or 3
                  // generic format of next line... Display1media_SetAdd(image1H, images1L); to set the address
                  Display1.media_SetAdd(img_pkg[img_num][c - 1],img_pkg[img_num][c + 2]);    // point to proper H & L addresses of  img_num
                  // generic format of the next line...Display1.media_Image(x,y); where x,y is location on screen
                  Display1.media_Image(img_loc[loc_num][0],img_loc[loc_num][1]);  // set x,y based on loc_num
              // here's function to erase an image location
              void Erase_Message(int loc_num)
                      //image locations - two dimensional array of ints for image display location coordinates and size of screen x, y, w, h
                  // generic call for next line...Display1.gfx_RectangleFilled(x1,y1,x2,y2,color) using values contained in img_loc[ ][ ]
              Here's a crappy cell-phone pic of the screen display, in person the colors are much better looking. The bottom line is debugging, with brite_level =2, showing gfx_Contrast(3) and using the "2" images which are 20% black mask

              Click image for larger version  Name:	uOLED-160G2_screenshot.jpg Views:	0 Size:	29.3 KB ID:	70073
              Below is sample code that would generate the messages in the screenshot shown above. I've omitted the code for printing the variables at the bottom.
              Erase_Message(0); // clear the screen with ERASECOLOR = black
              Pop_Message(1,1); // show top banner - aircraft "N" number and ICAO type
              Pop_Message(4,2); // caution message
              Pop_Message(6,3); // warning message
              Pop_Message(11,4); // lo volts message
              Pop_Message(9,5); // gear up message
              Pop_Message(7,6); // hydraulic pump message
              Pop_Message(8,7); // gear down message
              Display1.gfx_RectangleFilled(0,25,159,127,0x4A69) // 77Gray box at bottom banner location
              BTW here's a great website which converts colors into RGB565 code to use on this display
              for example the 0x4A69 in last line of above code is red=77 green=77 blue-77 GRAY
              Last edited by db2wings; 26 October 2019, 06:54 AM.


              • John Kevin
                John Kevin commented
                Editing a comment

                I am glad that you managed to sort this out. Thank you for sharing your code and your ideas.

                Best Regards,

            • #9

              I really appreciate the help you guys provide on the forum. In the beginning, since I'm not a trained programmer or computer scientist, it was tough learning how to use your displays and it took lots of time and reading, but now that I understand them I think they're great! I like that the three processors are mostly similar in how they work, except for the Goldelox not being able to read FAT file system on the SDcard.


              • John Kevin
                John Kevin commented
                Editing a comment

                Sure, no problem. We are all trying to learn something here. At first, it may be a little difficult to follow, however, repetitively doing the tasks will surely benefit you greatly. We also thank you for the feedback. We do appreciate your post as well.

                Best Regards,