diff --git a/README.md b/README.md
index 9b671e12bf..5ffd35aa59 100644
--- a/README.md
+++ b/README.md
@@ -580,20 +580,21 @@ you specific needs.
PCA9548A |
PCA9685 |
+SH1106 |
SIEMENS-S65 |
SIEMENS-S75 |
SK6812 |
SK9822 |
SSD1306 |
-STUSB4500 |
+STUSB4500 |
SX1276 |
TCS3414 |
TCS3472 |
TLC594X |
TMP102 |
-TMP175 |
+TMP175 |
TOUCH2046 |
VL53L0 |
VL6180 |
diff --git a/src/modm/driver/display/sh1106.hpp b/src/modm/driver/display/sh1106.hpp
new file mode 100644
index 0000000000..92120d7c80
--- /dev/null
+++ b/src/modm/driver/display/sh1106.hpp
@@ -0,0 +1,75 @@
+/*
+ * 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/.
+ */
+// ----------------------------------------------------------------------------
+
+#pragma once
+
+#include "ssd1306.hpp"
+
+namespace modm
+{
+
+/**
+ * SH1106 is said to be 'compatible' with SSD1306. However there's a relevant
+ * difference: SH1106 does only support MemoryMode::PAGE. This requires a little
+ * 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 for SSD1306 in MemoryMode::HORIZONTAL / MemoryMode::VERTICAL
+ *
+ * @ingroup modm_driver_sh1106
+ */
+template
+class Sh1106 : public Ssd1306
+{
+public:
+ Sh1106(uint8_t address = 0x3C) : Ssd1306(address) {}
+
+protected:
+ modm::ResumableResult
+ startWriteDisplay() override
+ {
+ RF_BEGIN();
+
+ 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));
+
+ RF_WAIT_UNTIL(
+ this->transaction.configureDisplayWrite((uint8_t*)&this->buffer[page], 128));
+ RF_WAIT_UNTIL(this->startTransaction());
+ RF_WAIT_WHILE(this->isTransactionRunning());
+ this->transaction_success &= this->wasTransactionSuccessful();
+ };
+
+ RF_END_RETURN(this->transaction_success);
+ }
+
+ modm::ResumableResult
+ initializeMemoryMode() override
+ {
+ RF_BEGIN();
+ // Default on Power-up - can be omitted
+ this->commandBuffer[0] = ssd1306::AdressingCommands::MemoryMode;
+ this->commandBuffer[1] = ssd1306::MemoryMode::PAGE;
+ this->transaction_success &= RF_CALL(this->writeCommands(2));
+ RF_END();
+ }
+
+private:
+ size_t page;
+};
+
+} // namespace modm
diff --git a/src/modm/driver/display/sh1106.lb b/src/modm/driver/display/sh1106.lb
new file mode 100644
index 0000000000..4222f45849
--- /dev/null
+++ b/src/modm/driver/display/sh1106.lb
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 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/.
+# -----------------------------------------------------------------------------
+
+
+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")
diff --git a/src/modm/driver/display/ssd1306.hpp b/src/modm/driver/display/ssd1306.hpp
index 0db73ed44c..e62881d154 100644
--- a/src/modm/driver/display/ssd1306.hpp
+++ b/src/modm/driver/display/ssd1306.hpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2014, 2016-2017, Sascha Schade
* Copyright (c) 2014-2016, 2018, Niklas Hauser
+ * Copyright (c) 2021, Thomas Sommer
*
* This file is part of the modm project.
*
@@ -18,69 +19,15 @@
#include
#include
+#include "ssd1306_register.hpp"
+
namespace modm
{
/// @ingroup modm_driver_ssd1306
-struct ssd1306
+struct ssd1306 : public ssd1306_register
{
-protected:
- /// @cond
- enum Command : uint8_t
- {
- // fundamental commands
- SetContrastControl = 0x81,
- SetChargePump = 0x8D,
- SetEntireDisplayResumeToRam = 0xA4,
- SetEntireDisplayIgnoreRam = 0xA5,
- SetNormalDisplay = 0xA6,
- SetInvertedDisplay = 0xA7,
- SetDisplayOff = 0xAE,
- SetDisplayOn = 0xAF,
-
- // scrolling commands
- SetHorizontalScrollRight = 0x26,
- SetHorizontalScrollLeft = 0x27,
- SetVerticalAndHorizontalScrollRight = 0x29,
- SetVerticalAndHorizontalScrollLeft = 0x2A,
- SetDisableScroll = 0x2E,
- SetEnableScroll = 0x2F,
- SetVerticalScrollArea = 0xA3,
-
- // addressing commands
- SetLowerColumnStartAddress = 0x00,
- SetHigherColumnStartAddress = 0x10,
- SetMemoryMode = 0x20,
- SetColumnAddress = 0x21,
- SetPageAddress = 0x22,
- SetPageStartAddress = 0xB0,
-
- // Hardware configuration
- SetDisplayStartLine = 0x40,
- SetSegmentRemap0 = 0xA0,
- SetSegmentRemap127 = 0xA1,
- SetMultiplexRatio = 0xA8,
- SetComOutputScanDirectionIncrement = 0xC0,
- SetComOutputScanDirectionDecrement = 0xC8,
- SetDisplayOffset = 0xD3,
- SetComPins = 0xDA,
-
- // timing configuration
- SetDisplayClockDivideRatio = 0xD5,
- SetPreChargePeriod = 0xD9,
- SetV_DeselectLevel = 0xDB,
- Nop = 0xE3,
- };
- /// @endcond
-
public:
- enum class
- Rotation : bool
- {
- Normal,
- UpsideDown
- };
-
enum class
ScrollStep : uint8_t
{
@@ -97,37 +44,28 @@ struct ssd1306
enum class
ScrollDirection : uint8_t
{
- Right = SetHorizontalScrollRight,
- Left = SetHorizontalScrollLeft
+ Right = HorizontalScrollRight,
+ Left = HorizontalScrollLeft,
+ // RightBottom = VerticalAndHorizontalScrollRight,
+ // LeftBottom = VerticalAndHorizontalScrollLeft,
};
enum class
DisplayMode : uint8_t
{
- Normal = SetNormalDisplay,
- Inverted = SetInvertedDisplay
+ Normal = NormalDisplay,
+ Inverted = InvertedDisplay
};
-protected:
- /// @cond
- static constexpr uint8_t
- i(ScrollDirection direction) { return uint8_t(direction); }
- static constexpr uint8_t
- i(ScrollStep step) { return uint8_t(step); }
-
public:
- template < uint8_t Height >
- class DataTransmissionAdapter : public modm::I2cWriteTransaction
+ /// @cond
+ class Ssd1306_I2cWriteTransaction : public modm::I2cWriteTransaction
{
public:
- DataTransmissionAdapter(uint8_t address);
-
- void modm_always_inline
- setCommandBuffer(uint8_t *buffer)
- { commands = buffer; }
+ Ssd1306_I2cWriteTransaction(uint8_t address);
bool
- configureDisplayWrite(uint8_t (*buffer)[Height / 8], std::size_t size);
+ configureDisplayWrite(const uint8_t *buffer, std::size_t size);
protected:
virtual Writing
@@ -136,13 +74,16 @@ struct ssd1306
virtual void
detaching(modm::I2c::DetachCause cause) override;
+ inline bool
+ isWritable()
+ { return !transfer_active; }
+
private:
- uint8_t *commands;
- public:
- bool writeable;
+ uint8_t transfer_type;
+ bool transfer_active;
};
/// @endcond
-}; // struct ssd1306
+}; // struct ssd1306
/**
* Driver for SSD1306 based OLED-displays using I2C.
@@ -150,11 +91,13 @@ struct ssd1306
* the frame rate to about 40Hz.
*
* @author Niklas Hauser
+ * @author Thomas Sommer
* @ingroup modm_driver_ssd1306
*/
-template < class I2cMaster, uint8_t Height = 64 >
-class Ssd1306 : public ssd1306, public MonochromeGraphicDisplayVertical<128, Height>,
- public I2cDevice>
+template
+class Ssd1306 : public ssd1306,
+ public MonochromeGraphicDisplayVertical<128, Height>,
+ public I2cDevice
{
static_assert((Height == 64) or (Height == 32), "Display height must be either 32 or 64 pixel!");
@@ -162,34 +105,23 @@ class Ssd1306 : public ssd1306, public MonochromeGraphicDisplayVertical<128, Hei
Ssd1306(uint8_t address = 0x3C);
/// Pings the display
- bool inline
- pingBlocking()
- {
- return RF_CALL_BLOCKING(this->ping());
- }
+ bool inline pingBlocking()
+ { return RF_CALL_BLOCKING(this->ping()); }
/// initializes for 3V3 with charge-pump
- bool inline
- initializeBlocking()
- {
- return RF_CALL_BLOCKING(initialize());
- }
+ bool inline initializeBlocking()
+ { return RF_CALL_BLOCKING(initialize()); }
/// Update the display with the content of the RAM buffer.
void
update() override
- {
- RF_CALL_BLOCKING(startWriteDisplay());
- }
+ { RF_CALL_BLOCKING(startWriteDisplay()); }
/// Use this method to synchronize writing to the displays buffer
/// to avoid tearing.
/// @return `true` if the frame buffer is not being copied to the display
- bool modm_always_inline
- isWritable()
- {
- return this->transaction.writeable;
- }
+ bool isWritable()
+ { return this->transaction.isWriteable(); }
// MARK: - TASKS
/// initializes for 3V3 with charge-pump asynchronously
@@ -197,62 +129,63 @@ class Ssd1306 : public ssd1306, public MonochromeGraphicDisplayVertical<128, Hei
initialize();
// starts a frame transfer and waits for completion
- modm::ResumableResult
+ virtual modm::ResumableResult
writeDisplay();
-
- modm::ResumableResult modm_always_inline
+ modm::ResumableResult
setDisplayMode(DisplayMode mode = DisplayMode::Normal)
- { return writeCommand(static_cast(mode)); }
+ {
+ commandBuffer[0] = mode;
+ return writeCommands(1);
+ }
- modm::ResumableResult modm_always_inline
+ modm::ResumableResult
setContrast(uint8_t contrast = 0xCE)
- { return writeCommand(Command::SetContrastControl, contrast); }
+ {
+ commandBuffer[0] = FundamentalCommands::ContrastControl;
+ commandBuffer[1] = contrast;
+ return writeCommands(2);
+ }
+ /**
+ * \param orientation glcd::Orientation::Landscape0 or glcd::Orientation::Landscape180
+ */
modm::ResumableResult
- setOrientation(glcd::Orientation orientation = glcd::Orientation::Landscape0);
-
+ setOrientation(glcd::Orientation orientation);
modm::ResumableResult
- configureScroll(uint8_t origin, uint8_t size,
- ScrollDirection direction, ScrollStep steps);
+ configureScroll(uint8_t origin, uint8_t size, ScrollDirection direction, ScrollStep steps);
- modm::ResumableResult modm_always_inline
+ modm::ResumableResult
enableScroll()
- { return writeCommand(Command::SetEnableScroll); }
+ {
+ commandBuffer[0] = ScrollingCommands::EnableScroll;
+ return writeCommands(1);
+ }
- modm::ResumableResult modm_always_inline
+ modm::ResumableResult
disableScroll()
- { return writeCommand(Command::SetDisableScroll); }
+ {
+ commandBuffer[0] = ScrollingCommands::DisableScroll;
+ return writeCommands(1);
+ }
protected:
- /// Write a command without data
modm::ResumableResult
- writeCommand(uint8_t command);
+ writeCommands(std::size_t length);
- /// Write a command with one byte data
- modm::ResumableResult
- writeCommand(uint8_t command, uint8_t data);
-
- /// Write a command with two bytes data
- modm::ResumableResult
- writeCommand(uint8_t command, uint8_t data1, uint8_t data2);
+ virtual modm::ResumableResult
+ initializeMemoryMode();
-private:
- modm::ResumableResult
+ virtual modm::ResumableResult
startWriteDisplay();
- bool
- startTransactionWithLength(uint8_t length);
-
-private:
- uint8_t commandBuffer[14];
+ uint8_t commandBuffer[7];
+ bool transaction_success;
};
-} // namespace modm
+} // namespace modm
#include "ssd1306_impl.hpp"
-#include "ssd1306_transmission_impl.hpp"
-
-#endif // MODM_SSD1306_HPP
+#endif // MODM_SSD1306_HPP
diff --git a/src/modm/driver/display/ssd1306.lb b/src/modm/driver/display/ssd1306.lb
index 8868c522eb..0b138e8811 100644
--- a/src/modm/driver/display/ssd1306.lb
+++ b/src/modm/driver/display/ssd1306.lb
@@ -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.cpp")
diff --git a/src/modm/driver/display/ssd1306_i2c_transaction_impl.cpp b/src/modm/driver/display/ssd1306_i2c_transaction_impl.cpp
new file mode 100644
index 0000000000..7ab1876784
--- /dev/null
+++ b/src/modm/driver/display/ssd1306_i2c_transaction_impl.cpp
@@ -0,0 +1,52 @@
+// coding: utf-8
+/*
+ * Copyright (c) 2015, Niklas Hauser
+ * Copyright (c) 2017, Sascha Schade
+ * 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/.
+ */
+// ----------------------------------------------------------------------------
+#include "ssd1306.hpp"
+
+// ----------------------------------------------------------------------------
+modm::ssd1306::Ssd1306_I2cWriteTransaction::Ssd1306_I2cWriteTransaction(uint8_t address) :
+ I2cWriteTransaction(address), transfer_type(ssd1306::Transfer::COMMAND_BURST), transfer_active(false)
+{}
+
+bool
+modm::ssd1306::Ssd1306_I2cWriteTransaction::configureDisplayWrite(const uint8_t *buffer, std::size_t size)
+{
+ if (I2cWriteTransaction::configureWrite(buffer, size))
+ {
+ transfer_type = Transfer::DATA_BURST;
+ return true;
+ }
+ return false;
+}
+
+modm::I2cTransaction::Writing
+modm::ssd1306::Ssd1306_I2cWriteTransaction::writing()
+{
+ if (!transfer_active)
+ {
+ transfer_active = true;
+ return Writing(&transfer_type, 1, OperationAfterWrite::Write);
+ }
+ return I2cWriteTransaction::writing();
+}
+
+void
+modm::ssd1306::Ssd1306_I2cWriteTransaction::detaching(modm::I2c::DetachCause cause)
+{
+ I2cWriteTransaction::detaching(cause);
+ if (transfer_active or (cause != modm::I2c::DetachCause::NormalStop))
+ {
+ transfer_type = Transfer::COMMAND_BURST;
+ transfer_active = false;
+ }
+}
diff --git a/src/modm/driver/display/ssd1306_impl.hpp b/src/modm/driver/display/ssd1306_impl.hpp
index aa884659d2..cde8634f40 100644
--- a/src/modm/driver/display/ssd1306_impl.hpp
+++ b/src/modm/driver/display/ssd1306_impl.hpp
@@ -10,64 +10,106 @@
// ----------------------------------------------------------------------------
#ifndef MODM_SSD1306_HPP
-# error "Don't include this file directly, use 'ssd1306.hpp' instead!"
+#error "Don't include this file directly, use 'ssd1306.hpp' instead!"
#endif
-template < class I2cMaster, uint8_t Height >
+template
modm::Ssd1306::Ssd1306(uint8_t address)
-: I2cDevice>(address),
- commandBuffer{0x80, 0, 0x80, 0, 0x80, 0, 0x80, 0, 0x80, 0, 0x80, 0, 0x80, 0}
-{
- this->transaction.setCommandBuffer(commandBuffer);
-}
+ : I2cDevice(address)
+{}
// ----------------------------------------------------------------------------
// MARK: - Tasks
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
modm::Ssd1306::initialize()
{
RF_BEGIN();
+ transaction_success = true;
+
+ commandBuffer[0] = FundamentalCommands::DisplayOff;
+ commandBuffer[1] = TimingAndDrivingCommands::DisplayClockDivideRatio;
+ commandBuffer[2] = 8 << 4; // Frequency (influences scrolling speed too)
+ commandBuffer[2] |= 0; // Prescaler
+ commandBuffer[3] = HardwareConfigCommands::MultiplexRatio;
+ commandBuffer[4] = 63; // Range 0-63
+ commandBuffer[5] = HardwareConfigCommands::DisplayOffset;
+ commandBuffer[6] = 0; // Range 0-63
+ transaction_success &= RF_CALL(writeCommands(7));
+
+ RF_CALL(initializeMemoryMode());
+
+ commandBuffer[0] = TimingAndDrivingCommands::ChargePump;
+ commandBuffer[1] = ChargePump::V7_5;
+ commandBuffer[2] = HardwareConfigCommands::SegmentRemap127;
+ commandBuffer[3] = HardwareConfigCommands::ComOutputScanDirectionDecrement;
+ commandBuffer[4] = HardwareConfigCommands::DisplayStartLine;
+ commandBuffer[4] |= 0; // Range 0-63
+ transaction_success &= RF_CALL(writeCommands(5));
+
+ commandBuffer[0] = HardwareConfigCommands::ComPinsOrder;
+ commandBuffer[1] = Height == 64 ? 0x12 : 0x02;
+ commandBuffer[2] = FundamentalCommands::ContrastControl;
+ commandBuffer[3] = 0xCF; // Strange non-linear beahaviour
+ commandBuffer[4] = TimingAndDrivingCommands::PreChargePeriod;
+ commandBuffer[5] = 1; // [3:0] Phase 1 period
+ commandBuffer[5] |= 15 << 4;// [7:4] Phase 2 period
+ transaction_success &= RF_CALL(writeCommands(6));
+
+ commandBuffer[0] = TimingAndDrivingCommands::V_DeselectLevel;
+ commandBuffer[1] = 4 << 4; // [7:4] See Datasheet
+ commandBuffer[2] = ScrollingCommands::DisableScroll;
+ commandBuffer[3] = FundamentalCommands::EntireDisplayResumeToRam;
+ commandBuffer[4] = FundamentalCommands::NormalDisplay;
+ transaction_success &= RF_CALL(writeCommands(5));
+
+ commandBuffer[0] = FundamentalCommands::DisplayOn;
+ transaction_success &= RF_CALL(writeCommands(1));
+
+ RF_END_RETURN(transaction_success);
+}
+
+/**
+ * @brief MemoryMode::HORIZONTAL and MemoryMode::VERTICAL
+ * have the best performance cause the whole buffer
+ * is send in one transaction.
+ */
+template
+modm::ResumableResult
+modm::Ssd1306::initializeMemoryMode()
+{
+ RF_BEGIN();
+ commandBuffer[0] = AdressingCommands::MemoryMode;
+ commandBuffer[1] = MemoryMode::HORIZONTAL;
+ transaction_success &= RF_CALL(writeCommands(2));
+
+ // Default on Power-up - can be omitted
+ commandBuffer[0] = AdressingCommands::ColumnAddress;
+ commandBuffer[1] = 0;
+ commandBuffer[2] = 127;
+ commandBuffer[3] = AdressingCommands::PageAddress;
+ commandBuffer[4] = 0;
+ commandBuffer[5] = 7;
+ transaction_success &= RF_CALL(writeCommands(6));
- commandBuffer[11] = true;
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetDisplayOff));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetDisplayClockDivideRatio, 0xF0));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetMultiplexRatio, 0x3F));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetDisplayOffset, 0x00));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetDisplayStartLine | 0x00));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetChargePump, 0x14));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetMemoryMode, 0x01));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetSegmentRemap127));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetComOutputScanDirectionDecrement));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetComPins, ((Height == 64) ? 0x12 : 0x02)));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetContrastControl, 0xCE));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetPreChargePeriod, 0xF1));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetV_DeselectLevel, 0x40));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetEntireDisplayResumeToRam));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetNormalDisplay));
-// commandBuffer[11] &= RF_CALL(writeCommand(Command::SetColumnAddress, 0, 127));
-// commandBuffer[11] &= RF_CALL(writeCommand(Command::SetPageAddress, 0, 7));
- commandBuffer[11] &= RF_CALL(writeCommand(Command::SetDisplayOn));
-
- RF_END_RETURN(bool(commandBuffer[11]));
+ RF_END();
}
// ----------------------------------------------------------------------------
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
modm::Ssd1306::startWriteDisplay()
{
RF_BEGIN();
RF_WAIT_UNTIL(
- this->transaction.configureDisplayWrite(
- this->buffer,
- this->getBufferWidth() * this->getBufferHeight()) and this->startTransaction());
+ this->transaction.configureDisplayWrite((uint8_t*)(&this->buffer), sizeof(this->buffer)) and
+ this->startTransaction());
RF_END();
}
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
modm::Ssd1306::writeDisplay()
{
@@ -80,26 +122,30 @@ modm::Ssd1306::writeDisplay()
RF_END_RETURN(this->wasTransactionSuccessful());
}
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
modm::Ssd1306::setOrientation(glcd::Orientation orientation)
{
RF_BEGIN();
- if ( RF_CALL(writeCommand((orientation == glcd::Orientation::Landscape0) ?
- Command::SetSegmentRemap127 : Command::SetSegmentRemap0)) )
+ if (orientation == glcd::Orientation::Landscape0)
{
- RF_RETURN_CALL(writeCommand((orientation == glcd::Orientation::Landscape0) ?
- Command::SetComOutputScanDirectionDecrement : Command::SetComOutputScanDirectionIncrement));
+ commandBuffer[0] = HardwareConfigCommands::SegmentRemap127;
+ commandBuffer[1] = HardwareConfigCommands::ComOutputScanDirectionDecrement;
+ }
+ else if (orientation == glcd::Orientation::Landscape180)
+ {
+ commandBuffer[0] = HardwareConfigCommands::SegmentRemap0;
+ commandBuffer[1] = HardwareConfigCommands::ComOutputScanDirectionIncrement;
}
- RF_END_RETURN(false);
+ RF_END_RETURN_CALL(writeCommands(2));
}
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
modm::Ssd1306::configureScroll(uint8_t origin, uint8_t size,
- ScrollDirection direction, ScrollStep steps)
+ ScrollDirection direction, ScrollStep steps)
{
RF_BEGIN();
@@ -112,73 +158,29 @@ modm::Ssd1306::configureScroll(uint8_t origin, uint8_t size,
uint8_t endY = ((origin + size) > 7) ? 7 : (origin + size);
if (endY < beginY) endY = beginY;
- commandBuffer[1] = static_cast(direction);
- commandBuffer[3] = 0x00;
- commandBuffer[5] = beginY;
- commandBuffer[7] = i(steps);
- commandBuffer[9] = endY;
- commandBuffer[11] = 0x00;
- commandBuffer[13] = 0xFF;
+ commandBuffer[0] = uint8_t(direction);
+ commandBuffer[1] = 0x00;
+ commandBuffer[2] = beginY;
+ commandBuffer[3] = uint8_t(steps);
+ commandBuffer[4] = endY;
+ commandBuffer[5] = 0x00;
+ commandBuffer[6] = 0xFF;
}
- RF_WAIT_UNTIL( startTransactionWithLength(14) );
-
- RF_WAIT_WHILE(this->isTransactionRunning());
-
- RF_END_RETURN(this->wasTransactionSuccessful());
+ RF_END_RETURN_CALL(writeCommands(7));
}
// ----------------------------------------------------------------------------
// MARK: write command
-template < class I2cMaster, uint8_t Height >
+template
modm::ResumableResult
-modm::Ssd1306::writeCommand(uint8_t command)
+modm::Ssd1306::writeCommands(std::size_t length)
{
RF_BEGIN();
- commandBuffer[1] = command;
- RF_WAIT_UNTIL( startTransactionWithLength(2) );
+ RF_WAIT_UNTIL(this->startWrite(commandBuffer, length));
- RF_WAIT_WHILE( this->isTransactionRunning() );
-
- RF_END_RETURN( this->wasTransactionSuccessful() );
-}
-
-template < class I2cMaster, uint8_t Height >
-modm::ResumableResult
-modm::Ssd1306::writeCommand(uint8_t command, uint8_t data)
-{
- RF_BEGIN();
-
- commandBuffer[1] = command;
- commandBuffer[3] = data;
- RF_WAIT_UNTIL( startTransactionWithLength(4) );
-
- RF_WAIT_WHILE( this->isTransactionRunning() );
-
- RF_END_RETURN( this->wasTransactionSuccessful() );
-}
-
-template < class I2cMaster, uint8_t Height >
-modm::ResumableResult
-modm::Ssd1306::writeCommand(uint8_t command, uint8_t data1, uint8_t data2)
-{
- RF_BEGIN();
-
- commandBuffer[1] = command;
- commandBuffer[3] = data1;
- commandBuffer[5] = data2;
- RF_WAIT_UNTIL( startTransactionWithLength(6) );
-
- RF_WAIT_WHILE( this->isTransactionRunning() );
-
- RF_END_RETURN( this->wasTransactionSuccessful() );
-}
+ RF_WAIT_WHILE(this->isTransactionRunning());
-// ----------------------------------------------------------------------------
-template < class I2cMaster, uint8_t Height >
-bool
-modm::Ssd1306::startTransactionWithLength(uint8_t length)
-{
- return this->startWrite(commandBuffer, length);
+ RF_END_RETURN(this->wasTransactionSuccessful());
}
diff --git a/src/modm/driver/display/ssd1306_register.hpp b/src/modm/driver/display/ssd1306_register.hpp
new file mode 100644
index 0000000000..37d8ea0e5b
--- /dev/null
+++ b/src/modm/driver/display/ssd1306_register.hpp
@@ -0,0 +1,99 @@
+/*
+ * 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/.
+ */
+// ----------------------------------------------------------------------------
+
+#pragma once
+
+namespace modm
+{
+
+struct ssd1306_register
+{
+protected:
+ enum Transfer : uint8_t
+ {
+ COMMAND_BURST = 0x00,
+ DATA_BURST = 0x40,
+ COMMAND = 0x80,
+ DATA = 0xC0
+ };
+
+ enum FundamentalCommands : uint8_t
+ {
+ ContrastControl = 0x81, // Range 1-255
+ EntireDisplayResumeToRam = 0xA4,
+ EntireDisplayIgnoreRam = 0xA5,
+ NormalDisplay = 0xA6,
+ InvertedDisplay = 0xA7,
+ DisplayOff = 0xAE,
+ DisplayOn = 0xAF,
+ };
+
+ 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 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 ScrollingCommands : uint8_t
+ {
+ HorizontalScrollRight = 0x26,
+ HorizontalScrollLeft = 0x27,
+ VerticalAndHorizontalScrollRight = 0x29,
+ VerticalAndHorizontalScrollLeft = 0x2A,
+ VerticalScrollArea = 0xA3,
+ DisableScroll = 0x2E,
+ EnableScroll = 0x2F,
+ };
+
+ enum MemoryMode : uint8_t
+ {
+ HORIZONTAL = 0,
+ VERTICAL = 1,
+ PAGE = 2
+ };
+
+ 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,
+ };
+};
+
+} // namespace modm
diff --git a/src/modm/driver/display/ssd1306_transmission_impl.hpp b/src/modm/driver/display/ssd1306_transmission_impl.hpp
deleted file mode 100644
index 3b59501053..0000000000
--- a/src/modm/driver/display/ssd1306_transmission_impl.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-// coding: utf-8
-/*
- * Copyright (c) 2015, Niklas Hauser
- * Copyright (c) 2017, Sascha Schade
- *
- * 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_SSD1306_HPP
-# error "Don't include this file directly, use 'ssd1306.hpp' instead!"
-#endif
-
-// ----------------------------------------------------------------------------
-template < uint8_t Height >
-modm::ssd1306::DataTransmissionAdapter::DataTransmissionAdapter(uint8_t address) :
- I2cWriteTransaction(address), writeable(true)
-{}
-
-template < uint8_t Height >
-bool
-modm::ssd1306::DataTransmissionAdapter::configureDisplayWrite(uint8_t (*buffer)[Height / 8], std::size_t size)
-{
- if (I2cWriteTransaction::configureWrite(&buffer[0][0], size))
- {
- commands[13] = 0xfe;
- writeable = false;
- return true;
- }
- return false;
-}
-
-template < uint8_t Height >
-modm::I2cTransaction::Writing
-modm::ssd1306::DataTransmissionAdapter::writing()
-{
- // we first tell the display the column address again
- if (commands[13] == 0xfe)
- {
- commands[1] = Command::SetColumnAddress;
- commands[3] = 0;
- commands[5] = 127;
- commands[13] = 0xfd;
- return Writing(commands, 6, OperationAfterWrite::Restart);
- }
- // then the page address. again.
- if (commands[13] == 0xfd)
- {
- commands[1] = Command::SetPageAddress;
- commands[3] = (Height == 64 ? 0 : 4);
- commands[5] = 7;
- commands[13] = 0xfc;
- return Writing(commands, 6, OperationAfterWrite::Restart);
- }
- // then we set the D/C bit to tell it data is coming
- if (commands[13] == 0xfc)
- {
- commands[13] = 0x40;
- return Writing(&commands[13], 1, OperationAfterWrite::Write);
- }
-
- // now we write the entire frame buffer into it.
- return Writing(buffer, size, OperationAfterWrite::Stop);
-}
-
-template < uint8_t Height >
-void
-modm::ssd1306::DataTransmissionAdapter::detaching(modm::I2c::DetachCause cause)
-{
- I2cWriteTransaction::detaching(cause);
- if ((commands[13] == 0x40) or (cause != modm::I2c::DetachCause::NormalStop))
- {
- commands[13] = 0;
- writeable = true;
- }
-}