Coder Social home page Coder Social logo

tiny4koled's Introduction

Tiny4kOLED

This is a library for an ATTiny85 to use an SSD1306 powered, 128x64 pixel OLED, over I2C, with double buffering support for the common 128x32 sized screen.

The SSD1306 has enough RAM to support a 128 by 64 pixel display, and most SSD1306 controlled OLEDs are 128 by 64 pixels. However there are also other display sizes available. With a 128 by 32 pixel display, only half of the SSD1306's RAM is used, and the other half can be used as a frame buffer. This results in being able to have a slow ATTiny85 gradually update the display, then switch it into view when it is ready.

This library is an adaption of DigisparkOLED which in turn is a modification of the Tinusaur project's SSD1306xLED library. I have extensively re-written it, with the following changes:

  • Replaced digistump's Wire with TinyWireM (Digistump's Wire is a rename of TinyWireM, but Adafruit's includes a necessary bug fix.)
  • Fixed the sending of multiple bytes per I2C transmission.
  • Changed the initialization to be two I2C transmissions, instead of using a transmission per command byte.
  • Left the display off in the initialization, so that the display could be cleared before being shown.
  • Altered the library to be for a 128x32 display.
  • Added double buffering control code.
  • Exposed all of the SSD1306 features, with example code (in v1.2).
  • Optimised font usage, enabling custom fonts. (See TinyOLED-Fonts)
  • Optimised code size.
  • Exposed the blink and fade SSD1306 features documented in revision 1.2 of the SSD1306 Specification.
  • v1.1 Support three different I2C interfaces:
  • v1.3 Added back support for 128x64 screens, including double buffering when 'zoom' is enabled (32 lines are each drawn twice).
  • v1.4 Added support for SSD1306B documented features:
    • Ability to select internal current reference, providing consistent, bright displays. 72x40 displays typically do not include an external current reference.
    • Ability to select the voltage used by the internal charge pump (results in a minor difference in brightness).
    • Ability to horizontally scroll a portion of the display by one pixel (scrollContentLeft and scrollContentRight).
  • v1.5 Added init sequences and offsets for 128x64, 128x32, 72x40, 64x48, and 64x32 resolution screens.
  • v2.0 Extended the format used for fonts, adding support for:
    • Proportional fonts.
    • Multiple font subsets and unicode ranges.
    • UTF-8 encoded strings.
    • Printing double size text, with and without smoothing.
    • Option to reduce memory usage if print functions are not required.
  • v2.1 Added support for a user callback function to combine images. See the BatteryMonitor example.
  • v2.2 Replaced double size printing methods with double sized font selection methods.
    • Standard print methods, Unicode fonts, and new lines now work correctly with double sized text. See Refactoring to support double sized rendering. (Note: Double size text only works with fonts up to 16 pixels high.)
    • Added clearToEOP and fillToEOP where P stands for page, and fixed issue #10 so the EOL methods work with font heights larger than 8 pixels (1 page).
    • Added a 4th I2C interface to do raw bit-banging, but ignoring all the I2C rules.
    • Fixed double size text when double buffering (Issue #41) (v2.2.2)
  • v2.3 Fixed % character in FONT6X8 and derivatives (Issue #55)

I2C Speeds and External Pullup Resistors

v2.2 added an I2C speed test example, which can be used as a simple (but rough) guide to the performance of your solution. It display the number of ms it takes to fill the screen.

Important Notes:

  • Spence Konde (Author and maintainer of the best AVR Cores) has done more analysis of write speeds (see Issue #52), and showing the importance of ensuring your I2C lines have the correct external pullup resisters.
  • This section used to have a table of times for different I2C implementations, using an ATTiny85 with nothing but a single random SSD1306 OLED module connected, and NO EXTERNAL PULLUPS. Unfortunately it made the Wire library look bad. The Wire library is the default for Tiny4kOLED as it is the best for a wide range of I2C scenarios. Other implementations take shortcuts or make compromises that may result in incorrect behaviour depending on your hardware configuration choices.

Online Simulator

The Wokwi Online Arduino Simulator has quite good support for the core features of the 128x64 SSD1306. Here are links to some of the Tiny4kOLED examples:

128x64 / 128x32 / 72x40 / 64x48 / 64x32

The screens with a resolution of 128 by 64 pixels support a feature called 'zoom' where each row is drawn twice. This also only uses half the memory, and so the double buffering technique can be used when the screen is in that mode.

The double buffering technique doesn't have to be used, and library works with SSD1306 screens of different resolutions, however the default init sequence in this library is for a screen with 32 rows of pixel. Custom init sequences can be supplied. An empty init sequence can also be used with oled.begin(0,0); so the SSD1306 can be initialized by your own code.

The clear and fill commands, and the wrapping of lines of text by this library, use the screen's height in pages (a page is 8 rows of pixels). This library defaults the number of pages to 4. For screens with other geometries call the setPages method, or use the begin settings appropriate for your display.

The following begin parameters are supported for the various display resolutions. The b at the end means bright. The r at the end means rotated.

    // this is equivalent to tiny4koled_init_128x32r
    oled.begin();

    oled.begin(128, 64, sizeof(tiny4koled_init_128x64), tiny4koled_init_128x64);
    oled.begin(128, 64, sizeof(tiny4koled_init_128x64b), tiny4koled_init_128x64b);
    oled.begin(128, 64, sizeof(tiny4koled_init_128x64r), tiny4koled_init_128x64r);
    oled.begin(128, 64, sizeof(tiny4koled_init_128x64br), tiny4koled_init_128x64br);

    oled.begin(128, 32, sizeof(tiny4koled_init_128x32), tiny4koled_init_128x32);
    oled.begin(128, 32, sizeof(tiny4koled_init_128x32b), tiny4koled_init_128x32b);
    oled.begin(128, 32, sizeof(tiny4koled_init_128x32r), tiny4koled_init_128x32r);
    oled.begin(128, 32, sizeof(tiny4koled_init_128x32br), tiny4koled_init_128x32br);

    oled.begin(72, 40, sizeof(tiny4koled_init_72x40), tiny4koled_init_72x40);
    oled.begin(72, 40, sizeof(tiny4koled_init_72x40b), tiny4koled_init_72x40b);
    oled.begin(72, 40, sizeof(tiny4koled_init_72x40r), tiny4koled_init_72x40r);
    oled.begin(72, 40, sizeof(tiny4koled_init_72x40br), tiny4koled_init_72x40br);

    oled.begin(64, 48, sizeof(tiny4koled_init_64x48), tiny4koled_init_64x48);
    oled.begin(64, 48, sizeof(tiny4koled_init_64x48b), tiny4koled_init_64x48b);
    oled.begin(64, 48, sizeof(tiny4koled_init_64x48r), tiny4koled_init_64x48r);
    oled.begin(64, 48, sizeof(tiny4koled_init_64x48br), tiny4koled_init_64x48br);

    oled.begin(64, 32, sizeof(tiny4koled_init_64x32), tiny4koled_init_64x32);
    oled.begin(64, 32, sizeof(tiny4koled_init_64x32b), tiny4koled_init_64x32b);
    oled.begin(64, 32, sizeof(tiny4koled_init_64x32r), tiny4koled_init_64x32r);
    oled.begin(64, 32, sizeof(tiny4koled_init_64x32br), tiny4koled_init_64x32br);

The SSD1306 remembers many of its settings even when powered off. After experimenting with various features, it can be useful to reset all the settings to the default values, which can be done with the following initialization sequence (Note: by default the charge pump is turned off):

    oled.begin(128, 64, sizeof(tiny4koled_init_defaults), tiny4koled_init_defaults);
    oled.enableChargePump(); // The default is off, but most boards need this.
    oled.setRotation(1);     // The default orientation is not the most commonly used.

Example Usage

// Choose your I2C implementation before including Tiny4kOLED.h
// The default is selected is Wire.h

// To use the Wire library:
//#include <Wire.h>

// To use the Adafruit's TinyWireM library:
//#include <TinyWireM.h>

// To use the TinyI2C library from https://github.com/technoblogy/tiny-i2c
//#include <TinyI2CMaster.h>

// The blue OLED screen requires a long initialization on power on.
// The code to wait for it to be ready uses 20 bytes of program storage space
// If you are using a white OLED, this can be reclaimed by uncommenting
// the following line (before including Tiny4kOLED.h):
//#define TINY4KOLED_QUICK_BEGIN

#include <Tiny4kOLED.h>

void setup() {
  // Send the initialization sequence to the oled. This leaves the display turned off
  oled.begin();

  // Two rotations are supported,
  // The begin() method sets the rotation to 1.
  //oled.setRotation(0);

  // Some newer devices do not contain an external current reference.
  // Older devices may also support using the internal curret reference,
  // which provides more consistent brightness across devices.
  // The internal current reference can be configured as either low current, or high current.
  // Using true as the parameter value choses the high current internal current reference,
  // resulting in a brighter display, and a more effective contrast setting.
  //oled.setInternalIref(true);

  // Two fonts are supplied with this library, FONT8X16 and FONT6X8
  // Other fonts are available from the TinyOLED-Fonts library
  oled.setFont(FONT8X16);

  // Clear the memory before turning on the display
  oled.clear();

  // Turn on the display
  oled.on();

  // Switch the half of RAM that we are writing to, to be the half that is non currently displayed
  oled.switchRenderFrame();
}

void loop() {
  updateDisplay();
  delay(50);
}

void updateDisplay() {
  // Clear the half of memory not currently being displayed.
  oled.clear();

  // Position the text cursor
  // In order to keep the library size small, text can only be positioned
  // with the top of the font aligned with one of the four 8 bit high RAM pages.
  // The Y value therefore can only have the value 0, 1, 2, or 3.
  // usage: oled.setCursor(X IN PIXELS, Y IN ROWS OF 8 PIXELS STARTING WITH 0);
  oled.setCursor(0, 1);

  // Write text to oled RAM (which is not currently being displayed).
  oled.print(F("ms: "));

  // Write the number of milliseconds since power on.
  oled.print(millis());

  // Swap which half of RAM is being written to, and which half is being displayed.
  // This is equivalent to calling both switchRenderFrame and switchDisplayFrame.
  oled.switchFrame();
}

The 4k in the project name is because 128 multiplied by 32 is 4096. This library is for a display with only 4096 pixels, not for UHD displays.

tiny4koled's People

Contributors

datacute avatar matititam avatar rtlprmft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tiny4koled's Issues

Add SH1106 132x64 display support

Hello.
I post this adapted library (ad58375 on Aug 29) for the SH1106 controller.
Made it possible not to use (delete) unsupported functions if the parameter "#define SH1106" is defined in the Tiny4kOLED_common.h file.
Applicable for SH1106 controller as there are slight differences from SSD1306.
I made this library for myself.
Thanks.
Tiny4kOLED-ad58375.zip

Vertical Lines on cheap SSD1306 0.91" OLED

Good day,

i´m struggeling on a problem with some chinese 0.91OLEDs and the Tiny4kOLED Library.
Overall at first i tested the U8G2 Lib to verify the general health of my oled and got a positiv result. Every graphics test was successful.
After switching from the Arduino Pro Mini to the Attiny85 I have to shrink the code and found this Tiny4kOLED Library. So now i´m stuck on a working code with some issues on the OLED.

IMG20210829221245

At first i tested the health with the example codes and already there it seems something was happening with the output on the Oled.

I tried to fix it with Tiny4kOLED_Wire.h instead of Tiny4kOLED.h, but the result was the same.

Did i missed something?
The TinyWireM Library is at the latest version 1.1.0.

Can anybody help me?

external crystal problem

I have a sketch working fine on ATtiny85 with internal 8MHz setup.
I have then used "burn bootloader" external 8MHz - uploaded the code again (setup with the 8MHz crystal).
But after succesful code loading - the ATtiny85 dont work with the 128x32 OLED display.
Why?

Is there a way to mirror the output?

I've got a screen that is an SSD1312, and it works with the Adafruit 1306 library. I had to use some commands to mirror the screen with the Adafruit library, and it works fine.

The issue I'm having is whenever I try to use commands from Tiny4kOLED, the output is mirrored again.

Is there a command that will mirror the screen output? All the characters are backwards and left/right like from a mirror; see screen shot.

Love your library and fonts. I would really like to use them in my project. Any thoughts?

Thanks,

Mike
IMG_2355

OLED 128x32 - rotate 180dg?

I have been seaching for a function to rotate the text 180dg on a OLED 128x32 display, but I cannot find such a command.
Is it possible to rotate the text on the 128x32 OLED display?

static uint8_t invertByte() method includes two unused parameters (yet I can't understand how these are not essential)

These are very concerning to me - how could this method possibly work if the parameters aren't being used?!

C:\Users\Spence\Documents\Arduino\libraries\Tiny4kOLED\src\Tiny4kOLED.cpp: In function 'uint8_t invertByte(uint8_t, uint8_t, uint8_t)':
C:\Users\Spence\Documents\Arduino\libraries\Tiny4kOLED\src\Tiny4kOLED.cpp:132:35: warning: unused parameter 'x' [-Wunused-parameter]
 static uint8_t invertByte(uint8_t x, uint8_t y, uint8_t byte) {
                                   ^
C:\Users\Spence\Documents\Arduino\libraries\Tiny4kOLED\src\Tiny4kOLED.cpp:132:46: warning: unused parameter 'y' [-Wunused-parameter]
 static uint8_t invertByte(uint8_t x, uint8_t y, uint8_t byte) {
```                                              ^

There is no documentation of the API whatsoever.

So I've forked your repo largely for the purpose of adding at least a terse API reference so that I can use it. My style of programming is to look at the API reference first. But there isn't one here. I guess we're just supposed to reverse engineer the examples? But I don't learn well that way. I'll also likely end up adding some #ifdefs if I find ways to improve performance on modern (post-2016 revolution) AVRs.

Can you tell me which of the API functions are ones that are only be used internally and which should be called by user code? (should those be made private? or is there a reason they can't be?
In any event, stuff that users don't ever call don't need docs, which I feel like might drastically shrink the number of things that require documenting.

#### void begin();
#### void begin(uint8_t init_sequence_length, const uint8_t init_sequence []);
Okay where do we get the init sequences? how do we know what one to use?  Right now I only know how to use the full size ones, I'd like to  be able to use the others. 

#### void begin(uint8_t width, uint8_t height, uint8_t init_sequence_length, const uint8_t init_sequence []);
#### void begin(uint8_t xOffset, uint8_t yOffset, uint8_t width, uint8_t height, uint8_t init_sequence_length, const uint8_t init_sequence []);

#### void switchRenderFrame();
#### void switchDisplayFrame();
#### void switchFrame();
#### uint8_t currentRenderFrame();
#### uint8_t currentDisplayFrame();
I have no idea what these do

#### size_t write(uint8_t)

#### void setFont(const DCfont *font);
#### void setUnicodeFont(const DCUnicodeFont *unicode_font);
#### void setFontX2(const DCfont *font);
#### void setUnicodeFontX2(const DCUnicodeFont *unicode_font);
#### void setFontX2Smooth(const DCfont *font);
#### void setUnicodeFontX2Smooth(const DCUnicodeFont *unicode_font);
#### void setFontOnly(const DCfont *font);
#### void setSpacing(uint8_t spacing);
Is there a list of fonts?

#### void setCombineFunction(uint8_t (*combineFunc)(uint8_t, uint8_t, uint8_t));
#### uint8_t getExpectedUtf8Bytes();
#### uint16_t getCharacterDataOffset(uint8_t c);
These I have not a clue about

#### uint8_t getCharacterWidth(uint8_t c);
#### uint16_t getTextWidth(DATACUTE_F_MACRO_T *text);
These find the width of a character or string in pixels? 

#### void setCursor(uint8_t x, uint8_t y);
#### uint8_t getCursorX()
#### uint8_t getCursorY()
Cursor is where text will appear when written right? Units are pixels? (presumably to the first column of the character, upper or lower left corner?  or is it rows/columns?

#### void newLine();
#### void fill(uint8_t fill);
#### void fillToEOL(uint8_t fill);
#### void fillToEOP(uint8_t fill);
#### void fillLength(uint8_t fill, uint8_t length);
#### void clear();
#### void clearToEOL();
#### void clearToEOP();
What is the meaning of the argument to fill? 
EOL is... end of line? What is EOP? 

#### void bitmap(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t bitmap[]);

#### void setPages(uint8_t pages);
#### void setWidth(uint8_t width);
#### void setHeight(uint8_t height);
#### void setOffset(uint8_t xOffset, uint8_t yOffset);
#### void setRotation(uint8_t rotation);

#### void clipText(uint16_t startPixel, uint8_t width, DATACUTE_F_MACRO_T *text);
#### void clipTextP(uint16_t startPixel, uint8_t width, DATACUTE_F_MACRO_T *text);

#### void setContrast(uint8_t contrast);

#### void setEntireDisplayOn(bool enable);
For debugging?

#### void setInverse(bool enable);
#### void invertOutput(bool enable);
How are these two different? 

#### void off();
#### void on();
Hmmm, this is a real head scratcher, but I think I can figure it out

#### void setExternalIref();
#### void setInternalIref(bool bright);
???

#### void fadeOut(uint8_t interval);
#### void blink(uint8_t interval);
#### void disableFadeOutAndBlinking();
#### void enableZoomIn();
#### void disableZoomIn();
#### void scrollRight(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t startColumn = 0x00, uint8_t endColumn = 0xFF);
#### void scrollRightOffset(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t offset);
#### void scrollContentRight(uint8_t startPage, uint8_t endPage, uint8_t startColumn, uint8_t endColumn);
#### void scrollLeft(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t startColumn = 0x00, uint8_t endColumn = 0xFF);
#### void scrollLeftOffset(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t offset);
#### void scrollContentLeft(uint8_t startPage, uint8_t endPage, uint8_t startColumn, uint8_t endColumn);
#### void setVerticalScrollArea(uint8_t top, uint8_t rows);
#### void activateScroll();
#### void deactivateScroll();
These I can probably figure out with some work

#### void setColumnStartAddress(uint8_t startAddress)
#### void setMemoryAddressingMode(uint8_t mode);
#### void setColumnAddress(uint8_t startAddress, uint8_t endAddress);
#### void setPageAddress(uint8_t startPage, uint8_t endPage);
#### void setPageStartAddress(uint8_t startPage);
Are these user facing or internal?

#### void startData();
#### void sendData(const uint8_t data);
#### void repeatData(uint8_t data, uint8_t length);
#### void clearData(uint8_t length);
#### void endData();
Are these even things that should be user facing? 

#### void enableChargePump(uint8_t voltage = SSD1306_VOLTAGE_7_5);
#### void disableChargePump();
#### void setDisplayStartLine(uint8_t startLine);
#### void setSegmentRemap(uint8_t remap);
#### void setMultiplexRatio(uint8_t mux);
#### void setComOutputDirection(uint8_t direction);
#### void setDisplayOffset(uint8_t offset);
#### void setComPinsHardwareConfiguration(uint8_t alternative, uint8_t enableLeftRightRemap);
#### void setDisplayClock(uint8_t divideRatio, uint8_t oscillatorFrequency);
#### void setPrechargePeriod(uint8_t phaseOnePeriod, uint8_t phaseTwoPeriod);
#### void setVcomhDeselectLevel(uint8_t level);
#### void nop();
Same with these? These sound like internal functions? 

#### SSD1306Device(void (*wireBeginFunc)(), bool (*wireBeginTransmissionFunc)(), bool (*wireWriteFunc)(uint8_t byte), uint8_t (*wireEndTransmissionFunc)());

Little Bug in SSD1306Device::bitmap

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);
}

Writing too soon after asking to switch the displayed frame, results in writing to the ram that is still being displayed

If while a third of the way through displaying the top half of ram, your application has finished updating the second half of ram, and switches over, the display will finish showing the first half of ram before it starts showing the second half of ram. During that time your application might be updating the ram as it is being displayed.
There's no frame vertical sync exposed over I2C, so the only way to reduce the risk is to delay slightly after switching which half gets displayed before writing anything to the display ram.
I'm not going to add a delay in to the code, instead I'll document that your code to update the display should write to ram, then switch the display, rather than the other way around.

`fill` and `filltoEOL` don't account for vertical memory addressing mode

Hi there! thanks for making this library. I found a small issue with fill and probably a few other functions. In vertical addressing mode, according to the datasheet, when a segment is written the page address is incremented as opposed to the column address, opposite of horizontal and page addressing mode. In vertical addressing mode, the end of a line is 8 segments instead of 128, or 4 in our case due to double buffering.

What's interesting is despite commands 00-1F and B0-B7 being described as "for page addressing mode", setCursor seems to work just fine, though I am only using setCursor with an x value so far.

When using fill with vertical addressing mode, we use setCursor to get to the first segment, fill 128 segments (16 total lines of 8 segments per line, so transgressing into the buffer) and then setCursor back up to a column address of zero, resetting our progress. Whether or not the page address command is respected in vertical addressing mode, you clear at most ~17 total lines, since column address 0, page address 1 is only 8 segments into the memory instead of the normal 128.

I'm fine with clearing the entire screen and the buffer in my program, so I've replaced calls to clear() with 1024 data bytes of 0, taking advantage of the wrapping nature of the cursor in vertical addressing mode. It would be nice clear() and fill() worked out of the box in vertical addressing mode though!

ATTINY84 crashes

It seems this library was designed for the 85 series but other than pin layout it seems there are no real differences - so I assume it should run fine on the 84. Right now the lib crashes and the 85 and the Tiny is sent to an indefinite loop :(

Does anyone has successfully run this on an 84?

Thanks,

Andy

Extra dots

Hey dude, this looks like a great improvement on the digisparkOled but I'm having a little problem -
Running the example (with no modifications) draws extra pixels. Hard to see exactly what's happening but it possibly only occurs during fill and clear (not print).
A very consistent grid of problem pixels, perhaps it's chopping off a bit of a byte somewhere?

It doesn't occur with the digispark version but I'd rather not use that as it's slow AF

image

Non-Blocking when OLED disconnected?

This may seem like an odd usage case scenario, but I have a small ATTiny85 circuit, where the OLED screen is "optional"
The problem, I just discovered, is that if the OLED is not connected, nothing works! I assume it's preventing the sketch from continuing as the OLED was not detected. (Every GPIO pin is in use, so I don't have a spare one to use as a switch to toggle the OLED depending on the GPIO state)

Adafruit do this using this in the setup()

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

But of course, you can comment out or just remove the for(;;); part, and everything works and continues as normal even when the OLED is disconnected.

I can't seem to find where this Tink4KOLED library is doing this similar action? I presume it must be because, as I mentioned, if the OLED is disconnect, then it "freezes" - nothing continues.

So can I go about using this library in a non-blocking fashion? So that if the OLED is not connected, everything carries on as normal!?

INA219 problem

I have used htis library for several project and all works just fine.

Now I would like the following configuration:
ATtiny85
Oled 128x96
INA219 (problem) (with Adafruit_INA219.h )

Compiling -> a lot of errors.
What is the solution to this setup?

`
#include <Tiny4kOLED.h> // Display
#include <TinyWireM.h> // I2C bus
#include "Adafruit_INA219.h" // Display addr: 0x2C
Adafruit_INA219 POS(0x40); // INA219 Positive addr: 0x40

void setup(){
oled.begin(); // Display initialize
oled.clear(); // Display
oled.on(); // Display
POS.begin(); // INA219 POS initialize
POS.setCalibration_32V_1A(); // INA219 POS Sensitivity `
}

I have a feeling the problem is INA219 and TinyWireM?

Manipulation of a single pixel on the screen.

Is it possible for someone to help me create a function to write only 1 pixel on the screen, so it is possible to use the library to generate square or sine wave graphs using the whole screen instead of just 8 vertical pixels. I did an experiment to create vertical lines, but strangely my function, works on Atmega328P but not on STM32. I didn't understand the reason for the error. But the question is: Does anyone have a function to combine multiples of 8 and write 1 single pixel in any position on the screen?

Thanks.

void L_V(byte a, byte p) //vertical line size. horizontal position
{
  for (byte i = 1; i <= 4; i++)
  {
    oled.setCursor(p, 6 - i);
    oled.startData();
    oled.sendData(B11111111 << ((8 * i) - a));
    oled.endData();
  }
}

Adding 16x32 Fonts

Hello,

I have found on this website a modification of this library to support 16x32 Fonts. I can see that the code is quite different so I am not sure if this can be integrated straight away or it was done for an earlier release.

It would be nice to have this on the official library and to have the option of not uploading into program memory fonts that are not being used with the idea of saving program space.

Thank you

Screen Rotation 90º (vertical screen)

Hi, I'd like to be able to rotate the screen 90º to use it vertically. Is there any way to do it?
the oled.setRotation() only allows 0º or 180º.
Thank you!

Define display type?

How do I define when I connect:
OLED 64x128 display ?
OLED 32x128 display?
(driver SSD1306)

"Flickering" when clearing and printing

Hi!

I'm drawing a menu on the screen with the print function, on a button press I clear the menu and re-draw it.
The clear seems to take a half second causing a bit of a flicker, is there any way to avoid this?
I'm a bit of a noob so I've tried with switching frames and stuff but I haven't gotten it to work properly.

This is a slimmed down version of the code I'm currently using:

#include <TinyWireM.h
#include <Tiny4kOLED.h>
#include <Bounce2.h>

Bounce dB1 = Bounce(); 
Bounce dB2 = Bounce(); 
byte cursPos=1;

void setup() {
  pinMode(PB1,INPUT_PULLUP); // UP
  pinMode(PB5,INPUT_PULLUP); // DOWN
  dB1.attach(PB1);
  dB1.interval(5);
  dB2.attach(PB5);
  dB2.interval(5);
  oled.begin();
  oled.setFont(FONT6X8);
  drawMenu();
  oled.on();  
}

void drawMenu(){
  oled.clear();
  oled.setCursor(0, 0);
  oled.print(F("A"));
  oled.setCursor(6, 1);
  oled.print(F("B"));
  oled.setCursor(6, 2);
  oled.print(F("C"));
  oled.setCursor(6, 3);
  oled.print(F("D"));
  oled.setCursor(0, cursPos);
  oled.print(F(">"));
}

void loop() {
  dB1.update(); //UP
  dB2.update(); //DOWN
  
  if (dB1.fell()){
    if (cursPos > 1) {
      cursPos--;
      drawMenu();
    }
  } else if (dB2.fell()){
    if (cursPos < 3) {
      cursPos++;
      drawMenu();
    }
  }
}

Thanks!

clearToEOL only clears a single page

The clearToEOL function is useful when the screen is being overwritten instead of being cleared.
When using the 8x16 font, the clearToEOL function only clears one page, the top 8 pixels of the line, to the end of the line, instead of both pages.

Information on Wire.h speed (not an issue, but you don't have discussions enabled.

Test results from AVR128DB48, a flagship modern AVR
This went on a bit longer than I intended.

The data

Wire Clock Pullups F_CPU Fill time Notes
100000 Omitted 24 MHz 370-380 ms Image doesn't change
200000 Omitted 24 MHz 370-380 ms Image doesn't change
100000 usePullups() 24 MHz 101 ms Standard Mode
200000 usePullups() 24 MHz 51.4 ms
400000 usePullups() 24 MHz 29.1 ms Fast Mode
400000 usePullups() 32 MHz 27.8 ms Overclocked Int. Osc
400000 usePullups() 16 MHz 31.6 ms
400000 4.7k 24 MHz 29.0 ms
600000 4.7k 24 MHz 21.0 ms
600000 4.7k 24 MHz 22.0 ms With scope on scl
800000 4.7k 24 MHz 17.0 ms
1000000 4.7k 24 MHz 15.0 ms Fast Mode Plus
1000000 2.2k 24 MHz 15.0 ms No improvement
1000000 2.2k 48 MHz 12.1 ms Massive Overclock
400000 2.2k 48 MHz 25.6 ms Massive Overclock

NanoDB background So I wired up a screen to one of my Nano DB+ boards that I had out for testing
(it's the Rev. - version, which I rarely get right - but these actually appear to have come out just about flawlessly. Out of a run of 20, only 2 needed any rework at all (a tombstoned capacitor and a single bridge on the 0.4mm pitch QFN. The same chip in TQFP I typically have to do minor rework after reflow on almost half of the boards to clear bridges, and the damned things have virtually no self-centering because of the lack of a center pad). Plus maybe a few that needed work on the USB connector, which is always a pain - but that's the price for USB connectors that have pins going through the board, so the board would break in half before the connector got ripped off the board. This new solder I've found is amazing and just works miracles - lead free, composition known, melts under 200C, and verified to be lead free with lead test swabs (the common "S600 Lead free 183C" solder is actually leaded according to the lead test swabs. It beat out the previous lead-free contender, which melted at "158C", tested negative for lead, but wasn't normal horribad SnBiAg (never bother with that solder that's 64-65% Sn, 35% Bi and 0-1% silver. It is absolutely abysmal.).

So they've joined the queue of parts waiting for me to write descriptions so I can sell them). It uses an AVR128DB48 with the extended temperature range. It's part of the current AVR flagship DB-series (neither of the next two announced parts are going to change that: EA and EB have a fancy new ADC but the EA only goes up to 48 pins, 20 MHz and 64k (and the EB has less flash and fewer pins), while the DB's go up to 64 pins, 128k flash, and 24 MHz (rated - they overclock insanely well)). I modified the sketch to print out the time that it recorded before the >> 8 and used that to calculate the numbers so I would get more precise measurements.

Back to the process
Being a bit groggy at the time, I failed to check whether there were pullups on the breakout board, and just wired it up.
I got speeds even more miserable than you recorded for Wire on the t85, and increasing the Wire clock didn't change it. And the image on the screen didn't change either: I think that 370ms time is how long it takes for however many I2C transactions it takes to fill the screen to time out. That pointed to insufficient pullups.

note about I2C master and scl clock
The I2C master actually waits for the clock to go high before pausing for a specified amount of time. That's why setClock() is is complicated and the numbers you pass to it aren't the actual clock speed. (notice how connecting a scope probe to it slows it down - I measured 606-616 kHz when I had the scope on it). That is NOT a trivial change either - the calculations suggest that 15-16 of those 21ms that it takes are the part that depends on the wire clock, so that scope probe slowed the bus by something on the order of 5-7%! On DxCore and megaTinyCore (which use the same Wire library - actually almost all the libraries that both ship with are identical), the Wire baud calculations behind setClock() as supplied by the arduino core for the uno wifi/nano every were wrong, and then were rewritten by me twice (both times incorrectly), then by a user via PR (which was much less wrong), and then again (correctly this time) by our hero, @MX682X who subsequently pretty much rewrote all of Wire so it supports multi-master on all modern AVRs, and Dual Mode can be used where the hardware supports it - I also added a few hacky mechanisms for a slave to get the information it needs (particularly the number of bytes the master read, so it can update it's pointer) to implement an I2C interface that feels like I2C rather than a weird serial port (until then, I never understood why all the I2C slave devices made with Arduino had such a crude interface... but stock Wire.h doesn't give you the tools you would need to make any other kind!). The new Wire does all that with a smaller flash footprint too). Coincidentally, it was the same finnicky, non-I2C-compliant part which was highly SCL clock sensitive that led to both of those individuals examining setClock.

On pullups and external pullups
Okay, so we need pullups. On parts with proper TWI peripherals, even classic AVRs, you could use the internal pullups and although the internal pullups are way weaker than the spec says you need, it's often enough for a small bus without much on it. On classic AVRs, the internal pullups are always turned on by the stock Wire.h library (and all the third party cores use that stock implementation); I specifically made sure not to automatically use the internal pullups, because doing that makes debugging harder by hiding a simpler a problem, causing it to fail only when the number of devices on the bus or the length of the wires is increased, which makes the problem very hard to debug, so I decided to provide usePullups() on mTC/DxC, so someone can rely on the internal pullups, but can't do so unknowingly - they have to effectively declare "I know this isn't above board, and if I2C breaks, the first thing I'll try is adding pullups".

notes on how much of the time is going to I2C
So, using the pullups made things work: The screen flickered and eventually displayed a number. That got the times down to 101 ms at default speed (which is 100khz/standard mode). Setting the clock to 200 kHz nearly halved the update time. I then kicked it up to 400kHz, the spec'ed "Fast Mode" speed, and got 29.1 ms. At that point I played with the F_CPU to try to get a better idea of how much of the time it spent sending and how much of the time was used by the CPU., running it at 16 MHz, and overclocking to 32 MHz. My eventual determination was that at 24 MHz, 5.5ms of the time it takes is CPU time, and the rest is used to update

And back to our main story
It was time to stop fucking around and put on some real pullups. I assembled a 1x4 stacking pin header (the good kind of pin header comes in 1x40 and 2x40 sizes. To make smaller ones, I pull the plastic retainer off and remove the pins (and discard the plastic parts), then similarly depin a male and female normal header, discarding the metal parts, then combine them to make the desired size and color of stacking header that doesn't suck (the 1x4 stacking header you see for sale - and indeed almost all stacking pin header on the market is Garbage (with a capitol G)). Soldered it to one of my 4x4 mini protoboards (I sell them for like $2 for 8 or something like that, among many other shapes and sizes of mini-protoboard in my tindie store). Added the resistors, took out UsePullups() and got the same speed in fast mode as I did with usePullups() - not super surprising, since the wires are short and there's only the screen on the bus.

Okay, let's see what this bad boy can do...
600 kHz? Yup! 21ms. I put a scope on SCL to see how fast it actually was and calculated that it was like 606-616 kHz - but the scope probe slowed it down by a non-trivial amount. It was likely morelike 630 without the probe (makes sense, because the setClock() function would underestimate the bus capacitance because of the short wires and single device

800 kHz? Yup! 17 ms

Okay, let's try full on Fast Mode Plus - 1 MHz! Hell yeah! It works like a charm! Although we're getting diminishing returns. I wondered if we might be getting thrown off by a weak pullup - - 4.7k is normal for Fast Mode, but lower values are more typical for FM+, so let's make a 2.2k set... Nope, no difference at all!

For the hell of it
And just for fun, I ran the test on chip with a 48 MHz crystal (yes, this specimen runs fine at TWICE THE RATED SPEED at room temperature (I'm sure it wouldn't do so at the 125C maximum temperature - though I don't think there is voltage dependance above 2.1V or so on the Dx. I won't be able to test that until I get my next batch of serial adapters * - not all parts run at 48, but it's not rare for E-spec parts to work at 48. I-spec parts don't seem to be quite as good for overclocking, which makes sense - At room temperature, which chip would you expect to run faster, the one rated for 24 MHz at 105C, or the one rated for 24 MHz at 125C?

48MHzI2CSpeedTest
48 MHz and Fast Mode Plus

Anyway - These numbers give an idea of the speeds achievable on modern AVRs. Note that not all parts and not all portmux options support Fast Mode Plus (Standard and Fast Mode have limited drive strength per the I2C spec that us mere mortals aren't allowed to read. Phillips makes you pay just to read the I2C spec. FM+ uses a higher (~20mA) output drive to get faster fall-times).

Concern about the numbers you present for speed, and some information about how Wire.h is implemented on different parts on ATTinyCore, which seems to be what you use
I am suspicious that in your tests where you got those awful numbers with Wire, you may not have had external pullups installed. You say that you were using a tiny85. When using the Useless Serial Interface (USI - I think the first word is supposed to be "universal", but "useless" is a better description of it) parts like the t85 does not provide a way to enable to pullups when using USI for I2C. I am also not sure how much of setClock is implemented for ATTinyCore; It's much less flexible where it is implemented. If it works on the USI, it only works at a few fixed speeds, because the the USI is not a very helpful peripheral - all it does is clock bits in or out of the shiftregister on the appropriate edge of the clock. You want it to generate the clock too? Fat chance. Not unless you sacrifice a timer to it. We can't afford that on... well, certainly not on any part with a USI. So the clock is generated in software by writing to a USI clock strobe bit, with cyclecounting delays to get the timing right-ish). There are three tinyAVR parts that have neither a USI nor a real TWI (like the lucky 88/48 do). These unfortunate parts have a slave only TWI and nothing for TWI master: the 841, 441, and the 828. The first of those is probably the best of the classic tinyAVRs (except for the lack of any hardware assistance for I2C), and is the only tinyAVR with three timers, which would make using one to clock a USI viable, if it had one. And the 828 is just a tragedy in general - this is just another way in which it exemplifies poor execution of a great vision). On those parts, the Wire library uses a fully software/bitbanged implementation of I2C. (the 1634 also got the stupid slave TWI, and the busted pin - though at least it's busted pin is one that doesn't matter - but it managed to hang on to the USI, so ATtC uses that)

There are AFAICT no parts with enough timers that one could be dedicated to that task without causing pain to the user such that you would not want Wire to do that. All the classic AVRs with more than 2 timers with the exception of the tiny841/44 are ATmegas, not ATtinys, and I don't think any ATmega's ever shipped with the USI - it was always a way to cheap out on the peripherals that the tinies got, by replacing TWI and SPI with something that did both of them substantially worse. Modern AVRs are less timer-deprived, but they also all have at least one TWI, and it's a substantially (though not overwhelmingly) better TWI. (Well, okay, the 0-series modern tinyAVRs are timer deprived, and 2/4/8k 1-series kinda are too, since the TCD is not an easy peripheral to work with - but no sane person would choose to use them. They're strictly worse versions of the 1-series...)

Footnote about that voltage dependance and overclocking mentioned above
* To test voltage dependance of overclocking, see, I need a serial chip with a VIO pin. Those are frequently present on chips, but rarely broken out, so I have to design one. I have a very bad record with serial adapters. I designed and rev'ed one version, then abandoned it as unfit years ago, then later designed a batch of 3 serial adapters based on 3 different chips. One of them was rev'ed once before I found all the undocumented silicon bugs in Holtek's garbage serial adapter (which did have Vio - but the drivers crashed constantly, it couldn't do anything approximating arbitrary baud rates, just a limited number, and the modem control inputs were backwards and it sometimes failed to program for no reason). I built only 2 of each rev, and only one of each still "works". Another design was abandoned, and the third I went on to rev 4 times before deciding it was not going to make a good product - the Rev. D had an atrocious assembly yield of 0/24 with no rework, and maybe 75-80% with rework on all boards. Oh and we screwed up and reversed 2 parts on 24 of them causing the voltage to always be 5v instead of switchable. And built half of them with the wrong part in another location. I also recently made the mistake of trying to use FTDI's 4-port chip. Too many external components, and it put a whole pile of things that need to be as close to the chip as possible... on adjacent pins. First version failed to connect one of the power pins, so I rev'ed that once before renewing my vow to never build anything with an FTDI product again. I tried again with another serial chip and that worked, but I decided it wasn't marketable (and didn't have Vio). I've got 3 more designs going out to the board house. maybe the 14th time will be the charm, or the 15th, or the 16th. There's a deluxe single port adapter, plus two very similar dual adapters - one version is just 2 serial ports straight up, and the other has one of them wired as a UPDI programmer for programming modern AVRs, because even though all the mod requires is one diode, problems seem to be fairly common (and I've replaced 4 diodes on modded boards that had cracked somehow). All three of these have a VIO so soon I'll be able to maintain communication with a chip while varying it's voltage and "make these parts do the limbo!" and see how low I can bring the voltage while still overclocking the hell out of them (I do have one project underway which I don't think will meet it's design goals at 24 MHz - but I used E-spec parts and I don't plan to sell it at all, much less to the uninitiated, so 32, 40, or maybe even 48 is an option, and at those speeds, I'd be home free. Especially if my background WS2812 sending scheme works...

Please add support for special Characters

Hi,
Your library is awesome.
It would be very nice if you could add characters like the German Umlaute äÄöÖüÜ or the characters with accents or the ° symbol.
Regards
Florian S

-Not issue- is possible with this library power off the screen?

hi i am in a fork of a proyect and i was thinking of add power saving feature.

i have see this code in the internet.

display.ssd1306_command(SSD1306_DISPLAYOFF); // To switch display off

display.ssd1306_command(SSD1306_DISPLAYON); // To switch display back on

my question : is possible to use this code in this library, if not there are any code like this?

Many warnings produced by the font files [-Wmissing-field-initializers]

It looks like we're missing some field initializers, so compilation is throwing mad warnings.

I do not know whether these warnings have practical effect (they're C++ class stuff, but I'm not a classy guy - I don't have a very good understanding of classes in C++), but this makes me uncomfortable using this library - they should either be corrected, or if they are spurious, suppressed within the library.

The list of missing initializers includes at least:

font6x8digits.h:45:3:  warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font6x8digits.h:45:3:  warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font6x8digits.h:45:3:  warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]
font6x8caps.h:99:3:    warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font6x8caps.h:99:3:    warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font6x8caps.h:99:3:    warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]
font6x8.h:130:3:       warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font6x8.h:130:3:       warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font6x8.h:130:3:       warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]
font8x16.h:130:3:      warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font8x16.h:130:3:      warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font8x16.h:130:3:      warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]
font8x16digits.h:45:1: warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font8x16digits.h:45:1: warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font8x16digits.h:45:1: warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]
font8x16caps.h:99:3:   warning: missing initializer for member 'DCfont::widths16s' [-Wmissing-field-initializers]
font8x16caps.h:99:3:   warning: missing initializer for member 'DCfont::widths'    [-Wmissing-field-initializers]
font8x16caps.h:99:3:   warning: missing initializer for member 'DCfont::spacing'   [-Wmissing-field-initializers]

I normally program under a "warnings should be treated as errors (though I do not enforce this at the compiler level - it's a matter of "did you see orange text when you verified? Yes? Okay don't bother uploading, go fix those problems first". I generally do not bother to upload any code which produces warnings, as experience has shown that the warning almost always pointed to a bug and the program wold not have worked as intended. I firmly believe that more than 99% of the time, a warning is actually a serious bug or sign of lax programming practices (a matter not helped by the fact that Arduino disables warnings by default, which I consider an unpardonable sin); DxC and mTC (and future ATTinyCore) ignore the user request to disable warnings, and emit warnings regardless, since the default ide configuration is unacceptable (it hides information which would greatly expedite debugging). Since I can't change what the default is, all I could do was make all the options use -Wall. (Occasionally someone complains about this, but I shoot down those issues - My general policy is that I do not support blatantly stupid development practices. Suppressing all warnings counts as such a practice. Having warnings on has saved probably a cumulative week of development time alone, possibly much more

Compilation was performed for an ATtiny3224 (which, like DxC, has the latest modern AVR version of Wire.h which supports a superset of the standard API and uses less flash than the first refactor of Wire.h. That refactor was prompted by a user complaint that the implementation was so bloated that they couldn't compile Wire.h at all on a 4k part, nevermind the rest of the application. The inefficient implementation was easily cut it down by a large degree. The second refactor further reduced flash use while simultaneously adding the option to use master and slave simultaneously - whether on the same pins (any part) or separate pins (dual mode, DD-series and mega0 only), and adds the missing functions needed to implement I2C slave functionality that resembles what you see on commercial I2C devices). It also corrects the setClock() function to provide much better approximations of the baud rate (the actual baud rate depends on hardware conditions, namely the rise time of the SCL and SDA lines, which depends on the bus capacitance which is rarely known; reasonable assumptions are used.)

how to draw?

Hi, I found this lib when asking on arduino forum about how to make fast changes in an SSD1306 screen and the buffering works great. Problem is that I cant figure out how to draw, even a rectangle, none of the examples have it..

How could I draw a white rectangle?

Sorry for such a stupid question!

Thanks!

Scroll display

Would it be possible to scroll the display one line up when the text reaches extends beyond the bottom of the screen so that the display can act as a mini console? I have looked into the code but I haven't found an easy way... but maybe there is a solution?

Draw pixel by pixel

Hi,
Is there a way to draw single pixels on the screen? Preferably by giving the pixel coordinates instead of pages.

Thanks

Nothing Being Displayed

Hoping someone here would know if this is an issue with the Tiny4KOLED library, or my setup.

Day 3 of trying to fix this -

I am using the 128x32 example for Tiny4kOLED, with the board manager https://github.com/SpenceKonde/ATTinyCore.git, originally I couldn't compile the code with the board manager http://drazzy.com/package_drazzy.com_index.json so that is why I switched to the Spences.

I have all my wiring correct, and the OLED Display was working using the TinyOzLED Library for ATTiny85 https://github.com/SensorsIot/TinyOzOled

Here is the code for that example:

`/*

  • Tiny4kOLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x32 displays
  • Based on ssd1306xled, re-written and extended by Stephen Denne
  • from 2017-04-25 at https://github.com/datacute/Tiny4kOLED
  • This example shows a full screen rectangle,
  • writes the rectangle size inside the rectangle,
  • and scrolls the size off the screen.

*/

#include <Tiny4kOLED.h>

uint8_t width = 128;
uint8_t height = 32;

void setup() {
oled.begin(width, height, sizeof(tiny4koled_init_128x32br), tiny4koled_init_128x32br);
oled.setFont(FONT8X16);
drawScreen();
oled.on();
}

void loop() {
scrollScreen();
}

void drawScreen() {
// Set entire memory to hatched - if you see any of this hatching, then the display is not initialised correctly.
for (uint8_t y = 0; y < 8; y++) {
oled.setCursor(0, y);
oled.startData();
for (uint8_t x=0; x<128; x += 2) {
oled.sendData(0b10101010);
oled.sendData(0b01010101);
}
oled.endData();
}

oled.setCursor(0, 0);
oled.startData();
oled.sendData(0b11111111);
oled.repeatData(0b00000001, width - 2);
oled.sendData(0b11111111);
oled.endData();

for (uint8_t y = 1; y < (height - 8) / 8; y++) {
oled.setCursor(0, y);
oled.startData();
oled.sendData(0b11111111);
oled.repeatData(0b00000000, width - 2);
oled.sendData(0b11111111);
oled.endData();
}

oled.setCursor(0, (height - 8) / 8);
oled.startData();
oled.sendData(0b11111111);
oled.repeatData(0b10000000, width - 2);
oled.sendData(0b11111111);
oled.endData();

oled.setCursor(8, 1);
oled.print(width);
oled.print('x');
oled.print(height);
}

void scrollScreen() {
uint8_t startScrollPage = 1;
uint8_t endScrollPage = 2;
uint8_t startScrollColumn = 8;
uint8_t endScrollColumn = startScrollColumn + width - 16;
for (uint8_t x = 0; x < width - 16; x++)
{
delay(50);
oled.scrollContentRight(startScrollPage, endScrollPage, startScrollColumn, endScrollColumn);
}
}`

Compiles just fine, also here is my board setup
image

I've redone the wiring, swapped both the ATTINY85PU unit with another, and the display (here is a link https://www.amazon.com/dp/B08TLXYKS6?psc=1&ref=ppx_yo2_dt_b_product_details)

Can anyone here tell me if this is an issue with the 4kOled library, and what you guys are using that is working ?

Compiling Error

I am trying to get this working for my ATtyny85 project but I get compiler error:

Tiny4kOLED.cpp: In member function 'void SSD1306Device::setFont(const DCfont*)':
Tiny4kOLED.cpp:127:11: error: invalid conversion from 'const DCfont*' to 'DCfont*' [-fpermissive]
oledFont = font;
^
exit status 1

Board Digispark (16mhz - No USB)

Changing a function for wide range contrast

Hello.
There is a hack in which you can reduce the contrast of the display to the smallest values:

// 1. Fundamental Command Table

void SSD1306Device::setContrast(byte contrast) {
	byte val;
	if (contrast < 193) {
		//0x00 value of pre-charge period and vcomh allow us to wide change contrast of display
		setPrechargePeriod(0,0);
	    setVcomhDeselectLevel(0);
		val=round(contrast+45*1.074);
	}
	else {
		//reset pre-charge period and vcomh to default value
		setPrechargePeriod(2,2);
	    setVcomhDeselectLevel(2);
		val=contrast;
	}
	ssd1306_send_command2(0x81,val);
}

Video Preview:
https://drive.google.com/file/d/1vcizbV8zYmK-5RECyfEOGb9WmdbUL0Ce/view?usp=sharing

How to tune the cursor for y ONE pixle by ONE pixle? x is ok but y is 1 PAGE by 1 PAGE.

The function oled.setOffset(1,5); will offset the x,y coordinate to x+1, y+5*8

The oled.bitmap(x0,y0, x1, y1, bitMapData); function has also the problem. y0 is not the coordinate, it's the y0*8 coordinate. The y1 has to be set as (int)bitmap_height/8 + y0 i.e. the num of pages plus y0. Can you make it as y1=y0+bitmap_height? By pixle, not by page.

What if I want to offset the cursor_y exactly by 5 pixle?
The end coordinate of y (y1 in program) is setting by adding 8 pixles each 1 number. This is an inhuman design. Isn't it?

Why horizontal setting should seperate to 8

I cant handle the hole pixels for wake cause horizontal miss, how i can change .cpp file to write to directly in y coordinate?
(I had tried it about remove offset but idk what is the mean off offset in this case, lol my fault but i have miss )

Using scroll commands

Hello,

Would it be possible to add an example about how to use the scrolling commands?

void scrollRight(uint8_t startPage, uint8_t interval, uint8_t endPage);
void scrollLeft(uint8_t startPage, uint8_t interval, uint8_t endPage);
void scrollRightOffset(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t offset);
void scrollLeftOffset(uint8_t startPage, uint8_t interval, uint8_t endPage, uint8_t offset);
void deactivateScroll(void);
void activateScroll(void);
void setVerticalScrollArea(uint8_t top, uint8_t rows);

Not sure how to use these, thank you.

Digistump board doesn't define __FlashStringHelper

Arduino: 1.8.12 (Windows 7), Board: "Digispark (Default - 16.5mhz)"


In file included from E:\SkyRanger\Eigene Dateien\Arduino\libraries\Tiny4kOLED-1.5.0\src/Tiny4kOLED_Wire.h:12:0,

                 from E:\SkyRanger\Eigene Dateien\Arduino\libraries\Tiny4kOLED-1.5.0\src/Tiny4kOLED.h:19,

                 from R:\Arduino\DigisparkOLED_\DigisparkOLED_.ino:2:

E:\SkyRanger\Eigene Dateien\Arduino\libraries\Tiny4kOLED-1.5.0\src/Tiny4kOLED_common.h:74:59: error: '__FlashStringHelper' does not name a type

   void clipText(uint16_t startPixel, uint8_t width, const __FlashStringHelper *text);

                                                           ^

E:\SkyRanger\Eigene Dateien\Arduino\libraries\Tiny4kOLED-1.5.0\src/Tiny4kOLED_common.h:74:80: error: ISO C++ forbids declaration of 'text' with no type [-fpermissive]

   void clipText(uint16_t startPixel, uint8_t width, const __FlashStringHelper *text);

                                                                                ^

Support multiple geometries

64x48 screens driven by an SSD1306 have enough memory to double buffer the display. Can we swap the segment mapping? Would that require writing backwards to half the screen?

Vertical stripes

I've vertical stripes on a classic OLED 128x32 (see attached image) with every font I use.
I'm using Arduino IDE 1.8.13 and the latest version of the library (2.1.1).
Code is very simple, I want only to show a text:

`#include <Tiny4kOLED.h>
const DCfont *currentFont = FONT6X8;
void setup()
{
oled.begin();
oled.setFont(currentFont);
oled.clear();
oled.on();
oled.switchRenderFrame();
delay(50);
}

void loop()
{
oled.clear();
oled.print(millis());
oled.switchFrame();
delay(1000);
}`

img

Make printDoubleSize more convenient

I'm a total noob when it comes to c/c++ so bear with me please, but from what I understand oled.printDoubleSize() and oled.printDoubleSizeSmooth() either takes a string from flash with the F macro or needs to be fed byte-by-byte. Would it be possible to make it behave like regular oled.print() so I could easily print a variable? Or perhaps add an example demonstrating the right way to do it?

How to remove the dotted frame displayed on screen?

Hi,
How to remove the dots on the screen?

My code is below:

img_20180803_120114

#define USB_CFG_DEVICE_NAME     'D','i','g','i','B','l','i','n','k'
#define USB_CFG_DEVICE_NAME_LEN 9
#include <DigiUSB.h>
#include <Tiny4kOLED.h>


void setup() {
  pinMode(1,OUTPUT);
  // Send the initialization sequence to the oled. This leaves the display turned off
  oled.begin();
  oled.setFont(FONT8X16);
  // Clear the memory before turning on the display
  oled.clear();
  // Turn on the display
  oled.on();
  // Switch the half of RAM that we are writing to, to be the half that is non currently displayed
  oled.switchRenderFrame();
}


void loop() {
  digitalWrite(1,HIGH);
  delay(1000);
  digitalWrite(1,LOW);
  delay(1000);
  updateDisplay();
  
     
   
}

void updateDisplay() {
  // Clear the half of memory not currently being displayed.
  oled.clear();

  oled.setCursor(0, 0);

  // Write the number of milliseconds since power on.
  oled.print("Hello!");
  // Swap which half of RAM is being written to, and which half is being displayed.
  // This is equivalent to calling both switchRenderFrame and switchDisplayFrame.
  oled.switchFrame();
}

Improve font support

@entozoon in Issue #1 mentioned a desire for a large font.
I was considering changing this library to be able to specify the font, and to stop it loading two fonts even if you only use one.
That would then also support people creating/adapting their own fonts.
Fonts take heaps of precious space, so supporting a subset of characters is essential.
I'm not interested in trying to change the limitation of only supporting multiples of 8 bits (for font height and location).

`fill` and `filltoEOL` don't account for vertical memory addressing mode

Hi there! thanks for making this library. I found a small issue with fill and probably a few other functions. In vertical addressing mode, according to the datasheet, when a segment is written the page address is incremented as opposed to the column address, opposite of horizontal and page addressing mode. In vertical addressing mode, the end of a line is 8 segments instead of 128, or 4 in our case due to double buffering.

What's interesting is despite commands 00-1F and B0-B7 being described as "for page addressing mode", setCursor seems to work just fine, though I am only using setCursor with an x value so far

switchFrame vs setUnicodeFontX2?

Hello. There is a need to use both of these functions together. When applied at the same time, the first area is not drawn. Example of non-working code:

#define TINY4KOLED_NO_PRINT
#define SDA_PIN 6
#define SCL_PIN 4

#include <Tiny4kOLED_bitbang.h>
//#include <USIWire.h>
//#include <Tiny4kOLED.h>

uint8_t width = 128;
uint8_t height = 32;


// Fonts from this TinyOLED-Fonts library

// 2386 bytes in font + 3184 bytes for the program = 5570 byte total
#include "Open_Sans_Light_13_5_Unicode.h"
const DCUnicodeFont *currentFont = FONTOPENSANSLIGHT135;
//#define SAMPLE "Кириллические\nшрифты.\n"
#define SAMPLE "ЗАРЯД\n"

uint8_t currentCharacter;
uint8_t prc=0;

void setup() {
  // put your setup code here, to run once:
  oled.begin(width, height, sizeof(tiny4koled_init_128x32br), tiny4koled_init_128x32br);
 
  //oled.begin(128, 64, sizeof(tiny4koled_init_defaults), tiny4koled_init_defaults);
  oled.enableChargePump();
  oled.setRotation(1);
  oled.setUnicodeFont(currentFont);
  //oled.setUnicodeFontX2(currentFont);
  
  oled.on();
  oled.switchRenderFrame();
}

void loop() {
  drawScreen();
  delay(500);
  oled.switchFrame();
  //while(1);
}

void drawScreen() {
  //oled.setCursor(0, 0);
  oled.clear();
  oled.setUnicodeFontX2Smooth(currentFont);
  oled.setCursor(0, 0);
  
#ifndef TINY4KOLED_NO_PRINT
  oled.println(F(SAMPLE));

#else
  PGM_P p = reinterpret_cast<PGM_P>(F(SAMPLE));
  while (1) {
    byte c = pgm_read_byte(p++);
    if (c == 0) break;
    oled.write(c);
  }
#endif
}

Wont compile on Arduino IDE 1.8.13.

So I installed the library thought the IDE but when I got to compile it gives me these errors. Ive installed the Attiny85 boards files from here https://create.arduino.cc/projecthub/arjun/programming-attiny85-with-arduino-uno-afb829

Arduino: 1.8.13 (Linux), Board: "ATtiny25/45/85, ATtiny85, Internal 16 MHz"

/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_init':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:88:16: error: 'SDA' undeclared (first use in this function)
digitalWrite(SDA, 1);
^~~
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:88:16: note: each undeclared identifier is reported only once for each function it appears in
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:89:16: error: 'SCL' undeclared (first use in this function); did you mean 'SPL'?
digitalWrite(SCL, 1);
^~~
SPL
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:92:7: error: 'TWSR' undeclared (first use in this function); did you mean 'ACSR'?
cbi(TWSR, TWPS0);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:92:3: note: in expansion of macro 'cbi'
cbi(TWSR, TWPS0);
^~~
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:92:13: error: 'TWPS0' undeclared (first use in this function); did you mean 'TWSR'?
cbi(TWSR, TWPS0);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:92:3: note: in expansion of macro 'cbi'
cbi(TWSR, TWPS0);
^~~
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:93:13: error: 'TWPS1' undeclared (first use in this function); did you mean 'TWPS0'?
cbi(TWSR, TWPS1);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:93:3: note: in expansion of macro 'cbi'
cbi(TWSR, TWPS1);
^~~
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:94:3: error: 'TWBR' undeclared (first use in this function); did you mean 'TWSR'?
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
^~~~
TWSR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:102:3: error: 'TWCR' undeclared (first use in this function); did you mean 'TWBR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
^~~~
TWBR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:102:14: error: 'TWEN' undeclared (first use in this function); did you mean 'TWCR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:102:26: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:102:38: error: 'TWEA' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_disable':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:114:3: error: 'TWCR' undeclared (first use in this function); did you mean 'EECR'?
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
^~~~
EECR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:114:17: error: 'TWEN' undeclared (first use in this function); did you mean 'TWCR'?
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:114:29: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:114:41: error: 'TWEA' undeclared (first use in this function); did you mean 'TWEN'?
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:117:16: error: 'SDA' undeclared (first use in this function)
digitalWrite(SDA, 0);
^~~
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:118:16: error: 'SCL' undeclared (first use in this function); did you mean 'SPL'?
digitalWrite(SCL, 0);
^~~
SPL
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_setAddress':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:130:3: error: 'TWAR' undeclared (first use in this function); did you mean 'TIFR'?
TWAR = address << 1;
^~~~
TIFR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_setFrequency':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:141:3: error: 'TWBR' undeclared (first use in this function); did you mean 'TIFR'?
TWBR = ((F_CPU / frequency) - 16) / 2;
^~~~
TIFR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_readFrom':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:204:7: error: 'TWDR' undeclared (first use in this function); did you mean 'DWDR'?
TWDR = twi_slarw;
^~~~
DWDR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:209:13: error: 'TWCR' undeclared (first use in this function); did you mean 'TWDR'?
} while(TWCR & _BV(TWWC));
^~~~
TWDR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:209:24: error: 'TWWC' undeclared (first use in this function); did you mean 'TWCR'?
} while(TWCR & _BV(TWWC));
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:210:16: error: 'TWINT' undeclared (first use in this function)
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:210:29: error: 'TWEA' undeclared (first use in this function); did you mean 'TWWC'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:210:41: error: 'TWEN' undeclared (first use in this function); did you mean 'TWEA'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:210:53: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:213:65: error: 'TWSTA' undeclared (first use in this function); did you mean 'TWEA'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_writeTo':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:301:7: error: 'TWDR' undeclared (first use in this function); did you mean 'DWDR'?
TWDR = twi_slarw;
^~~~
DWDR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:306:13: error: 'TWCR' undeclared (first use in this function); did you mean 'TWDR'?
} while(TWCR & _BV(TWWC));
^~~~
TWDR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:306:24: error: 'TWWC' undeclared (first use in this function); did you mean 'TWCR'?
} while(TWCR & _BV(TWWC));
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:307:16: error: 'TWINT' undeclared (first use in this function)
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:307:29: error: 'TWEA' undeclared (first use in this function); did you mean 'TWWC'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:307:41: error: 'TWEN' undeclared (first use in this function); did you mean 'TWEA'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:307:53: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:310:65: error: 'TWSTA' undeclared (first use in this function); did you mean 'TWEA'?
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_reply':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:397:5: error: 'TWCR' undeclared (first use in this function); did you mean 'EECR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
^~~~
EECR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:397:16: error: 'TWEN' undeclared (first use in this function); did you mean 'TWCR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:397:28: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:397:40: error: 'TWINT' undeclared (first use in this function); did you mean 'TWIE'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:397:53: error: 'TWEA' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_stop':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:3: error: 'TWCR' undeclared (first use in this function); did you mean 'EECR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^~~~
EECR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:14: error: 'TWEN' undeclared (first use in this function); did you mean 'TWCR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:26: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:38: error: 'TWEA' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:50: error: 'TWINT' undeclared (first use in this function); did you mean 'TWIE'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:412:63: error: 'TWSTO' undeclared (first use in this function)
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_releaseBus':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:444:3: error: 'TWCR' undeclared (first use in this function); did you mean 'EECR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
^~~~
EECR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:444:14: error: 'TWEN' undeclared (first use in this function); did you mean 'TWCR'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:444:26: error: 'TWIE' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:444:38: error: 'TWEA' undeclared (first use in this function); did you mean 'TWEN'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:444:50: error: 'TWINT' undeclared (first use in this function); did you mean 'TWIE'?
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'twi_handleTimeout':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:475:29: error: 'TWBR' undeclared (first use in this function); did you mean 'TIFR'?
uint8_t previous_TWBR = TWBR;
^~~~
TIFR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:476:29: error: 'TWAR' undeclared (first use in this function); did you mean 'TWBR'?
uint8_t previous_TWAR = TWAR;
^~~~
TWBR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/compat/twi.h:36:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:29:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function 'TWI_vect':
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWSR' undeclared (first use in this function); did you mean 'ACSR'?
switch(TW_STATUS){
^
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWS7' undeclared (first use in this function); did you mean 'TWSR'?
switch(TW_STATUS){
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWS6' undeclared (first use in this function); did you mean 'TWS7'?
switch(TW_STATUS){
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWS5' undeclared (first use in this function); did you mean 'TWS6'?
switch(TW_STATUS){
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWS4' undeclared (first use in this function); did you mean 'TWS5'?
switch(TW_STATUS){
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:505:10: error: 'TWS3' undeclared (first use in this function); did you mean 'TWS4'?
switch(TW_STATUS){
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:510:7: error: 'TWDR' undeclared (first use in this function); did you mean 'TWSR'?
TWDR = twi_slarw;
^~~~
TWSR
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:530:10: error: 'TWCR' undeclared (first use in this function); did you mean 'TWDR'?
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
^~~~
TWDR
In file included from /home/facelessloser/arduino-1.8.13/hardware/tools/avr/avr/include/avr/io.h:99:0,
from /home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:26:
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:530:21: error: 'TWINT' undeclared (first use in this function)
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:530:34: error: 'TWSTA' undeclared (first use in this function); did you mean 'TWS3'?
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
^
/home/facelessloser/arduino-1.8.13/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:530:46: error: 'TWEN' undeclared (first use in this function); did you mean 'TWINT'?
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
^
exit status 1
Error compiling for board ATtiny25/45/85.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Please check the % character font.

The displayed % characters appear to be mirrored.
Could you please check the font header file?
Only font6x8.h has been confirmed.
thank you.
I'm sorry if I made a mistake.

oled.begin() not initializing properly

I've been trying to figure out this problem for the past few days wondering why this library does not initialize the OLED properly. Using other libraries such as ux8x/u8g2 writes to the display fine, but takes up too much memory/program space for my liking. I have successfully printed on the screen once a few days ago, but I am unable to repeat this process.

I have a separate program using u8g2 to write text to the OLED display, and when I flash the Tiny4kOLED script in, the display does not clear but the rest of the script works fine (led flash). I've tried reinstalling the library, but did not work.

I am currently using an ATTINY85 with a blue SSD1306 128x32 oled screen, which should work. I have pin 0 on SDA, and pin 2 on SCK, and I'm using an Arduino Uno as an ISP to program, which has been working fine.

#include <Tiny4kOLED.h>
#define TESTLED 3

void setup() {
  oled.begin();
  oled.setFont(FONT8X16);
  oled.clear();
  oled.on();
  oled.switchRenderFrame();
  
  pinMode(TESTLED,OUTPUT);
}

void loop() {
  updateDisplay();
  digitalWrite(TESTLED,HIGH);
  delay(500);
  digitalWrite(TESTLED,LOW);
  delay(500);
}
void updateDisplay(){
  oled.clear();
  oled.setFont(FONT8X16);
  oled.setCursor(0,1);
  oled.print("ms: ");
  oled.print(millis());
  oled.switchFrame();
}

The U8g2 script that currently works with my setup is below:

#include <U8g2lib.h>
#define TESTLED 3

U8X8_SSD1306_128X32_UNIVISION_SW_I2C u8x8(2,0);
void setup() {
  u8x8.begin();
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  pinMode(TESTLED,OUTPUT);
}

void loop() {
  u8x8.drawString(0,0,"Working");
  digitalWrite(TESTLED,LOW);
  delay(500);
  digitalWrite(TESTLED,HIGH);
  delay(500);
}

How to enter sleep mode?

The library running on attiny85 very well?
But i have to control power use, how to sleep the screen power and soft wake? chip avr/sleep? or use
oled.on / off function?

Is there more documentation somewhere?

There are a lot of functions used in the examples that arent properly explained or documented anywhere, or at least I cant seem to find them. For example I dont really understand how oled.fill is supposed to work. Is there some documentation that simply explains the functionality of each function?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.