From 6eb7da51c327be2e41c429a6068274cb3b907d7c Mon Sep 17 00:00:00 2001
From: Wolfgang Thaller <wolfgang.thaller@gmx.net>
Date: Tue, 24 Apr 2018 22:06:32 +0200
Subject: [PATCH] LaunchAPPL/Serial: configurable bauf rate

---
 LaunchAPPL/Client/Serial.cc           | 19 +++++++++++++++--
 LaunchAPPL/Server/LaunchAPPLServer.cc | 30 +++++++++++++++++++++++++--
 LaunchAPPL/Server/LaunchAPPLServer.r  | 17 ++++++++++++++-
 LaunchAPPL/Server/MacSerialStream.cc  | 22 ++++++++++++++++++++
 LaunchAPPL/Server/MacSerialStream.h   |  2 ++
 5 files changed, 85 insertions(+), 5 deletions(-)

diff --git a/LaunchAPPL/Client/Serial.cc b/LaunchAPPL/Client/Serial.cc
index 4ec4874b3f..1da5be8d2a 100644
--- a/LaunchAPPL/Client/Serial.cc
+++ b/LaunchAPPL/Client/Serial.cc
@@ -3,9 +3,9 @@
 #include "Utilities.h"
 #include "Stream.h"
 #include "ReliableStream.h"
+#include <termios.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <termios.h>
 #include <arpa/inet.h>
 #include <poll.h>
 
@@ -49,6 +49,7 @@ private:
 SerialStream::SerialStream(po::variables_map &options)
 {
     std::string port = options["serial-port"].as<std::string>();
+    int baud = options["serial-baud"].as<int>();
     fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
     if(fd < 0)
         throw std::runtime_error("Cannot open serial port.\n");
@@ -56,7 +57,20 @@ SerialStream::SerialStream(po::variables_map &options)
     struct termios tios;
     tcgetattr(fd,&tios);
 
-    tios.c_cflag = B19200 | CRTSCTS | CS8 | CLOCAL | CREAD;
+    tios.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
+
+    switch(baud)
+    {
+        case 9600:      tios.c_cflag |= B9600; break;
+        case 19200:     tios.c_cflag |= B19200; break;
+        case 38400:     tios.c_cflag |= B38400; break;
+        case 57600:     tios.c_cflag |= B57600; break;
+        case 115200:    tios.c_cflag |= B115200; break;
+        case 230400:    tios.c_cflag |= B230400; break;
+        default:
+            throw std::runtime_error("Unsupported baud rate.\n");
+    }
+
     tios.c_iflag = 0;//IGNPAR | ICRNL;
     tios.c_lflag = 0;
     tios.c_oflag = 0;
@@ -194,6 +208,7 @@ void Serial::GetOptions(options_description &desc)
 {
     desc.add_options()
         ("serial-port", po::value<std::string>()->default_value("/dev/ttyUSB0"), "serial port to use")
+        ("serial-baud", po::value<int>()->default_value(19200), "serial port speed")
         ;
 }
 
diff --git a/LaunchAPPL/Server/LaunchAPPLServer.cc b/LaunchAPPL/Server/LaunchAPPLServer.cc
index 881012952f..627d9aa9ce 100644
--- a/LaunchAPPL/Server/LaunchAPPLServer.cc
+++ b/LaunchAPPL/Server/LaunchAPPLServer.cc
@@ -40,7 +40,8 @@ enum
 {
     kMenuApple = 128,
     kMenuFile,
-    kMenuEdit
+    kMenuEdit,
+    kMenuSpeed
 };
 
 enum
@@ -50,6 +51,9 @@ enum
     kItemQuit = 1
 };
 
+long gBaud = 19200;
+
+void SetBaud(long baud);
 
 void ShowAboutBox()
 {
@@ -116,6 +120,16 @@ void UpdateMenus()
         DisableItem(m,5);
         DisableItem(m,6);
     }
