The SSD1306 as vector display/vectorscope, like the vectrex

i found out how to use the ssd1306 as vector display (and thanks to the youtuber @cnlohr for the idea!):

set the frequency to maximum.
set mux to 1
draw a line in the video ram from 0,0 to 63,63

now one can set the source line and destination line to draw a single pixel:

static void GfxApiVectorscopeDisplay(u8 x,u8 y)
{
      const u8 move_line[] = {0,
                          0xa8,1,0xd3,(y&63),0x40+(x&63)
      };
      os_i2c_write(move_line, sizeof(move_line));
}

when i draw fourier patterns with it it looks like this:

now i tried to draw a cube, and inserted a wait in my line function (to move the beam slower), here i draw this cube and keep increasing the delay, so the beam is slowing down:

how about battlezone?

5 Likes

Looks cool! Just wish I understood your latest experiments more… :sweat_smile:

this is so very simple:

this is in my framebuffer:

image

now i set the image height (mux) to 1, i get a 128x2 image

now i move the startline, and the offset, now select one of these 64 lines containing a single pixel, use the x coordinate for this and display at y.

now you can draw lines using commands without framebuffer, by moving this single point over the screen with a bresenham:


void GfxApiVectorScopeLine(int x1, int y1, int x2, int y2, int speed) {
    int dx = abs(x2 - x1);
    int dy = abs(y2 - y1);
    int sx = (x1 < x2) ? 1 : -1;
    int sy = (y1 < y2) ? 1 : -1;
    int err = dx - dy;
    u8 br=255;
    u8 sub=rand()&31;
    while (1) {
        GfxApiVectorscopeDisplay(x1, y1,br);
    
        br-=sub;
        if (x1 == x2 && y1 == y2) {
            break;
        }

        int e2 = 2 * err;
        if (e2 > -dy) {
            err -= dy;
            x1 += sx;
        }
        if (e2 < dx) {
            err += dx;
            y1 += sy;
        }
    }
}

when i switch my charge pump off before the start of a line i get a beautiful shading of the line:


  for(;;)
  {
   static u16 cnt;
   //cnt+=1; 
   if((cnt&0xff)==0)Serial.println(cnt);
      u8 x=sin(counter)*28+31;
     
      u8 y=sin(counter*1.1)*28+31;



      u8 x2=sin(counter*2.2)*28+31;
     
      u8 y2=sin(counter*2.3)*28+31;


      u8 x3=sin(counter*1.5)*28+31;
     
      u8 y3=sin(counter*1.6)*28+31;

GfxApiSetCharge(255);
   GfxApiVectorScopeLine(x,y,x2,y2,cnt);
GfxApiSetCharge(0);
      GfxApiVectorScopeLine(x2,y2,x3,y3,cnt);
GfxApiSetCharge(0);
   GfxApiVectorScopeLine(x3,y3,x,y,cnt);

;   
   counter+=0.01;
     adder+=0.0001;
     } 
}

fuzzing the undocumented register d1 while doing this gives intresting results:

1 Like

spacewar clock… and the flying points are back…

1 Like

writing to register 0xd2 has huge effects! (this can be done per “line/pixel”)