how to write to serial port from pattern?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

how to write to serial port from pattern?

shiihs
I am creating a piece in which I would like to send values to the serial port from a supercollider pattern.

Since I do not have a serial port available on the system I'm developing on at the moment, I first create a serial port in a console to test my code:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

This returns:

2016/12/31 20:33:25 socat[9456] N PTY is /dev/pts/4
2016/12/31 20:33:25 socat[9456] N PTY is /dev/pts/5
2016/12/31 20:33:25 socat[9456] N starting data transfer loop with FDs [5,5] and [7,7]

I then use the first device as a serial device (/dev/pts/4). In a (failed) attempt to be smart, I wrote a synthdef like (the following code is simplified from the actual code) and I used that as an \instrument in a pattern:

(
p = SerialPort(
        "/dev/pts/4",
        baudrate: 9600,
        crtscts: true);

d = SynthDef (\serialSynth, {
        | freq = 200|
        var msbSpeed = (freq.round(1) & 16rFF00) >> 8;
        var lsbSpeed = (freq.round(1) & 16r00FF);
        p.putAll(Int8Array[lsbSpeed, msbSpeed]);
});

q = Pdef(\a, Pbind(\instrument, \serialSynth, \degrees, Pseq([0],inf)));
q.play;
)

But this this throws errors (attached below). How could I still accomplish my goal?

Maybe it's possible to send an OSC message with the frequency from the server to the language and handle things there somehow (I still need to find out how to do that though), or perhaps there's a better/easier/more convenient/more elegant solution?

portName /dev/pts/4
ERROR: Primitive '_ArrayAdd' failed.
Wrong type.
RECEIVER:
Instance of Int8Array {    (0x515ec98, gc=50, fmt=06, flg=00, set=02)
  indexed slots [0]
}
PATH: /home/supercollider/testproblem.scd

PROTECTED CALL STACK:
        Meta_MethodError:new 0x2871fc0
                arg this = PrimitiveFailedError
                arg what = Wrong type.
                arg receiver = Int8Array[  ]
        Meta_PrimitiveFailedError:new 0x2878580
                arg this = PrimitiveFailedError
                arg receiver = Int8Array[  ]
        Object:primitiveFailed 0x206c900
                arg this = Int8Array[  ]
        a FunctionDef 0x4cca1c8
                sourceCode = "{
        | freq = 200|
        var msbSpeed = (freq.round(1) & 16rFF00) >> 8;
        var lsbSpeed = (freq.round(1) & 16r00FF);
        p.putAll(Int8Array[lsbSpeed, msbSpeed]);
}"
                arg freq = an OutputProxy
                var msbSpeed = a BinaryOpUGen
                var lsbSpeed = a BinaryOpUGen
        SynthDef:buildUgenGraph 0x40a8640
                arg this = SynthDef:serialSynth
                arg func = a Function
                arg rates = nil
                arg prependArgs = [  ]
                var result = nil
                var saveControlNames = nil
        a FunctionDef 0x40a6c80
                sourceCode = "<an open Function>"
        Function:prTry 0x2b543c0
                arg this = a Function
                var result = nil
                var thread = a Thread
                var next = nil
                var wasInProtectedFunc = false
       
CALL STACK:
        MethodError:reportError   0x5475d28
                arg this = <instance of PrimitiveFailedError>
        Nil:handleError   0x639c618
                arg this = nil
                arg error = <instance of PrimitiveFailedError>
        Thread:handleError   0x644cab8
                arg this = <instance of Thread>
                arg error = <instance of PrimitiveFailedError>
        Object:throw   0x235ded8
                arg this = <instance of PrimitiveFailedError>
        Function:protect   0x49651f8
                arg this = <instance of Function>
                arg handler = <instance of Function>
                var result = <instance of PrimitiveFailedError>
        SynthDef:build   0x7fcde040bab8
                arg this = <instance of SynthDef>
                arg ugenGraphFunc = <instance of Function>
                arg rates = nil
                arg prependArgs = nil
        < closed FunctionDef >  (no arguments or variables)
        Interpreter:interpretPrintCmdLine   0x7fcde02814e8
                arg this = <instance of Interpreter>
                var res = nil
                var func = <instance of Function>
                var code = "(
p = SerialPort(
        "/dev/pts..."
                var doc = nil
                var ideClass = <instance of Meta_ScIDE>
        Process:interpretPrintCmdLine   0x44ce458
                arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Primitive '_ArrayAdd' failed.
Wrong type.
RECEIVER: Int8Array[  ]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

shiihs
In the end it was solved pretty easily using the "SendReply" class to send back values from the Synth to the language, and to send them to the serial port in the OSCresponderNode.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

j-3-3
Great you got this working - do you mind posting the code? I will be doing this soon and it would be good having a place to start.

I'm also curious about how well it is working - any dropouts or crashing the serial port with fast patterns? Is the timing sell synchronised?

Best,

Jeremy

On Sun, Jan 1, 2017 at 3:24 AM, shiihs <[hidden email]> wrote:
In the end it was solved pretty easily using the "SendReply" class to send
back values from the Synth to the language, and to send them to the serial
port in the OSCresponderNode.




--
View this message in context: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/how-to-write-to-serial-port-from-pattern-tp7629867p7629869.html
Sent from the SuperCollider Users New (Use this!!!!) mailing list archive at Nabble.com.

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/



--
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

ddw_music
In reply to this post by shiihs
On January 1, 2017 03:43:39 shiihs <stefaan.himpe@gmail.com> wrote:

> I am creating a piece in which I would like to send values to the serial port
> from a supercollider pattern.
>
> I then use the first device as a serial device (/dev/pts/4). In a (failed)
> attempt to be smart, I wrote a synthdef like (the following code is
> simplified from the actual code) and I used that as an \instrument in a
> pattern:

That fails because serial port sending is a language-side operation, and
synths run in the server, and the server can't do language-only things.

So: Occam's Razor. You have values in the language that need to be sent
using a language-side mechanism. But, instead of keeping everything in the
language, you're sending the values to the server, then sending them back
to the language, and finally out the serial port. There is some wasted effort
there.

I guess you're assuming that the only thing that patterns can do is to
produce synths. Not true. Patterns produce events, and events can do
anything you need. It happens that the *default* event type plays a synth
on the server, but there is no restriction that it has to be that way.

You can override the event's "play" function:

p = Pbind(
    \play, {
        var freq;
        if(currentEnvironment.isRest.not) {
            // first convert degree to freq
            freq = ~freq.value;
            ... serial port thing here...
        };
    },
    ....
).play:

It's also possible to create a new event type, but I think the above will
be enough for you.

hjh
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

shiihs
Hi James,

Thanks for the explanation about overriding the \play function.
Despite trying to read up on patterns I hadn't found this feature yet.

I will be sure to try it out as it eliminates some overhead.

From your example code I think I understand that the arguments
from the pattern are available as environment variables?

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

shiihs
Aha! Of course I didn't see it in pattern documentation because in fact it is part of event documentation.
This seems to be essential reading in this context: http://doc.sccode.org/Classes/Event.html 
The learning curve remains steep, but some day I'll get there :)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: how to write to serial port from pattern?

shiihs
In reply to this post by j-3-3
Hi Jeremy,

I've yet to hook up everything to real hardware so I cannot answer a lot to your questions at this moment. I can already tell, however, that James' suggestion to avoid OSC messages appears to work.

Loading...