diff --git a/README.md b/README.md
index dd5bcb6ca5..a95bece81d 100644
--- a/README.md
+++ b/README.md
@@ -179,58 +179,59 @@ can easily configure them for you specific needs.
BME280 |
BMP085 |
BNO055 |
+CAT24AA |
DRV832X |
-DS1302 |
+DS1302 |
DS1631 |
DS18B20 |
EA-DOG |
FT245 |
FT6X06 |
-HCLAx |
+HCLAx |
HD44780 |
HMC58x |
HMC6343 |
I2C-EEPROM |
ITG3200 |
-L3GD20 |
+L3GD20 |
LAWICEL |
LIS302DL |
LIS3DSH |
LM75 |
LSM303A |
-LTC2984 |
+LTC2984 |
MAX6966 |
MAX7219 |
MCP23X17 |
MCP2515 |
NOKIA5110 |
-NRF24 |
+NRF24 |
TFT-DISPLAY |
PAT9125EL |
PCA8574 |
PCA9535 |
PCA9548A |
-PCA9685 |
+PCA9685 |
SIEMENS-S65 |
SIEMENS-S75 |
SK6812 |
SK9822 |
SSD1306 |
-TCS3414 |
+TCS3414 |
TCS3472 |
TLC594X |
TMP102 |
TMP175 |
VL53L0 |
-VL6180 |
+VL6180 |
WS2812 |
diff --git a/src/modm/driver/storage/cat24aa.cpp b/src/modm/driver/storage/cat24aa.cpp
new file mode 100644
index 0000000000..d8a583f2a5
--- /dev/null
+++ b/src/modm/driver/storage/cat24aa.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, Mike Wolfram
+ *
+ * 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 "cat24aa.hpp"
+
+modm::cat24Aa::DataTransmissionAdapter::DataTransmissionAdapter(uint8_t address) :
+ I2cWriteReadTransaction(address), writeAddress(false)
+{}
+
+bool
+modm::cat24Aa::DataTransmissionAdapter::configureWrite(uint16_t address,
+ const uint8_t *buffer, std::size_t size)
+{
+ if (I2cWriteReadTransaction::configureWrite(buffer, size))
+ {
+ addressBuffer[0] = uint8_t(address & 0xff);
+ writeAddress = true;
+ return true;
+ }
+ return false;
+}
+
+bool
+modm::cat24Aa::DataTransmissionAdapter::configureRead(uint16_t address,
+ uint8_t *buffer, std::size_t size)
+{
+ addressBuffer[0] = uint8_t(address & 0xff);
+ writeAddress = false;
+ return I2cWriteReadTransaction::configureWriteRead(addressBuffer, 1, buffer, size);
+}
+
+modm::I2cTransaction::Writing
+modm::cat24Aa::DataTransmissionAdapter::writing()
+{
+ if (writeAddress)
+ {
+ writeAddress = false;
+ return Writing(addressBuffer, 1, OperationAfterWrite::Write);
+ }
+ return I2cWriteReadTransaction::writing();
+}
diff --git a/src/modm/driver/storage/cat24aa.hpp b/src/modm/driver/storage/cat24aa.hpp
new file mode 100644
index 0000000000..8788726a80
--- /dev/null
+++ b/src/modm/driver/storage/cat24aa.hpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2020, Mike Wolfram
+ *
+ * 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_CAT24AA_HPP
+#define MODM_CAT24AA_HPP
+
+#include
+#include
+
+namespace modm
+{
+
+/// @cond
+struct cat24Aa {
+ class DataTransmissionAdapter : public modm::I2cWriteReadTransaction
+ {
+ public:
+ DataTransmissionAdapter(uint8_t address = 0x50);
+
+ bool
+ configureWrite(uint16_t address, const uint8_t *buffer, std::size_t size);
+
+ bool
+ configureRead(uint16_t address, uint8_t *buffer, std::size_t size);
+
+ inline static constexpr uint8_t getAddress() {
+ return 0x50;
+ }
+
+ protected:
+ virtual Writing
+ writing() override;
+
+ uint8_t addressBuffer[1];
+ bool writeAddress;
+ };
+};
+/// @endcond
+
+/**
+ * I2C Eeprom CAT24AA
+ *
+ * Driver for OnSemi CAT24AA Eeprom.
+ * I2C eeprom with an 11-bit address pointer, encoded in 3 bits of the device
+ * slave address plus the address byte.
+ * Base address is fixed to 0x50.
+ *
+ * @ingroup modm_driver_i2c_eeprom
+ * @author Mike Wolfram
+ */
+template
+class Cat24Aa : public modm::I2cDevice
+{
+public:
+ Cat24Aa();
+
+ /**
+ * Write byte
+ *
+ * @param address Address
+ * @param data Data byte
+ *
+ * @return `true` if the data could be written,
+ * `false` otherwise
+ */
+ inline modm::ResumableResult
+ writeByte(uint32_t address, uint8_t data)
+ {
+ return write(address, &data, 1);
+ }
+
+ /**
+ * Write block
+ *
+ * @param address Address
+ * @param data Data block
+ * @param length Number of bytes to be written
+ *
+ * @return `true` if the data could be written,
+ * `false` otherwise
+ */
+ modm::ResumableResult
+ write(uint32_t address, const uint8_t *data, std::size_t length);
+
+ /**
+ * Convenience function
+ *
+ * Shortcut for:
+ * @code
+ * return write(address, static_cast(&data), sizeof(T));
+ * @endcode
+ */
+ template
+ inline modm::ResumableResult
+ write(uint32_t address, const T& data)
+ {
+ return write(address, reinterpret_cast(&data), sizeof(T));
+ }
+
+ /// Read byte
+ inline modm::ResumableResult
+ readByte(uint32_t address, uint8_t &data)
+ {
+ return read(address, &data, 1);
+ }
+
+ /// Read block
+ modm::ResumableResult
+ read(uint32_t address, uint8_t *data, std::size_t length);
+
+ /**
+ * Convenience function
+ *
+ * Shortcut for:
+ * @code
+ * return read(address, static_cast(&data), sizeof(T));
+ * @endcode
+ */
+ template
+ inline modm::ResumableResult
+ read(uint16_t address, T& data)
+ {
+ return read(address, reinterpret_cast(&data), sizeof(T));
+ }
+};
+
+} // namespace modm
+
+#include "cat24aa_impl.hpp"
+
+#endif // MODM_CAT24AA_HPP
diff --git a/src/modm/driver/storage/cat24aa.lb b/src/modm/driver/storage/cat24aa.lb
new file mode 100644
index 0000000000..1fe3cfea32
--- /dev/null
+++ b/src/modm/driver/storage/cat24aa.lb
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2020, Mike Wolfram
+#
+# 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:cat24aa"
+ module.description = """\
+# CAT24AAxx I2C Eeprom
+
+Compatible with the OnSemi CAT24AA I2C eeprom (1 kBit to 16 kBit).
+It uses a 8-bit address pointer, the top 3 bits of the address pointer
+are added to the the slave address, which is fixed to 0x50.
+"""
+
+def prepare(module, options):
+ module.depends(":architecture:i2c.device")
+ return True
+
+def build(env):
+ env.outbasepath = "modm/src/modm/driver/storage"
+ env.copy("cat24aa.hpp")
+ env.copy("cat24aa.cpp")
+ env.copy("cat24aa_impl.hpp")
diff --git a/src/modm/driver/storage/cat24aa_impl.hpp b/src/modm/driver/storage/cat24aa_impl.hpp
new file mode 100644
index 0000000000..863b97b3d5
--- /dev/null
+++ b/src/modm/driver/storage/cat24aa_impl.hpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020, Mike Wolfram
+ *
+ * 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_CAT24AA_HPP
+# error "Don't include this file directly, use 'cat24aa.hpp' instead!"
+#endif
+
+// ----------------------------------------------------------------------------
+template
+modm::Cat24Aa::Cat24Aa() :
+ I2cDevice(0x50)
+{
+}
+
+template
+modm::ResumableResult
+modm::Cat24Aa::write(uint32_t address, const uint8_t *data,
+ std::size_t length)
+{
+ RF_BEGIN();
+
+ this->setAddress(this->transaction.getAddress() | ((address >> 8) & 0x07));
+
+ RF_WAIT_UNTIL( this->transaction.configureWrite(address, data, length) and this->startTransaction() );
+
+ RF_WAIT_WHILE( this->isTransactionRunning() );
+
+ RF_END_RETURN( this->wasTransactionSuccessful() );
+}
+
+template
+modm::ResumableResult
+modm::Cat24Aa::read(uint32_t address, uint8_t *data, std::size_t length)
+{
+ RF_BEGIN();
+
+ this->setAddress(this->transaction.getAddress() | ((address >> 8) & 0x07));
+
+ RF_WAIT_UNTIL( this->transaction.configureRead(address, data, length) and this->startTransaction() );
+
+ RF_WAIT_WHILE( this->isTransactionRunning() );
+
+ RF_END_RETURN( this->wasTransactionSuccessful() );
+}