Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[driver] SSD1306 SPI display #1090

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ your specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cat24aa">CAT24AA</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cycle_counter">CYCLE-COUNTER</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X-SPI</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1302">DS1302</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1631">DS1631</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds18b20">DS18B20</a></td>
Expand Down Expand Up @@ -792,27 +792,28 @@ your specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-qmc5883l">QMC5883L</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106">SH1106</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106-i2c">SH1106-I2C</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s65">SIEMENS-S65</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s75">SIEMENS-S75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306-i2c">SSD1306-I2C</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306-spi">SSD1306-SPI</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7586s">ST7586S</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7789">ST7789</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx128x">SX128X</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx128x">SX128X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
Expand Down
2 changes: 1 addition & 1 deletion examples/generic/ros/environment/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</options>
<modules>
<module>modm:driver:bme280</module>
<module>modm:driver:ssd1306</module>
<module>modm:driver:ssd1306.i2c</module>
<module>modm:ros</module>
<module>modm:communication:ros</module>
<module>modm:processing:timer</module>
Expand Down
4 changes: 2 additions & 2 deletions examples/generic/ros/environment/thread_display.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <modm/processing/timer.hpp>
#include <modm/processing/protothread.hpp>

#include <modm/driver/display/ssd1306.hpp>
#include <modm/driver/display/ssd1306_i2c.hpp>

#include "hardware.hpp"

Expand Down Expand Up @@ -55,7 +55,7 @@ class DisplayThread: public modm::pt::Protothread
}

protected:
modm::Ssd1306<MyI2cMaster, 64> display;
modm::Ssd1306I2c<MyI2cMaster, 64> display;
modm::ShortTimeout boot_timeout;
bool _dirty;
int32_t _seq;
Expand Down
68 changes: 68 additions & 0 deletions examples/nucleo_g474re/sh1106_i2c/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2023, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <modm/board.hpp>
#include <modm/driver/display/sh1106_i2c.hpp>
// #include <modm/driver/display/ssd1306_i2c.hpp>

/// SH1106 display in I2C mode
using MyI2cMaster = modm::platform::I2cMaster1;
using Scl = Board::D15;
using Sda = Board::D14;

using Display = modm::Sh1106I2c<MyI2cMaster>;
// using Display = modm::Ssd1306<MyI2cMaster>;

Display display;

int
main()
{
Board::initialize();

modm::delay(100ms);

MyI2cMaster::connect<Sda::Sda, Scl::Scl>();
// Use 20kHz I2C and internal pull-ups, works without external pull-ups
// if the jumper wires are short enought
MyI2cMaster::connect<Sda::Sda, Scl::Scl>(MyI2cMaster::PullUps::Internal);

modm::delay(100ms);

RF_CALL_BLOCKING(display.initialize());
RF_CALL_BLOCKING(display.setOrientation(modm::glcd::Orientation::Landscape0));
RF_CALL_BLOCKING(display.setDisplayMode(Display::DisplayMode::Inverted));
RF_CALL_BLOCKING(display.setContrast(80));

display.setFont(modm::font::Assertion);

modm::ShortPeriodicTimer timer(333ms);
uint16_t counter(0);

while (true)
{
if (timer.execute())
{
display.clear();
display.setCursor(1, 1);
display << "Hello World!";
display.setCursor(1, 17);
display << counter++;
display.setCursor(1, 33);
display << "Line 3";
display.setCursor(1, 49);
display << "Line 4";

display.update();
}
}

return 0;
}
13 changes: 13 additions & 0 deletions examples/nucleo_g474re/sh1106_i2c/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<library>
<extends>modm:nucleo-g474re</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_g474re/sh1106_i2c</option>
</options>
<modules>
<module>modm:driver:sh1106.i2c</module>
<module>modm:driver:ssd1306.i2c</module>
<module>modm:platform:gpio</module>
<module>modm:platform:i2c:1</module>
<module>modm:build:scons</module>
</modules>
</library>
85 changes: 85 additions & 0 deletions examples/nucleo_g474re/ssd1306_spi/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2023, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <modm/board.hpp>
#include <modm/driver/display/ssd1306_spi.hpp>

/**
* SSD1306 display in SPI 4-wire mode
*
* SCK <-> Arduino D3 / GpioB3
* MOSI <-> Arduino D4 / GpioB5
* CS <-> Arduino D5 / GpioB4
* D/C# <-> Arduino D2 / GpioA10
* RESET# <-> Arduino D7 / GpioA8
*
* En7V5 <-> Arduino D6 / GpioB10
*
* TODO: Describe charge pump setup for 7.5V
*/

using MySpiMaster = modm::platform::SpiMaster1;
using Sck = Board::D3;
using Mosi = Board::D4;
using Cs = Board::D5;
using Dc = Board::D2;
using Reset = Board::D7;
using En7V5 = Board::D6;
using Display = modm::Ssd1306Spi<MySpiMaster, Cs, Dc, 32>;
Display display;

