From 178835c160940772341615dab7a239c45a875807 Mon Sep 17 00:00:00 2001
From: Daniel Friesel <derf@finalrewind.org>
Date: Tue, 7 Aug 2018 17:31:59 +0200
Subject: [PATCH] Add AM2320 driver

---
 Makefile                  |  5 ++++
 include/driver/am2320.h   | 22 ++++++++++++++
 src/app/i2cdetect/main.cc | 14 +++++++++
 src/driver/am2320.cc      | 61 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+)
 create mode 100644 include/driver/am2320.h
 create mode 100644 src/driver/am2320.cc

diff --git a/Makefile b/Makefile
index 466cebc..4e74e6a 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,11 @@ ifneq ($(findstring lm75,${drivers}), )
 	COMMON_FLAGS += -DDRIVER_LM75
 endif
 
+ifneq ($(findstring am2320,${drivers}), )
+	TARGETS += src/driver/am2320.cc
+	COMMON_FLAGS += -DDRIVER_AM2320
+endif
+
 ifneq ($(findstring max44006,${drivers}), )
 	TARGETS += src/driver/max44006.cc
 	COMMON_FLAGS += -DDRIVER_MAX44006
diff --git a/include/driver/am2320.h b/include/driver/am2320.h
new file mode 100644
index 0000000..39c5f7e
--- /dev/null
+++ b/include/driver/am2320.h
@@ -0,0 +1,22 @@
+#ifndef AM2320_H
+#define AM2320_H
+
+class AM2320 {
+	private:
+		AM2320(const AM2320 &copy);
+		unsigned char const address;
+		unsigned char txbuf[3];
+		unsigned char rxbuf[8];
+
+	public:
+		AM2320(unsigned char const addr) : address(addr) {}
+
+		void read();
+		unsigned char getStatus();
+		float getTemp();
+		float getHumidity();
+};
+
+extern AM2320 am2320;
+
+#endif
diff --git a/src/app/i2cdetect/main.cc b/src/app/i2cdetect/main.cc
index 141c65a..5094fd5 100644
--- a/src/app/i2cdetect/main.cc
+++ b/src/app/i2cdetect/main.cc
@@ -9,6 +9,9 @@
 #ifdef DRIVER_LM75
 #include "driver/lm75.h"
 #endif
+#ifdef DRIVER_AM2320
+#include "driver/am2320.h"
+#endif
 #ifdef DRIVER_MAX44009
 #include "driver/max44009.h"
 #endif
@@ -22,6 +25,17 @@ void loop(void)
 	kout.printf_float(lm75.getTemp());
 	kout << endl;
 #endif
+#ifdef DRIVER_AM2320
+	am2320.read();
+	if (am2320.getStatus() == 0) {
+		kout.printf_float(am2320.getTemp());
+		kout << " degC @ ";
+		kout.printf_float(am2320.getHumidity());
+		kout << " rel%" << endl;
+	} else {
+		kout << "AM2320 error " << dec << am2320.getStatus() << endl;
+	}
+#endif
 #ifdef DRIVER_MAX44009
 	kout.printf_float(max44009.getLux());
 	kout << endl;
diff --git a/src/driver/am2320.cc b/src/driver/am2320.cc
new file mode 100644
index 0000000..25e2ffe
--- /dev/null
+++ b/src/driver/am2320.cc
@@ -0,0 +1,61 @@
+#include "driver/am2320.h"
+#if defined(MULTIPASS_ARCH_HAS_I2C) && !defined(DRIVER_SOFTI2C)
+#include "driver/i2c.h"
+#else
+#include "driver/soft_i2c.h"
+#endif
+#include "arch.h"
+
+void AM2320::read()
+{
+	txbuf[0] = 0;
+	i2c.xmit(address, 1, txbuf, 0, rxbuf);
+	arch.delay_ms(1);
+	txbuf[0] = 3;
+	txbuf[1] = 0;
+	txbuf[2] = 4;
+	rxbuf[3] = rxbuf[4] = rxbuf[5] = rxbuf[6] = 0;
+	i2c.xmit(address, 3, txbuf, 0, rxbuf);
+	arch.delay_ms(3);
+	i2c.xmit(address, 0, txbuf, 8, rxbuf);
+}
+
+unsigned char AM2320::getStatus()
+{
+	if (rxbuf[0] != 3) {
+		return 1;
+	}
+	if (rxbuf[1] != 4) {
+		return 2;
+	}
+	unsigned short checksum = 0xffff;
+	for (unsigned char i = 0; i < 6; i++) {
+		checksum ^= rxbuf[i] & 0x00ff;
+		for (unsigned char j = 0; j < 8; j++) {
+			if (checksum & 0x0001) {
+				checksum = (checksum >> 1) ^ 0xa001;
+			} else {
+				checksum >>= 1;
+			}
+		}
+	}
+	if ((rxbuf[6] != (checksum & 0x00ff)) || (rxbuf[7] != (checksum >> 8) & 0x00ff)) {
+		return 3;
+	}
+	return 0;
+}
+
+float AM2320::getTemp()
+{
+	if (txbuf[5] & 0x80) {
+		return (-256 * (rxbuf[4] & 0x7f) + rxbuf[5]) / 10.;
+	}
+	return (256 * rxbuf[4] + rxbuf[5]) / 10.;
+}
+
+float AM2320::getHumidity()
+{
+	return (rxbuf[2] * 256 + rxbuf[3]) / 10.;
+}
+
+AM2320 am2320(0x5c);
-- 
GitLab