HyperCard Serial Toolkit

Want to move your code and projects to LiveCode but don't know where to start?

Moderators: FourthWorld, heatherlaine, Klaus, robinmiller

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

HyperCard Serial Toolkit

Post by melristau » Sun Aug 14, 2016 5:59 pm

Does LC have the communication capabilities provided by HyperCard Serial Toolkit for HC?
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Sun Aug 14, 2016 6:09 pm

LiveCode has the "open driver", "read from driver", "write ___ to driver" and "close driver commands". I'm not familiar with the HC Serial Toolkit, but although the syntax won't be the same, I imagine that everything you can do with the toolkit can be done with the above commands.

If you provide some sample lines of code from the serial toolkit, I could perhaps help in rewriting them in LiveCode?

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Sun Aug 14, 2016 8:16 pm

Andrew, I'm listing here the command and function descriptions used in my previous HC project... and it might be that I am sending much more that you are willing to help with! If there is any other info I can provide, please let me know. Thanks!

Intro
The HyperCard Serial Port Toolkit consists of a set of HyperTalk commands and functions which allow HyperCard stacks to control the serial ports of the Macintosh and communicate through them.

To use the Toolkit, select the port and configure it with the SPConfigure command. If you want the input buffered, you can use the setSPortBufferSize command to allocate the appropriate buffer.

Then the sendSPort, recvChars, recvUpTo, charsAvailable, and breakSPort commands can be used to send and receive data.

When done, the closeSPort command can be used to close the port. It is EXTREMELY IMPORTANT that this command be called before leaving HyperCard. Otherwise buffer space allocated for the serial port to use may still be used by the serial driver, which may cause obscure bugs to arise in subsequently invoked applications.

------------------

closeSPort [dontCloseDriver]
dontCloseDriver, if present, free the buffers but don't actually close the driver.
Close the port and release any buffer associated with it. If a buffer has been allocated with the bufferSPort command, it is EXTREMELY IMPORTANT that this command be called before exiting the stack.
If the dontCloseDriver parameter is present, the driver is left open although the buffers are still freed. This can be useful if you want to leave the driver open between uses or across applications. The driver drops DTR when closed.

configureSPort param1, param2, …
each parameter is a keyword that specified one part of the configuration, or selects which port to configure and use.
This command selects which port is to be used in subsequent serial port commands, and it configures the port's speed, data format, and editing characteristics. Each parameter is a keyword which specified one part of that configuration. The following is a list of all available keywords:
----
"modemPort" or "port1": select the modem port.
"printerPort" or "port2": select the printer port.
----
"baud300", "baud600", "baud1200", "baud1800", "baud2400",
"baud3600", "baud4800", "baud7200", "baud9600", "baud19200",
"baud57600": set the baud rate of the selected port.
----
"stop10", "stop15", "stop20": set the number of stop bits to 1.0, 1.5, or 2.0.
----
"parityOff", "parityOdd", "parityEven": set the parity.
----
"data5", "data6", "data7", "data8": set the number of data bits.
----
"XOnOutOn", "XOnOutOff": enable or disable x-on/x-off flow control on the outgoing data stream.
----
"CTSOutOn", "CTSOutOff": enable or disable signal flow control on the outgoing data stream.
----
"linefeedsOn", "lineFeedsOff": enable or disable automatic output of a linefeed character after each carriage return character output.
----
"echoOn", "echoOff": enable or disable automatic echoing of input back to the output.
----
"editOn", "editOff": enable or disable automatic editing of input with backspace.
----
"stripOn", "stripOff": enable or disable automatic striping of the top bit of incoming characters.
----
"stripControlsOn", "stripControlsOff": enable for disable automatic striping of control characters, except for the control characters carriage return and tab.
——
"autoWrapOn", "autoWrapOff": enable or disable automatic wrapping of characters at the ends of lines. This works for both output (with sendSPort) and input (with recvUpTo), and is intended for applications where HyperCard is the "host."
----

killSPort
killSPort inOutBoth, "in" for input only, "out" for output only, or "both" for both input and output.
Kills an in progress input or output on the port. The parameter specifies whether to kill the input, output, or both.

charsAvailable()
This function returns the number of characters waiting to be read from the serial port. If no characters are available, it returns zero.

recvChars(n)
Receive characters from the serial port. (n) the number of characters to receive.
This function returns n characters from the serial port. If n characters are not yet available, it will wait until they are. This function does not perform echoing or editing (see recvUpTo).

