I assume you understand how to create the I2C byte sequence for the SSD1306 but I'll repeat it anyway: The SSD1306 distinguishes between commands (incl. command parameters) and data (pixel data). With SPI, it uses a dedicated input pin to distinguish commands and data.
With I2C, 0x80 needs to be prepended to each command byte. 0x40 switch to data mode. The data mode continues until the end of the I2C transaction (indicated by a STOP condition).
To update a part of the screen, the start address of the top left corner has to be set and then the data can be sent. A valid byte sequence for starting at the coordinates (20, 16) for x and y looks like this:
0x80, 0xb1, // page start address: 0xb0 | (y >> 3)
0x80, 0x04, // lower nibble of column: 0x00 | (x & 0x0f)
0x80, 0x11, // upper nibble of column: 0x10 | ((x >> 4) & 0x0f)
0x40, // switch to data mode
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, ... // pixel data
The memory is divided into pages. Each page covers 8 pixel rows. So you can only update stripes of 8 vertical pixels and the stripes must be aligned to multiples of 8. As you can see in the first line of the byte sequence, the lower 3 bits of y are simply discarded.
The horizontal start position is provided in two parts: the upper and lower nibble. A nibble is four bits, i.e. half a byte. See lines 2 and 3 above.
The remaining two lines switch to data mode and send the pixel data. With each byte, the address advances by 1, i.e. it advances horizontally from left to right and each byte written affects a vertical piece of 8 pixels.
With the different addressing modes (command 0x20 to 0x22), you can determine how the address advances at the end of page, at the end of your update area etc. The simplest approach is to write to each page separately and to explicitly set the address the beginning of each page.
Note that there are clones of the SSD1306 chips that do not support the different addressing modes.
Always start with the Data sheet for the device and read
https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
See 8.3 Oscillator Circuit and Display Time Generator
The screen your showing looks to be the wrong resolution or the clock frequency has been set incorrectly.
I would say it is in the initialisation that you have a problem, maybe the wrong number entered or you have failed to initialise something as simple as not initialising the divide ratio for the clock.
I would recheck you code and make sure everything was initialised correctly.
Best Answer
This layout makes it extremely easy to display 8 lines of text on the display -- an 8-pixel-high character font can be stored as a sequence of 8-bit values to be written to the display. This display mode has the advantage of making it easy to draw text at any horizontal position, allowing for the easy use of variable-width fonts. (A layout which treated each byte as eight horizontal pixels would require bit-shifting and masking operations to draw text at horizontal positions not divisible by 8.)
The main disadvantage of this layout is that it makes it difficult to draw text or graphics at arbitrary vertical positions. However, this is an acceptable limitation for many applications.