int
main()
{
Board::initialize();

En7V5::reset();
En7V5::setOutput();
Reset::reset();
Reset::setOutput();

Cs::setOutput();
Dc::setOutput();
MySpiMaster::connect<Sck::Sck, Mosi::Mosi>();
MySpiMaster::initialize<Board::SystemClock, 660_kHz>();

Cs::set();
En7V5::set();
modm::delay(500ms);

Reset::set();
modm::delay(1ms);

RF_CALL_BLOCKING(display.initialize());
RF_CALL_BLOCKING(display.setOrientation(modm::glcd::Orientation::Landscape0));
RF_CALL_BLOCKING(display.setDisplayMode(Display::DisplayMode::Inverted));
RF_CALL_BLOCKING(display.setContrast(80));

display.setFont(modm::font::Assertion);

modm::ShortPeriodicTimer timer(333ms);
uint16_t counter(0);

while (true)
{
if (timer.execute())
{
display.clear();
display.setCursor(1, 1);
display << "Hello World!";
display.setCursor(1,17);
display << counter++;

display.update();
}
}

return 0;
}
12 changes: 12 additions & 0 deletions examples/nucleo_g474re/ssd1306_spi/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<library>
<extends>modm:nucleo-g474re</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_g474re/ssd1306_spi</option>
</options>
<modules>
<module>modm:driver:ssd1306.spi</module>
<module>modm:platform:gpio</module>
<module>modm:platform:spi:1</module>
<module>modm:build:scons</module>
</modules>
</library>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

#include <modm/board.hpp>
#include <modm/driver/display/ssd1306.hpp>
#include <modm/driver/display/ssd1306_i2c.hpp>

/**
* Example to demonstrate a MODM graphics display SSD1306.
Expand All @@ -24,7 +24,7 @@
typedef GpioB9 Sda;
typedef GpioB8 Scl;
typedef I2cMaster1 MyI2cMaster;
modm::Ssd1306<MyI2cMaster> display;
modm::Ssd1306I2c<MyI2cMaster> display;

// ----------------------------------------------------------------------------
int
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<library>
<extends>modm:disco-f407vg</extends>
<options>
<option name="modm:build:build.path">../../../../build/stm32f4_discovery/display/ssd1306</option>
<option name="modm:build:build.path">../../../../build/stm32f4_discovery/display/ssd1306_i2c</option>
</options>
<modules>
<module>modm:driver:ssd1306</module>
<module>modm:driver:ssd1306.i2c</module>
<module>modm:platform:gpio</module>
<module>modm:platform:i2c:1</module>
<module>modm:build:scons</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#pragma once

#include "ssd1306.hpp"
#include "ssd1306_i2c.hpp"

namespace modm
{
Expand All @@ -26,10 +26,10 @@ namespace modm
* @ingroup modm_driver_sh1106
*/
template<class I2cMaster, uint8_t Height = 64>
class Sh1106 : public Ssd1306<I2cMaster, Height>
class Sh1106I2c : public Ssd1306I2c<I2cMaster, Height>
{
public:
Sh1106(uint8_t address = 0x3C) : Ssd1306<I2cMaster, Height>(address) {}
Sh1106I2c(uint8_t address = 0x3C) : Ssd1306I2c<I2cMaster, Height>(address) {}

protected:
modm::ResumableResult<void>
Expand All @@ -39,13 +39,10 @@ class Sh1106 : public Ssd1306<I2cMaster, Height>

this->transaction_success = true;

this->commandBuffer[0] = ssd1306::AdressingCommands::HigherColumnStartAddress;
this->commandBuffer[1] = 0x02;

for (page = 0; page < Height / 8; page++)
{
this->commandBuffer[2] = 0xB0 | page;
this->transaction_success &= RF_CALL(this->writeCommands(3));
Comment on lines -42 to -48
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command sequence {0x10, 0x02, 0xB0 | page} gets interpreted (at least on my SSD1306 GME12864 module) as three command:
1.0x10: Set Higher Column Start Address for Page Addressing Mode (10h~1Fh) to value 0
2.0x02 Set Lower Column Start Address for Page Addressing Mode (00h~0Fh) to value 2
3. 0xB0 Set Page Start Address for Page Addressing Mode (B0h~B7h) to value page

The first two commands result in the first two columns of display pixels displaying garbage and the last two columns of the frame not getting displayed, so I removed them.
SSD1106 should behave the same way like SH1106 in Page Addressing Mode, but I don't have SH1106 hardware laying arround, so I can't test it. Maybe @TomSaw could check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the hardware test shows:
These lines have a purpose. Whitout, the displays pages (columns of pixels) get ugly shifted.
I remember having read about this necessary micro-management in an adafruit or arduino library comment, not in the datasheet or elsewhere.

this->commandBuffer[0] = std::to_underlying(ssd1306::AdressingCommands::PageStartAddress) | page;
this->transaction_success &= RF_CALL(this->writeCommands(1));

RF_WAIT_UNTIL(
this->transaction.configureDisplayWrite((uint8_t*)&this->buffer[page], 128));
Expand All @@ -62,14 +59,14 @@ class Sh1106 : public Ssd1306<I2cMaster, Height>
{
RF_BEGIN();
// Default on Power-up - can be omitted
this->commandBuffer[0] = ssd1306::AdressingCommands::MemoryMode;
this->commandBuffer[1] = ssd1306::MemoryMode::PAGE;
this->commandBuffer[0] = std::to_underlying(ssd1306::AdressingCommands::MemoryMode);
this->commandBuffer[1] = std::to_underlying(ssd1306::MemoryMode::PAGE);
this->transaction_success &= RF_CALL(this->writeCommands(2));
RF_END();
}

private:
size_t page;
uint8_t page;
};

} // namespace modm
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@


def init(module):
module.name = ":driver:sh1106"
module.description = "SH1106 Display"
module.name = ":driver:sh1106.i2c"
module.description = "SH1106 Display in I2C mode"

def prepare(module, options):
module.depends(":driver:ssd1306")
module.depends(":driver:ssd1306.i2c")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/display"
env.copy("sh1106.hpp")
env.copy("sh1106_i2c.hpp")
Loading