From 4e11af1da01eff2485ce54e2d77cad9ef5014ec8 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Fri, 15 Dec 2023 21:31:34 +0000 Subject: [PATCH 1/4] =?UTF-8?q?Arduino:=20Use=20400kHz=20clock=20for=20I?= =?UTF-8?q?=C2=B2C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EEPROM in the cartridges support 'Fast I²C' at 400kHz. Testing it out, it seems to work fine despite the high pull-ups, so update the Arduino code to enjoy the 4x speed-up ! --- Arduino/ReceiveCart/ReceiveCart.ino | 1 + Arduino/SendCart/SendCart.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/Arduino/ReceiveCart/ReceiveCart.ino b/Arduino/ReceiveCart/ReceiveCart.ino index b1a41d8..4534669 100644 --- a/Arduino/ReceiveCart/ReceiveCart.ino +++ b/Arduino/ReceiveCart/ReceiveCart.ino @@ -45,6 +45,7 @@ void setup() { Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); Wire.begin(); + Wire.setClock(400000); } void loop() { diff --git a/Arduino/SendCart/SendCart.ino b/Arduino/SendCart/SendCart.ino index 54de478..6bb0292 100644 --- a/Arduino/SendCart/SendCart.ino +++ b/Arduino/SendCart/SendCart.ino @@ -33,6 +33,7 @@ void setup() { Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); Wire.begin(); + Wire.setClock(400000); } /* From a18c37daa18033ffff7923731e49b71826e3d884 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Fri, 15 Dec 2023 22:07:46 +0000 Subject: [PATCH 2/4] Unity: Add delay after serial connection The Arduino will block if sent data too quickly after connection. Add a new coroutine to force waiting for 1s+ and update the UI accordingly. Update some comments throughout. --- Assets/Scripts/Arduino_Com.cs | 41 ++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/Assets/Scripts/Arduino_Com.cs b/Assets/Scripts/Arduino_Com.cs index c5f1bad..16c941d 100644 --- a/Assets/Scripts/Arduino_Com.cs +++ b/Assets/Scripts/Arduino_Com.cs @@ -14,6 +14,7 @@ public class Arduino_Com : MonoBehaviour { Déconnecté, Connecté, + Connexion, Lecture, Écriture, Invalide @@ -68,11 +69,21 @@ public class Arduino_Com : MonoBehaviour return sum; } + // Core communication function. + // Receives all the data from the cartridge and writes it out to the png file. + // As the computer will probably read the serial data faster than the Arduino + // /and/ the transfer is quite slow (lots of bits, low baudrate), make this a + // coroutine. + // This prevents the whole application freezing up why waiting for data and + // allow presenting visual feedback. private IEnumerator ReceiveSerialData() { do { + // We could use an event instead but as Unity is lagging behind .NET versions, + // it wouldn't be cross-platform. yield return new WaitUntil(() => _serial.BytesToRead >= 1); + // Read all available data, up to the PageSize. _readBytes += _serial.Read(_pageBuffer, _readBytes, PageSize - _readBytes); @@ -104,6 +115,7 @@ public class Arduino_Com : MonoBehaviour _readBytes = 0; } } while (_currentPage < PageCount); + // We are done receiving the cart, we don't expect more data to be received so the coroutine can return. _currentPage = 0; _state = ArduinoState.Connecté; @@ -222,14 +234,7 @@ public class Arduino_Com : MonoBehaviour return; } - // TODO: Wait ~2s for Arduino startup - _arduinoControlButton.text = "Déconnecter"; - - _cartLoadButton.SetEnabled(true); - // _cartWriteButton.SetEnabled(true); TODO: Not implemented - _arduinoSerialPort.SetEnabled(false); - - _state = ArduinoState.Connecté; + StartCoroutine(DoSerialConnection()); } } @@ -244,4 +249,24 @@ public class Arduino_Com : MonoBehaviour _state = SerialPort.GetPortNames().Contains(newPort.newValue) ? ArduinoState.Déconnecté : ArduinoState.Invalide; _arduinoControlButton.SetEnabled(_state != ArduinoState.Invalide); } + + // Update UI during connection and when ready, prevent interacting too quickly. + IEnumerator DoSerialConnection() + { + _arduinoControlButton.text = "Connexion..."; + _arduinoControlButton.SetEnabled(false); + _arduinoSerialPort.SetEnabled(false); + _state = ArduinoState.Connexion; + + // Delay enabling transfers because the Arduino is slow to set-up the serial. + yield return new WaitForSeconds(1.5f); + + _arduinoControlButton.text = "Déconnecter"; + _arduinoControlButton.SetEnabled(true); + + _cartLoadButton.SetEnabled(true); + // _cartWriteButton.SetEnabled(true); TODO: Not implemented + + _state = ArduinoState.Connecté; + } } From 91dae1be7ee2fc68e55daeecc493b351850b1f6f Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Sat, 16 Dec 2023 11:45:04 +0000 Subject: [PATCH 3/4] Unity: Fix hardcoded page size in ReceiveSerialData() Remove the hardocded '128' that checked for a full page being received and replace it with the appropriate constant. --- Assets/Scripts/Arduino_Com.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/Arduino_Com.cs b/Assets/Scripts/Arduino_Com.cs index 16c941d..b931200 100644 --- a/Assets/Scripts/Arduino_Com.cs +++ b/Assets/Scripts/Arduino_Com.cs @@ -88,7 +88,7 @@ public class Arduino_Com : MonoBehaviour _readBytes += _serial.Read(_pageBuffer, _readBytes, PageSize - _readBytes); // Full page received, check checksum and ACK/NAK, write received page. - if (_readBytes >= 128) + if (_readBytes >= PageSize) { Byte[] checksum = new byte[2]; // There might be less than the two characters of the checksum available, loop until complete. From 610ccc630aa75e2185f4295e08b395c50bf701b4 Mon Sep 17 00:00:00 2001 From: Teo-CD Date: Sat, 16 Dec 2023 12:30:30 +0000 Subject: [PATCH 4/4] Unity: Use UInt16.MaxValue rather than hardcoding 65536 Unity provides constants that reflect the maximum value of integer types, use it for checking the checksum overflow rather than using 65536 directly. This makes the intent more clear. --- Assets/Scripts/Arduino_Com.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/Arduino_Com.cs b/Assets/Scripts/Arduino_Com.cs index b931200..bf7a9a3 100644 --- a/Assets/Scripts/Arduino_Com.cs +++ b/Assets/Scripts/Arduino_Com.cs @@ -99,7 +99,8 @@ public class Arduino_Com : MonoBehaviour } while (checksumRead < 2); // Implicit type of the sum is 4 bytes, so the overflow doesn't occur. Compute manually. - if (65536 - (BitConverter.ToUInt16(checksum) + ComputeChecksum(_pageBuffer)) == 0) + if ((UInt16.MaxValue + 1) - + (BitConverter.ToUInt16(checksum) + ComputeChecksum(_pageBuffer)) == 0) { // Checksum valid, write it out to the cart. _cart.Write(_pageBuffer);