Skip to content

Commit

Permalink
support for SH1106, improved SSD1306
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSaw committed Apr 27, 2021
1 parent ce9487b commit 3c137ee
Show file tree
Hide file tree
Showing 13 changed files with 448 additions and 441 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,20 +580,21 @@ you specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</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-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-stusb4500">STUSB4500</a></td>
</tr><tr>
<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-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-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
91 changes: 91 additions & 0 deletions src/modm/driver/display/sh1106.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2021, Thomas Sommer
*
* 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/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_SH1106_HPP
#define MODM_SH1106_HPP

#include "ssd1306.hpp"
namespace modm
{
/**
* \brief SH1106 is said to be 'compatible' with SSD1306. However
* there's one relevant difference: SH1106 does only support
* MemoryMode::PAGE. This requires a more extensive writeDisplay()
* routine. We have to alternate between setting Page-address and
* sending page-data instead of sending the whole buffer at once
* like is possible for MemoryMode::VERTICAL or MemoryMode::HORIZONTAL.
*/
template<class I2cMaster, uint8_t Height = 64>
class Sh1106 : public Ssd1306<I2cMaster, Height>
{
public:
Sh1106(uint8_t address) : Ssd1306<I2cMaster, Height>(address) {}

modm::ResumableResult<bool>
writeDisplay() override
{
RF_BEGIN();
this->TransactionSuccess = true;
currentPage = 0;

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

while (currentPage < Height / 8)
{
this->commandBuffer[2] = 0xB0 | currentPage;
this->TransactionSuccess &= RF_CALL(this->writeCommands(3));

// TODO Rearrange MonochromeGraphicDisplay::buffer so we do not have to convert
// HACK Transform buffer - very unperformant transitional solution
for (size_t i = 0; i < 128; i++)
pageBuffer[i] = this->buffer[i][currentPage];

RF_CALL(startWriteDisplay());
RF_WAIT_WHILE(this->isTransactionRunning());
// this->TransactionSuccess &= RF_CALL(this->wasTransactionSuccessful());

currentPage++;
}

RF_END_RETURN(this->TransactionSuccess);
}

protected:
// TODO Generalize in Ssd1306 so no more override is required
inline modm::ResumableResult<void>
startWriteDisplay() override
{
RF_BEGIN();

RF_WAIT_UNTIL(this->transaction.configureDisplayWrite(pageBuffer, 128) and this->startTransaction());

RF_END();
}

inline modm::ResumableResult<void>
initializeMemoryMode() override
{
RF_BEGIN();
// Default on Power-up - can be omitted
this->commandBuffer[0] = ssd1306::AdressingCommands::MemoryMode;
this->commandBuffer[1] = ssd1306::MemoryMode::PAGE;
this->TransactionSuccess &= RF_CALL(this->writeCommands(2));
RF_END();
}

private:
uint8_t pageBuffer[128];
size_t currentPage;
};
} // namespace modm

#endif // MODM_SH1106_HPP
25 changes: 25 additions & 0 deletions src/modm/driver/display/sh1106.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018, Niklas Hauser
#
# 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/.
# -----------------------------------------------------------------------------


def init(module):
module.name = ":driver:sh1106"
module.description = "SH1106 Display"

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

def build(env):
env.outbasepath = "modm/src/modm/driver/display"
env.copy("sh1106.hpp")
150 changes: 23 additions & 127 deletions src/modm/driver/display/ssd1306.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,119 +20,15 @@
#include <modm/processing/timer.hpp>
#include <modm/ui/display/monochrome_graphic_display_vertical.hpp>

#include "ssd1306_register.hpp"

