0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Adafruit_SSD1306みたいなことをJUCEでやる

Last updated at Posted at 2025-03-06

SSD1306 を緩くシミュレート

SSD1306 (ちっさいOLED) を使ったハードウェアシンセサイザーを作ってるんだけど、コードをガリガリ書いてテストするのは完全にMacでやりたいんで、SSD1306部分をシミュレートするものが欲しかった。なのでChatGPTに書かせた。これで実機を離れてコード書ける。実機での確認はたまにやればいい感じで!

IMG_8349.jpeg

凄いバッチリなフォントあった!!!ありがとう素晴らしい!!!
https://fontstruct.com/fontstructions/show/2422258/adafruits-gfx-library-default-font

SSD1306Similator.h
#pragma once

#include <JuceHeader.h>
#include <cstdarg>

class SSD1306Simulator : public juce::Component
{
public:
    SSD1306Simulator(int width, int height)
        : displayWidth(width), displayHeight(height),
          image(juce::Image::PixelFormat::RGB, displayWidth, displayHeight, true),
          graphics(image),
          typeface(juce::Typeface::createSystemTypefaceFor(BinaryData::Adafruits5x7_otf, BinaryData::Adafruits5x7_otfSize)),
          lcdFont(juce::FontOptions(typeface).withHeight(8.0f))
    {
        setTextSize(1);
        clearDisplay();
    }

    SSD1306Simulator() : SSD1306Simulator(128, 64) {}

    bool begin()
    {
        clearDisplay();
        return true;
    }

    void setTextSize(int size)
    {
        textSize = juce::jlimit(1, 4, size);
        lcdFont = juce::FontOptions(typeface).withHeight(textSize * 8.0f);
    }

    void setTextColor(juce::Colour fg, juce::Colour bg = juce::Colours::transparentBlack)
    {
        textColour = fg;
        bgColour = bg;
    }

    void setTextWrap(bool w) { textWrap = w; }

    void clearDisplay()
    {
        graphics.fillAll(inverted ? juce::Colours::white : juce::Colours::black);
        cursorX = 0;
        cursorY = 0;
    }

    void invertDisplay(bool i)
    {
        inverted = i;
        clearDisplay();
    }

    void dim(bool d)
    {
        dimmed = d;
        displayColour = dimmed ? juce::Colours::grey : juce::Colours::white;
    }

    void drawPixel(int x, int y, bool color)
    {
        if (x < 0 || x >= displayWidth || y < 0 || y >= displayHeight) return;
        graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black);
        graphics.fillRect(x, y, 1, 1);
    }

    void drawLine(int x0, int y0, int x1, int y1, bool color)
    {
        graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black);
        graphics.drawLine((float)x0, (float)y0, (float)x1, (float)y1);
    }

    void drawFastHLine(int x, int y, int w, bool color) { fillRect(x, y, w, 1, color); }
    void drawFastVLine(int x, int y, int h, bool color) { fillRect(x, y, 1, h, color); }
    void drawRect(int x, int y, int w, int h, bool color) { graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black); graphics.drawRect(x, y, w, h); }
    void fillRect(int x, int y, int w, int h, bool color) { graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black); graphics.fillRect(x, y, w, h); }
    void fillScreen(bool color) { graphics.fillAll((color ^ inverted) ? textColour : juce::Colours::black); }

    void drawCircle(int x, int y, int r, bool color) { graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black); graphics.drawEllipse(x - r, y - r, r * 2, r * 2, 1.0f); }
    void fillCircle(int x, int y, int r, bool color) { graphics.setColour((color ^ inverted) ? textColour : juce::Colours::black); graphics.fillEllipse(x - r, y - r, r * 2, r * 2); }

    void setCursor(int x, int y) { cursorX = x; cursorY = y; }

    void print(const char* text)
    {
        if (!text) return;
        juce::Graphics g(image);
        g.setFont(lcdFont);
        g.setColour(textColour);

        // `drawText()` を使って確実に描画
        g.drawText(text, cursorX, cursorY, displayWidth - cursorX, textSize * 8, juce::Justification::topLeft);

        cursorX += static_cast<int>(std::strlen(text)) * (textSize * 6);
    }

    void printf(const char* format, ...)
    {
        if (!format) return;
        va_list args;
        va_start(args, format);
        
        char buffer[256];
        int len = std::vsnprintf(buffer, sizeof(buffer), format, args);
        
        va_end(args);
        
        if (len < 0 || len >= static_cast<int>(sizeof(buffer))) {
            return; // エラー時やバッファが足りなかった場合は何もしない
        }
        
        print(buffer);
    }

    void println(const char* text) { print(text); cursorX = 0; cursorY += textSize * 8; }
    void println()
    {
        cursorX = 0;
        cursorY += textSize * 8;
    }

    void display()
    {
        repaint(); // `display()` で画面更新
    }

    void paint(juce::Graphics& g) override
    {
        g.drawImage(image, getLocalBounds().toFloat()); // `juce::Image` の内容を `Graphics` に描画
    }

private:
    int displayWidth, displayHeight;
    juce::Image image;
    juce::Graphics graphics;
    juce::Typeface::Ptr typeface;
    juce::Font lcdFont;
    juce::Colour displayColour = juce::Colours::white;
    juce::Colour textColour = juce::Colours::white;
    juce::Colour bgColour = juce::Colours::black;
    int cursorX = 0;
    int cursorY = 0;
    int textSize = 1;
    bool inverted = false;
    bool dimmed = false;
    bool textWrap = true;
};
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?