recvUpTo(termChar,timeOut,oldString)
termChar, character after which to terminate the receive, or empty if any characters up to the time-out are to be read.
timeOut, number of ticks (1/60ths of a second) to wait, or zero.
oldString, string of previously received characters.
This is the principle, and most powerfull receive character function. It inputs character until a particular character is received or until a time-out occurs. It will echo and edit input if those features have been enabled with the configureSPort command. If editing is enabled, backspacing is allowed not only on new input, but also on previous input, which should be passed to the function in the oldString paramter. recvUpTo returns both the old string and any new input.

sendSPort string
string, the string to send.
This command sends a string to the serial port. The output is done asynchronously. Therefore, the fact that this function has returned does not necessarily imply that the output has finished. Use the sendSPortDone() function to test for this. If enabled by using the configureSPort commands, this command will append linefeeds to any carriage returns in the output string

sendSPortDone()
Returns true if all pending output has finished.

setSPortBufferSize sizeOfBuffer
Change the size of the serial port input buffer.
sizeOfBuffer, the size of the new buffer to be allocated, or zero if the default port buffer is to be used.
This commands sets the size of the input buffer. It allocates a new buffer and then configures the port to use that buffer.
It is EXTREMELY IMPORTANT that you call closeSPort if you call this command. Otherwise, the serial port will continue to use the buffer even after HyperCard has exited and deallocated that buffer space. This can cause strange and complicated system crashes.

SPortBufferSize()
Returns the size of the current input buffer.
This functions returns the size of the current serial port input buffer, or zero if the default buffer is being used.

SPortConfiguration()
This function returns the current configuration of the port as a comma-separated list. The same keywords are used as in configureSPort. Therefore, the following code will set the port to the configuration it is currently set to (i.e., do nothing):
do "configureSPort" && SPortConfiguration()
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Sun Aug 14, 2016 10:28 pm

Okay.

From your response, it is clear that the HC Serial Toolkit you were using is quite a bit more low-level than the serial commands LiveCode offers. As such, not all of the commands and functions you listed can be implemented in LiveCode. I have tried though, and my code is below:

Code: Select all

local sending, gPort, lineFeeds, tEdit, echo, strip, stripControls, autoWrap

constant port1="COM1:",port2="COM2:"

on closeSPort
   if the params contains "dontCloseDriver" then return 0
   close driver gPort
end closeSPort

on configureSPort
   put getData("baud", 9600) into baud
   put getData("parity", "n") into parity
   put getData("data", 8) into dBits
   put getData("stop", 1) into stopBits
   put getData("xon", "") into xOnOut
   put getData("octs", "") into CTSOut
   repeat with x = 2 to the number of words of the params
      put stripQuote(word x of the params) into paramy
      if paramy is "modemPort" or paramy is "port1" then put port1 into gPort
      if paramy is "printerPort" or paramy is "port2" then put port2 into gPort
      if char 1 to 4 of paramy is "baud" then put char 5 to (the number of chars of paramy) of paramy into baud
      if char 1 to 4 of paramy is "stop" then put char 5 to 6 of paramy into stopBits
      if char 1 to 6 of paramy is "parity" then put char 7 to (the number of chars of paramy) of paramy into parity
      if char 1 to 4 of paramy is "data" then put char 5 of paramy into dBits
      if char 1 to 6 of paramy is "XOnOut" then put char 7 to (the number of chars of paramy) of paramy into xOnOut
      if char 1 to 6 of paramy is "CTSOut" then put char 7 to (the number of chars of paramy) of paramy into CTSOut
      if char 1 to 9 of paramy is "linefeeds" then put char 10 to (the number of chars of paramy) of paramy into linefeeds
      if char 1 to 4 of paramy is "echo" then put char 5 to (the number of chars of paramy) of paramy into echo
      if char 1 to 4 of paramy is "edit" then put char 5 to (the number of chars of paramy) of paramy into tEdit
      if char 1 to 13 of paramy is "stripControls" then put char 14 to (the number of chars of paramy) of paramy into stripControls
      if char 1 to 7 of paramy is "stripOn" then put "On" into strip
      if char 1 to 8 of paramy is "stripOff" then put "Off" into strip
      if char 1 to 8 of paramy is "autoWrap" then put char 9 to (the number of chars of paramy) of paramy into autoWrap
   end repeat
   put stopBits / 10 into stopBits
   put "baud=" & baud && "parity=" & parity && "data=" & dBits && "stop=" & stopBits into scs
   if xOnOut is not empty then put " xon=" & xOnOut after scs
   if CTSOut is not empty then put " octs=" & CTSOut after scs
   set the serialControlString to scs