+
+    m = GetMenu(kMenuSpeed);
+    for(int i = 1; i <= CountMenuItems(m); i++)
+    {
+        Str255 str;
+        long baud;
+        GetMenuItemText(m, i, str);
+        StringToNum(str, &baud);
+        CheckMenuItem(m, i, baud == gBaud);
+    }
 }
 
 void DoMenuCommand(long menuCommand)
@@ -154,7 +168,12 @@ void DoMenuCommand(long menuCommand)
             // edit command not handled by desk accessory
         }
     }
-
+    else if(menuID == kMenuSpeed)
+    {
+        GetMenuItemText(GetMenu(menuID), menuItem, str);
+        StringToNum(str, &gBaud);
+        SetBaud(gBaud);
+    }
     HiliteMenu(0);
 }
 
@@ -313,6 +332,12 @@ public:
 
 short outRefNum;
 long outSize, outSizeRemaining;
+MacSerialStream *gSerialStream;
+
+void SetBaud(long baud)
+{
+    gSerialStream->setBaud(baud);
+}
 
 int main()
 {
@@ -334,6 +359,7 @@ int main()
     statusWindow = GetNewWindow(129, NULL, (WindowPtr) -1);
     SetStatus(AppStatus::ready);
     MacSerialStream stream;
+    gSerialStream = &stream;
 
 //#define SIMULATE_ERRORS
 #ifdef SIMULATE_ERRORS
diff --git a/LaunchAPPL/Server/LaunchAPPLServer.r b/LaunchAPPL/Server/LaunchAPPLServer.r
index ac138c794b..2a80efe404 100644
--- a/LaunchAPPL/Server/LaunchAPPLServer.r
+++ b/LaunchAPPL/Server/LaunchAPPLServer.r
@@ -55,8 +55,23 @@ resource 'MENU' (130) {
     }
 };
 
+resource 'MENU' (131) {
+    131, textMenuProc;
+    allEnabled, enabled;
+    "Speed";
+    {
+        "9600", noIcon, noKey, noMark, plain;
+        "19200", noIcon, noKey, check, plain;
+        "38400", noIcon, noKey, noMark, plain;
+        "57600", noIcon, noKey, noMark, plain;
+        "115200", noIcon, noKey, noMark, plain;
+        "230400", noIcon, noKey, noMark, plain;
+    }
+};
+
+
 resource 'MBAR' (128) {
-    { 128, 129, 130 };
+    { 128, 129, 130, 131 };
 };
 
 data 'TEXT' (128) {
diff --git a/LaunchAPPL/Server/MacSerialStream.cc b/LaunchAPPL/Server/MacSerialStream.cc
index 97c44d78bc..d096e5f463 100644
--- a/LaunchAPPL/Server/MacSerialStream.cc
+++ b/LaunchAPPL/Server/MacSerialStream.cc
@@ -67,3 +67,25 @@ void MacSerialStream::idle()
         notifyReceive((uint8_t*)readBuffer, count1);
     }
 }
+
+void MacSerialStream::setBaud(int baud)
+{
+    short baudval = 0;
+    switch(baud)
+    {
+        case 9600:      baudval = baud9600; break;
+        case 14400:     baudval = baud14400; break;
+        case 19200:     baudval = baud19200; break;
+        case 28800:     baudval = baud28800; break;
+        case 38400:     baudval = baud38400; break;
+        case 57600:     baudval = baud57600; break;
+        case 115200:    baudval = 0; break;
+        case 230400:    baudval = 0; break;
+    }
+	SerReset(outRefNum, baudval | data8 | noParity | stop10);
+
+    if(baud == 115200)
+        Control(outRefNum, kSERD115KBaud, nullptr);
+    else if(baud == 230400)
+        Control(outRefNum, kSERD230KBaud, nullptr);
+}
diff --git a/LaunchAPPL/Server/MacSerialStream.h b/LaunchAPPL/Server/MacSerialStream.h
index 8680e5c57a..2c246c23ca 100644
--- a/LaunchAPPL/Server/MacSerialStream.h
+++ b/LaunchAPPL/Server/MacSerialStream.h
@@ -20,6 +20,8 @@ public:
     ~MacSerialStream();
 
     void close();
+
+    void setBaud(int baud);
 };
 
 #endif