namespace modm
{

/// @ingroup modm_driver_ssd1306
struct ssd1306
struct ssd1306 : public ssd1306_register
{
protected:
enum Transfer : uint8_t
{
COMMAND_BURST = 0x00, // Auto increment
COMMAND = 0x80, // No auto increment
DATA_BURST = 0x40, // Auto increment
DATA = 0xC0 // No auto increment
};

enum FundamentalCommands : uint8_t
{
ContrastControl = 0x81, // Range 1-255
EntireDisplayResumeToRam = 0xA4,
EntireDisplayIgnoreRam = 0xA5,
NormalDisplay = 0xA6,
InvertedDisplay = 0xA7,
DisplayOff = 0xAE,
DisplayOn = 0xAF,
};

enum ScrollingCommands : uint8_t
{
HorizontalScrollRight = 0x26,
HorizontalScrollLeft = 0x27,
VerticalAndHorizontalScrollRight = 0x29,
VerticalAndHorizontalScrollLeft = 0x2A,
VerticalScrollArea = 0xA3,
DisableScroll = 0x2E,
EnableScroll = 0x2F,
};

// SSD1315 only
enum FadingCommands : uint8_t
{
SetFading = 0x23
};

enum FadingMode : uint8_t
{
Disable = 0x00,
Fading = 0x20,
Blinking = 0x30,
// A[3:0] Fading-Interval, Range x = 0-15: Frames_ges = x + 1 * 8Frames
};

enum AdressingCommands : uint8_t
{
MemoryMode = 0x20, // enum MemoryMode
// HORIZONTAL and VERTICAL addressing only
ColumnAddress = 0x21, // Range 0-127
PageAddress = 0x22, // Range 0-7
// PAGE addressing only
PageStartAddress = 0xB0, // Range 0-7
LowerColumnStartAddress = 0x00,
HigherColumnStartAddress = 0x10,
};

enum MemoryMode : uint8_t
{
HORIZONTAL = 0,
VERTICAL = 1,
PAGE = 2
};

enum HardwareConfigCommands : uint8_t
{
DisplayStartLine = 0x40,
SegmentRemap0 = 0xA0,
SegmentRemap127 = 0xA1,
MultiplexRatio = 0xA8, // Range 16-64
ComOutputScanDirectionIncrement = 0xC0,
ComOutputScanDirectionDecrement = 0xC8,
DisplayOffset = 0xD3, // Range 0-63
ComPinsOrder = 0xDA, // enum ComPinsOrder
};

enum ComPinsOrder : uint8_t
{
DEFAULT = 0,
ALTERNATIVE = Bit0,
LEFT_RIGHT_REMAP = Bit1,
};

enum TimingAndDrivingCommands : uint8_t
{
ChargePump = 0x8D, // enum ChargePump
DisplayClockDivideRatio = 0xD5, // [7:4] Frequency [3:0] Prescaler
PreChargePeriod = 0xD9,
V_DeselectLevel = 0xDB, // 0: ~0.65 x VCC, 1: 0.71 x VCC, 2: 0.77 x VCC, 3: 0.83 x VCC
Nop = 0xE3
};

enum ChargePump : uint8_t
{
DISABLE = 0x00,
V7_5 = 0x14,
V8_5 = 0x94,
V9 = 0x95,
};

public:
enum class Rotation : bool
{
Normal,
UpsideDown
};

enum class ScrollStep : uint8_t
{
Frames2 = 0b111,
Expand Down Expand Up @@ -160,13 +56,13 @@ struct ssd1306
};

public:
template<uint8_t Height>
class DataTransmissionAdapter : public modm::I2cWriteTransaction
class Ssd1306_I2cWriteTransaction : public modm::I2cWriteTransaction
{
public:
DataTransmissionAdapter(uint8_t address);
Ssd1306_I2cWriteTransaction(uint8_t address);

bool configureDisplayWrite(uint8_t (*buffer)[Height / 8], std::size_t size);
bool
configureDisplayWrite(const uint8_t *buffer, const std::size_t size);

protected:
virtual Writing
Expand All @@ -178,11 +74,12 @@ struct ssd1306
inline bool
isWritable()
{
return operationBuffer[0] & Transfer::DATA_BURST;
return !transfer_active;
}

private:
uint8_t operationBuffer[1];
uint8_t transfer_type;
bool transfer_active;
};
/// @endcond
}; // struct ssd1306
Expand All @@ -198,10 +95,9 @@ struct ssd1306
template<class I2cMaster, uint8_t Height = 64>
class Ssd1306 : public ssd1306,
public MonochromeGraphicDisplayVertical<128, Height>,
public I2cDevice<I2cMaster, 2, ssd1306::DataTransmissionAdapter<Height>>
public I2cDevice<I2cMaster, 2, ssd1306::Ssd1306_I2cWriteTransaction>
{
static_assert((Height == 64) or (Height == 32),
"Display height must be either 32 or 64 pixel!");
static_assert((Height == 64) or (Height == 32), "Display height must be either 32 or 64 pixel!");

public:
Ssd1306(uint8_t address = 0x3C);
Expand Down Expand Up @@ -230,11 +126,11 @@ class Ssd1306 : public ssd1306,

// MARK: - TASKS
/// initializes for 3V3 with charge-pump asynchronously
modm::ResumableResult<bool>
inline modm::ResumableResult<bool>
initialize();

// starts a frame transfer and waits for completion
modm::ResumableResult<bool>
virtual modm::ResumableResult<bool>
writeDisplay();

inline modm::ResumableResult<bool>
Expand All @@ -252,6 +148,9 @@ class Ssd1306 : public ssd1306,
return writeCommands(2);
}

/**
* \param orientation glcd::Orientation::Landscape0 or glcd::Orientation::Landscape180
*/
inline modm::ResumableResult<bool>
setOrientation(glcd::Orientation orientation);

Expand All @@ -272,26 +171,23 @@ class Ssd1306 : public ssd1306,
return writeCommands(1);
}

// SSD1315 Only
inline modm::ResumableResult<bool>
setFading(FadingMode mode, uint8_t interval);

protected:
modm::ResumableResult<bool>
writeCommands(std::size_t length);

private:
modm::ResumableResult<void>
virtual inline modm::ResumableResult<void>
initializeMemoryMode();

virtual inline modm::ResumableResult<void>
startWriteDisplay();

private:
uint8_t commandBuffer[7];
bool initStatus;
bool TransactionSuccess;
};

} // namespace modm

#include "ssd1306_i2c_transaction_impl.hpp"
#include "ssd1306_impl.hpp"
#include "ssd1306_transmission_impl.hpp"

#endif // MODM_SSD1306_HPP
3 changes: 2 additions & 1 deletion src/modm/driver/display/ssd1306.lb
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ def build(env):
env.outbasepath = "modm/src/modm/driver/display"
env.copy("ssd1306.hpp")
env.copy("ssd1306_impl.hpp")
env.copy("ssd1306_transmission_impl.hpp")
env.copy("ssd1306_register.hpp")
env.copy("ssd1306_i2c_transaction_impl.hpp")
Loading

0 comments on commit 3c137ee

Please sign in to comment.