end configureSPort

function recvChars charsToRead
   read from driver gPort for charsToRead chars in 100 seconds
end recvChars

function recvUpTo termChar, timeOut, oldString
   if timeOut is 0 then put empty into timeOut
   if termChar is empty and timeOut is empty then
      read from driver gPort for charsToRead chars in 100 seconds
   else if termChar is empty then
      read from driver gPort for charsToRead chars in timeOut ticks
   else if timeOut is empty then
      read from driver gPort until termChar
   end if
end recvUpTo

on sendSPort str
   put true into sending
   send "serSend" && str to me in 1 millisecond
end sendSPort

on serSend str
   if linefeeds is "on" then replace numToChar(13) with numToChar(13) & numToChar(10) in str
   write str to driver gPort
   put false into sending
end serSend

function sendSPortDone
   if sending then return false
   return true
end sendSPortDone

function SPortConfiguration
   put the serialControlString into scs
   if gPort is port1 then put "port1," into rtn
   if gPort is port2 then put "port2," into rtn
   repeat for each word t in scs
      put the number of chars of t into tt
      if char 1 to 4 of scs is "baud" then put "baud" & char 6 to tt of t & comma after rtn
      if char 1 to 6 of scs is "parity" then put "parity" & char 8 to tt of t & comma after rtn
      if char 1 to 4 of scs is "data" then put "data" & char 6 to tt of t & comma after rtn
      if char 1 to 4 of scs is "stop" then put "stop" & (char 6 to tt of t) * 10 & comma after rtn
      if char 1 to 3 of scs is "xon" then put "XOnOut" & char 5 to tt of t & comma after rtn
      if char 1 to 4 of scs is "octs" then put "CTSOut" & char 6 to tt of t & comma after rtn
   end repeat
   if linefeeds is not empty then put "linefeeds" & linefeeds & comma after rtn
   if echo is not empty then put "echo" & echo & comma after rtn
   if tEdit is not empty then put "edit" & tEdit & comma after rtn
   if strip is not empty then put "strip" & strip & comma after rtn
   if stripControls is not empty then put "stripControls" & stripControls & comma after rtn
   if autoWrap is not empty then put "autoWrap" & autoWrap & comma after rtn
   return rtn
end SPortConfiguration

function stripQuote str
   if char 1 of str is quote then put empty into char 1 of str
   if char -1 of str is quote then put empty into char -1 of str
   return str
end stripQuote

function getData dItem, defVal
   put the serialControlString into scs
   if dItem is not in scs then return defVal
   put wordOffset(dItem, scs) into wOf
   put word wOf of scs into par
   return char (the number of chars of dItem+2) to (the number of chars of par) of par
end getData
Now for an explanation of what I've tried to do. The above code reimplements several, but not all, of the commands / functions you listed. Here's what should work:
  • closeSPort - minus the buffer support
    configureSPort - minus the echo, edit, strip, stripControls and autoWrap settings (you can set them but nothing happens)
    recvChars - but will only wait for 100 seconds before exiting (you can change this time, but it cannot be infinite)
    recvUpTo - minus editing, echoing and oldString, as they are too low-level for LiveCode
    sendSPort
    sendSPortDone
    SPortConfiguration - with the same limitations as configureSPort
Now, I realise given the missing commands and the large number of caveats in the above list, this is not probably going to be very helpful. If you could list some places in the code where the toolkit is used that might be useful. Also (I'm not sure how familuar you are with the stack), but do you know if it uses any of the following serial options:
  • buffer
    echo
    edit
    strip
    stripControls
    autoWrap
    charsAvailable
If it does, then that could be more troublesome, as I don't believe LiveCode supports these features (someone correct me if I'm wrong). It then may be necessary to dive into the all new widgets layer and create some custom widgets to get the features you need.

Andrew

