From 5471509e033abcddb078383cc4656af06c265ce6 Mon Sep 17 00:00:00 2001
From: Daniel Friesel <derf@finalrewind.org>
Date: Mon, 15 Oct 2018 16:22:55 +0200
Subject: [PATCH] Enable busy waiting in I2C driver to reach selected I2C clock

---
 include/arch.h                  |  4 ++--
 src/arch/arduino-nano/arch.cc   |  4 ++--
 src/arch/blinkenrocket/arch.cc  |  4 ++--
 src/arch/msp430fr5969lp/arch.cc |  8 ++++----
 src/driver/soft_i2c.cc          | 30 ++++++++++++++++++------------
 5 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/include/arch.h b/include/arch.h
index 8024818..094b230 100644
--- a/include/arch.h
+++ b/include/arch.h
@@ -10,8 +10,8 @@ class Arch {
 		void setup();
 		void idle_loop();
 		void idle();
-		void delay_us(unsigned char const us);
-		void delay_ms(unsigned char const ms);
+		void delay_us(unsigned int const us);
+		void delay_ms(unsigned int const ms);
 };
 
 extern Arch arch;
diff --git a/src/arch/arduino-nano/arch.cc b/src/arch/arduino-nano/arch.cc
index 3009637..b034348 100644
--- a/src/arch/arduino-nano/arch.cc
+++ b/src/arch/arduino-nano/arch.cc
@@ -67,12 +67,12 @@ void Arch::idle(void)
 	asm("wdr");
 }
 
-void Arch::delay_us(unsigned char const us)
+void Arch::delay_us(unsigned int const us)
 {
 	_delay_us(us);
 }
 
-void Arch::delay_ms(unsigned char const ms)
+void Arch::delay_ms(unsigned int const ms)
 {
 	_delay_ms(ms);
 }
diff --git a/src/arch/blinkenrocket/arch.cc b/src/arch/blinkenrocket/arch.cc
index 8042679..1261515 100644
--- a/src/arch/blinkenrocket/arch.cc
+++ b/src/arch/blinkenrocket/arch.cc
@@ -64,12 +64,12 @@ void Arch::idle(void)
 	asm("wdr");
 }
 
-void Arch::delay_us(unsigned char const us)
+void Arch::delay_us(unsigned int const us)
 {
 	_delay_us(us);
 }
 
-void Arch::delay_ms(unsigned char const ms)
+void Arch::delay_ms(unsigned int const ms)
 {
 	_delay_ms(ms);
 }
diff --git a/src/arch/msp430fr5969lp/arch.cc b/src/arch/msp430fr5969lp/arch.cc
index b475c5f..b5b23b6 100644
--- a/src/arch/msp430fr5969lp/arch.cc
+++ b/src/arch/msp430fr5969lp/arch.cc
@@ -93,15 +93,15 @@ extern void loop();
 volatile char run_loop = 0;
 #endif
 
-void Arch::delay_us(unsigned char const us)
+void Arch::delay_us(unsigned int const us)
 {
-	for (int i = 0; i < us/10; i++) {
+	for (unsigned int i = 0; i < us/10; i++) {
 		__delay_cycles(160);
 	}
 }
-void Arch::delay_ms(unsigned char const ms)
+void Arch::delay_ms(unsigned int const ms)
 {
-	for (int i = 0; i < ms; i++) {
+	for (unsigned int i = 0; i < ms; i++) {
 		__delay_cycles(16000);
 	}
 }
diff --git a/src/driver/soft_i2c.cc b/src/driver/soft_i2c.cc
index e69bd2c..39754a3 100644
--- a/src/driver/soft_i2c.cc
+++ b/src/driver/soft_i2c.cc
@@ -27,6 +27,12 @@
 
 #ifndef SOFTI2C_TIMER
 
+#if F_I2C < 50000
+#define I2C_WAIT arch.delay_us((500000UL / F_I2C) - 10)
+#else
+#define I2C_WAIT
+#endif
+
 signed char SoftI2C::setup()
 {
 	SDA_HIGH;
@@ -38,20 +44,20 @@ void SoftI2C::start()
 {
 	SDA_HIGH;
 	SCL_HIGH;
-	//
+	I2C_WAIT;
 	SDA_LOW;
-	//
+	I2C_WAIT;
 	SCL_LOW;
 }
 
 void SoftI2C::stop()
 {
 	SCL_LOW;
-	//
+	I2C_WAIT;
 	SDA_LOW;
-	//
+	I2C_WAIT;
 	SCL_HIGH;
-	//
+	I2C_WAIT;
 	SDA_HIGH;
 }
 
@@ -65,17 +71,17 @@ bool SoftI2C::tx(unsigned char byte)
 			SDA_LOW;
 		}
 		byte <<= 1;
-		//
+		I2C_WAIT;
 		SCL_HIGH;
 		while (!gpio.read(scl)) ;
-		//
+		I2C_WAIT;
 		if (i == 8) {
 			if (!gpio.read(sda)) {
 				got_ack = 1;
 			}
 		}
 		SCL_LOW;
-		//
+		I2C_WAIT;
 	}
 	return got_ack;
 }
@@ -85,16 +91,16 @@ unsigned char SoftI2C::rx(bool send_ack)
 	unsigned char byte = 0;
 	SDA_HIGH;
 	for (unsigned char i = 0; i <= 8; i++) {
-		//
+		I2C_WAIT;
 		SCL_HIGH;
 		while (!gpio.read(scl)) ;
-		//
+		I2C_WAIT;
 		if ((i < 8) && gpio.read(sda)) {
 			byte |= 1 << (7 - i);
 		}
-		//
+		I2C_WAIT;
 		SCL_LOW;
-		//
+		I2C_WAIT;
 		if ((i == 7) && send_ack) {
 			SDA_LOW;
 		} else if ((i == 8) && send_ack) {
-- 
GitLab