Commit 4791f7b0b4144d27c60407086bf68cff27f711d0
receivedFri, 2. Aug 2024, 18:44:25 (by user sx)
Fri, 2 Aug 2024 16:44:25 +0000 (18:44 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Fri, 2 Aug 2024 16:44:18 +0000 (18:44 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Fri, 2 Aug 2024 16:44:18 +0000 (18:44 +0200)
13 files changed:
software/test_2024-07-23/src/adafruit/bme280.cpp
software/test_2024-07-23/src/adafruit/bme280.h
software/test_2024-07-23/src/adafruit/ens160.cpp
software/test_2024-07-23/src/adafruit/ens160.h
software/test_2024-07-23/src/i2cdevice.cpp [deleted file]
software/test_2024-07-23/src/i2cdevice.hpp [deleted file]
software/test_2024-07-23/src/i2cmaster.cpp [new file with mode: 0644]
software/test_2024-07-23/src/i2cmaster.hpp [new file with mode: 0644]
software/test_2024-07-23/src/i2cslave.cpp [new file with mode: 0644]
software/test_2024-07-23/src/i2cslave.hpp [new file with mode: 0644]
software/test_2024-07-23/src/main.cpp
software/test_2024-07-23/src/units/i2c.cpp
software/test_2024-07-23/src/units/i2c.hpp

index 6ff5bc8394edb10bb98486f42e20e886064105cc..95a0f49e5f7293d5c195d66d4a4d4487e5849d1d 100644 (file)
@@ -8,7 +8,7 @@ Adafruit_BME280_Pressure bm280PressureSensor;
 Adafruit_BME280_Humidity bm280HumiditySensor;
 
 Adafruit_BME280::Adafruit_BME280() {
-       static I2cDevice i2cDevice;
+       static I2cMaster i2cDevice;
        t_fine_adjust = 0;
        temp_sensor = &bm280TempSensor;
        pressure_sensor = &bm280PressureSensor;
index 94c3927a6449957c138befce9b08576a14c5ea95..b842782afb6881c18ec5d62c0d3ec380a6fc3762 100644 (file)
@@ -30,7 +30,7 @@
 // #include <Adafruit_Sensor.h>
 
 
-#include "../i2cdevice.hpp"
+#include "../i2cmaster.hpp"
 #include "../main.hpp"
 #define byte uint8_t
 
@@ -246,7 +246,7 @@ public:
   void setTemperatureCompensation(float);
 
 protected:
-  I2cDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
+  I2cMaster *i2c_dev = NULL; ///< Pointer to I2C bus interface
   // Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface
 
   Adafruit_BME280_Temp *temp_sensor;
index 85b98facc83b8b98e51b0d86952055db457f8218..ef23404a5a7880464238afe3590cb6035b42e640 100644 (file)
@@ -12,6 +12,8 @@
 #include "ens160.h"
 #include "math.h"
 #include <util/delay.h>
+#include <stdio.h>
+#include <avr/io.h>
 
 ScioSense_ENS160::ScioSense_ENS160 () {
    _revENS16x = 0;
@@ -30,7 +32,6 @@ ScioSense_ENS160::ScioSense_ENS160 () {
 bool ScioSense_ENS160::begin () {
    i2cDevice.begin(ENS160_I2CADDR_1);
        _delay_ms(ENS160_BOOTING);
-  
        if (reset()) {
       if (checkPartID()) {
          if (setMode(ENS160_OPMODE_IDLE)) {
@@ -93,12 +94,9 @@ bool ScioSense_ENS160::reset () {
 
 // Reads the part ID and confirms valid sensor
 bool ScioSense_ENS160::checkPartID () {
-       uint8_t i2cbuf[2];
        uint16_t part_id;
        
-       read16(ENS160_REG_PART_ID, &part_id);
-       part_id = i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8);
-       
+   read16(ENS160_REG_PART_ID, &part_id);
        _delay_ms(ENS160_BOOTING);
 
        if (part_id == ENS160_PARTID) {
@@ -249,6 +247,15 @@ bool ScioSense_ENS160::addCustomStep (uint16_t time, bool measureHP0, bool measu
        return true;
 }
 
+bool ScioSense_ENS160::readStatus (uint8_t *status) {
+   return read8(ENS160_REG_DATA_STATUS, status);
+}
+
+bool ScioSense_ENS160::readData (ENS160_DATA *data) {
+   uint8_t buffer[1] = { 0x21 };
+   return i2cDevice.write_then_read(buffer, 1, (uint8_t *)data, sizeof(ENS160_DATA));
+}
+       
 // Perform prediction measurement and stores result in internal variables
 bool ScioSense_ENS160::measure (bool waitForNew) {
        uint8_t i2cbuf[8];
@@ -257,10 +264,10 @@ bool ScioSense_ENS160::measure (bool waitForNew) {
        // Set default status for early bail out
        if (waitForNew) {
                do {
-                       _delay_ms(1);
          if (!read8(ENS160_REG_DATA_STATUS, &status)) {
             return false;
          }
+         _delay_ms(1);
                } while (!IS_NEWDAT(status));
        } else {
                if (!read8(ENS160_REG_DATA_STATUS, &status)) {
@@ -268,11 +275,13 @@ bool ScioSense_ENS160::measure (bool waitForNew) {
       }
        }
        
+
        // Read predictions
        if (IS_NEWDAT(status)) {
                if (!readBytes(ENS160_REG_DATA_AQI, i2cbuf, 7)) {
          return false;
       }
+      return false;
                _data_aqi = i2cbuf[0];
                _data_tvoc = i2cbuf[1] | ((uint16_t)i2cbuf[2] << 8);
                _data_eco2 = i2cbuf[3] | ((uint16_t)i2cbuf[4] << 8);
index e3ecdcfd319bbe55c33e31a0657be7c861202224..fb6925daba395187d317e2c63c830da699d28245 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef __SCIOSENSE_ENS160_H_
 #define __SCIOSENSE_ENS160_H_
 
-#include "../i2cdevice.hpp"
+#include "../i2cmaster.hpp"
 #include <stdint.h>
 #define byte uint8_t
 
 #define CONVERT_RS_RAW2OHMS_I(x)       (1 << ((x) >> 11))
 #define CONVERT_RS_RAW2OHMS_F(x)       (pow (2, (float)(x) / 2048))
 
+typedef struct {
+   uint8_t aqi;
+   uint16_t tvoc;
+   uint16_t eco2;
+} ENS160_DATA;
+
 class ScioSense_ENS160 {
                
        public:
@@ -114,8 +120,10 @@ class ScioSense_ENS160 {
                bool                            addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3);
                                                                                                                                                                                        // Add a step to custom measurement profile with definition of duration, enabled data acquisition and temperature for each hotplate
                                                                                                                                                                                        
-               bool                            measure(bool waitForNew = true);                                // Perform measurement and stores result in internal variables
-               bool                            measureRaw(bool waitForNew = true);                             // Perform raw measurement and stores result in internal variables
+      bool  readData (ENS160_DATA *data);
+      bool  readStatus(uint8_t *status);
+               bool                            measure(bool waitForNew);                               // Perform measurement and stores result in internal variables
+               bool                            measureRaw(bool waitForNew);                            // Perform raw measurement and stores result in internal variables
                bool                            set_envdata(float t, float h);                                  // Writes t (degC) and h (%rh) to ENV_DATA. Returns "0" if I2C transmission is successful
                bool                            set_envdata210(uint16_t t, uint16_t h);                         // Writes t and h (in ENS210 format) to ENV_DATA. Returns "0" if I2C transmission is successful
                uint8_t                         getMajorRev()   { return this->_fw_ver_major; }                 // Get major revision number of used firmware
@@ -137,7 +145,7 @@ class ScioSense_ENS160 {
                uint8_t                         getMISR()               { return this->_misr; }                 // Return status code of sensor
 
        private:
-      I2cDevice i2cDevice;
+      I2cMaster i2cDevice;
                bool                            reset();                                                        // Sends a reset to the ENS160. Returns false on I2C problems.
                bool                            checkPartID();                                                  // Reads the part ID and confirms valid sensor
                bool                            clearCommand();                                                 // Initialize idle mode and confirms 
diff --git a/software/test_2024-07-23/src/i2cdevice.cpp b/software/test_2024-07-23/src/i2cdevice.cpp
deleted file mode 100644 (file)
index 47be4af..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#include <avr/io.h>
-#include <stdio.h>
-
-#include "i2cdevice.hpp"
-
-I2cDevice i2cDevice;
-
-I2cDevice::I2cDevice () {
-   address = 0;
-}
-        
-bool I2cDevice::begin (uint8_t addr) {
-   this->address = addr;
-   // TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
-   TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
-   TWCR = (1 << TWEN);
-   return true;
-}
-
-void I2cDevice::end () {
-   TWCR = (1 << TWEN);
-   TWBR = 0;
-}
-
-bool I2cDevice::write (const uint8_t *buffer, uint8_t len) {
-   if (start(false)) {
-      if (writeBytes(buffer, len)) {
-         if (stop()) {
-            return true;
-         }
-      }
-   }
-   return false;
-}
-
-bool I2cDevice::write_then_read (const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len) {
-   if (start(false)) {
-      if (writeBytes(write_buffer, write_len)) {
-         if (start(true)) {
-            if (readBytes(read_buffer, read_len)) {
-               if (stop()) {
-                  return true;
-               }
-            }
-         }
-      }
-   }
-   return false;
-}
-
-bool I2cDevice::readBytes (uint8_t *buffer, uint8_t len) {
-   while (len-- > 0) {
-      if (len > 0) {
-         TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN); // read data byte with ACK enabled
-      } else {
-         TWCR = (1 << TWINT) | (1 << TWEN); // read data byte with ACK disabled
-      }
-      while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
-      uint8_t sr = TWSR & 0xf8;
-      if ((len > 0 && sr != 0x50) || (len == 0 && sr != 0x58)) {
-         return false;
-      }
-      *buffer++ = TWDR;
-   }
-   return true;
-}
-
-bool I2cDevice::writeBytes (const uint8_t *buffer, uint8_t len) {
-   while (len-- > 0) {
-      // printf("[wB:len=%d, byte=%02x]", len + 1, *buffer);
-      TWDR = *buffer++;
-      TWCR = (1 << TWINT) | (1 << TWEN); // send data byte
-      while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
-      //printf("TWSR=%02x", TWSR);
-      if ((TWSR & 0xf8) != 0x28) {
-         return false;
-      }
-   }
-   return true;
-}
-
-bool I2cDevice::writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len) {
-   do {
-      TWDR = byte;
-      TWCR = (1 << TWINT) | (1 << TWEN); // send byte
-      while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
-      if ((TWSR & 0xf8) != 0x28) {
-         return false;
-      }
-      byte = *buffer++;
-   } while (len-- > 0);
-   return true;
-}
-
-bool I2cDevice::start (bool read) {
-   TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition
-   while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
-   uint8_t sr = TWSR & 0xf8;
-   if (sr != 0x08 && sr != 0x10) {
-      return false;
-   }
-   TWDR = (address << 1) | (read ? 1 : 0); // address + R/nW
-   TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW
-   while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
-   sr = TWSR & 0xf8;
-   if ((!read && sr != 0x18) || (read && sr != 0x40)) {
-      return false;
-   }
-   return true;
-}
-
-bool I2cDevice::stop () {
-   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
-   while (TWCR & ( 1 << TWSTO));
-   return true;
-}
-
diff --git a/software/test_2024-07-23/src/i2cdevice.hpp b/software/test_2024-07-23/src/i2cdevice.hpp
deleted file mode 100644 (file)
index e59d737..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef I2C_DEVICE
-#define I2C_DEVICE
-
-#include <stdint.h>
-
-class I2cDevice {
-   public:
-      static void end ();
-   
-   public:
-      I2cDevice ();
-      bool begin (uint8_t addr);
-      bool write(const uint8_t *buffer, uint8_t len);
-      bool write_then_read(const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len);
-      bool writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len);
-
-   private:
-      uint8_t address;
-      bool start (bool read);
-      bool stop ();
-      bool writeBytes (const uint8_t *buffer, uint8_t len);
-      bool readBytes (uint8_t *buffer, uint8_t len);
-};
-
-extern I2cDevice i2cDevice;
-
-#endif
\ No newline at end of file
diff --git a/software/test_2024-07-23/src/i2cmaster.cpp b/software/test_2024-07-23/src/i2cmaster.cpp
new file mode 100644 (file)
index 0000000..21ff990
--- /dev/null
@@ -0,0 +1,143 @@
+#include <avr/io.h>
+#include <stdio.h>
+
+#include "i2cmaster.hpp"
+
+I2cMaster::I2cMaster () {
+   address = 0;
+   timer = 0;
+}
+
+void I2cMaster::tick1ms () {
+   if (timer > 0) {
+      timer--;
+   }
+}
+
+bool I2cMaster::begin (uint8_t addr) {
+   this->address = addr;
+   // TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
+   TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
+   TWCR = (1 << TWEN);
+   return true;
+}
+
+void I2cMaster::end () {
+   TWCR = (1 << TWEN);
+   TWBR = 0;
+}
+
+bool I2cMaster::read (uint8_t *buffer, uint8_t len) {
+   if (start(true)) {
+      if (readBytes(buffer, len)) {
+         if (stop()) {
+            return true;
+         }
+      }
+   }
+   return false;
+}
+
+
+bool I2cMaster::write (const uint8_t *buffer, uint8_t len) {
+   if (start(false)) {
+      if (writeBytes(buffer, len)) {
+         if (stop()) {
+            return true;
+         }
+      }
+   }
+   return false;
+}
+
+bool I2cMaster::writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len) {
+   if (start(false)) {
+      do {
+         TWDR = byte;
+         TWCR = (1 << TWINT) | (1 << TWEN); // send byte
+         while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+         if ((TWSR & 0xf8) != 0x28) {
+            return false;
+         }
+         byte = *buffer++;
+      } while (len-- > 0);
+      return true;
+   }
+   return false;
+}
+
+
+bool I2cMaster::write_then_read (const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len) {
+   if (start(false)) {
+      if (writeBytes(write_buffer, write_len)) {
+         if (start(true)) {
+            if (readBytes(read_buffer, read_len)) {
+               if (stop()) {
+                  return true;
+               }
+            }
+         }
+      }
+   }
+   return false;
+}
+
+// -------------------------------------------------------------
+
+bool I2cMaster::readBytes (uint8_t *buffer, uint8_t len) {
+   while (len-- > 0) {
+      if (len > 0) {
+         TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN); // read data byte with ACK enabled
+      } else {
+         TWCR = (1 << TWINT) | (1 << TWEN); // read data byte with ACK disabled
+      }
+      while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+      uint8_t sr = TWSR & 0xf8;
+      if ((len > 0 && sr != 0x50) || (len == 0 && sr != 0x58)) {
+         return false;
+      }
+      *buffer++ = TWDR;
+   }
+   return true;
+}
+
+bool I2cMaster::writeBytes (const uint8_t *buffer, uint8_t len) {
+   while (len-- > 0) {
+      // printf("[wB:len=%d, byte=%02x]", len + 1, *buffer);
+      TWDR = *buffer++;
+      TWCR = (1 << TWINT) | (1 << TWEN); // send data byte
+      timer = 5;
+      while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
+      if (!timer || (TWSR & 0xf8) != 0x28) {
+         return false;
+      }
+   }
+   return true;
+}
+
+
+bool I2cMaster::start (bool read) {
+   TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition
+   timer = 5;
+   while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
+   uint8_t sr = TWSR & 0xf8;
+   if (!timer || (sr != 0x08 && sr != 0x10)) {
+      return false;
+   }
+   TWDR = (address << 1) | (read ? 1 : 0); // address + R/nW
+   TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW
+   timer = 5;
+   while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
+   sr = TWSR & 0xf8;
+   if (!timer || (!read && sr != 0x18) || (read && sr != 0x40)) {
+      return false;
+   }
+   return true;
+}
+
+bool I2cMaster::stop () {
+   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
+   while (TWCR & ( 1 << TWSTO));
+   return true;
+}
+
diff --git a/software/test_2024-07-23/src/i2cmaster.hpp b/software/test_2024-07-23/src/i2cmaster.hpp
new file mode 100644 (file)
index 0000000..e70326c
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef I2C_MASTER
+#define I2C_MASTER
+
+#include <stdint.h>
+
+class I2cMaster {
+   public:
+      static void end ();
+   
+   public:
+      I2cMaster ();
+      void tick1ms ();
+      bool begin (uint8_t addr);
+      bool read (uint8_t *buffer, uint8_t len);
+      bool write(const uint8_t *buffer, uint8_t len);
+      bool write_then_read(const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len);
+      bool writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len);
+
+   private:
+      uint8_t address;
+      uint8_t timer;
+      bool start (bool read);
+      bool stop ();
+      bool writeBytes (const uint8_t *buffer, uint8_t len);
+      bool readBytes (uint8_t *buffer, uint8_t len);
+};
+
+#endif
\ No newline at end of file
diff --git a/software/test_2024-07-23/src/i2cslave.cpp b/software/test_2024-07-23/src/i2cslave.cpp
new file mode 100644 (file)
index 0000000..2bf6ac2
--- /dev/null
@@ -0,0 +1,92 @@
+#include <avr/io.h>
+#include <stdio.h>
+#include <util/atomic.h>
+
+#include "i2cslave.hpp"
+
+I2cSlave::I2cSlave () {
+   timer = 0;
+   fromMaster.rIndex = 0;
+   fromMaster.wIndex = 0;
+   toMaster.rIndex = 0;
+   toMaster.wIndex = 0;
+}
+
+void I2cSlave::tick1ms () {
+   if (timer > 0) {
+      timer--;
+   }
+}
+
+bool I2cSlave::begin (uint8_t addr, bool acceptGeneralCalls) {
+   if (addr > 127) {
+      return false;
+   }
+   TWAR = addr << 1 | (acceptGeneralCalls ? 1 : 0);
+   TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
+   TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE);
+   return true;
+}
+
+void I2cSlave::end () {
+   TWCR = (1 << TWEN);
+   TWBR = 0;
+}
+
+int I2cSlave::read () {
+   return getByte(fromMaster);
+}
+
+void I2cSlave::write (uint8_t byte) {
+   putByte(toMaster, byte);
+}
+
+
+void I2cSlave::putByte (RingBuffer& buffer, uint8_t byte) {
+   ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      buffer.data[buffer.wIndex++] = byte;
+      if (buffer.wIndex >= sizeof(buffer.data)) {
+         buffer.wIndex = 0;
+      }
+      if (buffer.wIndex == buffer.rIndex) {
+         buffer.rIndex++;
+         if (buffer.rIndex >= sizeof(buffer.data)) {
+            buffer.rIndex = 0;
+         }
+      }
+   }
+}
+
+int I2cSlave::getByte (RingBuffer& buffer) {
+   uint8_t b;
+   ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      if (buffer.rIndex == buffer.wIndex) {
+         return EOF;
+      }
+      b = buffer.data[buffer.rIndex++];
+      if (buffer.rIndex >= sizeof(buffer.data)) {
+         buffer.rIndex = 0;
+      }
+   }
+   return b;
+}
+
+void I2cSlave::handleTWIIsr () {
+   uint8_t sr = TWSR & 0xf8;
+   switch (sr) {
+      case 0x80: { // Previously addressed with own SLA+W; data has been received; ACK has been returned
+         putByte(fromMaster, TWDR);
+         TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // no TWEA -> only one byte accepted
+         break;
+      }
+      case 0xa8: { // Own SLA+R has been received; ACK has been returned
+         int response = getByte(toMaster);;
+         TWDR = response < 0 ? 0x00 : (uint8_t)response;
+         TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // no TWEA -> only one byte accepted
+         break;
+      }
+      default: TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); break;
+   }
+  
+}
+
diff --git a/software/test_2024-07-23/src/i2cslave.hpp b/software/test_2024-07-23/src/i2cslave.hpp
new file mode 100644 (file)
index 0000000..2fe2dc7
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef I2C_SLAVE
+#define I2C_SLAVE
+
+#include <stdint.h>
+
+class I2cSlave {
+   private:
+      typedef struct {
+         uint8_t rIndex;
+         uint8_t wIndex;
+         uint8_t data[8];
+   } RingBuffer;
+
+   public:
+      I2cSlave ();
+      void tick1ms ();
+      bool begin (uint8_t addr, bool acceptGeneralCalls);
+      void end ();
+      void handleTWIIsr ();
+      int read ();
+      void write (uint8_t byte);
+
+   private:
+      uint8_t timer;
+      RingBuffer fromMaster;
+      RingBuffer toMaster;
+      void putByte (RingBuffer& buffer, uint8_t byte);
+      int getByte (RingBuffer& buffer);
+
+};
+
+#endif
\ No newline at end of file
index d64b6e0601473f4c066ed7ec3450294f06721528..c363d6097cd24289be95904b042a37e483c59e99 100644 (file)
@@ -92,9 +92,9 @@ extern "C" {
    Uart1 uart1;
    Modbus modbus;
    Ieee485 ieee485;
-   I2c i2cSparkfun(SparkFunEnvCombo);
-   I2c i2cMaster(Master);
-   I2c i2cSlave(Slave);
+   I2c i2cSparkfun(I2c::SparkFunEnvCombo);
+   I2c i2cMaster(I2c::Master);
+   I2c i2cSlave(I2c::Slave);
 
 }
 
@@ -242,6 +242,9 @@ ISR (TIMER2_COMPA_vect) { // every 100us
          timer1ms--;
       }
       systemMillis++;
+      i2cMaster.tick1ms();
+      i2cSlave.tick1ms();
+      i2cSparkfun.tick1ms();
    }
 
    timer500ms++;
index df1fe75aad807e9d7830a1755d201b2b2ee54ffd..64454cd03a4bf09ab97ef7597a83571e33b9b7bb 100644 (file)
@@ -1,9 +1,10 @@
 #include <stdio.h>
 #include <avr/io.h>
 #include <util/delay.h>
+#include <math.h>
 
 #include "i2c.hpp"
-#include "../i2cdevice.hpp"
+#include "../adafruit/bme280.h"
 #include "../main.hpp"
 
 
@@ -26,6 +27,8 @@ void I2c::cleanup () {
    enabled = false;
    TWCR = (1 << TWEN);
    TWBR = 0;
+   ADMUX = 0;
+   ADCSRA = 0;
 }
 
 int8_t I2c::run (uint8_t subtest) {
@@ -34,10 +37,12 @@ int8_t I2c::run (uint8_t subtest) {
       TWBR = 28; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
       TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
       TWCR = (1 << TWEN);
+      ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
+      ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
       enabled = true;
       printf("init");
 
-   } else if (subtest == 1 && mode == SparkFunEnvCombo) {
+   } else if (subtest == 1 && mode == I2c::SparkFunEnvCombo) {
       printf(" BM280 ... ");
       if (!bm280.begin()) {
          printf("ERROR");
@@ -48,151 +53,150 @@ int8_t I2c::run (uint8_t subtest) {
          printf("ERROR");
          return -1;
       }
+      if (!ens160.setMode(ENS160_OPMODE_STD)) {
+         printf("ERROR");
+         return -1;
+      }
+      if (!ens160.set_envdata(25.0, 65)) {
+         printf("ERROR");
+         return -1;
+      }
+
       printf("OK");
+      float accTemp = 0, accHumidity = 0;
+      int8_t accCount = -1;
 
       do {
+         // BME280 
          float p = bm280.readPressure();
-         printf("\n => pressure: %.3fhPa", (double)p);
+         printf("\n => BM280: P= %.3fbar", (double)p / 100000.0);
          float t = bm280.readTemperature();
-         printf(", temp: %.2f°C", (double)t);
+         printf(", T= %.2f°C", (double)t);
          float h = bm280.readHumidity();
-         printf(", humidity: %.2f%%", (double)h);
-      } while (wait(1000) == EOF);
+         printf(", H= %.2f%%", (double)h);
 
-   } else if (subtest == 1) {
-      int key = EOF;
-      uint8_t buffer[18];
-      int errorCode;
-      while (key == EOF) {
-         printf("\n => START+WRITE -> ");
-         errorCode = startWrite(0x77);
-         if (errorCode > 0) {
-            stop();
-            printf ("ERROR (0x%04x)", errorCode);
-            continue;
+         if (accCount >= 0 && !isnanf(h) && !isnan(t)) {
+            accTemp += t;
+            accHumidity += h;
+            accCount++;
          }
-         printf("OK");
 
-         printf(", DATA 0xd0 ->");
-         errorCode = writeByte(0xd0);
-         if (errorCode > 0) {
-            stop();
-            printf ("ERROR (0x%04x)", errorCode);
-            continue;
-         }
-         printf("OK");
+         bm280.setSampling(
+            Adafruit_BME280::MODE_NORMAL,
+            Adafruit_BME280::SAMPLING_X16,
+            Adafruit_BME280::SAMPLING_X16,
+            Adafruit_BME280::SAMPLING_X16,
+            Adafruit_BME280::FILTER_OFF,
+            Adafruit_BME280::STANDBY_MS_1000
+         );
 
-         printf("\n => RESTART+READ -> ");
-         errorCode = startRead(0x77);
-         if (errorCode > 0) {
-            stop();
-            printf ("ERROR (0x%04x)", errorCode);
-            continue;
+         // ENS160 only activated every 32s to avoid wrong temperature measuerment
+         // if ES160 would be continously active, the temperature would be 4°C higher
+         // -> ES160 has not enough distance to BM280
+         // This solution causes only a +0.3°C higher temperatur value
+         if (accCount < 0 || accCount >= 32) {
+            printf("  | ENS160 (");
+            if (accCount > 0) { 
+               h = accHumidity / accCount;
+               t = accTemp / accCount;
+               accTemp = 0;
+               accHumidity = 0;
+            }
+            accCount = 0;            
+            if (!ens160.set_envdata(t, h)) {
+               printf("E1)");
+            } else {
+               printf("%.1f°C/%.1f%%): ", (double)t, (double)h);
+               if (!ens160.setMode(ENS160_OPMODE_STD)) {
+                  printf("E2");
+               } else {
+                  for (uint8_t i = 0; i < 100; i++) {
+                     _delay_ms(15);
+                     uint8_t status;
+                     if (ens160.readStatus(&status)) {
+                        if (status & ENS160_DATA_STATUS_NEWDAT) {
+                           ENS160_DATA data;
+                           if (ens160.readData(&data)) {
+                              printf(" aqi=%d(", data.aqi);
+                              switch(data.aqi) {
+                                 case 1: printf("excellent"); break;
+                                 case 2: printf("good"); break;
+                                 case 3: printf("moderate"); break;
+                                 case 4: printf("poor"); break;
+                                 case 5: printf("unhealthy"); break;
+                                 default: printf("?"); break;
+                              }
+                              printf("), tvoc=%dppb", data.tvoc);
+                              printf(", eco2=%d(", data.eco2);
+                              if (data.eco2 < 400) {
+                                 printf("?");
+                              } else if (data.eco2 < 600) {
+                                 printf("excellent");
+                              } else if (data.eco2 < 800) {
+                                 printf("good");
+                              } else if (data.eco2 < 1000) {
+                                 printf("fair");
+                              } else if (data.eco2 < 1500) {
+                                 printf("poor");
+                              } else {
+                                 printf("dad");
+                              }
+                              printf(")");
+                           }
+                           break;
+                        }
+                     }
+                  }
+               }
+               if (!ens160.setMode(ENS160_OPMODE_IDLE)) {
+                  printf("E3");
+               }
+            }
          }
-         printf("OK");
 
-         printf(", DATA -> ");
-         errorCode = readData(1, buffer);
-         if (errorCode > 0) {
-            stop();
-            printf ("ERROR (0x%04x)", errorCode);
-            continue;
-         }
-         printf("OK (%02x %02x)", buffer[0], buffer[1]);
+      } while (wait(1000) == EOF);
 
-         printf("\n => read trimming -> ");
-         errorCode = startWrite(0x77);
-         if (errorCode == 0) {
-            errorCode = writeByte(0x88); // dig_T1
-            errorCode = errorCode != 0 ? 0x1000 | errorCode : 0;
-         }
-         if (errorCode == 0) {
-            errorCode = startRead(0x77);
-            errorCode = errorCode != 0 ? 0x2000 | errorCode : 0;
-         }
-         if (errorCode == 0) {
-            errorCode = readData(6, buffer);
-            errorCode = errorCode != 0 ? 0x3000 | errorCode : 0;
+   } else if (subtest == 1 && mode == I2c::Master) {
+      if (!master.begin(0x01)) {
+         printf("E1");
+         return -1;
+      }
+      do {
+         uint8_t buffer[1];
+         // read poti
+         ADCSRA |= (1 << ADSC); // start ADC
+         while (ADCSRA & (1 << ADSC)) {} // wait for result
+         buffer[0] = ADCH;
+         printf("\n write 0x%02x", buffer[0]);
+         if (!master.write(buffer, 1)) {
+            printf(" -> ERROR");
          }
-         if (errorCode == 0) {
-            // bm280.digT[0] = ((uint16_t)buffer[1] << 8) | buffer[0];
-            // bm280.digT[1] = ((uint16_t)buffer[3] << 8) | buffer[2];
-            // bm280.digT[2] = ((uint16_t)buffer[5] << 8) | buffer[4];
-            // printf("  T(%04x %04x %04x)", bm280.digT[0], bm280.digT[1], bm280.digT[2]);
+         printf(",  read ");
+         if (master.read(buffer, 1)) {
+            printf("0x%02x", buffer[0]);   
          } else {
-            stop();
-            printf("ERROR(%04x)", errorCode);
-            continue;
-         }
-
-         printf("\n => set ctrl register f2 and f4");
-         errorCode = startWrite(0x77);
-         errorCode = errorCode != 0 ? 0x1000 | errorCode : 0;
-         if (errorCode == 0) {
-            errorCode = writeByte(0xf2); // ctl_hum
-            errorCode = errorCode != 0 ? 0x2000 | errorCode : 0;
-         }
-         if (errorCode == 0) {
-            errorCode = writeByte(0x01); // oversampling x 1
-            errorCode = errorCode != 0 ? 0x3000 | errorCode : 0;
+            printf(" -> ERROR");
          }
+      } while (wait(1000) == EOF);
+      master.end();
 
-         if (errorCode == 0) {
-            errorCode = startWrite(0x77);
-            errorCode = errorCode != 0 ? 0x4000 | errorCode : 0;
-         }
-         if (errorCode == 0) {
-            errorCode = writeByte(0xf4); // ctl_meas
-            errorCode = errorCode != 0 ? 0x5000 | errorCode : 0;
-         }
-         if (errorCode == 0) {
-            errorCode = writeByte((3 << 4) | (3 << 2) | 3); // oversampling 1, normal mode
-            errorCode = errorCode != 0 ? 0x6000 | errorCode : 0;
+   } else if (subtest == 1 && mode == I2c::Slave) {
+      if (!slave.begin(0x01, false)) {
+         printf("E1");
+         return -1;
+      }
+      do {
+         int fromMaster = slave.read();
+         if (fromMaster != EOF) {
+            ADCSRA |= (1 << ADSC); // start ADC
+            while (ADCSRA & (1 << ADSC)) {} // wait for result
+            slave.write(ADCH);
+            printf("\n => from master: 0x%02x -> to master: 0x%02x", fromMaster, ADCH);
          }
-
-         stop();
-         _delay_us(200);
-
-         do {
-            if (errorCode == 0) {
-               printf("\n => register 0xf7..0xff:");
-               errorCode = startWrite(0x77);
-               errorCode = errorCode != 0 ? 0x7000 | errorCode : 0;
-            }
-            if (errorCode == 0) {
-               errorCode = writeByte(0xf7);
-               errorCode = errorCode != 0 ? 0x8000 | errorCode : 0;
-            }
-            if (errorCode == 0) {
-               errorCode = startRead(0x77);
-               errorCode = errorCode != 0 ? 0x9000 | errorCode : 0;
-            }
-            if (errorCode == 0) {
-               errorCode = readData(8, buffer);
-               errorCode = errorCode != 0 ? 0xa000 | errorCode : 0;
-            }
-            if (errorCode == 0) {
-               for (uint8_t i = 0; i < 8; i++) {
-                  printf(" %02x", buffer[i]);
-               }
-               int32_t adcT = (int32_t)( ((uint32_t)(buffer[3] << 12)) | (uint16_t)(buffer[4] << 4) | (buffer[5] >> 4) );
-               int32_t t = compensateBm280T(adcT);
-               printf("  T=%ld ", t);
-            } else {
-               printf("ERROR (%04x)", errorCode);
-               break;
-            }
-            stop();
-            key = wait(5000);
-         } while (key == EOF);
-
-         stop();
-         printf("\n");
-
-      } while (wait(5000) == EOF);
+      } while (wait(0) == EOF);
+      slave.end();
 
    } else {
-      I2cDevice::end();
       printf("end");
       return -1;
    }
@@ -201,7 +205,14 @@ int8_t I2c::run (uint8_t subtest) {
 }
 
 void I2c::handleTwiIrq () {
-   TWCR |= (1 << TWINT); // clear Interrupt Request
+   if (mode == I2c::Slave) {
+      DDRD |= (1 << PD7);
+      PORTD |= (1 << PD7);
+      slave.handleTWIIsr();
+      PORTD &= ~(1 << PD7);
+   } else {
+      TWCR |= (1 << TWINT); // clear Interrupt Request
+   }
 }
 
 uint16_t I2c::startRead (uint8_t address) {
index 6e4a5334ff261594d9398c4d413c7b74bceec578..b4390383c22b2cf7e37b3b6e9e6c6adc03cb7c75 100644 (file)
@@ -5,21 +5,27 @@
 #include "../main.hpp"
 #include "../adafruit/bme280.h"
 #include "../adafruit/ens160.h"
-
-typedef enum I2cMode { SparkFunEnvCombo, Master, Slave } I2cMode;
+#include "../i2cmaster.hpp"
+#include "../i2cslave.hpp"
 
 
 class I2c : public TestUnit {
+   public:
+      typedef enum I2cMode { SparkFunEnvCombo, Master, Slave } I2cMode;
+
    private:
       I2cMode mode;
       Adafruit_BME280 bm280;
       ScioSense_ENS160 ens160;
+      I2cMaster master;
+      I2cSlave slave;
 
    public:
       bool enabled;
 
    public:
       I2c (I2cMode mode) { enabled = false; this->mode = mode; }
+      void tick1ms () { master.tick1ms(); slave.tick1ms(); }
       virtual void cleanup ();
       virtual int8_t run (uint8_t subtest);
       virtual const char *getName ();