diff --git a/code/firmware/SerialIO/SerialIO.ino b/code/firmware/SerialIO/SerialIO.ino
index e153ed2..9973b9b 100644
--- a/code/firmware/SerialIO/SerialIO.ino
+++ b/code/firmware/SerialIO/SerialIO.ino
@@ -102,8 +102,8 @@ void display_boot_message()
Serial.print(VT100_RESET_CURSOR);
Serial.print(VT100_OFF);
Serial.print(VT100_DEFAULT);
- Serial.println("+-----------------------+");
- Serial.print("| ");
+ Serial.println("+------------------------+");
+ Serial.print("| ");
Serial.print(VT100_OFF);
Serial.print(VT100_BOLD);
Serial.print("APPLE 1 MINI");
@@ -112,10 +112,10 @@ void display_boot_message()
Serial.println(" |");
Serial.print(VT100_OFF);
Serial.print(VT100_DEFAULT);
- Serial.println("|-----------------------|");
- Serial.println("| FIRMWARE VERSION 1.0 |");
- Serial.println("| RUUD VAN FALIER, 2017 |");
- Serial.println("+-----------------------+");
+ Serial.println("|------------------------|");
+ Serial.println("| FIRMWARE VERSION 1.0 |");
+ Serial.println("| RUUD VAN FALIER, 2017 |");
+ Serial.println("+------------------------+");
Serial.println();
Serial.println("READY...");
Serial.println();
diff --git a/code/utilities/DataUploader/DataUploader.exe b/code/utilities/DataUploader/DataUploader.exe
new file mode 100644
index 0000000..4783f18
Binary files /dev/null and b/code/utilities/DataUploader/DataUploader.exe differ
diff --git a/code/utilities/DataUploader/DataUploader/Program.cs b/code/utilities/DataUploader/DataUploader/Program.cs
deleted file mode 100644
index 7a65d07..0000000
--- a/code/utilities/DataUploader/DataUploader/Program.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.IO.Ports;
-using System.Text;
-using System.Threading;
-using System.Windows.Forms;
-
-namespace DataUploader
-{
- class Program
- {
- private const string PORT = "COM5";
- private const int DELAY_CHAR = 30;
- private const int DELAY_LINE = 100;
-
- private static SerialPort serial = new SerialPort(PORT, 9600, Parity.None, 8, StopBits.One);
- private static bool receiving;
- private static Stopwatch duration;
-
- [STAThread]
- static void Main(string[] args)
- {
- var dialog = new OpenFileDialog();
-
- dialog.Title = "Select file to upload...";
-
- if (dialog.ShowDialog() == DialogResult.OK)
- {
- serial.DataReceived += Serial_DataReceived;
- serial.Open();
-
- Console.WriteLine("Connected...");
- Console.WriteLine($"Uploading {dialog.FileName}");
-
- // Wait for firmware to load (Arduino may reset on connect).
- Thread.Sleep(2000);
-
- // Clear the buffer
- SendNewLine();
-
- duration = Stopwatch.StartNew();
-
- using (var reader = new StreamReader(dialog.FileName, Encoding.ASCII))
- {
- int progress = 0;
- long total = reader.BaseStream.Length;
-
- while (reader.Peek() >= 0)
- {
- int data = reader.Read();
-
- // Don't send any data if we are busy receiving
- while (receiving)
- {
- Thread.Sleep(10);
- }
-
- if (data < 96)
- {
- if (data != 10 && data != 13)
- {
- serial.Write(((char) data).ToString());
- Thread.Sleep(DELAY_CHAR);
- }
- else if (data == 13)
- {
- SendNewLine();
- }
-
- Console.Write((char) data);
- }
- else
- {
- Debug.Write(string.Format("[{0}]", data));
- }
-
- Progress(++progress, total);
- }
- }
-
- Console.WriteLine("");
- Console.WriteLine("Finishing...");
-
- SendNewLine();
-
- serial.Close();
-
- Console.Title = "Upload succeeded!";
- Console.WriteLine("\r\nDone! Connection closed.");
- }
-
- Console.ReadKey();
- }
-
- private static void SendNewLine()
- {
- serial.Write("\r");
- Thread.Sleep(DELAY_CHAR);
- serial.Write("\n");
- Thread.Sleep(DELAY_LINE);
- }
-
- private static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
- {
- receiving = true;
- serial.ReadExisting();
- receiving = false;
- }
-
- private static void Progress(int progress, long total)
- {
- decimal percentage = progress / ((decimal)total / 100);
- int bytesPerSec = (int)(progress / duration.Elapsed.TotalSeconds);
-
- Console.Title = $"Uploading... ({progress:N0} of {total:N0} bytes - {bytesPerSec} bytes/sec - {percentage:N2}%)";
- }
- }
-}
diff --git a/code/utilities/DataUploader/DataUploader.sln b/code/utilities/DataUploader/src/DataUploader.sln
similarity index 100%
rename from code/utilities/DataUploader/DataUploader.sln
rename to code/utilities/DataUploader/src/DataUploader.sln
diff --git a/code/utilities/DataUploader/DataUploader/App.config b/code/utilities/DataUploader/src/DataUploader/App.config
similarity index 100%
rename from code/utilities/DataUploader/DataUploader/App.config
rename to code/utilities/DataUploader/src/DataUploader/App.config
diff --git a/code/utilities/DataUploader/DataUploader/DataUploader.csproj b/code/utilities/DataUploader/src/DataUploader/DataUploader.csproj
similarity index 100%
rename from code/utilities/DataUploader/DataUploader/DataUploader.csproj
rename to code/utilities/DataUploader/src/DataUploader/DataUploader.csproj
diff --git a/code/utilities/DataUploader/src/DataUploader/Program.cs b/code/utilities/DataUploader/src/DataUploader/Program.cs
new file mode 100644
index 0000000..575012f
--- /dev/null
+++ b/code/utilities/DataUploader/src/DataUploader/Program.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.IO.Ports;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace DataUploader
+{
+ class Program
+ {
+ private const int DELAY_CHAR = 30;
+ private const int DELAY_LINE = 100;
+
+ private static SerialPort serial;
+ private static bool receiving;
+ private static Stopwatch duration;
+
+ ///
+ /// Main program logic.
+ ///
+ ///
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ bool execute = true;
+
+ while (execute)
+ {
+ Console.Clear();
+
+ // Display boot message and ask user what COM port to use for the serial connection.
+ string comPort = DisplayBootMessage();
+
+ // Display file selection dialog.
+ Console.WriteLine("Select the file that you would like to upload...");
+ var dialog = new OpenFileDialog
+ {
+ Title = "Select file to upload..."
+ };
+
+ if (dialog.ShowDialog() == DialogResult.OK)
+ {
+ Console.WriteLine($"Selected {dialog.FileName}\r\n");
+ Console.WriteLine($"Connecting to {comPort}...");
+
+ // Create and open serial connection.
+ serial = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
+ serial.DataReceived += Serial_DataReceived;
+ serial.Open();
+
+ // Wait for firmware to load (Arduino may reset on connect).
+ // This turns out to be necessary for the upload to succeed.
+ Thread.Sleep(2000);
+ SendNewLine();
+
+ Console.WriteLine("Connected...\r\n");
+ Console.WriteLine($"Uploading data...");
+
+ duration = Stopwatch.StartNew();
+ int progress = 0;
+
+ // Read the data from the selected file.
+ using (var reader = new StreamReader(dialog.FileName, Encoding.ASCII))
+ {
+ long total = reader.BaseStream.Length;
+
+ while (reader.Peek() >= 0)
+ {
+ int data = reader.Read();
+
+ while (receiving)
+ {
+ // Don't send any data while the Serial_DataReceived eventhandler is busy.
+ Thread.Sleep(10);
+ }
+
+ if (data < 96) // Only process Apple 1 compatible characters.
+ {
+ if (data != 10 && data != 13
+ ) // Skip CR and LF characters, we'll handle these differently.
+ {
+ serial.Write(((char) data).ToString());
+ Thread.Sleep(DELAY_CHAR); // Wait for the Apple 1 to process the input.
+ }
+ else if (data == 13)
+ {
+ SendNewLine(); // Send a CRLF sequence.
+ }
+
+ Console.Write((char) data); // Display the data we have sent in the console.
+ }
+
+ Progress(++progress, total);
+ }
+ }
+
+ Console.WriteLine("");
+ Console.WriteLine("Finishing...");
+
+ // Send an extra CRLF and close the connection.
+ SendNewLine();
+ serial.Close();
+
+ Console.Title = "Upload succeeded!";
+ Console.WriteLine("Upload succeeded!\r\n");
+ }
+ else
+ {
+ Console.WriteLine("No file was selected.\r\n");
+ }
+
+ Console.Write("Would you like to upload another file? (Y/N) ");
+ execute = Console.ReadLine().Equals("Y", StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
+ ///
+ /// Display the boot message and prompt user for COM port.
+ ///
+ ///
+ private static string DisplayBootMessage()
+ {
+ Console.WriteLine("+------------------------+");
+ Console.WriteLine("| APPLE 1 MINI |");
+ Console.WriteLine("|------------------------|");
+ Console.WriteLine("| DATA UPLOADER UTILITY |");
+ Console.WriteLine("+------------------------+");
+ Console.WriteLine("");
+
+ int portNumber = 0;
+
+ while (portNumber == 0)
+ {
+ Console.Write("What COM port number would you like to use? ");
+
+ if (int.TryParse(Console.ReadLine(), out portNumber))
+ {
+ Console.WriteLine($"Using COM{portNumber}\r\n");
+ return $"COM{portNumber}";
+ }
+ else
+ {
+ Console.WriteLine("That's not a valid number, try again.");
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Send serial data for CRLF.
+ ///
+ private static void SendNewLine()
+ {
+ serial.Write("\r");
+ Thread.Sleep(DELAY_CHAR);
+ serial.Write("\n");
+ Thread.Sleep(DELAY_LINE);
+ }
+
+ ///
+ /// Serial DataReceived event handler.
+ ///
+ ///
+ ///
+ private static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
+ {
+ receiving = true;
+ serial.ReadExisting();
+ receiving = false;
+ }
+
+ ///
+ /// Update the progress indication (console window title).
+ ///
+ ///
+ ///
+ private static void Progress(int progress, long total)
+ {
+ decimal percentage = progress / ((decimal)total / 100);
+ int bytesPerSec = (int)(progress / duration.Elapsed.TotalSeconds);
+
+ Console.Title = $"Uploading... ({progress:N0} of {total:N0} bytes - {bytesPerSec} bytes/sec - {percentage:N2}%)";
+ }
+ }
+}
diff --git a/code/utilities/DataUploader/DataUploader/Properties/AssemblyInfo.cs b/code/utilities/DataUploader/src/DataUploader/Properties/AssemblyInfo.cs
similarity index 100%
rename from code/utilities/DataUploader/DataUploader/Properties/AssemblyInfo.cs
rename to code/utilities/DataUploader/src/DataUploader/Properties/AssemblyInfo.cs