P.S. Out of curiosity, what stack are you trying to convert? (I'm just interested in what stack has a serial device that can work with both old macs and new computers)

P.P.S. I've tried to test as much of the code as I can, but I don't have any serial devices on hand at this time to test anything fully, so there may be some bugs. In addition, it is getting quite late here in Scotland, so I may have made some mistakes... (but hopefully not)

Edit: Whoops! Already found a mistake in SPortConfiguration. Fixed that now.

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Mon Aug 15, 2016 12:55 am

Andrew - Goodness - More than I hoped for!
Out of curiosity, what stack are you trying to convert?
The stack was named "Planner" and consists of a main stack + folder of 12 "substacks" of scripts and resources. (I'd post the whole set for you to run in HC but its non functional without the hardware.) I've posted a folder with some additional info on the hardware (3-page PDF) and a few chapters from the front of the curriculum that sketches how the software/hardware were used. As far as I know, Mediagrden's SP1 (a PIC based microcontroller) was predated only by the MIT Stamp. I'm working on a revised software... Thinking to interface with Raspberry Pi or Arduino, etc.
https://www.dropbox.com/sh/gfbwxsdz8pok ... 99gLa?dl=0

Any thoughts appreciated,
Mel
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Mon Aug 15, 2016 12:54 pm

Ah, OK. From your reply I think that you are not only updating the software from HyperCard to LiveCode, but also the hardware from PIC to Arduino/Raspberry Pi. If that is the case then the easiest option is probably to rewrite the lines of code that deal with serial control from Serial Toolkit into native LiveCode, as they will need rewriting anyway to work with the new hardware.

As for choosing between Arduino and Raspberry Pi, it really depends on what you want to do (I have done both, for different things). Arduino is much more like the PIC controller the stack would have used originally, and can be interfaced over serial control. Raspberry Pi is different in the way that you can run the stack on the Pi itself and interface directly with the hardware.

IMHO, I would use Arduino as it sounds more like what the stack was originally designed to use. There is also limited support for the Pi at the moment (it is 'community supported'). You would need to write an Arduino program that can interface with the rewritten LiveCode serial stuff. How familiar are you with Arduino?

Andrew

P.S. Would you be able to post the original stacks? It would help me work out how much rewriting of serial code is necessary, and what sort of code the Arduino / Pi would need to be running.

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Mon Aug 15, 2016 6:46 pm

Thanks again Andrew
How familiar are you with Arduino?
Purchased but not gotten into. (Focused on getting the software interface updated and running.)

Have posted my original HC stacks and the LC conversions made a few weeks ago. Also a compilation of all the stack scripts in a text file.
https://www.dropbox.com/sh/7ygymd4oo0q1 ... roHSa?dl=0

I greatly appreciate your looking into this. Please let me know if I can provide anything additional,
Mel
rebuilding visual programming app originally created in 1993 as Hypercard stack

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9801
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: HyperCard Serial Toolkit

Post by FourthWorld » Mon Aug 15, 2016 7:31 pm

Since you're considering using Raspberry Pi, I wonder if sockets may provide you greater efficiency and flexibility instead of serial comms.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Mon Aug 15, 2016 8:21 pm

Based on Andrew's opinion, I'm thinking Arduino is probably the best place to start.
Once I have the graphic front end working, I'll post the LC stack for other to play with and will be open to any suggestions on hardware/communications.
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Mon Aug 15, 2016 8:49 pm

OK, long reply time...

I've looked at what you uploaded, in particular the full script text file (how did you export that, by the way?). This is what I have found:

Most of the serial commands in the HC Serial Toolkit are not being used. The ones that are being used should be rewriteable in LiveCode, so I don't forsee any major problems. A summary with notes is below.
  • configureSPort - used, see notes
    killSPort - not used
    charsAvailable - not used
    recvChars - not used
    recvUpTo - used, see notes
    sendSPort - used, can be reimplemented in LiveCode
    sendSPortDone - used, can be reimplemented in LiveCode
    setSPortBufferSize - used once to set buffer to 10240, may be OK without it
    SPortBufferSize - not used
    SPortConfiguration - not used
Notes:
1.) The configureSPort command is one which may be more difficult to reimplement in LiveCode simply due to its low-level and flexible nature. The specific set of settings use by the stack is (with a few variations for different baud rates, but everything else seems normal):
configureSPort printerPort,baud19200,data8,stop10,parityOff,stripOn,stripControlsOn,EditOn,linefeedOn
The problematic areas are the last four settings (stripOn,stripControlsOn,EditOn,linefeedOn) as they are functionality not offered by LiveCode. However there are ways round this, see later on in my answer.

2.) recvUpTo is an interesting command, and I confess that I don't understand entirely how it works. My confusion comes from the idea of being able to edit data as it is received - I don't see how this would work. Unfortunately EditOn is one of the settings passed to configureSPort, so it may be necessary to have editing. However, the only time recvUpTo is used (and, in fact, the only time serial data is read, rather than written - this seems to be a very output-centric stack) is twice with the same line: recvUpTo(empty,2,empty). I'll cover this later.

