Coder Social home page Coder Social logo

pico-ssd1306's People

Contributors

bdhar1 avatar ewnb avatar harbys avatar michaelgroni avatar randomspaceship 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

Watchers

 avatar  avatar  avatar

pico-ssd1306's Issues

Issue building the Lib

Have everything setup, but when building the lib getting

In file included from /Users/jeffo/desktop/dev/weather/pico-ssd1306-master/textRenderer/TextRenderer.cpp:1:
In file included from /Users/jeffo/desktop/dev/weather/pico-ssd1306-master/textRenderer/TextRenderer.h:4:
/Users/jeffo/desktop/dev/weather/pico-ssd1306-master/textRenderer/../ssd1306.h:5:10: fatal error: 'hardware/i2c.h' file not found
#include "hardware/i2c.h"
^~~~~~~~~~~~~~~~
1 error generated.

the pico SDK is setup and the env var is setup correctly. Have tried a few things with CMakeLists.txt with no luck. Trying to build the examples for basic text. Any help / direction would be appreciated.

Font workflow?

Can you share your workflow for generating the existing font headers?

I've been struggling to find a reliable conversion process for the expected format, especially for fonts taller than 8px.

Unexpected full ascii chars

Hello,
I've just tested the full ascii chars feature.

I tried to display following characters:
\xe8 \xe9 \xea \xeb
This should result to the following display:
è é ê ë
Instead I got some unexpected greek letters

Potential memory leak for the buffer in FrameBuffer

The buffer in the FrameBuffer is allocated but never freed. This could cause memory leak if the SSD1306 is out of scope or a new buffer is set. Granted this may not be a very big issue since in most of the use cases SSD1306 lifespan will be the whole program lifespan. It's just that personally I think this still should be handled properly. Alternatively, instead of allocating the buffer on heap, just put it on stack, as the buffer size will always be 1024, and keep a member variable to point to member buffer or user-set buffer.

"M" turned "H"

It seems that the letter "M" has been substituted in the 5x8_font with the letter "H".

The cause seems to be that the following data appears twice in each #ifndef or #else section in 5x8_font.h, once for "H" (as it should) and again for "M":

        0x7c,
        0x10,
        0x10,
        0x7c,
        0x0,

Note that the 'ndef' SSD1306_ASCII_FULL entries have trailing whitespace but the SSD1306_ASCII_FULL entries don't, which can screw with non-regexp file contents searches.

Double construction of `frameBuffer`

I think the line this->frameBuffer = FrameBuffer(); (ssd1306.cpp:19) in the SSD1306 constructor is both redundant and can cause problems.

What I think is happening is that frameBuffer is already initialized by the time the body of the SSD1306 constructor is entered. The line this->frameBuffer = FrameBuffer(); replaces the address to first FrameBuffer with the address of a second FrameBuffer that is constructed in the scope of the SSD1306 constructor. When the SSD1306 constructor is exited, the second FrameBuffer is destructed and it's buffer is freed. This leaves the just-constructed SSD1306 object with a frameBuffer member pointing to a FrameBuffer object with a buffer that has been freed, causing it to corrupt other data when that memory is allocated to something else.

On member initialization, from https://en.cppreference.com/w/cpp/language/constructor:

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished.

As a test, I added print statements to the constructor and destructor in FrameBuffer.cpp:

#include <stdio.h>

FrameBuffer::FrameBuffer() {
    this->buffer = new unsigned char[FRAMEBUFFER_SIZE];
    printf("FrameBuffer() (%p) new buffer: %p\n", this, this->buffer);
}

FrameBuffer::~FrameBuffer() {
    printf("~FrameBuffer() (%p) delete buffer: %p\n", this, this->buffer);
    delete[] this->buffer;
}

I then modified the basic_text example to add in some more print statements and to match the hardware I have:

#include <cstdio>
#include "pico/stdlib.h"
#include "pico-ssd1306/ssd1306.h"
#include "pico-ssd1306/textRenderer/TextRenderer.h"
#include "hardware/i2c.h"

// Use the namespace for convenience
using namespace pico_ssd1306;

int main(){
    // Initialise usb serial for debugging and give our terminal monitor
    // a bit of time to connect.
    stdio_init_all();
    sleep_ms(2000);
    printf("comms test\n");

    // Init i2c0 controller
    i2c_init(i2c0, 1000000);
    // Set up pins 12 and 13
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

    // If you don't do anything before initializing a display pi pico is too fast and starts sending
    // commands before the screen controller had time to set itself up, so we add an artificial delay for
    // ssd1306 to set itself up
    sleep_ms(250);

    // Create a new display object at address 0x3D and size of 128x64
    printf("before SSD1306()\n");
    SSD1306 display = SSD1306(i2c0, 0x3C, Size::W128xH32);
    printf("after SSD1306()\n");
    printf("display.frameBuffer.get(): %p\n", display.frameBuffer.get());

    // Here we rotate the display by 180 degrees, so that it's not upside down from my perspective
    // If your screen is upside down try setting it to 1 or 0
    display.setOrientation(0);

    // Draw text on display
    // After passing a pointer to display, we need to tell the function what font and text to use
    // Available fonts are listed in textRenderer's readme
    // Last we tell this function where to anchor the text
    // Anchor means top left of what we draw
    drawText(&display, font_12x16, "TEST text", 0 ,0);

    // Send buffer to the display
    display.sendBuffer();
    printf("end\n");
}

Note that I also made frameBuffer public so I could call display.frameBuffer.get() in main().

The resulting output was:

19:24:20:727 -> comms test
19:24:20:977 -> before SSD1306()
19:24:20:980 -> FrameBuffer() (20041FE4) new buffer: 200035E0
19:24:20:984 -> FrameBuffer() (20041F9C) new buffer: 200039E8
19:24:20:988 -> ~FrameBuffer() (20041F9C) delete buffer: 200039E8
19:24:21:003 -> after SSD1306()
19:24:21:004 -> display.frameBuffer.get(): 200039E8
19:24:21:018 -> end
19:24:21:020 -> ~FrameBuffer() (20041FE4) delete buffer: 200039E8

This output seems to show two FrameBuffer objects being created, and the second freeing its buffer before we get back to main(). Further, the address of that freed buffer is what display.frameBuffer.get() returns so the SSD1306 will use that freed buffer, clobbering anything written there after it is reallocated.

The fix seems simple. Delete this->frameBuffer = FrameBuffer(); from ssd1306.cpp.

Extended charset ?

Hello,
Thank you for your simple but usefull driver.
The available fonts, with a size from 5x8 to 16x32 are perfect for my usage.
However, the charset of these fonts are limited to the range 32 to 127 in the ascii table.

Would it be possible to get an extended charset (say 32 to 255 for instance) in order to include also characters such as é, ï ê, etc?
Or even better, a mechanism that allow to build our own font set ?

Nothing on screen

Compared to the other C++ libraries out there, I've had better luck integrating this library into an external project and getting it to compile, but I'm not seeing anything on the screen.

This is the 128x32 OLED I'm using: https://www.amazon.com/DSD-TECH-OLED-Display-Arduino/dp/B07D9H83R4

SDA pin is GPIO 4, SCL pin is GPIO 5.

#include "pico-ssd1306/ssd1306.h"
#include "hardware/i2c.h"

#define I2C_PORT i2c0
#define I2C_PIN_SDA 4
#define I2C_PIN_SCL 5

int main() {
  i2c_init(I2C_PORT, 1000000); //Use i2c port with baud rate of 1Mhz
  gpio_set_function(I2C_PIN_SDA, GPIO_FUNC_I2C);
  gpio_set_function(I2C_PIN_SCL, GPIO_FUNC_I2C);
  gpio_pull_up(I2C_PIN_SDA);
  gpio_pull_up(I2C_PIN_SCL);
  sleep_ms(250); // Allow time for initialization
  // Create a new display object
  pico_ssd1306::SSD1306 display = pico_ssd1306::SSD1306(I2C_PORT, 0x3D, pico_ssd1306::Size::W128xH32);
  for (int y=0; y < 32; y++) {
    display.setPixel(20, y);
  }
  display.sendBuffer();
  sleep(10000);
}

Compiles and runs beautifully but the screen is blank. Am I missing something here?

I know they're wired up correctly to the I2C pins physically, because I can get the martinkooij driver's example code to run and display stuff on screen. I've tried I2C address 0x3C and 0x3D.

#pragma once and #ifdef/#define are redundant

Every include file starts with #pragma once and continues with #ifndef FILENAME_H and #define FILENAME_H
The two methods do fundamentally the same thing.
I would remove the #ifndef / #define / #endif as it is more verbose and supposedly, #pragma once can be more efficient.
Supposedly, not all compilers have supported #pragma once, but GCC and Clang do and I have yet to encounter a modern compiler that does not. The pico SDK uses GCC, so even if some exotic compiler does not like #pragma once, it is not an issue for this project.

Text display bug on some letters

Hello,
Thank your for this simple but efficient driver.
It works fine for my usage, which is very basic.
I've however noticed that, for some letters with long legs, such as 'p', 'q', 'y' are not displayed very well. It's like if the bottom pixels where displayed at the top of the letter.

Initialization outside the constructor

If you move the SSD1306 outside the constructor, you will be able to create a new object as global.
Otherwise, if you try right now, the RP2040 never boot up.

namespace pico_ssd1306 {
    SSD1306::SSD1306(i2c_inst *i2CInst, uint16_t Address, Size size) {
        // Set class instanced variables
        this->i2CInst = i2CInst;
        this->address = Address;
        this->size = size;

        this->width = 128;

        if (size == Size::W128xH32) {
            this->height = 32;
        } else {
            this->height = 64;
        }

        // create a frame buffer
        this->frameBuffer = FrameBuffer();

        // display is not inverted by default
        this->inverted = false;

    }

    void SSD1306::init() {

        // this is a list of setup commands for the display
        uint8_t setup[] = {
                SSD1306_DISPLAY_OFF,
                SSD1306_LOWCOLUMN,
                SSD1306_HIGHCOLUMN,
                SSD1306_STARTLINE,

                SSD1306_MEMORYMODE,
                SSD1306_MEMORYMODE_HORZONTAL,

                SSD1306_CONTRAST,
                0xFF,

                SSD1306_INVERTED_OFF,

                SSD1306_MULTIPLEX,
                63,

                SSD1306_DISPLAYOFFSET,
                0x00,

                SSD1306_DISPLAYCLOCKDIV,
                0x80,

                SSD1306_PRECHARGE,
                0x22,

                SSD1306_COMPINS,
                0x12,

                SSD1306_VCOMDETECT,
                0x40,

                SSD1306_CHARGEPUMP,
                0x14,

                SSD1306_DISPLAYALL_ON_RESUME,
                SSD1306_DISPLAY_ON
        };

        // send each one of the setup commands
        for (uint8_t &command: setup) {
            this->cmd(command);
        }

        // clear the buffer and send it to the display
        // if not done display shows garbage data
        this->clear();
        this->sendBuffer();

    }
#include "../pico-ssd1306/ssd1306.h"
pico_ssd1306::SSD1306 display(I2C_PORT, 0x3C, pico_ssd1306::Size::W128xH64);

[...]

int main() {
display.init();
[...]
}

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.