datacute / Tiny4kOLED

Library for an ATTiny85 to use an SSD1306 powered, double buffered, 128x32 pixel OLED, over I2C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Little Bug in SSD1306Device::bitmap

Seifenhase opened this issue · comments

Hi,
I found a little bug in the function "SSD1306Device::bitmap".
The loops only count to 1 below the Y1 and X1 variables.
This distorts the bitmaps and the last band is missing.

void SSD1306Device::bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t bitmap[]) {
	uint16_t j = 0;
 	for (uint8_t y = y0; y < y1; y++) {
		setCursor(x0,y);
		ssd1306_send_data_start();
		for (uint8_t x = x0; x < x1; x++) {
			ssd1306_send_data_byte(pgm_read_byte(&bitmap[j++]));
		}
		ssd1306_send_stop();
	}
	setCursor(0, 0);
}

A +1 in the loops corrects the error.

void SSD1306Device::bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t bitmap[]) {
	uint16_t j = 0;
 	for (uint8_t y = y0; y < y1 +1; y++) {
		setCursor(x0,y);
		ssd1306_send_data_start();
		for (uint8_t x = x0; x < x1 +1; x++) {
			ssd1306_send_data_byte(pgm_read_byte(&bitmap[j++]));
		}
		ssd1306_send_stop();
	}
	setCursor(0, 0);
}

Thanks for the report.

I haven't actually used that method - but kept it from the code when I started enhancing it for my needs. It has probably only ever been called with x0 and y0 as 0, and the other two parameters treated as width and height.

Using "<=" instead of "+1" is probably slightly smaller and faster.

I'm considering changing the API instead so that x0 and y0 are not needed, but the current cursor position is used instead, and so that the cursor position after the loop is to the right of the bitmap.
The parameters would be the bitmap, and the width and height.
You could then call it in a loop with the same parameters to repeat the bitmap across the screen, saving one call to setCursor per call of the bitmap function.

Actually, I think that adding "+1" or using "<=" is not the right solution here. If bitmap is less than screen dimensions in size and the cursor position is (x0!=0;y0!=0), then the bitmap will just be truncated beyond x1 and y1 values. So the code should look like this:

void SSD1306Device::bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t bitmap[]) {
	uint16_t j = 0;
 	for (uint8_t y = y0; y < y0 + y1; y++) {
		setCursor(x0,y);
		ssd1306_send_data_start();
		for (uint8_t x = x0; x < x0 + x1; x++) {
			ssd1306_send_data_byte(pgm_read_byte(&bitmap[j++]));
		}
		ssd1306_send_stop();
	}
	setCursor(0, 0);
}