The other commands (with the exception of setSPortBufferSize, and I suspect you would not need this with a modern computer and Arduino) should be able to be easily redone in LiveCode - in fact, the method I posted in my first answer should work for many of the commands.


Reimplementing the PIC / Arduino-side

Speaking from experience, serial communication is quite easy in Arduino, and the way the stack communicates with the PIC (now Arduino) is straightforward, as far as I can see. I have gone through the code and found what I think is all the commands that are ever sent to the PIC, although I may have missed one or two. They are:
  • shutDown()
    sense("&Port&")" & return
    configure("&port&","&how&")
    move("&a&","&b&")
    moveSpeed("&a&","&b&")
    Date("&s&")
    Time("&s&")
    Time(Set,"&s&")
    comset("&duplex&")
    reset()
    Prompt(on)
    Prompt(off)
    readSerial(29)
    sendSerial(29,"&m&")
(apologies for the inclusion of the LiveCode text-formatting characters, it was to much bother to remove them!)

Some of these, such as reset() and shutdown(), are obvious in what they do. Others, such as configure(), take two parameters, and I am not at this point entirely sure what those parameters are. Further investigation will be required, but on the whole, this should be possible to write in Arduino.


Final Notes

There is one rather peculiar thing I came across in the code that I wondered if you could perhaps help explain (did you create this stack originally?). The only times that data is received from the PIC, it is used in a way that doesn't make sense (at least, to me). Here's a code snippet.

Code: Select all

sendSport "readSerial(29)"& return
wait 10
put recvUpTo(empty,2,empty) after serialIn1
So, line 1 sends a readSerial() command to the PIC. At a guess, 29 means read for 29 characters. Line 2 waits for 10 ticks, and then line 3 reads back from the PIC! To me this is the wrong way round: after telling the PIC to read, surely you want to write to it! Any thoughts?

Andrew

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Mon Aug 15, 2016 10:06 pm

So, line 1 sends a readSerial() command to the PIC.
I apologize Andrew! Memory hiccup on my end regarding the PIC version:
My stacks (System 9 Mac / Hypercard) talked to the first generation MediaGarden "modeling computer" based on the Z80.
The PIC version was Windows app only and I did not write that software! :oops:

Still, all of what you have posted will be of great help when I get to the hardware side of this project.
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Tue Aug 16, 2016 12:45 am

That's no problem.

Let me know if you need any other help and I'll do my best (there are some good tutorials out there for converting HyperCard stacks to LiveCode, such as http://www.hyperactivesw.com/mctutorial/rrintro.html ).

Also, do you have any images / reference diagrams / schematics for the modelling computer? It is of no relevence now, but I collect old computing equipment and it intrigues me - sadly there appear to be no photos of it in the PDFs you uploaded.

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Tue Aug 16, 2016 5:25 pm

Sure Andrew - A PDF with a few images for you. (Will update as I find more.)
https://www.dropbox.com/s/c7wzo9wu28x0o ... y.pdf?dl=0

The Windows 7 version of Planner software (that I am updating in LC) is posted here:
https://www.dropbox.com/sh/4qpugbsyotmk ... cVQXa?dl=0
rebuilding visual programming app originally created in 1993 as Hypercard stack

andrewferguson
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 184
Joined: Wed Apr 10, 2013 5:09 pm

Re: HyperCard Serial Toolkit

Post by andrewferguson » Tue Aug 16, 2016 8:50 pm

Thanks !

melristau
Posts: 56
Joined: Tue Jul 14, 2015 5:15 pm
Location: Northern Colorado
Contact:

Re: HyperCard Serial Toolkit

Post by melristau » Fri May 19, 2017 5:37 pm

After several months away I am now revisiting my previous work on this project... and having to relearn why I scripted what I scripted! My intent is not commercial.
rebuilding visual programming app originally created in 1993 as Hypercard stack

Post Reply

Return to “Converting to LiveCode”