mrpeach/ 0000755 0001750 0001750 00000000000 14110766277 012742 5 ustar zmoelnig zmoelnig mrpeach/osc/ 0000755 0001750 0001750 00000000000 14110766276 013525 5 ustar zmoelnig zmoelnig mrpeach/osc/unpackOSC-help.pd 0000644 0001750 0001750 00000003573 11716546644 016642 0 ustar zmoelnig zmoelnig #N canvas 4 80 664 396 10;
#X obj -104 176 cnv 15 100 60 empty empty empty 20 12 0 14 -4034 -66577
0;
#X obj -85 190 unpackOSC;
#X floatatom 16 207 10 0 0 1 - - -;
#X obj -85 257 pipelist;
#X text -126 337 see:;
#X text 21 337 for a way to send OSC over TCP or serial connections.
;
#X obj -91 338 unpackOSCstream;
#X obj -92 214 print unpacked;
#X text -29 253 If the OSC packet has a timetag \, [pipelist] will
delay it until the time occurs;
#N canvas 521 651 494 344 META 0;
#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 5 KEYWORDS control list_op;
#X text 12 45 DESCRIPTION parses lists of floats (only integers on
[0..255]) assuming they represent OSC packets.;
#X text 12 75 INLET_0 list of floats on [0..255];
#X text 12 95 OUTLET_0 OSC message;
#X text 13 115 OUTLET_1 milliseconds until timetag time;
#X text 12 135 AUTHOR Martin Peach;
#X restore 449 362 pd META;
#X obj -85 73 packOSC;
#X obj -62 113 print bytes;
#X msg -113 28 /some/path 1 2 3;
#X msg -134 7 [ \, /another/one/ 4 \, ];
#X obj -85 284 print delayed;
#X msg -92 49 timetagoffset 1.1e+06;
#X obj -46 93 print bundle_depth;
#X text 354 317 2012/02/14 Martin Peach;
#X text 107 15 [unpackOSC] processes lists of floats (only integers
on [0..255]) as though they were OSC packets.;
#X text -76 134 <- usually the bytes pass over the network with [udpsend]/[udpreceive]
\, or serial port using [comport] with [slipenc] and [slipdec];
#X text 48 49 timetag offset is in microseconds relative to sender's
clock;
#X text 83 201 second outlet is timetag offset in millieconds relative
to receiver's clock;
#X connect 1 0 3 0;
#X connect 1 0 7 0;
#X connect 1 1 2 0;
#X connect 1 1 3 1;
#X connect 3 0 14 0;
#X connect 10 0 11 0;
#X connect 10 0 1 0;
#X connect 10 1 16 0;
#X connect 12 0 10 0;
#X connect 13 0 10 0;
#X connect 15 0 10 0;
mrpeach/osc/LICENSE.txt 0000644 0001750 0001750 00000001332 11616504076 015343 0 ustar zmoelnig zmoelnig OpenSoundControl for Pure data
Copyright (C) 2006-2011 Martin Peach
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
mrpeach/osc/pipelist.c 0000644 0001750 0001750 00000012417 11034222475 015515 0 ustar zmoelnig zmoelnig /* pipelist.c 20070711 Martin Peach based on pipe from x_time.c */
/* 20080706 added anything method for meta-messages */
#include "m_pd.h"
/* -------------------------- pipe -------------------------- */
static t_class *pipelist_class;
typedef struct _hang
{
t_clock *h_clock;
struct _hang *h_next;
struct _pipelist *h_owner;
int h_n; /* number of atoms in h_list */
t_atom *h_atoms; /* pointer to a list of h_n t_atoms */
} t_hang;
typedef struct _pipelist
{
t_object x_obj;
float x_deltime;
t_outlet *x_pipelistout;
t_hang *x_hang;
} t_pipelist;
static void *pipelist_new(t_symbol *s, int argc, t_atom *argv);
static void pipelist_hang_free(t_hang *h);
static void pipelist_hang_tick(t_hang *h);
static void pipelist_any_hang_tick(t_hang *h);
static void pipelist_list(t_pipelist *x, t_symbol *s, int ac, t_atom *av);
static void pipelist_anything(t_pipelist *x, t_symbol *s, int ac, t_atom *av);
static void pipelist_flush(t_pipelist *x);
static void pipelist_clear(t_pipelist *x);
void pipelist_setup(void);
static void *pipelist_new(t_symbol *s, int argc, t_atom *argv)
{
t_pipelist *x = (t_pipelist *)pd_new(pipelist_class);
float deltime;
if (argc)
{ /* We accept one argument to set the delay time, ignore any further args */
if (argv[0].a_type != A_FLOAT)
{
char stupid[80];
atom_string(&argv[argc-1], stupid, 79);
post("pipelist: %s: bad time delay value", stupid);
deltime = 0;
}
else deltime = argv[argc-1].a_w.w_float;
}
else deltime = 0;
x->x_pipelistout = outlet_new(&x->x_obj, &s_list);
floatinlet_new(&x->x_obj, &x->x_deltime);
x->x_hang = NULL;
x->x_deltime = deltime;
return (x);
}
static void pipelist_hang_free(t_hang *h)
{
freebytes(h->h_atoms, h->h_n*sizeof(t_atom));
clock_free(h->h_clock);
freebytes(h, sizeof(t_hang));
}
static void pipelist_hang_tick(t_hang *h)
{
t_pipelist *x = h->h_owner;
t_hang *h2, *h3;
/* excise h from the linked list of hangs */
if (x->x_hang == h) x->x_hang = h->h_next;
else for (h2 = x->x_hang; ((h3 = h2->h_next)!=NULL); h2 = h3)
{
if (h3 == h)
{
h2->h_next = h3->h_next;
break;
}
}
/* output h's list */
outlet_list(x->x_pipelistout, &s_list, h->h_n, h->h_atoms);
/* free h */
pipelist_hang_free(h);
}
static void pipelist_any_hang_tick(t_hang *h)
{
t_pipelist *x = h->h_owner;
t_hang *h2, *h3;
/* excise h from the linked list of hangs */
if (x->x_hang == h) x->x_hang = h->h_next;
else for (h2 = x->x_hang; ((h3 = h2->h_next)!=NULL); h2 = h3)
{
if (h3 == h)
{
h2->h_next = h3->h_next;
break;
}
}
/* output h's atoms */
outlet_anything(x->x_pipelistout, h->h_atoms[0].a_w.w_symbol, h->h_n-1, &h->h_atoms[1]);
/* free h */
pipelist_hang_free(h);
}
static void pipelist_list(t_pipelist *x, t_symbol *s, int ac, t_atom *av)
{
if (x->x_deltime > 0)
{ /* if delay is real, save the list for output in delay milliseconds */
t_hang *h;
int i;
h = (t_hang *)getbytes(sizeof(t_hang));
h->h_n = ac;
h->h_atoms = (t_atom *)getbytes(h->h_n*sizeof(t_atom));
for (i = 0; i < h->h_n; ++i)
h->h_atoms[i] = av[i];
h->h_next = x->x_hang;
x->x_hang = h;
h->h_owner = x;
h->h_clock = clock_new(h, (t_method)pipelist_hang_tick);
clock_delay(h->h_clock, (x->x_deltime >= 0 ? x->x_deltime : 0));
}
/* otherwise just pass the list straight through */
else outlet_list(x->x_pipelistout, &s_list, ac, av);
}
static void pipelist_anything(t_pipelist *x, t_symbol *s, int ac, t_atom *av)
{
if (x->x_deltime > 0)
{ /* if delay is real, save the list for output in delay milliseconds */
t_hang *h;
int i;
h = (t_hang *)getbytes(sizeof(t_hang));
h->h_n = ac+1;
h->h_atoms = (t_atom *)getbytes(h->h_n*sizeof(t_atom));
SETSYMBOL(&h->h_atoms[0], s);
for (i = 1; i < h->h_n; ++i)
h->h_atoms[i] = av[i-1];
h->h_next = x->x_hang;
x->x_hang = h;
h->h_owner = x;
h->h_clock = clock_new(h, (t_method)pipelist_any_hang_tick);
clock_delay(h->h_clock, (x->x_deltime >= 0 ? x->x_deltime : 0));
}
/* otherwise just pass it straight through */
else outlet_anything(x->x_pipelistout, s, ac, av);
}
static void pipelist_flush(t_pipelist *x)
{
while (x->x_hang) pipelist_hang_tick(x->x_hang);
}
static void pipelist_clear(t_pipelist *x)
{
t_hang *hang;
while ((hang = x->x_hang) != NULL)
{
x->x_hang = hang->h_next;
pipelist_hang_free(hang);
}
}
void pipelist_setup(void)
{
pipelist_class = class_new(gensym("pipelist"),
(t_newmethod)pipelist_new, (t_method)pipelist_clear,
sizeof(t_pipelist), 0, A_GIMME, 0);
class_addlist(pipelist_class, pipelist_list);
class_addanything(pipelist_class, pipelist_anything);
class_addmethod(pipelist_class, (t_method)pipelist_flush, gensym("flush"), 0);
class_addmethod(pipelist_class, (t_method)pipelist_clear, gensym("clear"), 0);
}
/* end of pipelist.c*/
mrpeach/osc/unpackOSCstream.pd 0000644 0001750 0001750 00000000462 11522077656 017117 0 ustar zmoelnig zmoelnig #N canvas 693 326 361 208 10;
#X obj 9 7 inlet;
#X obj 9 135 unpackOSC;
#X obj 9 158 outlet;
#X obj 60 158 outlet;
#X text 172 144 Author: Roman Haefeli;
#X text 172 160 Version: 2011-02-01;
#X obj 9 71 mrpeach/slipdec 65536;
#X connect 0 0 6 0;
#X connect 1 0 2 0;
#X connect 1 1 3 0;
#X connect 6 0 1 0;
mrpeach/osc/unpackOSCstream-help.pd 0000644 0001750 0001750 00000002726 11533764023 020043 0 ustar zmoelnig zmoelnig #N canvas 1 53 638 435 10;
#X text 8 369 check also:;
#X obj 240 386 tcpreceive;
#X obj 183 386 tcpsend;
#X obj 318 386 tcpserver;
#X obj 389 386 tcpclient;
#X text 472 374 Author: Roman Haefeli;
#X text 472 390 Version: 2008-09-09;
#X text 158 65 [unpackOSCstream] is meant to be a replacement for [unpackOSC]
\, when receiving from a stream based protocol \, such as TCP.;
#X obj 18 197 unpackOSCstream;
#X obj 18 17 tcpreceive 9995;
#X obj 18 222 print;
#X floatatom 105 221 5 0 0 0 - - -;
#X text 159 283 reference:;
#X obj 10 386 packOSCstream;
#X obj 110 386 unpackOSC;
#X text 160 300 http://archive.cnmat.berkeley.edu/OpenSoundControl/OSC-spec.html
: Section "OSC Packets";
#X text 141 221 milliseconds delay;
#X text 158 119 [unpackOSCstream] will only be able to decode OSC packets
or bundles created by [packOSCstream]. OSC packets that were generated
by [packOSC] will cause errors or wrong output.;
#N canvas 507 340 494 344 META 0;
#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 5 KEYWORDS control network abstraction;
#X text 12 46 DESCRIPTION meant to be a replacement for [unpackOSC]
\, when receiving from a stream based protocol \, such as TCP.;
#X text 12 75 INLET_0 anything;
#X text 12 95 OUTLET_0 anything;
#X text 12 115 OUTLET_1 float;
#X text 12 135 AUTHOR Roman Haefeli;
#X restore 591 413 pd META;
#X connect 8 0 10 0;
#X connect 8 1 11 0;
#X connect 9 0 8 0;
mrpeach/osc/packOSC-help.pd 0000644 0001750 0001750 00000010241 12741545524 016260 0 ustar zmoelnig zmoelnig #N canvas 201 81 1158 705 12;
#X obj 301 434 cnv 15 100 40 empty empty empty 20 12 0 14 -4034 -66577
0;
#X obj 330 548 udpsend;
#X msg 323 521 disconnect;
#X msg 301 499 connect 127.0.0.1 9997;
#X obj 330 447 packOSC;
#X obj 330 583 tgl 15 0 empty empty 1=connected 20 8 0 8 -4034 -257985
-1 1 1;
#X msg -130 -33 send /test/one/two/three zz 88 T;
#X msg -84 13 send /test 1 2 3;
#X msg -107 -10 send /west 35;
#X msg -38 59 send /*/left 22;
#X msg -13 84 send /?est/ 1;
#X text 293 13 packOSC is like sendOSC except that it outputs a list
of floats instead of directly connecting to the network;
#X text 103 -33 send a type-guessed message;
#X obj 515 541 routeOSC;
#X text 436 540 see also:;
#X msg 318 415 typetags \$1;
#X obj 318 397 tgl 15 0 empty empty empty 17 7 0 10 -257985 -258113
-1 0 1;
#X text 414 414 typetags are on by default;
#X text 578 107 Useable types are:;
#X text 578 125 i: 32 bit integer;
#X text 578 143 f: 32-bit float;
#X text 578 161 s: string;
#X text 359 107 send a type-forced message;
#X msg 10 107 sendtyped /test/one/two/three sis zz 88 T;
#X msg 33 130 sendtyped /left/right TTiTIFNfisf 1.1 2.1 3.1 4.1 5.1
;
#X text 578 179 T: true (no argument);
#X text 578 197 F: false (no argument);
#X text 578 215 I: infinitum (no argument);
#X text 578 232 N: Nil (no argument);
#X msg 277 374 bufsize 100;
#X text 376 374 set buffer size (default is 64000 bytes);
#X msg 79 176 prefix /test;
#X text 186 175 set the OSC path prefix for subsequent messages;
#X msg -61 36 /left one two;
#X msg 56 153 /right 88;
#X text 139 153 'send' prefix is not required;
#X msg 55 209 [;
#X msg 9 210 ];
#X text -97 211 close bundle;
#X msg 157 254 timetagoffset 0;
#X msg 180 277 timetagoffset -1;
#X text 319 254 send current time as timetag;
#X text 135 229 (timetags are sent in bundle messages only);
#X obj 9 186 t b a b;
#X msg -90 166 /test 5 6 7;
#X text 323 277 immediate time tag (default);
#X floatatom 376 476 5 0 0 0 - - -, f 5;
#X text 426 476 bundle depth;
#X obj 495 499 cnv 15 380 30 empty empty empty 20 12 0 14 -24198 -66577
0;
#X text 589 540 and http://opensoundcontrol.org/cnmat;
#X msg 203 300 timetagoffset 1e+06;
#X text 499 506 <- First open routeOSC-help \, then connect;
#X text 88 210 open a bundle (and generate time tag);
#X obj 418 568 packOSCstream;
#X text 383 567 see:;
#X text 534 568 for a way to send OSC over TCP or serial connections.
;
#X text 366 299 current time plus 1 second (delay is in microseconds)
;
#X text 578 248 b: blob (a list of bytes \, or floats on [0..255])
;
#X text 722 341 send a blob;
#X msg 253 334 sendtyped /left b 0 1 2 3 124 125 126 127 128 129 255
254 253 252 -14 -15 -16 17 18 19 20 21 22 23 24 25 26 27 28;
#N canvas 496 61 548 344 META 0;
#X text 12 185 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 165 AUTHOR Martin Peach;
#X text 12 5 KEYWORDS control network;
#X text 12 45 DESCRIPTION packOSC is like sendOSC except it outputs
a list of floats instead of directly connecting to the network;
#X text 12 85 INLET_0 anything send sendtyped prefix timetagoffset
bufsize typetags;
#X text 12 125 OUTLET_0 anything;
#X text 12 145 OUTLET_1 float;
#X restore 832 595 pd META;
#X msg 150 65 sendtyped /a/midi/message mm 0 144 60 64 0 144 62 32
;
#X obj 175 530 print >>;
#X text 578 263 m: MIDI (4 bytes per MIDI message:;
#X text 601 278 Port \, Status \, Param1 \, Param2;
#X text -75 570 2009-2016 Martin Peach;
#X obj 175 506 spigot;
#X obj 220 473 tgl 15 0 empty empty raw 17 7 0 12 -257985 -258113 -1
0 1;
#X connect 1 0 5 0;
#X connect 2 0 1 0;
#X connect 3 0 1 0;
#X connect 4 0 1 0;
#X connect 4 0 66 0;
#X connect 4 1 46 0;
#X connect 6 0 4 0;
#X connect 7 0 4 0;
#X connect 8 0 4 0;
#X connect 9 0 4 0;
#X connect 10 0 4 0;
#X connect 15 0 4 0;
#X connect 16 0 15 0;
#X connect 23 0 4 0;
#X connect 24 0 4 0;
#X connect 29 0 4 0;
#X connect 31 0 4 0;
#X connect 33 0 4 0;
#X connect 34 0 4 0;
#X connect 36 0 4 0;
#X connect 37 0 4 0;
#X connect 39 0 4 0;
#X connect 40 0 4 0;
#X connect 43 0 37 0;
#X connect 43 1 4 0;
#X connect 43 2 36 0;
#X connect 44 0 43 0;
#X connect 50 0 4 0;
#X connect 59 0 4 0;
#X connect 61 0 4 0;
#X connect 66 0 62 0;
#X connect 67 0 66 1;
mrpeach/osc/packOSCstream-help.pd 0000644 0001750 0001750 00000004200 11533764023 017465 0 ustar zmoelnig zmoelnig #N canvas 1 53 609 569 10;
#X obj 69 119 packOSCstream;
#X obj 69 451 tcpsend;
#X text -24 496 check also:;
#X obj -22 513 unpackOSCstream;
#X obj 93 513 packOSC;
#X msg 38 403 connect localhost 9995;
#X obj 208 513 tcpreceive;
#X obj 151 513 tcpsend;
#X obj 286 513 tcpserver;
#X obj 357 513 tcpclient;
#X msg 58 423 disconnect;
#X obj 69 473 tgl 15 0 empty empty empty 17 7 0 10 -4034 -257985 -1
0 1;
#X obj 181 403 cnv 15 380 30 empty empty empty 20 12 0 14 -24198 -66577
0;
#X text 196 408 <- First open unpackOSCstream-help \, then connect
;
#X text 440 501 Author: Roman Haefeli;
#X text 440 517 Version: 2008-09-09;
#X text 74 254 [packOSCstream] uses the same methods as [packOSC].
Please consult packOSC-help.pd for the complete documentation.;
#X text 75 189 [packOSstream] puts a frame length header (int32) in
front of every OSC packet or bundle \, so that the receiving side knows
\, how to split the incoming stream into OSC packets again.;
#X msg -24 9 /first/message 1 \, /second/message 2;
#X text 79 330 reference:;
#X text 80 347 http://archive.cnmat.berkeley.edu/OpenSoundControl/OSC-spec.html
: Section "OSC Packets";
#X msg -4 29 send /test/one/two/three zz 88 T;
#X msg 16 49 sendtyped /test/one/two/three sis zz 88 T;
#X msg 36 69 prefix /test;
#X msg 56 89 [ \, /previous/page 666 \, /next/page 999 \, ];
#X text 72 142 [packOSCstream] is meant to be a replacement for [packOSC]
\, when sending over a stream based protocol \, such as TCP.;
#N canvas 499 120 494 344 META 0;
#X text 12 135 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 115 AUTHOR Roman Haefeli;
#X text 12 75 INLET_0 anything send sendtyped prefix connect disconnect
;
#X text 12 45 DESCRIPTION meant to be a replacement for [packOSC] \,
when sending over a stream based protocol \, such as TCP;
#X text 12 95 OUTLET_0 float;
#X text 12 5 KEYWORDS control network abstraction;
#X restore 532 544 pd META;
#X connect 0 0 1 0;
#X connect 1 0 11 0;
#X connect 5 0 1 0;
#X connect 10 0 1 0;
#X connect 18 0 0 0;
#X connect 21 0 0 0;
#X connect 22 0 0 0;
#X connect 23 0 0 0;
#X connect 24 0 0 0;
mrpeach/osc/packOSCstream.pd 0000644 0001750 0001750 00000000457 11522077656 016560 0 ustar zmoelnig zmoelnig #N canvas 642 471 204 215 10;
#X obj 9 35 packOSC;
#X obj 9 14 inlet;
#X obj 9 139 outlet;
#X text 36 157 Author: Roman Haefeli;
#X obj 135 139 outlet;
#X obj 9 80 mrpeach/slipenc 65536;
#X text 36 173 version: 2011-02-01;
#X connect 0 0 5 0;
#X connect 0 1 4 0;
#X connect 1 0 0 0;
#X connect 5 0 2 0;
mrpeach/osc/packingOSC.h 0000644 0001750 0001750 00000001575 12453053113 015652 0 ustar zmoelnig zmoelnig /* packingOSC.h */
#ifndef _PACKINGOSC
#include "m_pd.h"
#include
#include
#include
#ifdef _WIN32
#include
#include
#else
#include
#include
#include
#include
#endif /* _WIN32 */
/* Declarations */
#ifdef WIN32
typedef unsigned __int64 osc_time_t;
#else
typedef unsigned long long osc_time_t;
#endif
#define MAX_MESG 65536 /* same as MAX_UDP_PACKET */
/* The maximum depth of bundles within bundles within bundles within...
This is the size of a static array. If you exceed this limit you'll
get an error message. */
#define MAX_BUNDLE_NESTING 32
typedef struct
{
uint32_t seconds;
uint32_t fraction;
} OSCTimeTag;
typedef union
{
int i;
float f;
} intfloat32;
#endif // _PACKINGOSC
/* end of packingOSC.h */
mrpeach/osc/routeOSC-help.pd 0000644 0001750 0001750 00000007202 12741545524 016503 0 ustar zmoelnig zmoelnig #N canvas 81 134 1070 758 12;
#X obj 11 524 cnv 15 820 130 empty empty empty 20 12 0 14 -261207 -66577
0;
#X obj -31 10 udpreceive 9997;
#X floatatom 160 82 3 0 0 0 - - -, f 3;
#X floatatom 191 82 3 0 0 0 - - -, f 3;
#X floatatom 222 82 3 0 0 0 - - -, f 3;
#X floatatom 253 82 3 0 0 0 - - -, f 3;
#X text 120 81 from;
#X obj -31 134 unpackOSC;
#X text 369 78 see also:;
#X obj 445 79 packOSC;
#X floatatom 528 154 10 0 0 1 millisecond_delay - -, f 10;
#X obj -31 161 pipelist;
#X text 529 529 arguments are OSC addresses to be routed;
#X text 88 677 see:;
#X text 248 678 for a way to send OSC over TCP or serial connections.
;
#X obj 123 678 unpackOSCstream;
#X obj -65 188 print unpacked;
#X obj 160 58 unpack 0 0 0 0 0;
#X floatatom 285 82 8 0 0 0 - - -, f 8;
#X obj 86 35 route received from;
#X floatatom 86 103 5 0 0 0 - - -, f 5;
#X text 129 103 bytes;
#X text 98 9 Open [packOSC-help] to send packets to this patch.;
#X text 39 156 If the OSC packet has a timetag \, [pipelist] will delay
it until the time occurs;
#X obj 317 623 print match_1;
#X obj 393 601 print match_2;
#X obj 546 557 print no_match;
#N canvas 499 254 494 344 META 0;
#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 5 KEYWORDS control list_op;
#X text 12 75 INLET_0 list verbosity paths set;
#X text 12 95 OUTLET_N list;
#X text 12 115 OUTLET_R list;
#X text 12 135 AUTHOR Martin Peach;
#X text 12 45 DESCRIPTION routes lists as OSC packets.;
#X restore 833 655 pd META;
#X text 657 627 2012/03/13 Martin Peach;
#X text 44 119 [unpackOSC] parses lists of floats (only integers on
[0..255]) as OSC packets.;
#X obj 11 219 cnv 15 600 160 empty empty empty 20 12 0 14 -204786 -66577
0;
#X obj 172 382 cnv 15 600 140 empty empty empty 20 12 0 14 -261234
-66577 0;
#X msg 121 313 set /left;
#X msg 98 290 set /left /right;
#X text 226 311 (but new outlets can't be created);
#X msg 72 264 paths;
#X msg 49 241 verbosity \$1;
#X obj 49 223 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
#X text 67 219 set to 1 for debugging;
#X text 295 335 routeOSC will match deep paths;
#X text 232 289 [set( reassigns outputs from left to right;
#X text 126 264 [paths( will print the current OSC addresses to Pd
console;
#X msg 190 382 /test any2 4 5;
#X msg 302 494 1 2 3;
#X msg 144 336 set /one/two/three;
#X msg 167 359 set /*;
#X text 220 358 this will match any OSC message;
#X msg 257 449 /* zap!;
#X msg 280 472 zorro trope;
#X text 379 472 not a valid OSC message;
#X text 350 493 not a valid OSC message;
#X text 308 382 input is a message whose selector is an OSC path;
#X text 411 404 or a list whose first element is an OSC path;
#X obj 469 579 print match_3;
#X obj 317 529 routeOSC /test /west /one/two;
#X msg 234 426 /one/two/three yikes!;
#X msg 212 404 list /west/rate any1 2 3;
#X text 11 556 [routeOSC] routes Open Sound Control* messages \, or
lists of anything beginning with a /path;
#X text 13 599 *See http://opensoundcontrol.org/spec-1_0;
#X connect 1 0 7 0;
#X connect 1 1 19 0;
#X connect 7 0 11 0;
#X connect 7 0 16 0;
#X connect 7 1 10 0;
#X connect 7 1 11 1;
#X connect 11 0 54 0;
#X connect 17 0 2 0;
#X connect 17 1 3 0;
#X connect 17 2 4 0;
#X connect 17 3 5 0;
#X connect 17 4 18 0;
#X connect 19 0 20 0;
#X connect 19 1 17 0;
#X connect 32 0 54 0;
#X connect 33 0 54 0;
#X connect 35 0 54 0;
#X connect 36 0 54 0;
#X connect 37 0 36 0;
#X connect 42 0 54 0;
#X connect 43 0 54 0;
#X connect 44 0 54 0;
#X connect 45 0 54 0;
#X connect 47 0 54 0;
#X connect 48 0 54 0;
#X connect 54 0 24 0;
#X connect 54 1 25 0;
#X connect 54 2 53 0;
#X connect 54 3 26 0;
#X connect 55 0 54 0;
#X connect 56 0 54 0;
mrpeach/osc/pipelist-help.pd 0000644 0001750 0001750 00000002625 11533764023 016630 0 ustar zmoelnig zmoelnig #N canvas 1 53 558 300 10;
#X obj 112 129 pipelist 1000;
#X msg 198 83 5000;
#X floatatom 198 107 5 0 0 0 - - -;
#X floatatom 222 42 5 0 0 0 - - -;
#X floatatom 181 42 5 0 0 0 - - -;
#X obj 112 62 pack s s 3 4 5;
#X obj 112 0 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X msg 135 -1 tik;
#X msg 57 13 alpha;
#X msg 50 41 beta;
#X floatatom 63 90 5 0 0 0 - - -;
#X obj 112 196 print;
#X obj 130 107 symbol;
#X msg 135 83 bb;
#X text 195 1 pipelist delays lists.;
#X text 237 106 Delay time is in milliseconds.;
#X text 208 131 Argument sets initial delay time.;
#X text 242 218 2007/07/11 Martin Peach;
#X text 229 182 see also:;
#X obj 305 183 pipe;
#X obj 339 183 delay;
#X obj 379 183 timer;
#X obj 135 21 symbol;
#N canvas 500 149 494 344 META 0;
#X text 12 145 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 125 AUTHOR Roman Haefeli;
#X text 12 5 KEYWORDS control list_op;
#X text 12 45 DESCRIPTION delay lists;
#X text 12 65 INLET_0 anything;
#X text 12 85 INLET_1 float;
#X text 12 105 OUTLET_0 list;
#X restore 492 265 pd META;
#X connect 0 0 11 0;
#X connect 1 0 2 0;
#X connect 2 0 0 1;
#X connect 3 0 5 4;
#X connect 4 0 5 3;
#X connect 5 0 0 0;
#X connect 6 0 5 0;
#X connect 7 0 22 0;
#X connect 8 0 5 0;
#X connect 9 0 5 0;
#X connect 10 0 0 0;
#X connect 12 0 0 0;
#X connect 13 0 12 0;
#X connect 22 0 5 1;
mrpeach/osc/unpackOSC.c 0000644 0001750 0001750 00000055476 12741545524 015537 0 ustar zmoelnig zmoelnig /* unpackOSC is like dumpOSC but outputs a list consisting of a single symbol for the path */
/* and a list of floats and/or symbols for the data, and adds an outlet for a time delay. */
/* This allows for the separation of the protocol and its transport. */
/* Started by Martin Peach 20060420 */
/* dumpOSC.c header follows: */
/*
Written by Matt Wright and Adrian Freed, The Center for New Music and
Audio Technologies, University of California, Berkeley. Copyright (c)
1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of
California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
*/
/*
dumpOSC.c
server that displays OpenSoundControl messages sent to it
for debugging client udp and UNIX protocol
by Matt Wright, 6/3/97
modified from dumpSC.c, by Matt Wright and Adrian Freed
version 0.2: Added "-silent" option a.k.a. "-quiet"
version 0.3: Incorporated patches from Nicola Bernardini to make
things Linux-friendly. Also added ntohl() in the right places
to support little-endian architectures.
to-do:
More robustness in saying exactly what's wrong with ill-formed
messages. (If they don't make sense, show exactly what was
received.)
Time-based features: print time-received for each packet
Clean up to separate OSC parsing code from socket/select stuff
pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c
-------------
-- added pd functions
-- socket is made differently than original via pd mechanisms
-- tweaks for Win32 www.zeggz.com/raf 13-April-2002
-- the OSX changes from cnmat didnt make it here yet but this compiles
on OSX anyway.
*/
//define DEBUG
#include "packingOSC.h"
static t_class *unpackOSC_class;
typedef struct _unpackOSC
{
t_object x_obj;
t_outlet *x_data_out;
t_outlet *x_delay_out;
int x_bundle_flag;/* non-zero if we are processing a bundle */
int x_recursion_level;/* number of times we reenter unpackOSC_list */
int x_abort_bundle;/* non-zero if unpackOSC_list is not well formed */
int x_reentry_count;
} t_unpackOSC;
void unpackOSC_setup(void);
static void *unpackOSC_new(void);
static void unpackOSC_free(t_unpackOSC *x);
static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv);
static int unpackOSC_path(t_atom *data_at, char *path);
static void unpackOSC_Smessage(t_atom *data_at, int *data_atc, void *v, int n);
static void unpackOSC_PrintTypeTaggedArgs(t_atom *data_at, int *data_atc, void *v, int n);
static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_atom *data_at, int *data_atc, void *v, int n, int skipComma);
static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary);
static int unpackOSC_IsNiceString(char *string, char *boundary);
static t_float unpackOSC_DeltaTime(OSCTimeTag tt);
static void *unpackOSC_new(void)
{
t_unpackOSC *x;
x = (t_unpackOSC *)pd_new(unpackOSC_class);
x->x_data_out = outlet_new(&x->x_obj, &s_list);
x->x_delay_out = outlet_new(&x->x_obj, &s_float);
x->x_bundle_flag = 0;
x->x_recursion_level = 0;
x->x_abort_bundle = 0;
return (x);
}
static void unpackOSC_free(t_unpackOSC *x)
{
}
void unpackOSC_setup(void)
{
unpackOSC_class = class_new(gensym("unpackOSC"),
(t_newmethod)unpackOSC_new, (t_method)unpackOSC_free,
sizeof(t_unpackOSC), 0, 0);
class_addlist(unpackOSC_class, (t_method)unpackOSC_list);
}
/* unpackOSC_list expects an OSC packet in the form of a list of floats on [0..255] */
static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv)
{
int size, messageLen, i, j;
char *messageName, *args, *buf;
OSCTimeTag tt;
t_atom data_at[MAX_MESG] ={{0}};/* symbols making up the path + payload */
int data_atc = 0;/* number of symbols to be output */
char raw[MAX_MESG];/* bytes making up the entire OSC message */
int raw_c;/* number of bytes in OSC message */
#ifdef DEBUG
printf(">>> unpackOSC_list: %d bytes, abort=%d, reentry_count %d recursion_level %d\n",
argc, x->x_abort_bundle, x->x_reentry_count, x->x_recursion_level);
#endif
if(x->x_abort_bundle) return; /* if backing quietly out of the recursive stack */
x->x_reentry_count++;
if ((argc%4) != 0)
{
post("unpackOSC: Packet size (%d) not a multiple of 4 bytes: dropping packet", argc);
goto unpackOSC_list_out;
}
if(argc > MAX_MESG)
{
post("unpackOSC: Packet size (%d) greater than max (%d). Change MAX_MESG and recompile if you want more.", argc, MAX_MESG);
goto unpackOSC_list_out;
}
/* copy the list to a byte buffer, checking for bytes only */
for (i = 0; i < argc; ++i)
{
if (argv[i].a_type == A_FLOAT)
{
j = (int)argv[i].a_w.w_float;
/* if ((j == argv[i].a_w.w_float) && (j >= 0) && (j <= 255)) */
/* this can miss bytes between 128 and 255 because they are interpreted somewhere as negative */
/* , so change to this: */
if ((j == argv[i].a_w.w_float) && (j >= -128) && (j <= 255))
{
raw[i] = (char)j;
}
else
{
post("unpackOSC: Data out of range (%d), dropping packet", argv[i].a_w.w_float);
goto unpackOSC_list_out;
}
}
else
{
post("unpackOSC: Data not float, dropping packet");
goto unpackOSC_list_out;
}
}
raw_c = argc;
buf = raw;
if ((argc >= 8) && (strncmp(buf, "#bundle", 8) == 0))
{ /* This is a bundle message. */
#ifdef DEBUG
printf("unpackOSC: bundle msg:\n");
#endif
if (argc < 16)
{
post("unpackOSC: Bundle message too small (%d bytes) for time tag", argc);
goto unpackOSC_list_out;
}
x->x_bundle_flag = 1;
/* Print the time tag */
#ifdef DEBUG
printf("unpackOSC bundle timetag: [ %x.%0x\n", ntohl(*((uint32_t *)(buf+8))),
ntohl(*((uint32_t *)(buf+12))));
#endif
/* convert the timetag into a millisecond delay from now */
tt.seconds = ntohl(*((uint32_t *)(buf+8)));
tt.fraction = ntohl(*((uint32_t *)(buf+12)));
/* pd can use a delay in milliseconds */
outlet_float(x->x_delay_out, unpackOSC_DeltaTime(tt));
/* Note: if we wanted to actually use the time tag as a little-endian
64-bit int, we'd have to word-swap the two 32-bit halves of it */
i = 16; /* Skip "#group\0" and time tag */
while(i < argc)
{
size = ntohl(*((int *) (buf + i)));
if ((size % 4) != 0)
{
post("unpackOSC: Bad size count %d in bundle (not a multiple of 4)", size);
goto unpackOSC_list_out;
}
if ((size + i + 4) > argc)
{
post("unpackOSC: Bad size count %d in bundle (only %d bytes left in entire bundle)",
size, argc-i-4);
goto unpackOSC_list_out;
}
/* Recursively handle element of bundle */
x->x_recursion_level++;
#ifdef DEBUG
printf("unpackOSC: bundle depth %d\n", x->x_recursion_level);
#endif
if (x->x_recursion_level > MAX_BUNDLE_NESTING)
{
post("unpackOSC: bundle depth %d exceeded", MAX_BUNDLE_NESTING);
x->x_abort_bundle = 1;/* we need to back out of the recursive stack*/
goto unpackOSC_list_out;
}
#ifdef DEBUG
printf("unpackOSC: bundle calling unpackOSC_list(x=%p, s=%s, size=%d, argv[%d]=%p)\n",
x, s->s_name, size, i+4, &argv[i+4]);
#endif
unpackOSC_list(x, s, size, &argv[i+4]);
i += 4 + size;
}
if (i != argc)
{
post("unpackOSC: This can't happen");
}
x->x_bundle_flag = 0; /* end of bundle */
#ifdef DEBUG
printf("unpackOSC: bundle end ] depth is %d\n", x->x_recursion_level);
#endif
}
else if ((argc == 24) && (strcmp(buf, "#time") == 0))
{
post("unpackOSC: Time message: %s\n :).\n", buf);
goto unpackOSC_list_out;
}
else
{ /* This is not a bundle message or a time message */
messageName = buf;
#ifdef DEBUG
printf("unpackOSC: message name string: %s length %d\n", messageName, raw_c);
#endif
args = unpackOSC_DataAfterAlignedString(messageName, buf+raw_c);
if (args == 0)
{
post("unpackOSC: Bad message name string: Dropping entire message.");
goto unpackOSC_list_out;
}
messageLen = args-messageName;
/* put the OSC path into a single symbol */
data_atc = unpackOSC_path(data_at, messageName); /* returns 1 if path OK, else 0 */
if (data_atc == 1)
{
#ifdef DEBUG
printf("unpackOSC_list calling unpackOSC_Smessage: message length %d\n", raw_c-messageLen);
#endif
unpackOSC_Smessage(data_at, &data_atc, (void *)args, raw_c-messageLen);
if (0 == x->x_bundle_flag)
outlet_float(x->x_delay_out, 0); /* no delay for message not in a bundle */
}
}
if (data_atc >= 1)
outlet_anything(x->x_data_out, atom_getsymbol(data_at), data_atc-1, data_at+1);
data_atc = 0;
x->x_abort_bundle = 0;
unpackOSC_list_out:
x->x_recursion_level = 0;
x->x_reentry_count--;
}
static int unpackOSC_path(t_atom *data_at, char *path)
{
int i;
if (path[0] != '/')
{
for (i = 0; i < 16; ++i) if ('\0' == path[i]) break;
path[i] = '\0';
post("unpackOSC: Path doesn't begin with \"/\", dropping message");
return 0;
}
for (i = 1; i < MAX_MESG; ++i)
{
if (path[i] == '\0')
{ /* the end of the path: turn path into a symbol */
SETSYMBOL(data_at, gensym(path));
return 1;
}
}
post("unpackOSC: Path too long, dropping message");
return 0;
}
#define SMALLEST_POSITIVE_FLOAT 0.000001f
static void unpackOSC_Smessage(t_atom *data_at, int *data_atc, void *v, int n)
{
char *chars = v;
if (n != 0)
{
if (chars[0] == ',')
{
if (chars[1] != ',')
{
#ifdef DEBUG
printf("unpackOSC_Smessage calling unpackOSC_PrintTypeTaggedArgs: message length %d\n", n);
#endif
/* This message begins with a type-tag string */
unpackOSC_PrintTypeTaggedArgs(data_at, data_atc, v, n);
}
else
{
#ifdef DEBUG
printf("unpackOSC_Smessage calling unpackOSC_PrintHeuristicallyTypeGuessedArgs: message length %d, skipComma 1\n", n);
#endif
/* Double comma means an escaped real comma, not a type string */
unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 1);
}
}
else
{
#ifdef DEBUG
printf("unpackOSC_Smessage calling unpackOSC_PrintHeuristicallyTypeGuessedArgs: message length %d, skipComma 0\n", n);
#endif
unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 0);
}
}
}
static void unpackOSC_PrintTypeTaggedArgs(t_atom *data_at, int *data_atc, void *v, int n)
{
char *typeTags, *thisType, *p;
int myargc = *data_atc;
t_atom *mya = data_at;
typeTags = v;
if (!unpackOSC_IsNiceString(typeTags, typeTags+n))
{
#ifdef DEBUG
printf("unpackOSC_PrintTypeTaggedArgs not nice string\n");
#endif
/* No null-termination, so maybe it wasn't a type tag
string after all */
unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 0);
return;
}
#ifdef DEBUG
printf("unpackOSC_PrintTypeTaggedArgs calling unpackOSC_DataAfterAlignedString %p to %p\n", typeTags, typeTags+n);
#endif
p = unpackOSC_DataAfterAlignedString(typeTags, typeTags+n);
#ifdef DEBUG
printf("unpackOSC_PrintTypeTaggedArgs p is %p: ", p);
#endif
if (p == NULL) return; /* malformed message */
for (thisType = typeTags + 1; *thisType != 0; ++thisType)
{
switch (*thisType)
{
case 'b': /* blob: an int32 size count followed by that many 8-bit bytes */
{
int i, blob_bytes = ntohl(*((int *) p));
#ifdef DEBUG
printf("blob: %u bytes\n", blob_bytes);
#endif
p += 4;
for (i = 0; i < blob_bytes; ++i, ++p, ++myargc)
SETFLOAT(mya+myargc,(*(unsigned char *)p));
while (i%4)
{
++i;
++p;
}
break;
}
case 'm': /* MIDI message is the next four bytes*/
{
int i;
#ifdef DEBUG
printf("MIDI: 0x%08X\n", ntohl(*((int *) p)));
#endif
for (i = 0; i < 4; ++i, ++p, ++myargc)
SETFLOAT(mya+myargc, (*(unsigned char *)p));
break;
}
case 'i': case 'r': case 'c':
#ifdef DEBUG
printf("integer: %d\n", ntohl(*((int *) p)));
#endif
SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p)));
myargc++;
p += 4;
break;
case 'f':
{
intfloat32 thisif;
thisif.i = ntohl(*((int *) p));
#ifdef DEBUG
printf("float: %f\n", thisif.f);
#endif
SETFLOAT(mya+myargc, thisif.f);
myargc++;
p += 4;
break;
}
case 'h': case 't':
#ifdef DEBUG
printf("[A 64-bit int]\n");
#endif
post("unpackOSC: PrintTypeTaggedArgs: [A 64-bit int] not implemented");
p += 8;
break;
case 'd':
#ifdef DEBUG
printf("[A 64-bit float]\n");
#endif
post("unpackOSC: PrintTypeTaggedArgs: [A 64-bit float] not implemented");
p += 8;
break;
case 's': case 'S':
if (!unpackOSC_IsNiceString(p, typeTags+n))
{
post("unpackOSC: PrintTypeTaggedArgs: Type tag said this arg is a string but it's not!\n");
return;
}
else
{
#ifdef DEBUG
printf("string: \"%s\"\n", p);
#endif
SETSYMBOL(mya+myargc,gensym(p));
myargc++;
p = unpackOSC_DataAfterAlignedString(p, typeTags+n);
}
break;
case 'T':
#ifdef DEBUG
printf("[True]\n");
#endif
SETFLOAT(mya+myargc,1.);
myargc++;
break;
case 'F':
#ifdef DEBUG
printf("[False]\n");
#endif
SETFLOAT(mya+myargc,0.);
myargc++;
break;
case 'N':
#ifdef DEBUG
printf("[Nil]\n");
#endif
SETFLOAT(mya+myargc,0.);
myargc++;
break;
case 'I':
#ifdef DEBUG
printf("[Infinitum]\n");
#endif
SETSYMBOL(mya+myargc,gensym("INF"));
myargc++;
break;
default:
#ifdef DEBUG
printf("unpackOSC_PrintTypeTaggedArgs unknown typetag %c (%0X)\n", *thisType, *thisType);
#endif
post("unpackOSC: PrintTypeTaggedArgs: [Unrecognized type tag %c]", *thisType);
return;
}
}
*data_atc = myargc;
}
static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_atom *data_at, int *data_atc, void *v, int n, int skipComma)
{
int i;
int *ints;
intfloat32 thisif;
char *chars, *string, *nextString;
int myargc = *data_atc;
t_atom* mya = data_at;
/* Go through the arguments 32 bits at a time */
ints = v;
chars = v;
for (i = 0; i < n/4; )
{
string = &chars[i*4];
thisif.i = ntohl(ints[i]);
/* Reinterpret the (potentially byte-reversed) thisif as a float */
if (thisif.i >= -1000 && thisif.i <= 1000000)
{
#ifdef DEBUG
printf("%d ", thisif.i);
#endif
SETFLOAT(mya+myargc,(t_float) (thisif.i));
myargc++;
i++;
}
else if (thisif.f >= -1000.f && thisif.f <= 1000000.f &&
(thisif.f <=0.0f || thisif.f >= SMALLEST_POSITIVE_FLOAT))
{
#ifdef DEBUG
printf("%f ", thisif.f);
#endif
SETFLOAT(mya+myargc,thisif.f);
myargc++;
i++;
}
else if (unpackOSC_IsNiceString(string, chars+n))
{
nextString = unpackOSC_DataAfterAlignedString(string, chars+n);
#ifdef DEBUG
printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string);
#endif
SETSYMBOL(mya+myargc,gensym(string));
myargc++;
i += (nextString-string) / 4;
}
else
{
/* unhandled .. ;) */
post("unpackOSC: PrintHeuristicallyTypeGuessedArgs: indeterminate type: 0x%x xx", ints[i]);
i++;
}
*data_atc = myargc;
}
}
#define STRING_ALIGN_PAD 4
static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary)
{
/* The argument is a block of data beginning with a string. The
string has (presumably) been padded with extra null characters
so that the overall length is a multiple of STRING_ALIGN_PAD
bytes. Return a pointer to the next byte after the null
byte(s). The boundary argument points to the character after
the last valid character in the buffer---if the string hasn't
ended by there, something's wrong.
If the data looks wrong, return 0 */
int i;
#ifdef DEBUG
printf("unpackOSC_DataAfterAlignedString boundary - string = %ld\n", boundary-string);
#endif
if ((boundary - string) %4 != 0)
{
post("unpackOSC: DataAfterAlignedString: bad boundary");
return 0;
}
for (i = 0; string[i] != '\0'; i++)
{
#ifdef DEBUG
printf("%0X(%c) ", string[i], string[i]);
#endif
if (string + i >= boundary)
{
post("unpackOSC: DataAfterAlignedString: Unreasonably long string");
return 0;
}
}
/* Now string[i] is the first null character */
#ifdef DEBUG
printf("\nunpackOSC_DataAfterAlignedString first null character at %p\n", &string[i]);
#endif
i++;
for (; (i % STRING_ALIGN_PAD) != 0; i++)
{
if (string + i >= boundary)
{
post("unpackOSC: DataAfterAlignedString: Unreasonably long string");
return 0;
}
if (string[i] != '\0')
{
post("unpackOSC: DataAfterAlignedString: Incorrectly padded string");
return 0;
}
}
#ifdef DEBUG
printf("unpackOSC_DataAfterAlignedString first non-null character at %p\n", &string[i]);
#endif
return string+i;
}
static int unpackOSC_IsNiceString(char *string, char *boundary)
{
/* Arguments same as DataAfterAlignedString(). Is the given "string"
really an OSC-string? I.e., is it
"A sequence of non-null ASCII characters followed by a null, followed
by 0-3 additional null characters to make the total number of bits a
multiple of 32"? (OSC 1.0)
Returns 1 if true, else 0. */
int i;
if ((boundary - string) %4 != 0)
{
post("unpackOSC: IsNiceString: bad boundary\n");
return 0;
}
/* any non-zero byte will be accepted, so UTF-8 sequences will also be accepted -- not strictly OSC v1.0 */
for (i = 0; string[i] != '\0'; i++)
/* if ((!isprint(string[i])) || (string + i >= boundary)) return 0; */ /* only ASCII printable chars */
/*if ((0==(string[i]&0xE0)) || (string + i >= boundary)) return 0;*/ /* onl;y ASCII space (0x20) and above */
if (string + i >= boundary) return 0; /* anything non-zero */
/* If we made it this far, it's a null-terminated sequence of characters
within the given boundary. Now we just make sure it's null padded... */
/* Now string[i] is the first null character */
i++;
for (; (i % STRING_ALIGN_PAD) != 0; i++)
if (string[i] != '\0') return 0;
return 1;
}
#define SECONDS_FROM_1900_to_1970 2208988800LL /* 17 leap years */
#define TWO_TO_THE_32_OVER_ONE_MILLION 4295LL
#define ONE_MILLION_OVER_TWO_TO_THE_32 0.00023283064365386963
/* return the time difference in milliseconds between an OSC timetag and now */
static t_float unpackOSC_DeltaTime(OSCTimeTag tt)
{
static double onemillion = 1000000.0f;
#ifdef _WIN32
static double onethousand = 1000.0f;
#endif /* ifdef _WIN32 */
if (tt.fraction == 1 && tt.seconds == 0) return 0.0; /* immediate */
else
{
OSCTimeTag ttnow;
double ttusec, nowusec, delta;
#ifdef _WIN32
struct _timeb tb;
_ftime(&tb); /* find now */
/* First get the seconds right */
ttnow.seconds = (unsigned) SECONDS_FROM_1900_to_1970 + (unsigned) tb.time;
/* find usec in tt */
ttusec = tt.seconds*onemillion + ONE_MILLION_OVER_TWO_TO_THE_32*tt.fraction;
nowusec = ttnow.seconds*onemillion + tb.millitm*onethousand;
#else
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz); /* find now */
/* First get the seconds right */
ttnow.seconds = (unsigned) SECONDS_FROM_1900_to_1970 + (unsigned) tv.tv_sec;
/* find usec in tt */
ttusec = tt.seconds*onemillion + ONE_MILLION_OVER_TWO_TO_THE_32*tt.fraction;
nowusec = ttnow.seconds*onemillion + tv.tv_usec;
#endif /* ifdef _WIN32 */
/* subtract now from tt to get delta time */
/* if (ttusec < nowusec) return 0.0; */
/*negative delays are all right */
delta = ttusec - nowusec;
return (float)(delta*0.001f);
}
}
/* end of unpackOSC.c */
mrpeach/osc/routeOSC.c 0000644 0001750 0001750 00000053655 12430231203 015366 0 ustar zmoelnig zmoelnig /* routeOSC.c 20060424 by Martin Peach, based on OSCroute and OSC-pattern-match.c. */
/* OSCroute.c header follows: */
/*
Written by Adrian Freed, The Center for New Music and Audio Technologies,
University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
The Regents of the University of California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
*/
/* OSC-route.c
Max object for OSC-style dispatching
To-do:
Match a pattern against a pattern?
[Done: Only Slash-Star is allowed, see MyPatternMatch.]
Declare outlet types / distinguish leaf nodes from other children
More sophisticated (2-pass?) allmessages scheme
set message?
pd
-------------
-- tweaks for Win32 www.zeggz.com/raf 13-April-2002
*/
/* OSC-pattern-match.c header follows: */
/*
Copyright © 1998. The Regents of the University of California (Regents).
All Rights Reserved.
Written by Matt Wright, The Center for New Music and Audio Technologies,
University of California, Berkeley.
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
The OpenSound Control WWW page is
http://www.cnmat.berkeley.edu/OpenSoundControl
*/
/*
OSC-pattern-match.c
Matt Wright, 3/16/98
Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
*/
/* the required include files */
#include "m_pd.h"
#define MAX_NUM 128 // maximum number of paths (prefixes) we can route
typedef struct _routeOSC
{
t_object x_obj; /* required header */
int x_num; /* Number of prefixes we store */
int x_verbosity; /* level of debug output required */
char **x_prefixes; /* the OSC addresses to be matched */
int *x_prefix_depth; /* the number of slashes in each prefix */
void **x_outlets; /* one for each prefix plus one for everything else */
} t_routeOSC;
/* prototypes */
void routeOSC_setup(void);
static void routeOSC_free(t_routeOSC *x);
static int MyPatternMatch (const char *pattern, const char *test);
static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv);
static void routeOSC_bang(t_routeOSC *x);
static void routeOSC_float(t_routeOSC *x, t_floatarg f);
static void routeOSC_symbol(t_routeOSC *x, t_symbol *s);
static void routeOSC_list(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv);
static void *routeOSC_new(t_symbol *s, int argc, t_atom *argv);
static void routeOSC_set(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv);
static void routeOSC_paths(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv);
static void routeOSC_verbosity(t_routeOSC *x, t_floatarg v);
static int routeOSC_count_slashes(char *prefix);
static char *NextSlashOrNull(char *p);
static char *NthSlashOrNull(char *p, int n);
static void StrCopyUntilSlash(char *target, const char *source);
static void StrCopyUntilNthSlash(char *target, const char *source, int n);
/* from
OSC-pattern-match.c
*/
static const char *theWholePattern; /* Just for warning messages */
static int MatchBrackets (const char *pattern, const char *test);
static int MatchList (const char *pattern, const char *test);
static int PatternMatch (const char * pattern, const char * test);
static t_class *routeOSC_class;
t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
static int MyPatternMatch (const char *pattern, const char *test)
{
// This allows the special case of "routeOSC /* " to be an outlet that
// matches anything; i.e., it always outputs the input with the first level
// of the address stripped off.
if (test[0] == '*' && test[1] == '\0') return 1;
else return PatternMatch(pattern, test);
}
static void routeOSC_free(t_routeOSC *x)
{
freebytes(x->x_prefixes, x->x_num*sizeof(char *)); /* the OSC addresses to be matched */
freebytes(x->x_prefix_depth, x->x_num*sizeof(int)); /* the number of slashes in each prefix */
freebytes(x->x_outlets, (x->x_num+1)*sizeof(void *)); /* one for each prefix plus one for everything else */
}
/* initialization routine */
void routeOSC_setup(void)
{
routeOSC_class = class_new(gensym("routeOSC"), (t_newmethod)routeOSC_new,
(t_method)routeOSC_free, sizeof(t_routeOSC), 0, A_GIMME, 0);
class_addanything(routeOSC_class, routeOSC_doanything);
class_addbang(routeOSC_class, routeOSC_bang);
class_addfloat(routeOSC_class, routeOSC_float);
class_addsymbol(routeOSC_class, routeOSC_symbol);
class_addlist(routeOSC_class, routeOSC_list);
class_addmethod(routeOSC_class, (t_method)routeOSC_set, gensym("set"), A_GIMME, 0);
class_addmethod(routeOSC_class, (t_method)routeOSC_paths, gensym("paths"), A_GIMME, 0);
class_addmethod(routeOSC_class, (t_method)routeOSC_verbosity, gensym("verbosity"), A_DEFFLOAT, 0);
ps_emptySymbol = gensym("");
// post("routeOSC object version 1.0 by Martin Peach, based on OSCroute by Matt Wright. pd: jdl Win32 raf.");
// post("OSCroute Copyright © 1999 Regents of the Univ. of California. All Rights Reserved.");
}
/* instance creation routine */
static void *routeOSC_new(t_symbol *s, int argc, t_atom *argv)
{
t_routeOSC *x = (t_routeOSC *)pd_new(routeOSC_class); // get memory for a new object & initialize
int i;
if (argc > MAX_NUM)
{
error("* routeOSC: too many arguments: %d (max %d)", argc, MAX_NUM);
return 0;
}
x->x_num = 0;
/* first verify that all arguments are symbols whose first character is '/' */
for (i = 0; i < argc; ++i)
{
if (argv[i].a_type == A_SYMBOL)
{
if (argv[i].a_w.w_symbol->s_name[0] == '/')
{ /* Now that's a nice prefix */
++(x->x_num);
}
else
{
error("routeOSC: argument %d does not begin with a slash(/).", i);
return(0);
}
}
else
{
error("routeOSC: argument %d is not a symbol.", i);
return 0;
}
}
/* now allocate the storage for each path */
x->x_prefixes = (char **)getzbytes(x->x_num*sizeof(char *)); /* the OSC addresses to be matched */
x->x_prefix_depth = (int *)getzbytes(x->x_num*sizeof(int)); /* the number of slashes in each prefix */
x->x_outlets = (void **)getzbytes((x->x_num+1)*sizeof(void *)); /* one for each prefix plus one for everything else */
/* put the pointer to the path in x_prefixes */
/* put the number of levels in x_prefix_depth */
for (i = 0; i < x->x_num; ++i)
{
x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
x->x_prefix_depth[i] = routeOSC_count_slashes(x->x_prefixes[i]);
}
/* Have to create the outlets in reverse order */
/* well, not in pd ? */
for (i = 0; i <= x->x_num; i++)
{
x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
}
x->x_verbosity = 0; /* quiet by default */
return (x);
}
static void routeOSC_set(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
if (argc > x->x_num)
{
pd_error (x, "routeOSC: too many paths");
return;
}
for (i = 0; i < argc; ++i)
{
if (argv[i].a_type != A_SYMBOL)
{
pd_error (x, "routeOSC: path %d not a symbol", i);
return;
}
if (argv[i].a_w.w_symbol->s_name[0] != '/')
{
pd_error (x, "routeOSC: path %d doesn't start with /", i);
return;
}
}
for (i = 0; i < argc; ++i)
{
if (argv[i].a_w.w_symbol->s_name[0] == '/')
{ /* Now that's a nice prefix */
x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
x->x_prefix_depth[i] = routeOSC_count_slashes(x->x_prefixes[i]);
}
}
}
static void routeOSC_paths(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{ /* print out the paths we are matching */
int i;
for (i = 0; i < x->x_num; ++i) post("path[%d]: %s (depth %d)", i, x->x_prefixes[i], x->x_prefix_depth[i]);
}
static void routeOSC_verbosity(t_routeOSC *x, t_floatarg v)
{
x->x_verbosity = (v == 0)? 0: 1;
if (x->x_verbosity) post("routeOSC_verbosity(%p) is %d", x, x->x_verbosity);
}
static int routeOSC_count_slashes(char *prefix)
{ /* find the path depth of the prefix by counting the numberof slashes */
int i = 0;
char *p = prefix;
while (*p != '\0') if (*p++ == '/') i++;
return i;
}
static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{
char *pattern, *nextSlash;
int i = 0, pattern_depth = 0, matchedAnything = 0;
int noPath = 0; // nonzero if we are dealing with a simple list (as from a previous [routeOSC])
pattern = s->s_name;
if (x->x_verbosity) post("routeOSC_doanything(%p): pattern is %s", x, pattern);
if (pattern[0] != '/')
{
/* output unmatched data on rightmost outlet */
if (x->x_verbosity) post("routeOSC_doanything no OSC path(%p) , %d args", x, argc);
outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
return;
}
pattern_depth = routeOSC_count_slashes(pattern);
if (x->x_verbosity) post("routeOSC_doanything(%p): pattern_depth is %i", x, pattern_depth);
nextSlash = NextSlashOrNull(pattern+1);
if (*nextSlash == '\0')
{ /* pattern_depth == 1 */
/* last level of the address, so we'll output the argument list */
for (i = 0; i < x->x_num; ++i)
{
if
(
(x->x_prefix_depth[i] <= pattern_depth)
&& (MyPatternMatch(pattern+1, x->x_prefixes[i]+1))
)
{
++matchedAnything;
if (noPath)
{ // just a list starting with a symbol
// The special symbol is s
if (x->x_verbosity) post("routeOSC_doanything _1_(%p): (%d) noPath: s is \"%s\"", x, i, s->s_name);
outlet_anything(x->x_outlets[i], s, argc, argv);
}
else // normal OSC path
{
// I hate stupid Max lists with a special first element
if (argc == 0)
{
if (x->x_verbosity) post("routeOSC_doanything _2_(%p): (%d) no args", x, i);
outlet_bang(x->x_outlets[i]);
}
else if (argv[0].a_type == A_SYMBOL)
{
// Promote the symbol that was argv[0] to the special symbol
if (x->x_verbosity) post("routeOSC_doanything _3_(%p): (%d) symbol: is \"%s\"", x, i, argv[0].a_w.w_symbol->s_name);
outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
}
else if (argc > 1)
{
// Multiple arguments starting with a number, so naturally we have
// to use a special function to output this "list", since it's what
// Max originally meant by "list".
if (x->x_verbosity) post("routeOSC_doanything _4_(%p): (%d) list:", x, i);
outlet_list(x->x_outlets[i], 0L, argc, argv);
}
else
{
// There was only one argument, and it was a number, so we output it
// not as a list
if (argv[0].a_type == A_FLOAT)
{
if (x->x_verbosity) post("routeOSC_doanything _5_(%p): (%d) a single float", x, i);
outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
}
else
{
pd_error(x, "* routeOSC: unrecognized atom type!");
}
}
}
}
}
}
else
{
/* There's more address after this part, so our output list will begin with
the next slash. */
t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
char patternBegin[1000];
/* Get the incoming pattern to match against all our prefixes */
for (i = 0; i < x->x_num; ++i)
{
restOfPattern = 0;
if (x->x_prefix_depth[i] <= pattern_depth)
{
StrCopyUntilNthSlash(patternBegin, pattern+1, x->x_prefix_depth[i]);
if (x->x_verbosity)
post("routeOSC_doanything _6_(%p): (%d) patternBegin is %s", x, i, patternBegin);
if (MyPatternMatch(patternBegin, x->x_prefixes[i]+1))
{
if (x->x_verbosity)
post("routeOSC_doanything _7_(%p): (%d) matched %s depth %d", x, i, x->x_prefixes[i], x->x_prefix_depth[i]);
++matchedAnything;
nextSlash = NthSlashOrNull(pattern+1, x->x_prefix_depth[i]);
if (x->x_verbosity)
post("routeOSC_doanything _8_(%p): (%d) nextSlash %s [%d]", x, i, nextSlash, nextSlash[0]);
if (*nextSlash != '\0')
{
if (x->x_verbosity) post("routeOSC_doanything _9_(%p): (%d) more pattern", x, i);
restOfPattern = gensym(nextSlash);
outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
}
else if (argc == 0)
{
if (x->x_verbosity) post("routeOSC_doanything _10_(%p): (%d) no more pattern, no args", x, i);
outlet_bang(x->x_outlets[i]);
}
else
{
if (x->x_verbosity) post("routeOSC_doanything _11_(%p): (%d) no more pattern, %d args", x, i, argc);
if (argv[0].a_type == A_SYMBOL) // Promote the symbol that was argv[0] to the special symbol
outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
else
outlet_anything(x->x_outlets[i], gensym("list"), argc, argv);
}
}
}
}
}
if (!matchedAnything)
{
// output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
if (x->x_verbosity) post("routeOSC_doanything _13_(%p) unmatched %d, %d args", x, i, argc);
outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
}
}
static void routeOSC_bang(t_routeOSC *x)
{
/* output non-OSC data on rightmost outlet */
if (x->x_verbosity) post("routeOSC_bang (%p)", x);
outlet_bang(x->x_outlets[x->x_num]);
}
static void routeOSC_float(t_routeOSC *x, t_floatarg f)
{
/* output non-OSC data on rightmost outlet */
if (x->x_verbosity) post("routeOSC_float (%p) %f", x, f);
outlet_float(x->x_outlets[x->x_num], f);
}
static void routeOSC_symbol(t_routeOSC *x, t_symbol *s)
{
/* output non-OSC data on rightmost outlet */
if (x->x_verbosity) post("routeOSC_symbol (%p) %s", x, s->s_name);
outlet_symbol(x->x_outlets[x->x_num], s);
}
static void routeOSC_list(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv)
{
/* output non-OSC data on rightmost outlet */
if (x->x_verbosity) post("routeOSC_list (%p) s=%s argc is %d", x, s->s_name, argc);
if (0 == argc) post("routeOSC_list (%p) empty list", x);/* this should never happen but catch it just in case... */
else if (argv[0].a_type == A_SYMBOL) routeOSC_doanything(x, argv[0].a_w.w_symbol, argc-1, &argv[1]);
else if (argv[0].a_type == A_FLOAT)
{
if (x->x_verbosity) post("routeOSC_list (%p) floats:", x);
outlet_list(x->x_outlets[x->x_num], 0L, argc, argv);
}
}
static char *NextSlashOrNull(char *p)
{
while (*p != '/' && *p != '\0') p++;
return p;
}
static char *NthSlashOrNull(char *p, int n)
{
int i;
for (i = 0; i < n; ++i)
{
while (*p != '/')
{
if (*p == '\0') return p;
p++;
}
if (i < n-1) p++; /* skip the slash unless it's the nth slash */
}
return p;
}
static void StrCopyUntilSlash(char *target, const char *source)
{
while (*source != '/' && *source != '\0')
{
*target = *source;
++target;
++source;
}
*target = 0;
}
static void StrCopyUntilNthSlash(char *target, const char *source, int n)
{ /* copy the path up but not including the nth slash */
int i = n;
while (i > 0)
{
while (*source != '/')
{
*target = *source;
if (*source == '\0') return;
++target;
++source;
}
i--;
/* got a slash. If it's the nth, don't include it */
if (i == 0)
{
*target = 0;
return;
}
*target = *source;
++source;
++target;
}
}
/* from
OSC-pattern-match.c
Matt Wright, 3/16/98
Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
*/
static int PatternMatch (const char * pattern, const char * test)
{
theWholePattern = pattern;
if (pattern == 0 || pattern[0] == 0) return test[0] == 0;
if (test[0] == 0)
{
if (pattern[0] == '*') return PatternMatch (pattern+1, test);
return 0;
}
switch (pattern[0])
{
case 0:
return test[0] == 0;
case '?':
return PatternMatch (pattern+1, test+1);
case '*':
if (PatternMatch (pattern+1, test)) return 1;
return PatternMatch (pattern, test+1);
case ']':
case '}':
error("routeOSC: Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
return 0;
case '[':
return MatchBrackets (pattern,test);
case '{':
return MatchList (pattern,test);
case '\\':
if (pattern[1] == 0) return test[0] == 0;
if (pattern[1] == test[0]) return PatternMatch (pattern+2,test+1);
return 0;
default:
if (pattern[0] == test[0]) return PatternMatch (pattern+1,test+1);
return 0;
}
}
/* we know that pattern[0] == '[' and test[0] != 0 */
static int MatchBrackets (const char *pattern, const char *test)
{
int result;
int negated = 0;
const char *p = pattern;
if (pattern[1] == 0)
{
error("routeOSC: Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return 0;
}
if (pattern[1] == '!')
{
negated = 1;
p++;
}
while (*p != ']')
{
if (*p == 0)
{
error("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return 0;
}
if (p[1] == '-' && p[2] != 0)
{
if (test[0] >= p[0] && test[0] <= p[2])
{
result = !negated;
goto advance;
}
}
if (p[0] == test[0])
{
result = !negated;
goto advance;
}
p++;
}
result = negated;
advance:
if (!result) return 0;
while (*p != ']')
{
if (*p == 0)
{
error("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
return 0;
}
p++;
}
return PatternMatch (p+1,test+1);
}
static int MatchList (const char *pattern, const char *test)
{
const char *restOfPattern, *tp = test;
for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++)
{
if (*restOfPattern == 0)
{
error("Unterminated { in pattern \".../%s/...\"", theWholePattern);
return 0;
}
}
restOfPattern++; /* skip close curly brace */
pattern++; /* skip open curly brace */
while (1)
{
if (*pattern == ',')
{
if (PatternMatch (restOfPattern, tp)) return 1;
tp = test;
++pattern;
}
else if (*pattern == '}') return PatternMatch (restOfPattern, tp);
else if (*pattern == *tp)
{
++pattern;
++tp;
}
else
{
tp = test;
while (*pattern != ',' && *pattern != '}') pattern++;
if (*pattern == ',') pattern++;
}
}
}
/* end of routeOSC.c */
mrpeach/osc/osc-meta.pd 0000644 0001750 0001750 00000000304 12430431643 015545 0 ustar zmoelnig zmoelnig #N canvas 18 212 200 200 10;
#N canvas 28 50 420 300 META 1;
#X text 13 61 NAME OSC;
#X text 13 85 VERSION 0.2;
#X text 13 129 AUTHOR Martin Peach;
#X text 19 189 NOTE:;
#X restore 10 10 pd META;
mrpeach/osc/Makefile 0000644 0001750 0001750 00000032341 11616773462 015173 0 ustar zmoelnig zmoelnig ## Pd library template version 1.0.9-zmoelnig
# For instructions on how to use this template, see:
# http://puredata.info/docs/developer/MakefileTemplate
#
# the name of this library
# must not contain any spaces or weird characters (as it's used for
# filenames,...)
LIBRARY_NAME = osc
# add your .c source files, one object per file, to the SOURCES
# variable, help files will be included automatically, and for GUI
# objects, the matching .tcl file too
SOURCES = packOSC.c pipelist.c routeOSC.c unpackOSC.c
# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
# be included automatically
PDOBJECTS = packOSCstream.pd unpackOSCstream.pd
# example patches and related files, in the 'examples' subfolder
EXAMPLES =
# manuals and related files, in the 'manual' subfolder
MANUAL =
# if you want to include any other files in the source and binary tarballs,
# list them here. This can be anything from header files, test patches,
# documentation, etc. README.txt and LICENSE.txt are required and therefore
# automatically included
EXTRA_DIST = packingOSC.h
HELPPATCHES = \
packOSC-help.pd \
packOSCstream-help.pd \
pipelist-help.pd routeOSC-help.pd \
unpackOSCstream-help.pd
#------------------------------------------------------------------------------#
#
# things you might need to edit if you are using other C libraries
#
#------------------------------------------------------------------------------#
# -I"$(PD_INCLUDE)" supports the header location for 0.43
ALL_CFLAGS = -I"$(PD_INCLUDE)"
ALL_LDFLAGS =
ALL_LIBS =
#------------------------------------------------------------------------------#
#
# you shouldn't need to edit anything below here, if we did it right :)
#
#------------------------------------------------------------------------------#
# these can be set from outside without (usually) breaking the build
CFLAGS = -Wall -W -g
LDFLAGS=
LIBS=
# get library version from meta file
LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd)
ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"'
PD_INCLUDE = $(PD_PATH)/include/pd
# where to install the library, overridden below depending on platform
prefix = /usr/local
libdir = $(prefix)/lib
pkglibdir = $(libdir)/pd-externals
objectsdir = $(pkglibdir)
INSTALL = install
INSTALL_PROGRAM = $(INSTALL) -p -m 644
INSTALL_DATA = $(INSTALL) -p -m 644
INSTALL_DIR = $(INSTALL) -p -m 755 -d
ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
$(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION)
UNAME := $(shell uname -s)
ifeq ($(UNAME),Darwin)
CPU := $(shell uname -p)
ifeq ($(CPU),arm) # iPhone/iPod Touch
SOURCES += $(SOURCES_iphoneos)
EXTENSION = pd_darwin
OS = iphoneos
PD_PATH = /Applications/Pd-extended.app/Contents/Resources
IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
CC=$(IPHONE_BASE)/gcc
CPP=$(IPHONE_BASE)/cpp
CXX=$(IPHONE_BASE)/g++
ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS)
ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
ALL_LIBS += -lc
STRIP = strip -x
DISTBINDIR=$(DISTDIR)-$(OS)
else # Mac OS X
SOURCES += $(SOURCES_macosx)
EXTENSION = pd_darwin
OS = macosx
PD_PATH = /Applications/Pd-extended.app/Contents/Resources
OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
# build universal 32-bit on 10.4 and 32/64 on newer
ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8)
FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4
else
FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
SOURCES += $(SOURCES_iphoneos)
endif
ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include
ALL_LDFLAGS += $(FAT_FLAGS) -bundle -undefined dynamic_lookup -L/sw/lib
# if the 'pd' binary exists, check the linking against it to aid with stripping
ALL_LDFLAGS += $(shell test -e $(PD_PATH)/bin/pd && echo -bundle_loader $(PD_PATH)/bin/pd)
ALL_LIBS += -lc
STRIP = strip -x
DISTBINDIR=$(DISTDIR)-$(OS)
# install into ~/Library/Pd on Mac OS X since /usr/local isn't used much
pkglibdir=$(HOME)/Library/Pd
endif
endif
# Tho Android uses Linux, we use this fake uname to provide an easy way to
# setup all this things needed to cross-compile for Android using the NDK
ifeq ($(UNAME),ANDROID)
CPU := arm
SOURCES += $(SOURCES_android)
EXTENSION = pd_linux
OS = android
PD_PATH = /usr
NDK_BASE := /usr/local/android-ndk
NDK_PLATFORM_VERSION := 5
NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm
NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]')
NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86
CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT)
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
CFLAGS +=
LDFLAGS += -Wl,--export-dynamic -shared
LIBS += -lc
STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \
--strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),Linux)
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -Wl,--export-dynamic -shared -fPIC
ALL_LIBS += -lc
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),GNU)
# GNU/Hurd, should work like GNU/Linux for basically all externals
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -Wl,--export-dynamic -shared -fPIC
ALL_LIBS += -lc
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),GNU/kFreeBSD)
# Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -Wl,--export-dynamic -shared -fPIC
ALL_LIBS += -lc
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
CPU := $(shell uname -m)
SOURCES += $(SOURCES_cygwin)
EXTENSION = dll
OS = cygwin
PD_PATH = $(cygpath $(PROGRAMFILES))/pd
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS +=
ALL_LDFLAGS += -Wl,--export-dynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin"
ALL_LIBS += -lc -lpd
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)
endif
ifeq (MINGW,$(findstring MINGW,$(UNAME)))
CPU := $(shell uname -m)
SOURCES += $(SOURCES_windows)
EXTENSION = dll
OS = windows
PD_PATH = $(shell cd "$(PROGRAMFILES)"/pd && pwd)
OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -mms-bitfields
ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import
ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" -lpd -lwsock32 -lkernel32 -luser32 -lgdi32
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)
endif
# in case somebody manually set the HELPPATCHES above
HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
CFLAGS += $(OPT_CFLAGS)
ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS)
ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS)
ALL_LIBS := $(LIBS) $(ALL_LIBS)
.PHONY = install libdir_install single_install install-doc install-exec install-examples install-manual clean dist etags $(LIBRARY_NAME)
all: $(SOURCES:.c=.$(EXTENSION))
%.o: %.c
$(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c"
%.$(EXTENSION): %.o
$(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS)
chmod a-x "$*.$(EXTENSION)"
# this links everything into a single binary file
$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o
$(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(ALL_LIBS)
chmod a-x $(LIBRARY_NAME).$(EXTENSION)
install: libdir_install
# The meta and help files are explicitly installed to make sure they are
# actually there. Those files are not optional, then need to be there.
libdir_install: $(SOURCES:.c=.$(EXTENSION)) install-doc install-examples install-manual
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(SOURCES))" || (\
$(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
$(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
test -z "$(strip $(shell ls $(SOURCES:.c=.tcl)))" || \
$(INSTALL_DATA) $(shell ls $(SOURCES:.c=.tcl)) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(PDOBJECTS))" || \
$(INSTALL_DATA) $(PDOBJECTS) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
# install library linked as single binary
single_install: $(LIBRARY_NAME) install-doc install-exec
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
install-doc:
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \
$(INSTALL_DATA) $(HELPPATCHES) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt
$(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt
install-examples:
test -z "$(strip $(EXAMPLES))" || \
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
for file in $(EXAMPLES); do \
$(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \
done
install-manual:
test -z "$(strip $(MANUAL))" || \
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \
for file in $(MANUAL); do \
$(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \
done
clean:
-rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o)
-rm -f -- $(SOURCES:.c=.$(EXTENSION))
-rm -f -- $(LIBRARY_NAME).o
-rm -f -- $(LIBRARY_NAME).$(EXTENSION)
distclean: clean
-rm -f -- $(DISTBINDIR).tar.gz
-rm -rf -- $(DISTBINDIR)
-rm -f -- $(DISTDIR).tar.gz
-rm -rf -- $(DISTDIR)
-rm -f -- $(ORIGDIR).tar.gz
-rm -rf -- $(ORIGDIR)
$(DISTBINDIR):
$(INSTALL_DIR) $(DISTBINDIR)
libdir: all $(DISTBINDIR)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR)
$(INSTALL_DATA) $(SOURCES) $(DISTBINDIR)
$(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR)
test -z "$(strip $(EXTRA_DIST))" || \
$(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR)
# tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
$(DISTDIR):
$(INSTALL_DIR) $(DISTDIR)
$(ORIGDIR):
$(INSTALL_DIR) $(ORIGDIR)
dist: $(DISTDIR)
$(INSTALL_DATA) Makefile $(DISTDIR)
$(INSTALL_DATA) README.txt $(DISTDIR)
$(INSTALL_DATA) LICENSE.txt $(DISTDIR)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR)
test -z "$(strip $(ALLSOURCES))" || \
$(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR)
test -z "$(strip $(shell ls $(ALLSOURCES:.c=.tcl)))" || \
$(INSTALL_DATA) $(shell ls $(ALLSOURCES:.c=.tcl)) $(DISTDIR)
test -z "$(strip $(PDOBJECTS))" || \
$(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR)
test -z "$(strip $(HELPPATCHES))" || \
$(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR)
test -z "$(strip $(EXTRA_DIST))" || \
$(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR)
test -z "$(strip $(EXAMPLES))" || \
$(INSTALL_DIR) $(DISTDIR)/examples && \
for file in $(EXAMPLES); do \
$(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \
done
test -z "$(strip $(MANUAL))" || \
$(INSTALL_DIR) $(DISTDIR)/manual && \
for file in $(MANUAL); do \
$(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \
done
tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
# make a Debian source package
dpkg-source:
debclean
make distclean dist
mv $(DISTDIR) $(ORIGDIR)
tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR)
rm -f -- $(DISTDIR).tar.gz
rm -rf -- $(DISTDIR) $(ORIGDIR)
cd .. && dpkg-source -b $(LIBRARY_NAME)
etags:
etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h
showsetup:
@echo "CFLAGS: $(CFLAGS)"
@echo "LDFLAGS: $(LDFLAGS)"
@echo "LIBS: $(LIBS)"
@echo "ALL_CFLAGS: $(ALL_CFLAGS)"
@echo "ALL_LDFLAGS: $(ALL_LDFLAGS)"
@echo "ALL_LIBS: $(ALL_LIBS)"
@echo "PD_INCLUDE: $(PD_INCLUDE)"
@echo "PD_PATH: $(PD_PATH)"
@echo "objectsdir: $(objectsdir)"
@echo "LIBRARY_NAME: $(LIBRARY_NAME)"
@echo "LIBRARY_VERSION: $(LIBRARY_VERSION)"
@echo "SOURCES: $(SOURCES)"
@echo "PDOBJECTS: $(PDOBJECTS)"
@echo "ALLSOURCES: $(ALLSOURCES)"
@echo "UNAME: $(UNAME)"
@echo "CPU: $(CPU)"
@echo "pkglibdir: $(pkglibdir)"
@echo "DISTDIR: $(DISTDIR)"
@echo "ORIGDIR: $(ORIGDIR)"
mrpeach/osc/packOSC.c 0000644 0001750 0001750 00000146312 14042312116 015143 0 ustar zmoelnig zmoelnig /* packOSC is like sendOSC but outputs a list of floats which are the bytes making up the OSC packet. */
/* This allows for the separation of the protocol and its transport. */
/* Started by Martin Peach 20060403 */
/* 20060425 version independent of libOSC */
/* 20070620 added packOSC_path and packOSC_anything methods by zmoelnig */
/* 20160713 added 'm' typetag for MIDI messages */
/* packOSC.c makes extensive use of code from OSC-client.c and sendOSC.c */
/* as well as some from OSC-timetag.c. These files have the following header: */
/*
Written by Matt Wright, The Center for New Music and Audio Technologies,
University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
The Regents of the University of California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
*/
//define DEBUG
#define SC_BUFFER_SIZE 64000
#include "packingOSC.h"
/* This is from OSC-client.h :*/
/*
OSC-client.h: library for constructing OpenSoundControl messages.
Derived from SynthControl.h
Author: Matt Wright
Version 0.1: 6/13/97
Version 0.2: 7/21/2000: Support for type-tagged messages
General notes:
This library abstracts away the data format for the OpenSoundControl
protocol. Users of this library can construct OpenSoundControl packets
with a function call interface instead of knowing how to lay out the bits.
All issues of memory allocation are deferred to the user of this library.
There are two data structures that the user must allocate. The first
is the actual buffer that the message will be written into. This buffer
can be any size, but if it's too small there's a possibility that it
will become overfull. The other data structure is called an OSCbuf,
and it holds all the state used by the library as it's constructing
a buffer.
All procedures that have the possibility of an error condition return int,
with 0 indicating no error and nonzero indicating an error. The variable
OSC_errorMessage will be set to point to a string containing an error
message explaining what the problem is.
*/
/*
OSC_timeTag.h: library for manipulating OSC time tags
Matt Wright, 5/29/97
Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the
top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom
32 bits giving fractional parts of a second. We represent this by an 8-byte
unsigned long if possible, or else a struct.
NB: On many architectures with 8-byte ints, it's illegal (like maybe a bus error)
to dereference a pointer to an 8 byte int that's not 8-byte aligned.
*/
/* Return the time tag 0x0000000000000001, indicating to the receiving device
that it should process the message immediately. */
static OSCTimeTag OSCTT_Immediately(void);
static OSCTimeTag OSCTT_Infinite(void);
static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint32_t offset);
static OSCTimeTag OSCTT_CurrentPdTimePlusOffset(uint32_t offset);
/* these are globals so other packOSCs will be in lockstep */
OSCTimeTag packOSCStartTimeTag;
double packOSCLogicalStartTime;
int packOSCs;
/* packOSCLogicalStartTime is Pd's count of DSP ticks. Use clock_gettimesince() to measure intervals in milliseconds from here */
/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
declared here in the header file only so your program will be able to
declare variables of type OSCbuf and have the right amount of memory
be allocated.) */
typedef struct OSCbuf_struct
{
char *buffer; /* The buffer to hold the OSC packet */
size_t size; /* Size of the buffer */
char *bufptr; /* Current position as we fill the buffer */
int state; /* State of partially-constructed message */
uint32_t *thisMsgSize; /* Pointer to count field before */
/* currently-being-written message */
uint32_t *prevCounts[MAX_BUNDLE_NESTING]; /* Pointers to count */
/* field before each currently open bundle */
int bundleDepth; /* How many sub-sub-bundles are we in now? */
char *typeStringPtr; /* This pointer advances through the type */
/* tag string as you add arguments. */
int gettingFirstUntypedArg; /* nonzero if this message doesn't have */
/* a type tag and we're waiting for the 1st arg */
} OSCbuf;
typedef struct
{
enum {INT_osc, FLOAT_osc, STRING_osc, BLOB_osc, NOTYPE_osc} type;
union
{
int i;
float f;
char *s;
} datum;
} typedArg;
/* Here are the possible values of the state field: */
#define EMPTY 0 /* Nothing written to packet yet */
#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
#define NEED_COUNT 2 /* Just opened a bundle; must write message name or */
/* open another bundle */
#define GET_ARGS 3 /* Getting arguments to a message. If we see a message */
/* name or a bundle open/close then the current message */
/* will end. */
#define DONE 4 /* All open bundles have been closed, so can't write */
/* anything else */
static int OSC_strlen(char *s);
static int OSC_padString(char *dest, char *str);
static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
static int OSC_WriteStringPadding(char *dest, int i);
static int OSC_WriteBlobPadding(char *dest, int i);
static int CheckTypeTag(OSCbuf *buf, char expectedType);
/* Initialize the given OSCbuf. The user of this module must pass in the
block of memory that this OSCbuf will use for a buffer, and the number of
bytes in that block. (It's the user's job to allocate the memory because
you do it differently in different systems.) */
static void OSC_initBuffer(OSCbuf *buf, size_t size, char *byteArray);
/* Reset the given OSCbuf. Do this after you send out the contents of
the buffer and want to start writing new data into it. */
static void OSC_resetBuffer(OSCbuf *buf);
/* Is the buffer empty? (I.e., would it be stupid to send the buffer
contents to the synth?) */
static int OSC_isBufferEmpty(OSCbuf *buf);
/* How much space is left in the buffer? */
static size_t OSC_freeSpaceInBuffer(OSCbuf *buf);
/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
static int OSC_isBufferDone(OSCbuf *buf);
/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
returns true), call these two procedures to get the OSC packet that's been
assembled and its size in bytes. (And then call OSC_resetBuffer() if you
want to re-use this OSCbuf for the next packet.) */
static char *OSC_getPacket(OSCbuf *buf);
static int OSC_packetSize(OSCbuf *buf);
static int OSC_CheckOverflow(OSCbuf *buf, size_t bytesNeeded);
/* Here's the basic model for building up OSC messages in an OSCbuf:
- Make sure the OSCbuf has been initialized with OSC_initBuffer().
- To open a bundle, call OSC_openBundle(). You can then write
messages or open new bundles within the bundle you opened.
Call OSC_closeBundle() to close the bundle. Note that a packet
does not have to have a bundle; it can instead consist of just a
single message.
- For each message you want to send:
- Call OSC_writeAddress() with the name of your message. (In
addition to writing your message name into the buffer, this
procedure will also leave space for the size count of this message.)
- Alternately, call OSC_writeAddressAndTypes() with the name of
your message and with a type string listing the types of all the
arguments you will be putting in this message.
- Now write each of the arguments into the buffer, by calling one of:
OSC_writeFloatArg()
OSC_writeIntArg()
OSC_writeStringArg()
OSC_writeNullArg()
- Now your message is complete; you can send out the buffer or you can
add another message to it.
*/
static int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
static int OSC_closeBundle(OSCbuf *buf);
static int OSC_writeAddress(OSCbuf *buf, char *name);
static int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types);
static int OSC_writeFloatArg(OSCbuf *buf, float arg);
static int OSC_writeIntArg(OSCbuf *buf, uint32_t arg);
static int OSC_writeBlobArg(OSCbuf *buf, typedArg *arg, size_t nArgs);
static int OSC_writeStringArg(OSCbuf *buf, char *arg);
static int OSC_writeNullArg(OSCbuf *buf, char type);
/* How many bytes will be needed in the OSC format to hold the given
string? The length of the string, plus the null char, plus any padding
needed for 4-byte alignment. */
static int OSC_effectiveStringLength(char *string);
static t_class *packOSC_class;
typedef struct _packOSC
{
t_object x_obj;
int x_typetags; /* typetag flag */
int x_timeTagOffset;
int x_bundle; /* bundle open flag */
OSCbuf x_oscbuf[1]; /* OSCbuffer */
t_outlet *x_bdpthout; /* bundle-depth floatoutlet */
t_outlet *x_listout; /* OSC packet list ouput */
size_t x_buflength; /* number of elements in x_bufferForOSCbuf and x_bufferForOSClist */
char *x_bufferForOSCbuf; /*[SC_BUFFER_SIZE];*/
t_atom *x_bufferForOSClist; /*[SC_BUFFER_SIZE];*/
char *x_prefix;
int x_reentry_count;
int x_use_pd_time;
} t_packOSC;
static void *packOSC_new(void);
static void packOSC_path(t_packOSC *x, t_symbol*s);
static void packOSC_openbundle(t_packOSC *x);
static void packOSC_closebundle(t_packOSC *x);
static void packOSC_settypetags(t_packOSC *x, t_floatarg f);
static void packOSC_setbufsize(t_packOSC *x, t_floatarg f);
static void packOSC_setTimeTagOffset(t_packOSC *x, t_floatarg f);
static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv);
static void packOSC_send_type_forced(t_packOSC *x, t_symbol *s, int argc, t_atom *argv);
static void packOSC_send(t_packOSC *x, t_symbol *s, int argc, t_atom *argv);
static void packOSC_anything(t_packOSC *x, t_symbol *s, int argc, t_atom *argv);
static void packOSC_free(t_packOSC *x);
void packOSC_setup(void);
static typedArg packOSC_parseatom(t_atom *a);
static typedArg packOSC_packMIDI(t_atom *a);
static typedArg packOSC_forceatom(t_atom *a, char ctype);
static typedArg packOSC_blob(t_atom *a);
static int packOSC_writetypedmessage(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args, char *typeStr);
static int packOSC_writemessage(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args);
static void packOSC_sendbuffer(t_packOSC *x);
static void *packOSC_new(void)
{
double delta_ms;
t_packOSC *x = (t_packOSC *)pd_new(packOSC_class);
x->x_typetags = 1; /* set typetags to 1 by default */
x->x_bundle = 0; /* bundle is closed */
x->x_buflength = SC_BUFFER_SIZE;
x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength);
if(x->x_bufferForOSCbuf == NULL)
{
pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength));
goto fail;
}
x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength);
if(x->x_bufferForOSClist == NULL)
{
pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength));
goto fail;
}
if (x->x_oscbuf != NULL)
OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
x->x_listout = outlet_new(&x->x_obj, &s_list);
x->x_bdpthout = outlet_new(&x->x_obj, &s_float);
x->x_timeTagOffset = -1; /* immediately */
x->x_reentry_count = 0;
x->x_use_pd_time = 1; /* TODO set this somehwere else */
if (0 == packOSCLogicalStartTime)
{
packOSCLogicalStartTime = clock_getlogicaltime();
packOSCStartTimeTag = OSCTT_CurrentTimePlusOffset(0L);
}
delta_ms = clock_gettimesince(packOSCLogicalStartTime);
packOSCs++;
post("packOSC[%d]: delta_ms %lf timetag: %ldsec %ld\n", packOSCs, delta_ms, packOSCStartTimeTag.seconds, packOSCStartTimeTag.fraction);
return (x);
fail:
if(x->x_bufferForOSCbuf != NULL) freebytes(x->x_bufferForOSCbuf, (long)(sizeof(char)*x->x_buflength));
if(x->x_bufferForOSClist != NULL) freebytes(x->x_bufferForOSClist, (long)(sizeof(char)*x->x_buflength));
return NULL;
}
static void packOSC_path(t_packOSC *x, t_symbol*s)
{
/* Set a default prefix to the OSC path */
if(s == gensym(""))
{
x->x_prefix = 0;
return;
}
if ((*s->s_name) != '/')
{
pd_error(x, "packOSC: bad path: '%s'", s->s_name);
return;
}
x->x_prefix = s->s_name;
}
static void packOSC_openbundle(t_packOSC *x)
{
int result;
t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth;
if (x->x_timeTagOffset == -1)
result = OSC_openBundle(x->x_oscbuf, OSCTT_Immediately());
else if (x->x_use_pd_time)
result = OSC_openBundle(x->x_oscbuf, OSCTT_CurrentPdTimePlusOffset((uint32_t)x->x_timeTagOffset));
else
result = OSC_openBundle(x->x_oscbuf, OSCTT_CurrentTimePlusOffset((uint32_t)x->x_timeTagOffset));
if (result != 0)
{ /* reset the buffer */
OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
x->x_bundle = 0;
}
else x->x_bundle = 1;
outlet_float(x->x_bdpthout, bundledepth);
}
static void packOSC_closebundle(t_packOSC *x)
{
t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth;
if (OSC_closeBundle(x->x_oscbuf))
{
pd_error(x, "packOSC: Problem closing bundle.");
return;
}
outlet_float(x->x_bdpthout, bundledepth);
/* in bundle mode we send when bundle is closed */
if((!OSC_isBufferEmpty(x->x_oscbuf)) && OSC_isBufferDone(x->x_oscbuf))
{
x->x_bundle = 0; /* call this before _sendbuffer() to be ready for recursive calls */
packOSC_sendbuffer(x);
return;
}
}
static void packOSC_settypetags(t_packOSC *x, t_floatarg f)
{
x->x_typetags = (f != 0)?1:0;
post("packOSC: setting typetags %d", x->x_typetags);
}
static void packOSC_setbufsize(t_packOSC *x, t_floatarg f)
{
if (x->x_bufferForOSCbuf != NULL) freebytes((void *)x->x_bufferForOSCbuf, sizeof(char)*x->x_buflength);
if (x->x_bufferForOSClist != NULL) freebytes((void *)x->x_bufferForOSClist, sizeof(t_atom)*x->x_buflength);
post("packOSC: bufsize arg is %f (%lu)", f, (long)f);
x->x_buflength = (long)f;
x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength);
if(x->x_bufferForOSCbuf == NULL)
pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength));
x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength);
if(x->x_bufferForOSClist == NULL)
pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength));
OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
post("packOSC: bufsize is now %d",x->x_buflength);
}
static void packOSC_setTimeTagOffset(t_packOSC *x, t_floatarg f)
{
x->x_timeTagOffset = (int)f;
}
/* this is the real and only sending routine now, for both typed and */
/* undtyped mode. */
static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv)
{
char messageName[MAXPDSTRING];
unsigned int nTypeTags = 0, typeStrTotalSize = 0;
unsigned int argsSize = sizeof(typedArg)*argc;
char* typeStr = NULL; /* might not be used */
typedArg* args = (typedArg*)getbytes(argsSize);
unsigned int i, nTagsWithData, nArgs, blobCount;
unsigned int m, tagIndex, typedArgIndex, argvIndex;
char c;
#ifdef DEBUG
printf("*** packOSC_sendtyped bundle %d reentry %d\n", x->x_bundle, x->x_reentry_count);
#endif
x->x_reentry_count++;
if (args == NULL)
{
pd_error(x, "packOSC: unable to allocate %lu bytes for args", (long)argsSize);
return;
}
messageName[0] = '\0'; /* empty */
if(x->x_prefix) /* if there is a prefix, prefix it to the path */
{
size_t len = strlen(x->x_prefix);
if(len >= MAXPDSTRING)
len = MAXPDSTRING-1;
strncpy(messageName, x->x_prefix, MAXPDSTRING);
atom_string(&argv[0], messageName+len, (unsigned)(MAXPDSTRING-len));
}
else
atom_string(&argv[0], messageName, MAXPDSTRING); /* the OSC address string */
if (x->x_typetags & 2)
{ /* second arg is typestring */
/* we need to find out how long the type string is before we copy it*/
nTypeTags = (unsigned int)strlen(atom_getsymbol(&argv[1])->s_name);
typeStrTotalSize = nTypeTags + 2;
typeStr = (char*)getzbytes(typeStrTotalSize);
if (typeStr == NULL)
{
pd_error(x, "packOSC: unable to allocate %u bytes for typeStr", nTypeTags);
return;
}
typeStr[0] = ',';
atom_string(&argv[1], &typeStr[1], typeStrTotalSize);
#ifdef DEBUG
printf("packOSC_sendtyped typeStr: %s, nTypeTags %u\n", typeStr, nTypeTags);
#endif
nArgs = argc-2;
for (m = nTagsWithData = blobCount = 0; m < nTypeTags; ++m)
{
#ifdef DEBUG
printf("packOSC_sendtyped typeStr[%d] %c\n", m+1, typeStr[m+1]);
#endif
if ((c = typeStr[m+1]) == 0) break;
if (!(c == 'T' || c == 'F' || c == 'N' || c == 'I'))
{
++nTagsWithData; /* anything other than these tags have at least one data byte */
if (c == 'm') nTagsWithData += 3; // MIDI tag should have four data bytes
/*
OSC-blob
An int32 size count, followed by that many 8-bit bytes of arbitrary binary data,
followed by 0-3 additional zero bytes to make the total number of bits a multiple of 32.
*/
if (c == 'b') blobCount++; /* b probably has more than one byte, so set a flag */
}
}
if (((blobCount == 0)&&(nTagsWithData != nArgs)) || ((blobCount != 0)&&(nTagsWithData > nArgs)))
{
pd_error(x, "packOSC: Tags count %d doesn't match argument count %d", nTagsWithData, nArgs);
goto cleanup;
}
if (blobCount > 1)
{
pd_error(x, "packOSC: Only one blob per packet at the moment...");
goto cleanup;
}
for (tagIndex = typedArgIndex = 0, argvIndex = 2; tagIndex < m; ++tagIndex) /* m is the number of tags */
{
c = typeStr[tagIndex+1];
if (c == 'b')
{ /* A blob has to be the last item, until we get more elaborate. */
if (tagIndex != m-1)
{
pd_error(x, "packOSC: Since I don't know how big the blob is, Blob must be the last item in the list");
goto cleanup;
}
/* Pack all the remaining arguments as a blob */
for (; typedArgIndex < nArgs; ++typedArgIndex, ++argvIndex)
{
#ifdef DEBUG
printf("packOSC_blob %d:\n", nArgs);
#endif
args[typedArgIndex] = packOSC_blob(&argv[argvIndex]);
/* Make sure it was blobbable */
if (args[typedArgIndex].type != BLOB_osc) goto cleanup;
}
}
else if (!(c == 'T' || c == 'F' || c == 'N' || c == 'I')) /* not no data */
{
if (c == 'm')
{ // pack the next four arguments into one int
args[typedArgIndex++] = packOSC_packMIDI(&argv[argvIndex]);
argvIndex += 4;
}
else args[typedArgIndex++] = packOSC_forceatom(&argv[argvIndex++], c);
}
}
//if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, nArgs, args, typeStr))
if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, typedArgIndex, args, typeStr))
{
pd_error(x, "packOSC: usage error, packOSC_writetypedmessage failed.");
goto cleanup;
}
}
else
{
for (i = 0; i < (unsigned)(argc-1); i++)
{
args[i] = packOSC_parseatom(&argv[i+1]);
#ifdef DEBUG
switch (args[i].type)
{
case INT_osc:
printf("packOSC: cell-cont: %d\n", args[i].datum.i);
break;
case FLOAT_osc:
printf("packOSC: cell-cont: %f\n", args[i].datum.f);
break;
case STRING_osc:
printf("packOSC: cell-cont: %s\n", args[i].datum.s);
break;
case BLOB_osc:
printf("packOSC: blob\n");
break;
case NOTYPE_osc:
printf("packOSC: unknown type\n");
break;
}
printf("packOSC: type-id: %d\n", args[i].type);
#endif
}
if(packOSC_writemessage(x, x->x_oscbuf, messageName, i, args))
{
pd_error(x, "packOSC: usage error, packOSC_writemessage failed.");
goto cleanup;
}
}
if(!x->x_bundle)
{
packOSC_sendbuffer(x);
}
cleanup:
if (typeStr != NULL) freebytes(typeStr, typeStrTotalSize);
if (args != NULL) freebytes(args, argsSize);
x->x_reentry_count--;
}
static void packOSC_send_type_forced(t_packOSC *x, t_symbol *s, int argc, t_atom *argv)
{ /* typetags are the argument following the OSC path */
x->x_typetags |= 2;/* tell packOSC_sendtyped to use the specified typetags... */
packOSC_sendtyped(x, s, argc, argv);
x->x_typetags &= ~2;/* ...this time only */
}
static void packOSC_send(t_packOSC *x, t_symbol *s, int argc, t_atom *argv)
{
if(!argc)
{
pd_error(x, "packOSC: not sending empty message.");
return;
}
packOSC_sendtyped(x, s, argc, argv);
}
static void packOSC_anything(t_packOSC *x, t_symbol *s, int argc, t_atom *argv)
{
/* If the message starts with '/', assume it's an OSC path and send it */
t_atom*ap = 0;
if ((*s->s_name)!='/')
{
pd_error(x, "packOSC: bad path: '%s'", s->s_name);
return;
}
ap = (t_atom*)getbytes((argc+1)*sizeof(t_atom));
SETSYMBOL(ap, s);
memcpy(ap+1, argv, argc * sizeof(t_atom));
packOSC_send(x, gensym("send"), argc+1, ap);
freebytes(ap, (argc+1)*sizeof(t_atom));
}
static void packOSC_free(t_packOSC *x)
{
if (x->x_bufferForOSCbuf != NULL) freebytes((void *)x->x_bufferForOSCbuf, sizeof(char)*x->x_buflength);
if (x->x_bufferForOSClist != NULL) freebytes((void *)x->x_bufferForOSClist, sizeof(t_atom)*x->x_buflength);
}
void packOSC_setup(void)
{
packOSC_class = class_new(gensym("packOSC"), (t_newmethod)packOSC_new,
(t_method)packOSC_free,
sizeof(t_packOSC), 0, A_DEFFLOAT, 0);
class_addmethod(packOSC_class, (t_method)packOSC_path,
gensym("prefix"), A_DEFSYM, 0);
class_addmethod(packOSC_class, (t_method)packOSC_settypetags,
gensym("typetags"), A_DEFFLOAT, 0);
class_addmethod(packOSC_class, (t_method)packOSC_setbufsize,
gensym("bufsize"), A_DEFFLOAT, 0);
class_addmethod(packOSC_class, (t_method)packOSC_setTimeTagOffset,
gensym("timetagoffset"), A_DEFFLOAT, 0);
class_addmethod(packOSC_class, (t_method)packOSC_send,
gensym("send"), A_GIMME, 0);
class_addmethod(packOSC_class, (t_method)packOSC_send,
gensym("senduntyped"), A_GIMME, 0);
class_addmethod(packOSC_class, (t_method)packOSC_send_type_forced,
gensym("sendtyped"), A_GIMME, 0);
class_addmethod(packOSC_class, (t_method)packOSC_openbundle,
gensym("["), 0, 0);
class_addmethod(packOSC_class, (t_method)packOSC_closebundle,
gensym("]"), 0, 0);
class_addanything(packOSC_class, (t_method)packOSC_anything);
}
static typedArg packOSC_parseatom(t_atom *a)
{
typedArg returnVal;
t_float f;
int i;
t_symbol s;
char buf[MAXPDSTRING];
atom_string(a, buf, MAXPDSTRING);
#ifdef DEBUG
printf("packOSC: atom type %d (%s)\n", a->a_type, buf);
#endif
/* It might be an int, a float, or a string */
switch (a->a_type)
{
case A_FLOAT:
f = atom_getfloat(a);
i = atom_getint(a);
if (f == (t_float)i)
{ /* assume that if the int and float are the same, it's an int */
returnVal.type = INT_osc;
returnVal.datum.i = i;
}
else
{
returnVal.type = FLOAT_osc;
returnVal.datum.f = f;
}
return returnVal;
case A_SYMBOL:
s = *atom_getsymbol(a);
returnVal.type = STRING_osc;
returnVal.datum.s = s.s_name;
return returnVal;
default:
atom_string(a, buf, MAXPDSTRING);
error("packOSC: atom type %d not implemented (%s)", a->a_type, buf);
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
return returnVal;
}
}
static typedArg packOSC_blob(t_atom *a)
{ /* ctype is one of i,f,s,T,F,N,I*/
typedArg returnVal;
t_float f;
int i;
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
/* the atoms must all be bytesl */
if(a->a_type != A_FLOAT)
{
error("packOSC_blob: all values must be floats");
return returnVal;
}
f = atom_getfloat(a);
i = (int)f;
if (i != f)
{
error("packOSC_blob: all values must be whole numbers");
return returnVal;
}
if ((i < -128) || (i > 255))
{
error("packOSC_blob: all values must be bytes");
return returnVal;
}
returnVal.type = BLOB_osc;
returnVal.datum.i = i;
return returnVal;
}
static typedArg packOSC_packMIDI(t_atom *a)
{ /* pack four bytes at a into one int32 */
int i;
typedArg returnVal;
int m[4];
for (i = 0; i < 4; ++i, ++a)
{
#ifdef DEBUG
atom_string(a, buf, MAXPDSTRING);
printf("packOSC: atom type %d (%s)\n", a->a_type, buf);
#endif
if ((a->a_type != A_FLOAT))
{
error("packOSC: MIDI parameters must be floats");
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
return returnVal;
}
m[i] = atom_getint(a);
#ifdef DEBUG
printf("packOSC_packMIDI: float to integer %d\n", m[i]);
#endif
if ((i < 2) && (m[i] != (m[i] & 0x0FF)))
{
error("packOSC: MIDI parameters must be less than 256");
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
return returnVal;
}
else if ((i > 1) && (m[i] != (m[i] & 0x07F)))
{
error("packOSC: MIDI parameters must be less than 128");
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
return returnVal;
}
}
returnVal.type = INT_osc;
returnVal.datum.i = (m[0]<<24) + (m[1]<<16) + (m[2]<<8) + m[3];
return returnVal;
}
static typedArg packOSC_forceatom(t_atom *a, char ctype)
{ /* ctype is one of i,f,s,T,F,N,I*/
typedArg returnVal;
t_float f;
int i;
t_symbol s;
static char buf[MAXPDSTRING];
#ifdef DEBUG
atom_string(a, buf, MAXPDSTRING);
printf("packOSC: atom type %d (%s)\n", a->a_type, buf);
#endif
/* the atom might be a float, or a symbol */
switch (a->a_type)
{
case A_FLOAT:
switch (ctype)
{
case 'i':
returnVal.type = INT_osc;
returnVal.datum.i = atom_getint(a);
#ifdef DEBUG
printf("packOSC_forceatom: float to integer %d\n", returnVal.datum.i);
#endif
break;
case 'f':
returnVal.type = FLOAT_osc;
returnVal.datum.f = atom_getfloat(a);
#ifdef DEBUG
printf("packOSC_forceatom: float to float %f\n", returnVal.datum.f);
#endif
break;
case 's':
f = atom_getfloat(a);
sprintf(buf, "%f", f);
returnVal.type = STRING_osc;
returnVal.datum.s = buf;
#ifdef DEBUG
printf("packOSC_forceatom: float to string %s\n", returnVal.datum.s);
#endif
break;
default:
post("packOSC: unknown OSC type %c", ctype);
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
break;
}
break;
case A_SYMBOL:
s = *atom_getsymbol(a);
switch (ctype)
{
case 'i':
i = atoi(s.s_name);
returnVal.type = INT_osc;
returnVal.datum.i = i;
#ifdef DEBUG
printf("packOSC_forceatom: symbol to integer %d\n", returnVal.datum.i);
#endif
break;
case 'f':
f = atof(s.s_name);
returnVal.type = FLOAT_osc;
returnVal.datum.f = f;
#ifdef DEBUG
printf("packOSC_forceatom: symbol to float %f\n", returnVal.datum.f);
#endif
break;
case 's':
returnVal.type = STRING_osc;
returnVal.datum.s = s.s_name;
#ifdef DEBUG
printf("packOSC_forceatom: symbol to string %s\n", returnVal.datum.s);
#endif
break;
default:
post("packOSC: unknown OSC type %c", ctype);
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
break;
}
break;
default:
atom_string(a, buf, MAXPDSTRING);
error("packOSC: atom type %d not implemented (%s)", a->a_type, buf);
returnVal.type = NOTYPE_osc;
returnVal.datum.s = NULL;
break;
}
return returnVal;
}
static int packOSC_writetypedmessage
(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args, char *typeStr)
{
int i, j, returnVal;
#ifdef DEBUG
printf("packOSC_writetypedmessage: messageName %p (%s) typeStr %p (%s)\n",
messageName, messageName, typeStr, typeStr);
#endif
returnVal = OSC_writeAddressAndTypes(buf, messageName, typeStr);
if (returnVal)
{
error("packOSC: Problem writing address. (%d)", returnVal);
return returnVal;
}
for (j = i = 0; (typeStr[i+1]!= 0) || (j < numArgs); j++, i++)
{
while (typeStr[i+1] == 'T' || typeStr[i+1] == 'F' || typeStr[i+1] == 'I' || typeStr[i+1] == 'N')
{
#ifdef DEBUG
printf("packOSC_writetypedmessage: NULL [%c]\n", typeStr[i+1]);
#endif
returnVal = OSC_writeNullArg(buf, typeStr[i+1]);
++i;
}
if (j < numArgs)
{
switch (args[j].type)
{
case INT_osc:
#ifdef DEBUG
printf("packOSC_writetypedmessage: int [%d]\n", args[j].datum.i);
#endif
returnVal = OSC_writeIntArg(buf, args[j].datum.i);
break;
case FLOAT_osc:
#ifdef DEBUG
printf("packOSC_writetypedmessage: float [%f]\n", args[j].datum.f);
#endif
returnVal = OSC_writeFloatArg(buf, args[j].datum.f);
break;
case STRING_osc:
#ifdef DEBUG
printf("packOSC_writetypedmessage: string [%s]\n", args[j].datum.s);
#endif
returnVal = OSC_writeStringArg(buf, args[j].datum.s);
break;
case BLOB_osc:
/* write all the blob elements at once */
#ifdef DEBUG
printf("packOSC_writetypedmessage calling OSC_writeBlobArg\n");
#endif
return OSC_writeBlobArg(buf, &args[j], numArgs-j);
default:
break; /* types with no data */
}
}
}
return returnVal;
}
static int packOSC_writemessage(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args)
{
int j, returnVal = 0, numTags;
#ifdef DEBUG
printf("packOSC_writemessage buf %p bufptr %p messageName %s %d args typetags %d\n", buf, buf->bufptr, messageName, numArgs, x->x_typetags);
#endif
if (!x->x_typetags)
{
#ifdef DEBUG
printf("packOSC_writemessage calling OSC_writeAddress with x->x_typetags %d\n", x->x_typetags);
#endif
returnVal = OSC_writeAddress(buf, messageName);
if (returnVal)
{
post("packOSC: Problem writing address.");
}
}
else
{
char *typeTags;
/* First figure out the type tags */
for (numTags = 0; numTags < numArgs; numTags++)
{
if (args[numTags].type == BLOB_osc) break; /* blob has one type tag and is the last element */
}
typeTags=(char*)getbytes(sizeof(char)*(numTags+2)); /* number of args + ',' + '\0' */
typeTags[0] = ',';
for (j = 0; j < numTags; ++j)
{
switch (args[j].type)
{
case INT_osc:
typeTags[j+1] = 'i';
break;
case FLOAT_osc:
typeTags[j+1] = 'f';
break;
case STRING_osc:
typeTags[j+1] = 's';
break;
case BLOB_osc:
typeTags[j+1] = 'b';
break;
default:
error("packOSC: arg %d type is unrecognized(%d)", j, args[j].type);
break;
}
}
typeTags[j+1] = '\0';
#ifdef DEBUG
printf("packOSC_writemessage calling OSC_writeAddressAndTypes with x->x_typetags %d typeTags %p (%s)\n", x->x_typetags, typeTags, typeTags);
#endif
returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags);
if (returnVal)
{
error("packOSC: Problem writing address.");
}
freebytes(typeTags, sizeof(char)*(numTags+2));
}
for (j = 0; j < numArgs; j++)
{
switch (args[j].type)
{
case INT_osc:
returnVal = OSC_writeIntArg(buf, args[j].datum.i);
break;
case FLOAT_osc:
returnVal = OSC_writeFloatArg(buf, args[j].datum.f);
break;
case STRING_osc:
returnVal = OSC_writeStringArg(buf, args[j].datum.s);
break;
case BLOB_osc:
#ifdef DEBUG
printf("packOSC_writemessage calling OSC_writeBlobArg\n");
#endif
return OSC_writeBlobArg(buf, &args[j], numArgs-j); /* All the remaining args are blob */
default:
break; /* just skip bad types (which we won't get anyway unless this code is buggy) */
}
}
return returnVal;
}
static void packOSC_sendbuffer(t_packOSC *x)
{
int i;
int length;
unsigned char *buf;
int reentry_count=x->x_reentry_count; /* must be on stack for recursion */
size_t bufsize=sizeof(t_atom)*x->x_buflength; /* must be on stack for recursion */
t_atom *atombuffer=x->x_bufferForOSClist; /* must be on stack in the case of recursion */
if(reentry_count>0) /* if we are recurse, let's move atombuffer to the stack */
atombuffer=(t_atom *)getbytes(bufsize);
if(!atombuffer) {
pd_error(x, "packOSC: unable to allocate %lu bytes for atombuffer", (long)bufsize);
return;
}
#ifdef DEBUG
printf("packOSC_sendbuffer: Sending buffer...\n");
#endif
if (OSC_isBufferEmpty(x->x_oscbuf))
{
post("packOSC_sendbuffer() called but buffer empty");
return;
}
if (!OSC_isBufferDone(x->x_oscbuf))
{
post("packOSC_sendbuffer() called but buffer not ready!, not exiting");
return;
}
length = OSC_packetSize(x->x_oscbuf);
buf = (unsigned char *)OSC_getPacket(x->x_oscbuf);
#ifdef DEBUG
printf("packOSC_sendbuffer: length: %u\n", length);
#endif
/* convert the bytes in the buffer to floats in a list */
for (i = 0; i < length; ++i) SETFLOAT(&atombuffer[i], buf[i]);
/* cleanup the OSCbuffer structure (so we are ready for recursion) */
OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf);
/* send the list out the outlet */
outlet_list(x->x_listout, &s_list, length, atombuffer);
/* cleanup our 'stack'-allocated atombuffer in the case of reentrancy */
if(reentry_count>0)
freebytes(atombuffer, bufsize);
}
/* The next part is copied and morphed from OSC-client.c. */
/*
Author: Matt Wright
Version 2.2: Calls htonl in the right places 20000620
Version 2.3: Gets typed messages right.
*/
/*
pd
-------------
raf@interaccess.com:
rev. for Win32 build (verified under Win-2ooo) 11-April-2002
-- changed licence part (20040820) jdl
-- Version 2.4 changes not in here (20040820) jdl
*/
static void OSC_initBuffer(OSCbuf *buf, size_t size, char *byteArray)
{
buf->buffer = byteArray;
buf->size = size;
OSC_resetBuffer(buf);
}
static void OSC_resetBuffer(OSCbuf *buf)
{
buf->bufptr = buf->buffer;
buf->state = EMPTY;
buf->bundleDepth = 0;
buf->prevCounts[0] = 0;
buf->gettingFirstUntypedArg = 0;
buf->typeStringPtr = 0;
}
static int OSC_isBufferEmpty(OSCbuf *buf)
{
return buf->bufptr == buf->buffer;
}
static size_t OSC_freeSpaceInBuffer(OSCbuf *buf)
{
return buf->size - (buf->bufptr - buf->buffer);
}
static int OSC_isBufferDone(OSCbuf *buf)
{
return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
}
static char *OSC_getPacket(OSCbuf *buf)
{
return buf->buffer;
}
static int OSC_packetSize(OSCbuf *buf)
{
return (buf->bufptr - buf->buffer);
}
static int OSC_CheckOverflow(OSCbuf *buf, size_t bytesNeeded)
{
if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf))
{
error("packOSC: buffer overflow");
return 1;
}
return 0;
}
static void PatchMessageSize(OSCbuf *buf)
{
uint32_t size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
*(buf->thisMsgSize) = htonl(size);
}
static int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt)
{
if (buf->state == ONE_MSG_ARGS)
{
post("packOSC: Can't open a bundle in a one-message packet");
return 3;
}
if (buf->state == DONE)
{
post("packOSC: This packet is finished; can't open a new bundle");
return 4;
}
if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING)
{
post("packOSC: Bundles nested too deeply: maybe change MAX_BUNDLE_NESTING from %d and recompile", MAX_BUNDLE_NESTING);
return 2;
}
if (CheckTypeTag(buf, '\0')) return 9;
if (buf->state == GET_ARGS)
{
PatchMessageSize(buf);
}
if (buf->state == EMPTY)
{
/* Need 16 bytes for "#bundle" and time tag */
if(OSC_CheckOverflow(buf, 16)) return 1;
}
else
{
/* This bundle is inside another bundle, so we need to leave
a blank size count for the size of this current bundle. */
if(OSC_CheckOverflow(buf, 20))return 1;
*((uint32_t *)buf->bufptr) = 0xaaaaaaaa;
buf->prevCounts[buf->bundleDepth] = (uint32_t *)buf->bufptr;
buf->bufptr += 4;
}
buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
*((OSCTimeTag *) buf->bufptr) = tt;
if (htonl(1) != 1)
{
/* Byte swap the 8-byte integer time tag */
uint32_t *intp = (uint32_t *)buf->bufptr;
intp[0] = htonl(intp[0]);
intp[1] = htonl(intp[1]);
/* tt is a struct of two 32-bit words, and even though
each word was wrong-endian, they were in the right order
in the struct.) */
}
buf->bufptr += sizeof(OSCTimeTag);
buf->state = NEED_COUNT;
buf->gettingFirstUntypedArg = 0;
buf->typeStringPtr = 0;
return 0;
}
static int OSC_closeBundle(OSCbuf *buf)
{
if (buf->bundleDepth == 0)
{
/* This handles EMPTY, ONE_MSG, ARGS, and DONE */
post("packOSC: Can't close bundle: no bundle is open!");
return 5;
}
if (CheckTypeTag(buf, '\0')) return 9;
if (buf->state == GET_ARGS)
{
PatchMessageSize(buf);
}
if (buf->bundleDepth == 1)
{
/* Closing the last bundle: No bundle size to patch */
buf->state = DONE;
}
else
{
/* Closing a sub-bundle: patch bundle size */
int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
*(buf->prevCounts[buf->bundleDepth]) = htonl(size);
buf->state = NEED_COUNT;
}
--buf->bundleDepth;
buf->gettingFirstUntypedArg = 0;
buf->typeStringPtr = 0;
return 0;
}
static int OSC_writeAddress(OSCbuf *buf, char *name)
{
uint32_t paddedLength;
#ifdef DEBUG
printf("-->OSC_writeAddress buf %p bufptr %p name %s\n", buf, buf->bufptr, name);
#endif
if (buf->state == ONE_MSG_ARGS)
{
post("packOSC: This packet is not a bundle, so you can't write another address");
return 7;
}
if (buf->state == DONE)
{
post("packOSC: This packet is finished; can't write another address");
return 8;
}
if (CheckTypeTag(buf, '\0')) return 9;
paddedLength = OSC_effectiveStringLength(name);
#ifdef DEBUG
printf("OSC_writeAddress paddedLength %d\n", paddedLength);
#endif
if (buf->state == EMPTY)
{
/* This will be a one-message packet, so no sizes to worry about */
if(OSC_CheckOverflow(buf, paddedLength))return 1;
buf->state = ONE_MSG_ARGS;
}
else
{
/* GET_ARGS or NEED_COUNT */
if(OSC_CheckOverflow(buf, 4+paddedLength))return 1;
if (buf->state == GET_ARGS)
{
/* Close the old message */
PatchMessageSize(buf);
}
buf->thisMsgSize = (uint32_t *)buf->bufptr;
*(buf->thisMsgSize) = 0xbbbbbbbb;
buf->bufptr += 4;
buf->state = GET_ARGS;
}
/* Now write the name */
buf->bufptr += OSC_padString(buf->bufptr, name);
buf->typeStringPtr = 0;
buf->gettingFirstUntypedArg = 1;
return 0;
}
static int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types)
{
int result;
uint32_t paddedLength;
#ifdef DEBUG
printf("OSC_writeAddressAndTypes buf %p name %s types %s\n", buf, name, types);
#endif
if (buf == NULL) return 10;
if (CheckTypeTag(buf, '\0')) return 9;
result = OSC_writeAddress(buf, name);
if (result) return result;
paddedLength = OSC_effectiveStringLength(types);
if(OSC_CheckOverflow(buf, paddedLength))return 1;
buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
buf->bufptr += OSC_padString(buf->bufptr, types);
#ifdef DEBUG
printf("OSC_writeAddressAndTypes buf->typeStringPtr now %p (%s) buf->bufptr now %p (%s)\n",
buf->typeStringPtr, buf->typeStringPtr, buf->bufptr, buf->bufptr);
#endif
buf->gettingFirstUntypedArg = 0;
buf->typeStringPtr = 0;// ready for a new type string
return 0;
}
static int CheckTypeTag(OSCbuf *buf, char expectedType)
{
char c;
if (buf->typeStringPtr)
{
#ifdef DEBUG
printf("CheckTypeTag buf->typeStringPtr %p (%s)\n", buf->typeStringPtr, buf->typeStringPtr);
#endif
c = *(buf->typeStringPtr);
#ifdef DEBUG
printf("CheckTypeTag buf %p expectedType %c c is %c\n", buf, expectedType, c);
#endif
if (c != expectedType)
{
if (expectedType == '\0')
{
post("packOSC: According to the type tag (%c) I expected more arguments.", c);
}
else if (*(buf->typeStringPtr) == '\0')
{
post("packOSC: According to the type tag I didn't expect any more arguments.");
}
else
{
post("packOSC: According to the type tag I expected an argument of a different type.");
post("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
}
return 9;
}
++(buf->typeStringPtr);
}
return 0;
}
static int OSC_writeFloatArg(OSCbuf *buf, float arg)
{
union intfloat32
{
int i;
float f;
};
union intfloat32 if32;
if(OSC_CheckOverflow(buf, 4))return 1;
if (CheckTypeTag(buf, 'f')) return 9;
/* Pretend arg is a long int so we can use htonl() */
if32.f = arg;
*((uint32_t *) buf->bufptr) = htonl(if32.i);
buf->bufptr += 4;
buf->gettingFirstUntypedArg = 0;
return 0;
}
static int OSC_writeIntArg(OSCbuf *buf, uint32_t arg)
{
if(OSC_CheckOverflow(buf, 4))return 1;
if (CheckTypeTag(buf, 'i')) return 9;
*((uint32_t *) buf->bufptr) = htonl(arg);
buf->bufptr += 4;
buf->gettingFirstUntypedArg = 0;
return 0;
}
static int OSC_writeBlobArg(OSCbuf *buf, typedArg *arg, size_t nArgs)
{
size_t i;
unsigned char b;
/* pack all the args as single bytes following a 4-byte length */
if(OSC_CheckOverflow(buf, nArgs+4))return 1;
if (CheckTypeTag(buf, 'b')) return 9;
*((uint32_t *) buf->bufptr) = htonl(nArgs);
#ifdef DEBUG
printf("OSC_writeBlobArg length : %lu\n", nArgs);
#endif
buf->bufptr += 4;
for (i = 0; i < nArgs; i++)
{
if (arg[i].type != BLOB_osc)
{
error("packOSC: blob element %lu not blob type", i);
return 9;
}
b = (unsigned char)((arg[i].datum.i)&0x0FF);/* force int to 8-bit byte */
#ifdef DEBUG
printf("OSC_writeBlobArg : %d, %d\n", arg[i].datum.i, b);
#endif
buf->bufptr[i] = b;
}
i = OSC_WriteBlobPadding(buf->bufptr, i);
buf->bufptr += i;
buf->gettingFirstUntypedArg = 0;
return 0;
}
static int OSC_writeStringArg(OSCbuf *buf, char *arg)
{
int len;
if (CheckTypeTag(buf, 's')) return 9;
len = OSC_effectiveStringLength(arg);
if (buf->gettingFirstUntypedArg && arg[0] == ',')
{
/* This un-type-tagged message starts with a string
that starts with a comma, so we have to escape it
(with a double comma) so it won't look like a type
tag string. */
if(OSC_CheckOverflow(buf, len+4))return 1; /* Too conservative */
buf->bufptr +=
OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
}
else
{
if(OSC_CheckOverflow(buf, len))return 1;
buf->bufptr += OSC_padString(buf->bufptr, arg);
}
buf->gettingFirstUntypedArg = 0;
return 0;
}
static int OSC_writeNullArg(OSCbuf *buf, char type)
{ /* Don't write any data, just check the type tag */
if(OSC_CheckOverflow(buf, 4))return 1;
if (CheckTypeTag(buf, type)) return 9;
buf->gettingFirstUntypedArg = 0;
return 0;
}
/* String utilities */
static int OSC_strlen(char *s)
{
int i;
for (i = 0; s[i] != '\0'; i++) /* Do nothing */ ;
return i;
}
#define STRING_ALIGN_PAD 4
static int OSC_effectiveStringLength(char *string)
{
int len = OSC_strlen(string) + 1; /* We need space for the null char. */
/* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
if ((len % STRING_ALIGN_PAD) != 0)
{
len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
}
return len;
}
static int OSC_padString(char *dest, char *str)
{
int i;
for (i = 0; str[i] != '\0'; i++) dest[i] = str[i];
return OSC_WriteStringPadding(dest, i);
}
static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str)
{
int i;
dest[0] = ',';
for (i = 0; str[i] != '\0'; i++) dest[i+1] = str[i];
return OSC_WriteStringPadding(dest, i+1);
}
static int OSC_WriteStringPadding(char *dest, int i)
{
/* pad with at least one zero to fit 4-byte */
dest[i] = '\0';
i++;
for (; (i % STRING_ALIGN_PAD) != 0; i++) dest[i] = '\0';
return i;
}
static int OSC_WriteBlobPadding(char *dest, int i)
{
/* pad if necessary to fit 4-byte */
for (; (i % STRING_ALIGN_PAD) != 0; i++) dest[i] = '\0';
return i;
}
/* The next bit is modified from OSC-timetag.c. */
/*
OSC_timeTag.c: library for manipulating OSC time tags
Matt Wright, 5/29/97
Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
*/
static OSCTimeTag OSCTT_Immediately(void)
{
OSCTimeTag tt;
tt.fraction = 1;
tt.seconds = 0;
return tt;
}
static OSCTimeTag OSCTT_Infinite(void)
{
OSCTimeTag tt;
tt.fraction = 0xffffffffL;
tt.seconds = 0xffffffffL;
return tt;
}
#define SECONDS_FROM_1900_to_1970 2208988800LL /* 17 leap years */
#define TWO_TO_THE_32_OVER_ONE_MILLION 4295LL
static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint32_t offset)
{ /* offset is in microseconds */
OSCTimeTag tt;
static unsigned int onemillion = 1000000;
#ifdef _WIN32
static unsigned int onethousand = 1000;
struct _timeb tb;
_ftime(&tb);
/* First get the seconds right */
tt.seconds = (unsigned)SECONDS_FROM_1900_to_1970 +
(unsigned)tb.time+
(unsigned)offset/onemillion;
/* Now get the fractional part. */
tt.fraction = (unsigned)tb.millitm*onethousand + (unsigned)(offset%onemillion); /* in usec */
#else
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
/* First get the seconds right */
tt.seconds = (unsigned) SECONDS_FROM_1900_to_1970 +
(unsigned) tv.tv_sec +
(unsigned) offset/onemillion;
/* Now get the fractional part. */
tt.fraction = (unsigned) tv.tv_usec + (unsigned)(offset%onemillion); /* in usec */
#endif
if (tt.fraction > onemillion)
{
tt.fraction -= onemillion;
tt.seconds++;
}
tt.fraction *= (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION; /* convert usec to 32-bit fraction of 1 sec */
return tt;
}
/* Use the global time that was set once by the first packOSC instance, to avoid OS/Pd clock jitter */
static OSCTimeTag OSCTT_CurrentPdTimePlusOffset(uint32_t offset)
{ /* offset is in microseconds */
OSCTimeTag tt;
static unsigned int onemillion = 1000000;
static unsigned int onethousand = 1000;
/* milliseconds since 'our' epoch */
double delta_ms = clock_gettimesince(packOSCLogicalStartTime);
/* First get the seconds right */
tt.seconds = floor(delta_ms/onethousand) +
packOSCStartTimeTag.seconds +
(unsigned) offset/onemillion;
/* Now get the fractional part. */
tt.fraction = (unsigned) (delta_ms*onethousand - tt.seconds*onemillion) +
packOSCStartTimeTag.fraction +
(unsigned)(offset%onemillion); /* in usec */
if (tt.fraction > onemillion)
{
tt.fraction -= onemillion;
tt.seconds++;
}
tt.fraction *= (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION; /* convert usec to 32-bit fraction of 1 sec */
post("delta_ms %lf timetag: %ldsec %ld\n", delta_ms, tt.seconds, tt.fraction);
return tt;
}
/* end packOSC.c*/
mrpeach/osc/README.txt 0000644 0001750 0001750 00000002323 11616510724 015214 0 ustar zmoelnig zmoelnig OpenSoundControl (OSC) for Pd
=============================
a collection of Pd objectclasses for OSC-messages.
these objects only convert between Pd-messages and OSC-messages (binary format),
so you will need a separate set of objects that implement the transport
(OSI-Layer 4), for instance [udpsend]/[udpreceive] for sending OSC over UDP.
Author: Martin Peach
objectclasses
- [packOSC]
convert a Pd-message to an OSC (binary) message
(useful if you want to transmit OSC over UDP or other protocols that
have the concept of variable length packets)
- [unpackOSC]
convert an OSC (binary) message to a Pd-message
(useful if you want to transmit OSC over UDP or other protocols that
have the concept of variable length packets)
- [routeOSC]
route OSC-like Pd-messages according to the first element in the path
- [pipelist]
delay lists
(useful if you want to respect timestamps)
- [packOSCstream]
convert a Pd-message to an OSC (binary) message suitable for streaming transport
(useful if you want to transmit OSC over TCP/IP or a serial line)
- [unpackOSCstream]
convert an OSC (binary) message suitable for streaming transport to a Pd-message
(useful if you want to transmit OSC over TCP/IP or a serial line)
mrpeach/mrpeach-meta.pd 0000644 0001750 0001750 00000000260 12571126663 015626 0 ustar zmoelnig zmoelnig #N canvas 15 49 200 200 10;
#N canvas 25 49 420 300 META 1;
#X text 13 41 NAME mrpeach;
#X text 10 25 AUTHOR Martin Peach;
#X text 10 10 VERSION 0.1;
#X restore 10 10 pd META;
mrpeach/rcosc~/ 0000755 0001750 0001750 00000000000 14110766277 014251 5 ustar zmoelnig zmoelnig mrpeach/rcosc~/rcosc~.c 0000644 0001750 0001750 00000007330 11361701054 015712 0 ustar zmoelnig zmoelnig /* rcosc~.c by Martin Peach 20100331 */
/* Pd external emulating a resistor-capacitor-controlled oscillator */
/* The first control parameter is a time constant in seconds (or resistance X capacitance) */
/* The second control parameter is a threshold above which the cap is set to discharge */
/* The third control parameter is a threshold below which the cap is set to charge */
#include "m_pd.h"
static t_class *rcosc_tilde_class;
typedef struct _rcosc_tilde
{
t_object rc_obj;
t_float rc_f;
t_float rc_upper_threshold; /* if rc_dir is 1, charge to here */
t_float rc_lower_threshold; /* if rc_dir is 0, discharge to here */
t_int rc_dir;
double rc_node;
double rc_one;
double rc_zero;
double rc_sp;
double rc_slewmax;
} t_rcosc_tilde;
static t_int *rcosc_tilde_perform(t_int *w);
static void rcosc_tilde_dsp(t_rcosc_tilde *x, t_signal **sp);
static void *rcosc_tilde_new(t_floatarg f);
static t_int *rcosc_tilde_perform(t_int *w)
{
t_rcosc_tilde *x = (t_rcosc_tilde *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
double slewrate, delta, node, overshoot;
int i, n_oversamples = 64;
// if (x->rc_rc < x->rc_sp) slewrate = 1.0;
// else slewrate = x->rc_sp/x->rc_rc;
while (n--)
{
slewrate = x->rc_one/(n_oversamples*(x->rc_sp*(*in++)));
if (slewrate < x->rc_zero) slewrate = x->rc_zero;
else if (slewrate > x->rc_one) slewrate = x->rc_one;
node = x->rc_node;
for (i = 0; i < n_oversamples; ++i)
{
if (x->rc_dir)
{
delta = slewrate*(x->rc_one - x->rc_node);
if (delta > x->rc_slewmax) delta = x->rc_slewmax;
x->rc_node += delta;
overshoot = x->rc_node - x->rc_upper_threshold;
if (overshoot > 0)
{
x->rc_dir = 0;
x->rc_node = x->rc_upper_threshold - overshoot; /* bounce */
}
}
else
{
delta = slewrate*(x->rc_zero - x->rc_node);
if (delta < -x->rc_slewmax) delta = -x->rc_slewmax;
x->rc_node += delta;
overshoot = x->rc_lower_threshold - x->rc_node;
if (overshoot > 0)
{
x->rc_dir = 1;
x->rc_node = x->rc_lower_threshold + overshoot; /* bounce */
}
}
}
*out++ = ((node + x->rc_node)*3)-3;
}
return (w+5);
}
static void rcosc_tilde_dsp(t_rcosc_tilde *x, t_signal **sp)
{
x->rc_sp = sys_getsr();
dsp_add(rcosc_tilde_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void *rcosc_tilde_new(t_floatarg f)
{
t_rcosc_tilde *x = (t_rcosc_tilde *)pd_new(rcosc_tilde_class);
x->rc_f = f;
x->rc_node = 0.0;
x->rc_upper_threshold = 0.666; /* if rc_dir is 1, charge to here */
x->rc_lower_threshold = 0.333; /* if rc_dir is 0, discharge to here */
x->rc_slewmax = 0.003;/* arbitrary slew rate limit */
x->rc_dir = 1; /* start charging */
x->rc_one = 1;
x->rc_zero = 0;
outlet_new(&x->rc_obj, &s_signal);
post("rcosc~ 20100331 Martin Peach");
return (void *)x;
}
void rcosc_tilde_setup(void)
{
rcosc_tilde_class = class_new(gensym("rcosc~"),
(t_newmethod)rcosc_tilde_new,
0, sizeof(t_rcosc_tilde),
CLASS_DEFAULT,
A_DEFFLOAT, 0);
class_addmethod(rcosc_tilde_class, (t_method)rcosc_tilde_dsp, gensym("dsp"), 0);
CLASS_MAINSIGNALIN(rcosc_tilde_class, t_rcosc_tilde, rc_f);
}
/* fin rcosc~.c */
mrpeach/rcosc~/rcosc~-help.pd 0000644 0001750 0001750 00000003205 11533764212 017024 0 ustar zmoelnig zmoelnig #N canvas 2 53 450 439 10;
#X obj 52 277 *~;
#X text 181 301 Author: Martin Peach;
#X obj 53 316 dac~;
#X obj 67 228 nbx 5 14 0 1000 0 1 empty empty level 60 8 0 10 -4034
-13381 -13381 8 256;
#X obj 67 253 / 1000;
#X obj 168 244 tabwrite~ \$0-rcoschelp;
#X obj 168 267 table \$0-rcoschelp;
#X obj 168 213 metro 100;
#X obj 168 194 tgl 15 0 empty empty graph 17 7 0 10 -4034 -13381 -1
0 1;
#X obj 52 169 rcosc~ 0.001;
#X floatatom 52 28 5 0 0 0 - - -;
#X obj 52 135 / 1;
#X obj 52 70 t b f;
#X msg 52 103 0.722057;
#X text 155 68 7.22057e+07;
#X text 223 68 70756;
#X text 147 68 0;
#X obj 52 5 r note_a;
#X obj 52 49 mtof;
#X floatatom 92 66 5 0 0 0 - - -;
#X text 49 -57 rcosc~ emulates an oscillator implemented with a capacitor
charging through a resistor. The creation argument can be overriden
by the inlet \, and represents a charging time constant in seconds.
;
#X text 180 320 2010/04/15;
#N canvas 455 293 494 344 META 0;
#X text 12 135 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 115 AUTHOR Martin Peach;
#X text 12 46 DESCRIPTION emulates an oscillator implemented with a
capacitor charging through a resistor;
#X text 12 5 KEYWORDS signal;
#X text 12 75 INLET_0 float;
#X text 12 95 OUTLET_0 signal;
#X restore 392 355 pd META;
#X connect 0 0 2 0;
#X connect 0 0 2 1;
#X connect 3 0 4 0;
#X connect 4 0 0 1;
#X connect 7 0 5 0;
#X connect 8 0 7 0;
#X connect 9 0 5 0;
#X connect 9 0 0 0;
#X connect 10 0 18 0;
#X connect 11 0 9 0;
#X connect 12 0 13 0;
#X connect 12 1 11 1;
#X connect 13 0 11 0;
#X connect 17 0 10 0;
#X connect 18 0 12 0;
#X connect 18 0 19 0;
mrpeach/LICENSE.txt 0000644 0001750 0001750 00000001325 12571126663 014564 0 ustar zmoelnig zmoelnig mrpeach - a bag of tricks
Copyright (C) 2006-2015 Martin Peach
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
mrpeach/which/ 0000755 0001750 0001750 00000000000 14110766276 014043 5 ustar zmoelnig zmoelnig mrpeach/which/which.c 0000644 0001750 0001750 00000013121 12760060035 015274 0 ustar zmoelnig zmoelnig /* which: an external for pure data */
/* Will output the path to the object named as its first argument */
/* Martin Peach 20090225 */
#include "m_pd.h"
#include
#include
#include /* for strncpy strncat */
#ifdef _WIN32
#include
#include
#include
#include
#include
#define close _close
#else
#include
#endif
static t_class *which_class;
typedef struct _which
{
t_object x_obj;
t_symbol *x_object_name;
t_symbol *x_object_path;
t_canvas *x_canvas;
} t_which;
/* We took this (sys_dllextent) from s_loader.c since it's not global */
/* Naming convention for externs. The names are kept distinct for those
who wich to make "fat" externs compiled for many platforms. Less specific
fallbacks are provided, primarily for back-compatibility; these suffice if
you are building a package which will run with a single set of compiled
objects. The specific name is the letter b, l, d, or m for BSD, linux,
darwin, or microsoft, followed by a more specific string, either "fat" for
a fat binary or an indication of the instruction set. */
#ifdef __FreeBSD__
static char sys_dllextent[] = ".b_i386", sys_dllextent2[] = ".pd_freebsd";
#endif
#ifdef __linux__
#ifdef __x86_64__
static char sys_dllextent[] = ".l_ia64", sys_dllextent2[] = ".pd_linux";
#else
static char sys_dllextent[] = ".l_i386", sys_dllextent2[] = ".pd_linux";
#endif
#endif
#ifdef __APPLE__
#ifndef MACOSX3
static char sys_dllextent[] = ".d_fat", sys_dllextent2[] = ".pd_darwin";
#else
static char sys_dllextent[] = ".d_ppc", sys_dllextent2[] = ".pd_darwin";
#endif
#endif
#ifdef _WIN32
static char sys_dllextent[] = ".m_i386", sys_dllextent2[] = ".dll";
#endif
static void which_any(t_which *x, t_symbol *s, int argc, t_atom *argv);
static void which_bang(t_which *x);
static void which_symbol(t_which *x, t_symbol *s);
static void which_set(t_which *x, t_symbol *s);
static void *which_new(t_symbol *s, int argc, t_atom *argv);
void which_setup(void);
static void which_set(t_which *x, t_symbol *s)
{
x->x_object_name = s;
}
static void which_symbol(t_which *x, t_symbol *s)
{
x->x_object_name = s;
}
static void which_any(t_which *x, t_symbol *s, int argc, t_atom *argv)
{
x->x_object_name = s;
which_bang(x);
}
static void which_bang(t_which *x)
{
int fd = -1;
char *nameptr = 0;
char filename[MAXPDSTRING];
char dirbuf[MAXPDSTRING];
/*
EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext,
char *dirresult, char **nameresult, unsigned int size, int bin);
*/
/* canvas_open is a utility function to read a file, looking first down
the canvas's search path (set with "declare" objects in the patch and
recursively in calling patches), then down the system one.
The filename is the concatenation of "name" and "ext".
"Name" may be absolute, or may be relative with slashes.
If anything can be opened, the true directory is put in the buffer
dirresult (provided by caller), which should be "size" bytes.
The "nameresult" pointer will be set somewhere in
the interior of "dirresult" and will give the file basename (with
slashes trimmed). If "bin" is set a 'binary' open is
attempted, otherwise ASCII (this only matters on Microsoft.)
If "x" is zero, the file is sought in the directory "." or in the
global path.
*/
/* try looking in the path for (objectname).(sys_dllextent) ... */
x->x_canvas = canvas_getcurrent();
//post("which_bang: canvas is %p", x->x_canvas);
//post("which_bang: name is %s", x->x_object_name->s_name);
//post("which_bang: ext is %s", sys_dllextent);
//post("which_bang: ext2 is %s", sys_dllextent2);
fd = canvas_open(x->x_canvas, x->x_object_name->s_name, sys_dllextent,
dirbuf, &nameptr, MAXPDSTRING, 1);
//post("which_bang 1: fd is %d", fd);
// if (fd >= 0) post("1");
if (fd < 0)
{/* same, with the more generic sys_dllextent2 */
fd = canvas_open(x->x_canvas, x->x_object_name->s_name, sys_dllextent2,
dirbuf, &nameptr, MAXPDSTRING, 1);
//post("which_bang 2: fd is %d", fd);
// if (fd >= 0) post("2");
}
if (fd < 0)
{
//post("which_bang: not found");
outlet_symbol(x->x_obj.te_outlet, gensym("not found"));
return;
}
close(fd);
//post("which_bang: dirbuf: %s", dirbuf);
//post("which_bang: nameptr: %s", nameptr);
/* rebuild the absolute pathname */
strncpy(filename, dirbuf, MAXPDSTRING);
filename[MAXPDSTRING-2] = 0;
strcat(filename, "/");
strncat(filename, nameptr, MAXPDSTRING-strlen(filename));
filename[MAXPDSTRING-1] = 0;
//post("which_bang: filename: %s", filename);
x->x_object_path = gensym(filename);
outlet_symbol(x->x_obj.te_outlet, x->x_object_path);
}
static void *which_new(t_symbol *s, int argc, t_atom *argv)
{
t_which *x = (t_which *)pd_new(which_class);
x->x_object_name = s;
if ((argc >= 1)&&(argv[0].a_type == A_SYMBOL)) x->x_object_name = argv[0].a_w.w_symbol;
outlet_new(&x->x_obj, &s_anything);
/// x->x_canvas = canvas_getcurrent();/* canvas_getcurrent only seems to work in the _new function: why? */
/// post("which_new: canvas is %p", x->x_canvas);
return (x);
}
void which_setup(void)
{
which_class = class_new(gensym("which"), (t_newmethod)which_new,
0, sizeof(t_which), 0, A_GIMME, 0);
class_addbang(which_class, (t_method)which_bang);
class_addsymbol(which_class, (t_method)which_symbol);
class_addanything(which_class, (t_method)which_any);
class_addmethod(which_class, (t_method)which_set, gensym("set"), A_DEFSYM, 0);
}
/* end which.c */
mrpeach/which/which-help.pd 0000644 0001750 0001750 00000002146 12760060035 016410 0 ustar zmoelnig zmoelnig #N canvas 354 468 693 285 10;
#X obj 129 170 which tcpclient;
#X obj 9 35 bng 15 250 50 0 empty empty output_path_to_object 17 7
0 10 -4034 -257985 -1;
#X text 9 7 [which] outputs the path to an object;
#X obj 57 56 bng 15 250 50 0 empty empty set_object_name 17 7 0 10
-4034 -257985 -1;
#X msg 78 102 set tabdump;
#X symbolatom 129 193 64 0 0 0 - - -, f 64;
#X obj 57 81 symbol Gem;
#X msg 120 144 expr;
#X msg 99 123 counter;
#X text 165 101 set object name;
#X text 155 122 set object name and output path;
#X text 245 169 argument is object name;
#N canvas 334 661 494 344 META 0;
#X text 12 125 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 105 AUTHOR Martin Peach;
#X text 12 5 KEYWORDS control;
#X text 12 46 DESCRIPTION output the path to an object;
#X text 12 65 INLET_0 anything set;
#X text 12 85 OUTLET_0 symbol;
#X restore 515 236 pd META;
#X text 130 222 2016/08/26 Martin Peach;
#X connect 0 0 5 0;
#X connect 1 0 0 0;
#X connect 3 0 6 0;
#X connect 4 0 0 0;
#X connect 6 0 0 0;
#X connect 7 0 0 0;
#X connect 8 0 0 0;
mrpeach/runningmean/ 0000755 0001750 0001750 00000000000 14110766277 015263 5 ustar zmoelnig zmoelnig mrpeach/runningmean/runningmean.c 0000644 0001750 0001750 00000010161 12430233607 017734 0 ustar zmoelnig zmoelnig /* runningmean.c MP 20080516 */
/* output the running mean of the input */
#include "m_pd.h"
/* We implement a circular buffer x_data of length x_n */
/* With each incoming value we sum the x_n values, then divide by */
/* x_n to get the mean value, x_mean. */
#define RUNNINGMEAN_MAX 128 /* a default value when no valid argument is supplied */
typedef struct _runningmean
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;
int x_n;
int x_originalsize;
t_float *x_data;
t_float x_mean;
int x_pointer;
} t_runningmean;
static t_class *runningmean_class;
void runningmean_setup(void);
static void *runningmean_new(t_floatarg f);
static void runningmean_free(t_runningmean *x);
static void runningmean_bang(t_runningmean *x);
static void runningmean_float(t_runningmean *x, t_float f);
static void runningmean_length(t_runningmean *x, t_float f);
static void runningmean_zero(t_runningmean *x, t_float f);
static void runningmean_float(t_runningmean *x, t_float f)
{
float *p = x->x_data;
float total = 0;
int i;
if (x->x_n > 0)
{
/* add a float at the current location, overwriting the oldest data */
x->x_data[x->x_pointer] = f;
if (++x->x_pointer >= x->x_n) x->x_pointer = 0; /* wrap pointer */
for (i = 0; i < x->x_n; ++i) total += *p++;
x->x_mean = total/x->x_n;
outlet_float(x->x_out, x->x_mean);
}
return;
}
static void runningmean_bang(t_runningmean *x)
{
outlet_float(x->x_out, x->x_mean);
return;
}
static void runningmean_length(t_runningmean *x, t_float f)
{
if ((f >= 1) && ((int)f == f) && (f <= x->x_originalsize))
{
x->x_n = (int)f;
runningmean_zero(x, x->x_mean); // set the entire new array to the old mean
}
else post("runningmean length must be an integer between 1 and %d.", x->x_originalsize);
return;
}
static void runningmean_zero(t_runningmean *x, t_float f)
{
float *p = x->x_data;
int i;
/* set the entire array to f */
for (i = 0; i < x->x_n; ++i) *p++ = f;
x->x_mean = f;
x->x_pointer = 0;
return;
}
static void runningmean_free(t_runningmean *x)
{
freebytes(x->x_data, x->x_originalsize);
x->x_originalsize = x->x_n = 0;
x->x_data = NULL;
return;
}
static void *runningmean_new(t_floatarg f)
{
t_runningmean *x;
x = (t_runningmean *)pd_new(runningmean_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("length"));
if (!((f >= 1) && ((int)f == f)))
{
post("runningmean length %0.2f must be an integer greater than 1, using %d", f, RUNNINGMEAN_MAX);
f = RUNNINGMEAN_MAX;
}
{
x->x_n = (int)f;
x->x_data = (t_float *)getbytes(sizeof(float)*x->x_n);
if (x->x_data == NULL)
{
post("runningmean unable to allocate %lu bytes of memory, using %d", sizeof(float)*x->x_n, RUNNINGMEAN_MAX);
x->x_n = RUNNINGMEAN_MAX;
//x->x_data = (t_float *)getbytes(x->x_n);
if (x->x_data == NULL)
{
post("runningmean unable to allocate %lu bytes of memory, using 0", x->x_n);
x->x_n = 0;
}
}
x->x_originalsize = x->x_n;
runningmean_zero(x, 0);
}
return (x);
}
void runningmean_setup(void)
{
runningmean_class = class_new
(
gensym("runningmean"),
(t_newmethod)runningmean_new,
(t_method)runningmean_free,
sizeof(t_runningmean),
CLASS_DEFAULT,
A_DEFFLOAT,
0
); /* one argument for length */
class_addbang(runningmean_class, runningmean_bang);
class_addfloat(runningmean_class, runningmean_float);
class_addmethod(runningmean_class, (t_method)runningmean_length, gensym("length"), A_FLOAT, 0);
class_addmethod(runningmean_class, (t_method)runningmean_zero, gensym("clear"), A_DEFFLOAT, 0);
}
/* end runningmean.c */
mrpeach/runningmean/runningmean-help.pd 0000644 0001750 0001750 00000003175 12155715447 021065 0 ustar zmoelnig zmoelnig #N canvas 216 528 808 369 10;
#X obj 191 231 runningmean 128;
#X msg 121 144 clear;
#X msg 165 189 length 10;
#X msg 278 209 22;
#X floatatom 191 262 5 0 0 0 - - -;
#X obj 11 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -257985 -1
-1;
#X text 29 35 bang outputs current mean;
#X msg 76 99 1;
#X msg 98 121 2;
#X text 155 261 mean:;
#X text 63 69 Incoming floats are added to the array. The mean is recalculated
for each incoming float;
#X text 287 231 Argument sets initial length. Default (no argument)
is 128;
#X text 10 4 [runningmean] outputs the running mean of the last n floats
to arrive on the left inlet.;
#X text 249 251 Length can be changed to any positive value less than
or equal to the length set by the creation argumwent;
#X text 505 289 Martin Peach 2009/04/10;
#N canvas 701 617 494 344 META 0;
#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan
Wilkes for Pd version 0.42.;
#X text 12 25 LICENSE GPL v2 or later;
#X text 12 135 AUTHOR Martin Peach;
#X text 12 5 KEYWORDS control analysis;
#X text 12 46 DESCRIPTION output the running mean of the last n floats
to arrive on the left inlet;
#X text 12 75 INLET_0 float bang clear length;
#X text 12 95 INLET_1 float;
#X text 12 115 OUTLET_0 float;
#X restore 621 319 pd META;
#X msg 145 168 clear 10;
#X text 231 189 set length (and sets the new array to the current mean)
;
#X text 304 208 another way to set length;
#X text 203 167 set the array to all 10s;
#X text 159 144 clear the array to all zeroes;
#X connect 0 0 4 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 1;
#X connect 5 0 0 0;
#X connect 7 0 0 0;
#X connect 8 0 0 0;
#X connect 16 0 0 0;
mrpeach/cmos/ 0000755 0001750 0001750 00000000000 14110766277 013703 5 ustar zmoelnig zmoelnig mrpeach/cmos/cd4075-help.pd 0000644 0001750 0001750 00000001053 11026462102 016042 0 ustar zmoelnig zmoelnig #N canvas 670 174 478 232 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 147 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 209 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X text 210 170 20070312_Martin_Peach;
#X text 18 47 cd4075 emulates 1/3 of the CMOS triple OR gate;
#X obj 86 106 cd4075 triple or;
#X connect 0 0 6 0;
#X connect 1 0 6 1;
#X connect 3 0 6 2;
#X connect 6 0 2 0;
mrpeach/cmos/cd4516-help.pd 0000644 0001750 0001750 00000005536 11026462102 016054 0 ustar zmoelnig zmoelnig #N canvas 406 127 747 414 12;
#X obj 75 -57 tgl 15 1 empty empty clock 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 96 -37 tgl 15 1 empty empty up_down 17 7 0 10 -44926 -258699
-1 1 1;
#X obj 117 -88 tgl 15 1 empty empty reset 17 7 0 10 -44926 -258699
-1 0 1;
#X obj 139 -111 tgl 15 1 empty empty preset_enable 17 7 0 10 -44926
-258699 -1 0 1;
#X obj 177 -24 tgl 15 0 empty empty P1 17 7 0 10 -260818 -258699 -1
1 1;
#X obj 211 -24 tgl 15 0 empty empty P2 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 243 -24 tgl 15 0 empty empty P3 17 7 0 10 -260818 -258699 -1
1 1;
#X obj 283 -24 tgl 15 0 empty empty P4 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 75 47 tgl 15 0 empty empty Q1 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 117 47 tgl 15 0 empty empty Q2 17 7 0 10 -24198 -258699 -1 0
1;
#X obj 160 47 tgl 15 0 empty empty Q3 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 203 47 tgl 15 0 empty empty Q4 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 246 47 tgl 15 0 empty empty carry_out 17 7 0 10 -62784 -258699
-1 1 1;
#X text 197 -90 1 clears counter;
#X text 285 204 20070314_MartinPeach;
#X obj 9 -121 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X obj 9 -89 metro 100;
#X obj 75 5 cd4516 up down counter;
#X text 283 -115 1 loads data into counter;
#X obj 160 -55 tgl 15 1 empty empty carry_in 17 7 0 10 -44926 -258699
-1 0 1;
#X text 32 -155 cd4516 emulates the CMOS binary up/down counter;
#X text 271 -1 0 to 1 transition on clock counts if reset = 0 and preset_enable
= 0 and carry_in = 0;
#X obj 208 82 tgl 15 0 empty empty P1 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 242 82 tgl 15 0 empty empty P2 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 274 82 tgl 15 0 empty empty P3 17 7 0 10 -260818 -258699 -1
1 1;
#X obj 314 82 tgl 15 0 empty empty P4 17 7 0 10 -260818 -258699 -1
1 1;
#X obj 143 163 tgl 15 0 empty empty Q1 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 185 163 tgl 15 0 empty empty Q2 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 228 163 tgl 15 0 empty empty Q3 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 271 163 tgl 15 0 empty empty Q4 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 314 163 tgl 15 0 empty empty carry_out 17 7 0 10 -62784 -258699
-1 1 1;
#X obj 123 108 cd4516 up down counter;
#X connect 0 0 17 0;
#X connect 0 0 31 0;
#X connect 1 0 17 1;
#X connect 1 0 31 1;
#X connect 2 0 17 2;
#X connect 2 0 31 2;
#X connect 3 0 17 3;
#X connect 3 0 31 3;
#X connect 4 0 17 5;
#X connect 5 0 17 6;
#X connect 6 0 17 7;
#X connect 7 0 17 8;
#X connect 15 0 16 0;
#X connect 16 0 0 0;
#X connect 17 0 8 0;
#X connect 17 1 9 0;
#X connect 17 2 10 0;
#X connect 17 3 11 0;
#X connect 17 4 12 0;
#X connect 17 4 31 4;
#X connect 19 0 17 4;
#X connect 22 0 31 5;
#X connect 23 0 31 6;
#X connect 24 0 31 7;
#X connect 25 0 31 8;
#X connect 31 0 26 0;
#X connect 31 1 27 0;
#X connect 31 2 28 0;
#X connect 31 3 29 0;
#X connect 31 4 30 0;
mrpeach/cmos/LICENSE.txt 0000644 0001750 0001750 00000001356 12571126767 015536 0 ustar zmoelnig zmoelnig CMOS digital logic emulation objects for Pure Data
Copyright (C) 2007-2014 Martin Peach
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
mrpeach/cmos/cd4516.c 0000644 0001750 0001750 00000016612 12430236316 014750 0 ustar zmoelnig zmoelnig /* cd4516.c MP 20070312 */
/* Emulate a cd4516b */
#include "m_pd.h"
typedef struct _cd4516
{
t_object x_obj;
t_outlet *x_Q1Out;
t_outlet *x_Q2Out;
t_outlet *x_Q3Out;
t_outlet *x_Q4Out;
t_outlet *x_CarryOut;
int x_clock;
int x_upDown;
int x_preset_enable;
int x_carry;
int x_P1;
int x_P2;
int x_P3;
int x_P4;
int x_reset;
int x_count;
t_inlet *x_UpDownIn;/* All inlets take one or zero as acceptable inputs. */
t_inlet *x_ResetIn;
t_inlet *x_PresetEnableIn;
t_inlet *x_CarryIn;
t_inlet *x_P1In;
t_inlet *x_P2In;
t_inlet *x_P3In;
t_inlet *x_P4In;
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4516;
static t_class *cd4516_class;
void cd4516_setup(void);
static void *cd4516_new(t_symbol *s, int argc, t_atom *argv);
static void cd4516_free(t_cd4516 *x);
static void cd4516_bang(t_cd4516 *x);
static void cd4516_float(t_cd4516 *x, t_float f);
static void cd4516_reset(t_cd4516 *x, t_float f);
static void cd4516_preset_enable(t_cd4516 *x, t_float f);
static void cd4516_up_down(t_cd4516 *x, t_float f);
static void cd4516_carry(t_cd4516 *x, t_float f);
static void cd4516_P1(t_cd4516 *x, t_float f);
static void cd4516_P2(t_cd4516 *x, t_float f);
static void cd4516_P3(t_cd4516 *x, t_float f);
static void cd4516_P4(t_cd4516 *x, t_float f);
static void cd4516_update_outlets(t_cd4516 *x);
static void cd4516_float(t_cd4516 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, count up. */
if ((x->x_clock == 0)&&(x->x_reset == 0)&&(x->x_preset_enable == 0)&&(x->x_carry == 0))
{
x->x_clock = 1;
if (x->x_upDown == 1) x->x_count = (x->x_count + 1)%16;
else x->x_count = (x->x_count - 1)%16;
cd4516_update_outlets(x);
}
}
else if (f == 0)
{
x->x_clock = 0;
}
else post("cd4516 accepts bang, 1 or 0.");
}
static void cd4516_bang(t_cd4516 *x)
{
if ((x->x_reset == 0)&&(x->x_preset_enable == 0)&&(x->x_carry == 0))
{
if (x->x_upDown == 1)x->x_count = (x->x_count + 1)%16;
else x->x_count = (x->x_count - 1)%16;
cd4516_update_outlets(x);
}
}
static void cd4516_reset(t_cd4516 *x, t_float f)
{
if (f == 1)
{
if (x->x_reset == 0)
{
x->x_count = 0;
cd4516_update_outlets(x);
x->x_reset = 1;
}
}
else if (f == 0)
{
x->x_reset = 0;
if (x->x_preset_enable == 1)
{ /* the strange case of a low-going reset enabling an already high preset enable */
x->x_count = x->x_P1 + 2*x->x_P2 + 4*x->x_P3 + 8*x->x_P4;
cd4516_update_outlets(x);
}
}
else
{
post("cd4516 reset takes 1 or 0 only.");
return;
}
}
static void cd4516_preset_enable(t_cd4516 *x, t_float f)
{
if (f == 0)
{
x->x_preset_enable = 0;
}
else if (f == 1)
{
if (x->x_preset_enable == 0)
{
x->x_preset_enable = 1;
if (x->x_reset == 0)
{
x->x_count = x->x_P1 + 2*x->x_P2 + 4*x->x_P3 + 8*x->x_P4;
cd4516_update_outlets(x);
}
}
}
else
{
post("cd4516 x_preset_enable takes 1 or 0 only.");
return;
}
}
static void cd4516_up_down(t_cd4516 *x, t_float f)
{
if (f == 1)
{
x->x_upDown = 1;
}
else if (f == 0)
{
x->x_upDown = 0;
}
else post("cd4516 updown accepts bang, 1 or 0.");
}
static void cd4516_carry(t_cd4516 *x, t_float f)
{
if (f == 1)
{
x->x_carry = 1;
}
else if (f == 0)
{
x->x_carry = 0;
}
else post("cd4516 carry accepts bang, 1 or 0.");
}
static void cd4516_P1(t_cd4516 *x, t_float f)
{
if (f == 1) x->x_P1 = 1;
else if (f == 0) x->x_P1 = 0;
else
{
post("cd4516 P1 takes 1 or 0 only.");
return;
}
}
static void cd4516_P2(t_cd4516 *x, t_float f)
{
if (f == 1) x->x_P2 = 1;
else if (f == 0) x->x_P2 = 0;
else
{
post("cd4516 P2 takes 1 or 0 only.");
return;
}
}
static void cd4516_P3(t_cd4516 *x, t_float f)
{
if (f == 1) x->x_P3 = 1;
else if (f == 0) x->x_P3 = 0;
else
{
post("cd4516 P3 takes 1 or 0 only.");
return;
}
}
static void cd4516_P4(t_cd4516 *x, t_float f)
{
if (f == 1) x->x_P4 = 1;
else if (f == 0) x->x_P4 = 0;
else
{
post("cd4516 P4 takes 1 or 0 only.");
return;
}
}
static void cd4516_update_outlets(t_cd4516 *x)
{
if (x->x_upDown == 1) outlet_float(x->x_CarryOut, (x->x_count == 15)?0:1);
else outlet_float(x->x_CarryOut, (x->x_count == 0)?0:1);
outlet_float(x->x_Q4Out, ((x->x_count & 8) != 0)?1:0);
outlet_float(x->x_Q3Out, ((x->x_count & 4) != 0)?1:0);
outlet_float(x->x_Q2Out, ((x->x_count & 2) != 0)?1:0);
outlet_float(x->x_Q1Out, ((x->x_count & 1) != 0)?1:0);
}
static void cd4516_free(t_cd4516 *x)
{
return;
}
static void *cd4516_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4516 *x;
x = (t_cd4516 *)pd_new(cd4516_class);
if (x == NULL) return (x);
x->x_Q1Out = outlet_new((t_object *)x, &s_float);
x->x_Q2Out = outlet_new((t_object *)x, &s_float);
x->x_Q3Out = outlet_new((t_object *)x, &s_float);
x->x_Q4Out = outlet_new((t_object *)x, &s_float);
x->x_CarryOut = outlet_new((t_object *)x, &s_float);
x->x_UpDownIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("updown"));
x->x_ResetIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("reset"));
x->x_PresetEnableIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("presetenable"));
x->x_CarryIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("carry"));
x->x_P1In = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P1"));
x->x_P2In = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P2"));
x->x_P3In = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P3"));
x->x_P4In = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P4"));
return (x);
}
void cd4516_setup(void)
{
cd4516_class = class_new(gensym("cd4516"),
(t_newmethod)cd4516_new,
(t_method)cd4516_free,
sizeof(t_cd4516), 0, 0); /* no arguments */
class_addbang(cd4516_class, cd4516_bang);
class_addfloat(cd4516_class, cd4516_float);
class_addmethod(cd4516_class, (t_method)cd4516_up_down, gensym("updown"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_preset_enable, gensym("presetenable"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_reset, gensym("reset"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_carry, gensym("carry"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_P1, gensym("P1"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_P2, gensym("P2"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_P3, gensym("P3"), A_FLOAT, 0);
class_addmethod(cd4516_class, (t_method)cd4516_P4, gensym("P4"), A_FLOAT, 0);
}
/* end cd4516.c */
mrpeach/cmos/cd4094.c 0000644 0001750 0001750 00000013214 12430236316 014744 0 ustar zmoelnig zmoelnig /* cd4094.c MP 20070312 */
/* Emulate a cd4094b */
#include "m_pd.h"
typedef struct _cd4094
{
t_object x_obj;
t_outlet *x_Q1Out;
t_outlet *x_Q2Out;
t_outlet *x_Q3Out;
t_outlet *x_Q4Out;
t_outlet *x_Q5Out;
t_outlet *x_Q6Out;
t_outlet *x_Q7Out;
t_outlet *x_Q8Out;
t_outlet *x_QSOut;
t_outlet *x_QprimeSOut;
int x_clock;
int x_data;
int x_data_in;
int x_strobe;
int x_output_enable;
int x_qprime;
t_inlet *x_StrobeIn;/* Strobe takes one or zero as acceptable inputs. */
t_inlet *x_DataIn;/* Data takes one or zero as acceptable inputs. */
t_inlet *x_OutputEnable;/* Output Enable takes one or zero as acceptable inputs. */
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4094;
static t_class *cd4094_class;
void cd4094_setup(void);
static void *cd4094_new(t_symbol *s, int argc, t_atom *argv);
static void cd4094_free(t_cd4094 *x);
static void cd4094_bang(t_cd4094 *x);
static void cd4094_float(t_cd4094 *x, t_float f);
static void cd4094_strobe(t_cd4094 *x, t_float f);
static void cd4094_data(t_cd4094 *x, t_float f);
static void cd4094_output_enable(t_cd4094 *x, t_float f);
static void cd4094_update_outlets(t_cd4094 *x);
static void cd4094_float(t_cd4094 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, clock it. */
if ((x->x_clock == 0)&&(x->x_strobe == 1))
{
x->x_data <<= 1;
if (x->x_data_in != 0) x->x_data |= 1;
cd4094_update_outlets(x);
}
x->x_clock = 1;
}
else if (f == 0)
{
if (x->x_clock == 1) /* if clock was high and is low, clock Q prime. */
{
x->x_qprime = ((x->x_data & 256) != 0)?1:0;
outlet_float(x->x_QprimeSOut, x->x_qprime);
}
x->x_clock = 0;
}
else post("cd4094 accepts bang, 1 or 0.");
}
static void cd4094_bang(t_cd4094 *x)
{
if (x->x_strobe == 1)
{
/* rising edge clock */
x->x_data <<= 1;
if (x->x_data_in != 0) x->x_data |= 1;
cd4094_update_outlets(x);
/* Q'7 is clocked on a falling edge */
x->x_qprime = ((x->x_data & 256) != 0)?1:0;
outlet_float(x->x_QprimeSOut, x->x_qprime);
}
}
static void cd4094_strobe(t_cd4094 *x, t_float f)
{
if (f == 1)
{
x->x_strobe = 1;
}
else if (f == 0)
{
x->x_strobe = 0;
}
else
{
post("cd4094 strobe takes 1 or 0 only.");
return;
}
}
static void cd4094_output_enable(t_cd4094 *x, t_float f)
{
if (f == 1)
{
x->x_output_enable = 1;
cd4094_update_outlets(x);
}
else if (f == 0)
{
x->x_output_enable = 0;
}
else
{
post("cd4094 output enable takes 1 or 0 only.");
return;
}
}
static void cd4094_data(t_cd4094 *x, t_float f)
{
if (f == 1) x->x_data_in = 1;
else if (f == 0) x->x_data_in = 0;
else
{
post("cd4094 data takes 1 or 0 only.");
return;
}
}
static void cd4094_update_outlets(t_cd4094 *x)
{
outlet_float(x->x_QprimeSOut, ((x->x_qprime) != 0)?1:0);
outlet_float(x->x_QSOut, ((x->x_data & 256) != 0)?1:0);
if (x->x_output_enable != 0)
{
outlet_float(x->x_QSOut, ((x->x_data & 256) != 0)?1:0);
outlet_float(x->x_Q8Out, ((x->x_data & 128) != 0)?1:0);
outlet_float(x->x_Q7Out, ((x->x_data & 64) != 0)?1:0);
outlet_float(x->x_Q6Out, ((x->x_data & 32) != 0)?1:0);
outlet_float(x->x_Q5Out, ((x->x_data & 16) != 0)?1:0);
outlet_float(x->x_Q4Out, ((x->x_data & 8) != 0)?1:0);
outlet_float(x->x_Q3Out, ((x->x_data & 4) != 0)?1:0);
outlet_float(x->x_Q2Out, ((x->x_data & 2) != 0)?1:0);
outlet_float(x->x_Q1Out, ((x->x_data & 1) != 0)?1:0);
}
}
static void cd4094_free(t_cd4094 *x)
{
return;
}
static void *cd4094_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4094 *x;
x = (t_cd4094 *)pd_new(cd4094_class);
if (x == NULL) return (x);
x->x_Q1Out = outlet_new((t_object *)x, &s_float);
x->x_Q2Out = outlet_new((t_object *)x, &s_float);
x->x_Q3Out = outlet_new((t_object *)x, &s_float);
x->x_Q4Out = outlet_new((t_object *)x, &s_float);
x->x_Q5Out = outlet_new((t_object *)x, &s_float);
x->x_Q6Out = outlet_new((t_object *)x, &s_float);
x->x_Q7Out = outlet_new((t_object *)x, &s_float);
x->x_Q8Out = outlet_new((t_object *)x, &s_float);
x->x_QSOut = outlet_new((t_object *)x, &s_float);
x->x_QprimeSOut = outlet_new((t_object *)x, &s_float);
x->x_StrobeIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("strobe"));
x->x_DataIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("data"));
x->x_OutputEnable = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("enableoutput"));
return (x);
}
void cd4094_setup(void)
{
cd4094_class = class_new(gensym("cd4094"),
(t_newmethod)cd4094_new,
(t_method)cd4094_free,
sizeof(t_cd4094), 0, 0); /* no arguments */
class_addbang(cd4094_class, cd4094_bang);
class_addfloat(cd4094_class, cd4094_float);
class_addmethod(cd4094_class, (t_method)cd4094_strobe, gensym("strobe"), A_FLOAT, 0);
class_addmethod(cd4094_class, (t_method)cd4094_data, gensym("data"), A_FLOAT, 0);
class_addmethod(cd4094_class, (t_method)cd4094_output_enable, gensym("enableoutput"), A_FLOAT, 0);
}
/* end cd4094.c */
mrpeach/cmos/cd4070-help.pd 0000644 0001750 0001750 00000000703 11026462102 016036 0 ustar zmoelnig zmoelnig #N canvas 670 174 454 208 12;
#X obj 86 107 cd4070;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 129 83 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X text 18 47 cd4070 emulates 1/4 of the CMOS Exclusive Or gate;
#X text 167 138 20070308_Martin_Peach;
#X connect 0 0 3 0;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
mrpeach/cmos/cd4082.c 0000644 0001750 0001750 00000006300 12430236316 014737 0 ustar zmoelnig zmoelnig /* cd4082.c MP 20070312 */
/* Emulate a cd4082b */
#include "m_pd.h"
typedef struct _cd4082
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
int x_in4;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
t_inlet *x_inlet4;/* Fourth inlet is 'live' like the first */
} t_cd4082;
static t_class *cd4082_class;
void cd4082_setup(void);
static void *cd4082_new(t_symbol *s, int argc, t_atom *argv);
static void cd4082_free(t_cd4082 *x);
static void cd4082_bang(t_cd4082 *x);
static void cd4082_float(t_cd4082 *x, t_float f);
static void cd4082_inlet2(t_cd4082 *x, t_float f);
static void cd4082_inlet3(t_cd4082 *x, t_float f);
static void cd4082_inlet4(t_cd4082 *x, t_float f);
static void cd4082_update_outlets(t_cd4082 *x);
static void cd4082_float(t_cd4082 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4082 inlet 2 accepts 1 or 0.");
return;
}
cd4082_update_outlets(x);
}
static void cd4082_bang(t_cd4082 *x)
{
cd4082_update_outlets(x);
}
static void cd4082_inlet2(t_cd4082 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4082 inlet 2 accepts 1 or 0.");
return;
}
cd4082_update_outlets(x);
}
static void cd4082_inlet3(t_cd4082 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4082 inlet 3 accepts 1 or 0.");
return;
}
cd4082_update_outlets(x);
}
static void cd4082_inlet4(t_cd4082 *x, t_float f)
{
if (f == 1) x->x_in4 = 1;
else if (f == 0) x->x_in4 = 0;
else
{
post("cd4082 inlet 4 accepts 1 or 0.");
return;
}
cd4082_update_outlets(x);
}
static void cd4082_update_outlets(t_cd4082 *x)
{ /* QUAD AND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3 + x->x_in4) == 4)?1:0);
}
static void cd4082_free(t_cd4082 *x)
{
return;
}
static void *cd4082_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4082 *x;
x = (t_cd4082 *)pd_new(cd4082_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
x->x_inlet4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet4"));
return (x);
}
void cd4082_setup(void)
{
cd4082_class = class_new(gensym("cd4082"),
(t_newmethod)cd4082_new,
(t_method)cd4082_free,
sizeof(t_cd4082), 0, 0); /* no arguments */
class_addbang(cd4082_class, cd4082_bang);
class_addfloat(cd4082_class, cd4082_float);
class_addmethod(cd4082_class, (t_method)cd4082_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4082_class, (t_method)cd4082_inlet3, gensym("inlet3"), A_FLOAT, 0);
class_addmethod(cd4082_class, (t_method)cd4082_inlet4, gensym("inlet4"), A_FLOAT, 0);
}
/* end cd4082.c */
mrpeach/cmos/cd4013-help.pd 0000644 0001750 0001750 00000002553 11026462102 016040 0 ustar zmoelnig zmoelnig #N canvas 581 224 651 219 12;
#X obj 79 38 tgl 15 0 empty empty CLK 17 7 0 10 -24198 -62784 -1 0
1;
#X obj 98 53 tgl 15 0 empty empty SET 17 7 0 10 -24198 -62784 -1 0
1;
#X obj 118 68 tgl 15 0 empty empty RESET 17 7 0 10 -24198 -62784 -1
0 1;
#X obj 138 83 tgl 15 0 empty empty D 17 7 0 10 -24198 -62784 -1 0 1
;
#X obj 138 172 tgl 15 0 empty empty /Q 17 7 0 10 -143491 -241291 -1
0 1;
#X obj 79 172 tgl 15 0 empty empty Q 17 7 0 10 -143491 -241291 -1 1
1;
#X obj 6 67 tgl 15 0 empty empty empty 17 7 0 10 -44926 -90881 -1 0
1;
#X text 27 5 cd4013 emulates one half of the CMOS logic D flipflop.
;
#X obj 79 146 cd4013 v;
#X text 172 80 D is clocked to the output on rising edge of a clock.
;
#X text 133 35 A 0-1 transition or a bang clocks D to the outlets.
;
#X text 147 50 Sets Q=1. Overrides Reset and Clock.;
#X text 183 65 Sets Q=0. Overrides Clock.;
#X obj 170 145 spigot;
#X obj 213 123 tgl 15 0 empty empty feedback 17 7 0 10 -44926 -1109
-1 1 1;
#X obj 42 115 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -241291
-1;
#X obj 6 89 metro 500;
#X text 272 172 20070308_Martin_Peach;
#X connect 0 0 8 0;
#X connect 1 0 8 1;
#X connect 2 0 8 2;
#X connect 3 0 8 3;
#X connect 4 0 13 0;
#X connect 6 0 16 0;
#X connect 8 0 5 0;
#X connect 8 1 4 0;
#X connect 13 0 3 0;
#X connect 14 0 13 1;
#X connect 15 0 8 0;
#X connect 16 0 15 0;
mrpeach/cmos/cd4081-help.pd 0000644 0001750 0001750 00000000672 11026462102 016045 0 ustar zmoelnig zmoelnig #N canvas 670 174 462 216 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 129 83 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X text 167 138 20070308_Martin_Peach;
#X obj 86 106 cd4081;
#X text 18 47 cd4081 emulates 1/4 of the CMOS AND gate;
#X connect 0 0 4 0;
#X connect 1 0 4 1;
#X connect 4 0 2 0;
mrpeach/cmos/cd4001-help.pd 0000644 0001750 0001750 00000000710 11026462102 016026 0 ustar zmoelnig zmoelnig #N canvas 670 174 486 240 12;
#X obj 86 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 161 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X text 210 170 20070315_Martin_Peach;
#X obj 86 106 cd4001 nor;
#X text 16 29 cd4001 emulates 1/4 of the CMOS two-input NOR gate;
#X connect 0 0 4 0;
#X connect 1 0 4 1;
#X connect 4 0 2 0;
mrpeach/cmos/cd4027.c 0000644 0001750 0001750 00000014025 12430236316 014741 0 ustar zmoelnig zmoelnig /* cd4027.c MP 20070306 */
/* Emulate a cd4027b */
#include "m_pd.h"
typedef struct _cd4027
{
t_object x_obj;
int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */
t_outlet *x_Q;
t_outlet *x_notQ;
t_inlet *x_set;/* set takes one or zero as acceptable inputs. */
t_inlet *x_reset;/* reset takes one or zero as acceptable inputs. */
t_inlet *x_j;/* j takes one or zero as acceptable inputs. */
t_inlet *x_k;/* k takes one or zero as acceptable inputs. */
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4027;
#define SET_4027 1
#define CLOCK_4027 2
#define RESET_4027 4
#define J_4027 8
#define K_4027 16
#define Q_4027 32
#define UPDATING_4027 64
#define CHANGED_4027 128
static t_class *cd4027_class;
void cd4027_setup(void);
static void *cd4027_new(t_symbol *s, int argc, t_atom *argv);
static void cd4027_free(t_cd4027 *x);
static void cd4027_bang(t_cd4027 *x);
static void cd4027_float(t_cd4027 *x, t_float f);
static void cd4027_set(t_cd4027 *x, t_float f);
static void cd4027_reset(t_cd4027 *x, t_float f);
static void cd4027_j(t_cd4027 *x, t_float f);
static void cd4027_k(t_cd4027 *x, t_float f);
static void cd4027_update_outlets(t_cd4027 *x);
static void cd4027_printstate (t_cd4027 *x);
static void cd4027_float(t_cd4027 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, clock it. */
if ((x->x_state & CLOCK_4027) == 0) cd4027_bang(x);
x->x_state |= CLOCK_4027;
}
else if (f == 0) x->x_state &= ~CLOCK_4027;
else post("cd4027 accepts bang, 1 or 0.");
}
static void cd4027_printstate (t_cd4027 *x)
{
post ("SET %d RESET %d J %d K %d Q %d", ((x->x_state & SET_4027) != 0)?1:0
, ((x->x_state & RESET_4027) != 0)?1:0
, ((x->x_state & J_4027) != 0)?1:0
, ((x->x_state & K_4027) != 0)?1:0
, ((x->x_state & Q_4027) != 0)?1:0);
}
static void cd4027_bang(t_cd4027 *x)
{
if ((x->x_state & (SET_4027 | RESET_4027)) == 0)
{ /* if set is low and reset is low, clock forward */
if ((x->x_state & Q_4027) != 0)
{ /* Q is high */
if ((x->x_state & K_4027)== 0) x->x_state |= Q_4027;
else x->x_state &= ~Q_4027;
}
else
{ /* Q is low */
if ((x->x_state & J_4027) != 0) x->x_state |= Q_4027;
else x->x_state &= ~Q_4027;
}
cd4027_update_outlets(x);
}
}
static void cd4027_set(t_cd4027 *x, t_float f)
{
if (f == 1)
{
x->x_state |= SET_4027; /* set = 1 */
}
else if (f == 0)
{
x->x_state &= ~SET_4027; /* set = 0 */
}
else
{
post("cd4027 set takes 1 or 0 only.");
return;
}
/* update outlets if not already doing that */
if ((x->x_state & UPDATING_4027) == 0)
{
cd4027_update_outlets(x);
}
else
{
x->x_state |= CHANGED_4027;
}
return;
}
static void cd4027_reset(t_cd4027 *x, t_float f)
{
if (f == 1)
{
x->x_state |= RESET_4027; /* reset = 1 */
}
else if (f == 0)
{
x->x_state &= ~RESET_4027; /* reset = 0 */
}
else
{
return;
}
/* update outlets if not already doing that */
if ((x->x_state & UPDATING_4027) == 0)
{
cd4027_update_outlets(x);
}
else
{
x->x_state |= CHANGED_4027;
}
return;
}
static void cd4027_j(t_cd4027 *x, t_float f)
{
if (f == 1)
{
x->x_state |= J_4027; /* j = 1 */
}
else if (f == 0)
{
x->x_state &= ~J_4027; /* j = 0 */
}
else post("cd4027 j takes 1 or 0 only.");
return;
}
static void cd4027_k(t_cd4027 *x, t_float f)
{
if (f == 1)
{
x->x_state |= K_4027; /* k = 1 */
}
else if (f == 0)
{
x->x_state &= ~K_4027; /* k = 0 */
}
else post("cd4027 k takes 1 or 0 only.");
return;
}
static void cd4027_update_outlets(t_cd4027 *x)
{
/* cd4027_printstate (x); */
x->x_state |= UPDATING_4027;/* updating outlets */
reset:
if ((x->x_state & SET_4027) != 0) x->x_state |= Q_4027;
else if ((x->x_state & RESET_4027) != 0) x->x_state &= ~Q_4027;
x->x_state &= ~CHANGED_4027; /* prepare to flag any changes that occur during outlet_update */
outlet_float(x->x_notQ, ((x->x_state & Q_4027) == 0)?1:0);
/* we might get set or reset as a result of feedback from one of these outlets. */
if ((x->x_state & CHANGED_4027) != 0) goto reset;
outlet_float(x->x_Q, ((x->x_state & Q_4027) != 0)?1:0);
if ((x->x_state & CHANGED_4027) != 0) goto reset;
x->x_state &= ~UPDATING_4027;/* finished updating outlets */
}
static void cd4027_free(t_cd4027 *x)
{
return;
}
static void *cd4027_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4027 *x;
x = (t_cd4027 *)pd_new(cd4027_class);
if (x == NULL) return (x);
x->x_Q = outlet_new((t_object *)x, &s_float);
x->x_notQ = outlet_new((t_object *)x, &s_float);
x->x_set = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("set"));
x->x_reset = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("reset"));
x->x_j = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("j"));
x->x_k = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("k"));
return (x);
}
void cd4027_setup(void)
{
cd4027_class = class_new(gensym("cd4027"),
(t_newmethod)cd4027_new,
(t_method)cd4027_free,
sizeof(t_cd4027), 0, 0); /* no arguments */
class_addbang(cd4027_class, cd4027_bang);
class_addfloat(cd4027_class, cd4027_float);
class_addmethod(cd4027_class, (t_method)cd4027_reset, gensym("reset"), A_FLOAT, 0);
class_addmethod(cd4027_class, (t_method)cd4027_set, gensym("set"), A_FLOAT, 0);
class_addmethod(cd4027_class, (t_method)cd4027_j, gensym("j"), A_FLOAT, 0);
class_addmethod(cd4027_class, (t_method)cd4027_k, gensym("k"), A_FLOAT, 0);
}
/* end cd4027.c */
mrpeach/cmos/cd4017-help.pd 0000644 0001750 0001750 00000006146 11026462102 016046 0 ustar zmoelnig zmoelnig #N canvas 0 0 684 247 10;
#X obj 9 123 cd4017 vvvvvvvvvvvvvvvvvvvvvvv;
#X obj 9 78 tgl 15 0 empty empty clock 17 7 0 10 -24198 -225271 -1
0 1;
#X obj 111 88 tgl 15 0 empty empty clock_inhibit 17 7 0 10 -24198 -225271
-1 0 1;
#X obj 214 103 tgl 15 0 empty empty reset 17 7 0 10 -24198 -225271
-1 0 1;
#X obj 9 39 metro 100;
#X obj 9 9 tgl 15 0 empty empty run 17 7 0 10 -24198 -225271 -1 1 1
;
#X obj 9 152 tgl 15 0 empty empty 0 3 23 0 10 -44926 -250685 -1 0 1
;
#X obj 29 152 tgl 15 0 empty empty 1 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 50 152 tgl 15 0 empty empty 2 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 70 152 tgl 15 0 empty empty 3 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 91 152 tgl 15 0 empty empty 4 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 111 152 tgl 15 0 empty empty 5 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 132 152 tgl 15 0 empty empty 6 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 152 152 tgl 15 0 empty empty 7 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 173 152 tgl 15 0 empty empty 8 3 23 0 10 -44926 -250685 -1 1
1;
#X obj 193 152 tgl 15 0 empty empty 9 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 214 152 tgl 15 0 empty empty carry_out 3 23 0 10 -44926 -250685
-1 0 1;
#X text 122 7 The CD4017 is a CMOS digital logic IC.;
#X text 123 25 It counts up to ten and sets one of the numbered outlets
high whenever it is clocked.;
#X text 123 55 A clock can be a bang or a 1 following a 0;
#X obj 332 142 cd4017 vvvvvvvvvvvvvvvvvvvvvvv;
#X obj 332 97 tgl 15 0 empty empty clock 17 7 0 10 -24198 -225271 -1
0 1;
#X obj 434 107 tgl 15 0 empty empty clock_inhibit 17 7 0 10 -24198
-225271 -1 0 1;
#X obj 537 122 tgl 15 0 empty empty reset 17 7 0 10 -24198 -225271
-1 0 1;
#X obj 332 171 tgl 15 0 empty empty 0 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 352 171 tgl 15 0 empty empty 1 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 373 171 tgl 15 0 empty empty 2 3 23 0 10 -44926 -250685 -1 1
1;
#X obj 393 171 tgl 15 0 empty empty 3 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 414 171 tgl 15 0 empty empty 4 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 434 171 tgl 15 0 empty empty 5 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 455 171 tgl 15 0 empty empty 6 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 475 171 tgl 15 0 empty empty 7 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 496 171 tgl 15 0 empty empty 8 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 516 171 tgl 15 0 empty empty 9 3 23 0 10 -44926 -250685 -1 0
1;
#X obj 537 171 tgl 15 0 empty empty carry_out 3 23 0 10 -44926 -250685
-1 1 1;
#X text 452 229 2007MartinPeach;
#X connect 0 0 6 0;
#X connect 0 1 7 0;
#X connect 0 2 8 0;
#X connect 0 3 9 0;
#X connect 0 4 10 0;
#X connect 0 5 11 0;
#X connect 0 6 12 0;
#X connect 0 7 13 0;
#X connect 0 8 14 0;
#X connect 0 9 15 0;
#X connect 0 10 16 0;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
#X connect 3 0 0 2;
#X connect 4 0 1 0;
#X connect 5 0 4 0;
#X connect 16 0 21 0;
#X connect 20 0 24 0;
#X connect 20 1 25 0;
#X connect 20 2 26 0;
#X connect 20 3 27 0;
#X connect 20 4 28 0;
#X connect 20 5 29 0;
#X connect 20 6 30 0;
#X connect 20 7 31 0;
#X connect 20 8 32 0;
#X connect 20 9 33 0;
#X connect 20 10 34 0;
#X connect 21 0 20 0;
#X connect 22 0 20 1;
#X connect 23 0 20 2;
#X connect 29 0 23 0;
mrpeach/cmos/cd4002.c 0000644 0001750 0001750 00000006161 12430236316 014734 0 ustar zmoelnig zmoelnig /* cd4002.c MP 20070315 */
/* Emulate a cd4002b */
#include "m_pd.h"
typedef struct _cd4002
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
int x_in4;
t_outlet *x_out;
t_inlet *x_inlet2;/* extra inlets are 'live' like the first */
t_inlet *x_inlet3;
t_inlet *x_inlet4;
} t_cd4002;
static t_class *cd4002_class;
void cd4002_setup(void);
static void *cd4002_new(t_symbol *s, int argc, t_atom *argv);
static void cd4002_free(t_cd4002 *x);
static void cd4002_bang(t_cd4002 *x);
static void cd4002_float(t_cd4002 *x, t_float f);
static void cd4002_inlet2(t_cd4002 *x, t_float f);
static void cd4002_inlet3(t_cd4002 *x, t_float f);
static void cd4002_inlet4(t_cd4002 *x, t_float f);
static void cd4002_update_outlets(t_cd4002 *x);
static void cd4002_float(t_cd4002 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4002 inlet 2 accepts 1 or 0.");
return;
}
cd4002_update_outlets(x);
}
static void cd4002_bang(t_cd4002 *x)
{
cd4002_update_outlets(x);
}
static void cd4002_inlet2(t_cd4002 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4002 inlet 2 accepts 1 or 0.");
return;
}
cd4002_update_outlets(x);
}
static void cd4002_inlet3(t_cd4002 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4002 inlet 3 accepts 1 or 0.");
return;
}
cd4002_update_outlets(x);
}
static void cd4002_inlet4(t_cd4002 *x, t_float f)
{
if (f == 1) x->x_in4 = 1;
else if (f == 0) x->x_in4 = 0;
else
{
post("cd4002 inlet 4 accepts 1 or 0.");
return;
}
cd4002_update_outlets(x);
}
static void cd4002_update_outlets(t_cd4002 *x)
{ /* Quadruple NOR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3 + x->x_in4) != 0)?0:1);
}
static void cd4002_free(t_cd4002 *x)
{
return;
}
static void *cd4002_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4002 *x;
x = (t_cd4002 *)pd_new(cd4002_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
x->x_inlet4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet4"));
return (x);
}
void cd4002_setup(void)
{
cd4002_class = class_new(gensym("cd4002"),
(t_newmethod)cd4002_new,
(t_method)cd4002_free,
sizeof(t_cd4002), 0, 0); /* no arguments */
class_addbang(cd4002_class, cd4002_bang);
class_addfloat(cd4002_class, cd4002_float);
class_addmethod(cd4002_class, (t_method)cd4002_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4002_class, (t_method)cd4002_inlet3, gensym("inlet3"), A_FLOAT, 0);
class_addmethod(cd4002_class, (t_method)cd4002_inlet4, gensym("inlet4"), A_FLOAT, 0);
}
/* end cd4002.c */
mrpeach/cmos/cd4081.c 0000644 0001750 0001750 00000004102 12430236316 014734 0 ustar zmoelnig zmoelnig /* cd4081.c MP 20070308 */
/* Emulate a cd4081b */
#include "m_pd.h"
typedef struct _cd4081
{
t_object x_obj;
int x_in1;
int x_in2;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
} t_cd4081;
static t_class *cd4081_class;
void cd4081_setup(void);
static void *cd4081_new(t_symbol *s, int argc, t_atom *argv);
static void cd4081_free(t_cd4081 *x);
static void cd4081_bang(t_cd4081 *x);
static void cd4081_float(t_cd4081 *x, t_float f);
static void cd4081_inlet2(t_cd4081 *x, t_float f);
static void cd4081_update_outlets(t_cd4081 *x);
static void cd4081_float(t_cd4081 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4081 inlet 2 accepts 1 or 0.");
return;
}
cd4081_update_outlets(x);
}
static void cd4081_bang(t_cd4081 *x)
{
cd4081_update_outlets(x);
}
static void cd4081_inlet2(t_cd4081 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4081 inlet 2 accepts 1 or 0.");
return;
}
cd4081_update_outlets(x);
}
static void cd4081_update_outlets(t_cd4081 *x)
{ /* AND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2) == 2)?1:0);
}
static void cd4081_free(t_cd4081 *x)
{
return;
}
static void *cd4081_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4081 *x;
x = (t_cd4081 *)pd_new(cd4081_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
return (x);
}
void cd4081_setup(void)
{
cd4081_class = class_new(gensym("cd4081"),
(t_newmethod)cd4081_new,
(t_method)cd4081_free,
sizeof(t_cd4081), 0, 0); /* no arguments */
class_addbang(cd4081_class, cd4081_bang);
class_addfloat(cd4081_class, cd4081_float);
class_addmethod(cd4081_class, (t_method)cd4081_inlet2, gensym("inlet2"), A_FLOAT, 0);
}
/* end cd4081.c */
mrpeach/cmos/cd4011.c 0000644 0001750 0001750 00000004112 12430236316 014726 0 ustar zmoelnig zmoelnig /* cd4011.c MP 20070315 */
/* Emulate a cd4011b */
#include "m_pd.h"
typedef struct _cd4011
{
t_object x_obj;
int x_in1;
int x_in2;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
} t_cd4011;
static t_class *cd4011_class;
void cd4011_setup(void);
static void *cd4011_new(t_symbol *s, int argc, t_atom *argv);
static void cd4011_free(t_cd4011 *x);
static void cd4011_bang(t_cd4011 *x);
static void cd4011_float(t_cd4011 *x, t_float f);
static void cd4011_inlet2(t_cd4011 *x, t_float f);
static void cd4011_update_outlets(t_cd4011 *x);
static void cd4011_float(t_cd4011 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4011 inlet 2 accepts 1 or 0.");
return;
}
cd4011_update_outlets(x);
}
static void cd4011_bang(t_cd4011 *x)
{
cd4011_update_outlets(x);
}
static void cd4011_inlet2(t_cd4011 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4011 inlet 2 accepts 1 or 0.");
return;
}
cd4011_update_outlets(x);
}
static void cd4011_update_outlets(t_cd4011 *x)
{ /* Double NAND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2) == 2)?0:1);
}
static void cd4011_free(t_cd4011 *x)
{
return;
}
static void *cd4011_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4011 *x;
x = (t_cd4011 *)pd_new(cd4011_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
return (x);
}
void cd4011_setup(void)
{
cd4011_class = class_new(gensym("cd4011"),
(t_newmethod)cd4011_new,
(t_method)cd4011_free,
sizeof(t_cd4011), 0, 0); /* no arguments */
class_addbang(cd4011_class, cd4011_bang);
class_addfloat(cd4011_class, cd4011_float);
class_addmethod(cd4011_class, (t_method)cd4011_inlet2, gensym("inlet2"), A_FLOAT, 0);
}
/* end cd4011.c */
mrpeach/cmos/cmos-meta.pd 0000644 0001750 0001750 00000000255 12571126767 016122 0 ustar zmoelnig zmoelnig #N canvas 15 49 200 200 10;
#N canvas 25 49 420 300 META 1;
#X text 13 41 NAME cmos;
#X text 10 25 AUTHOR Martin Peach;
#X text 10 10 VERSION 0.1;
#X restore 10 10 pd META;
mrpeach/cmos/cd4073-help.pd 0000644 0001750 0001750 00000001055 11026462102 016042 0 ustar zmoelnig zmoelnig #N canvas 670 174 474 228 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 151 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X obj 217 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X text 210 170 20070312_Martin_Peach;
#X text 18 47 cd4073 emulates 1/3 of the CMOS triple AND gate;
#X obj 86 106 cd4073 triple and;
#X connect 0 0 6 0;
#X connect 1 0 6 1;
#X connect 3 0 6 2;
#X connect 6 0 2 0;
mrpeach/cmos/cd4014-help.pd 0000644 0001750 0001750 00000003133 11026462102 016034 0 ustar zmoelnig zmoelnig #N canvas 633 293 527 277 12;
#X obj 95 151 cd4014 shift register;
#X obj 95 32 tgl 15 0 empty empty Clock 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 40 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -44926 -258699
-1;
#X obj 111 49 tgl 15 0 empty empty P1 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 127 65 tgl 15 0 empty empty P2 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 143 81 tgl 15 0 empty empty P3 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 160 98 tgl 15 0 empty empty P4 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 176 49 tgl 15 0 empty empty P5 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 192 65 tgl 15 0 empty empty P6 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 209 81 tgl 15 0 empty empty P7 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 225 98 tgl 15 0 empty empty P8 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 241 49 tgl 15 0 empty empty ParallelSerial 17 7 0 10 -44926
-258699 -1 0 1;
#X obj 258 66 tgl 15 0 empty empty SerialIn 17 7 0 10 -44926 -258699
-1 0 1;
#X obj 95 181 tgl 15 0 empty empty Q6 17 7 0 10 -258699 -241291 -1
0 1;
#X obj 176 181 tgl 15 0 empty empty Q7 17 7 0 10 -258699 -241291 -1
0 1;
#X obj 258 181 tgl 15 0 empty empty Q8 17 7 0 10 -258699 -241291 -1
0 1;
#X text 18 0 cd4014 emulates the CMOS 8-stage static shift register
;
#X text 147 226 20070315_MartinPeach;
#X connect 0 0 13 0;
#X connect 0 1 14 0;
#X connect 0 2 15 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 1;
#X connect 4 0 0 2;
#X connect 5 0 0 3;
#X connect 6 0 0 4;
#X connect 7 0 0 5;
#X connect 8 0 0 6;
#X connect 9 0 0 7;
#X connect 10 0 0 8;
#X connect 11 0 0 9;
#X connect 12 0 0 10;
mrpeach/cmos/cd4075.c 0000644 0001750 0001750 00000005204 12430236316 014743 0 ustar zmoelnig zmoelnig /* cd4075.c MP 20070312 */
/* Emulate a cd4075b */
#include "m_pd.h"
typedef struct _cd4075
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
} t_cd4075;
static t_class *cd4075_class;
void cd4075_setup(void);
static void *cd4075_new(t_symbol *s, int argc, t_atom *argv);
static void cd4075_free(t_cd4075 *x);
static void cd4075_bang(t_cd4075 *x);
static void cd4075_float(t_cd4075 *x, t_float f);
static void cd4075_inlet2(t_cd4075 *x, t_float f);
static void cd4075_inlet3(t_cd4075 *x, t_float f);
static void cd4075_update_outlets(t_cd4075 *x);
static void cd4075_float(t_cd4075 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4075 inlet 2 accepts 1 or 0.");
return;
}
cd4075_update_outlets(x);
}
static void cd4075_bang(t_cd4075 *x)
{
cd4075_update_outlets(x);
}
static void cd4075_inlet2(t_cd4075 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4075 inlet 2 accepts 1 or 0.");
return;
}
cd4075_update_outlets(x);
}
static void cd4075_inlet3(t_cd4075 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4075 inlet 3 accepts 1 or 0.");
return;
}
cd4075_update_outlets(x);
}
static void cd4075_update_outlets(t_cd4075 *x)
{ /* Triple OR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3) != 0)?1:0);
}
static void cd4075_free(t_cd4075 *x)
{
return;
}
static void *cd4075_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4075 *x;
x = (t_cd4075 *)pd_new(cd4075_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
return (x);
}
void cd4075_setup(void)
{
cd4075_class = class_new(gensym("cd4075"),
(t_newmethod)cd4075_new,
(t_method)cd4075_free,
sizeof(t_cd4075), 0, 0); /* no arguments */
class_addbang(cd4075_class, cd4075_bang);
class_addfloat(cd4075_class, cd4075_float);
class_addmethod(cd4075_class, (t_method)cd4075_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4075_class, (t_method)cd4075_inlet3, gensym("inlet3"), A_FLOAT, 0);
}
/* end cd4075.c */
mrpeach/cmos/cd4008-help.pd 0000644 0001750 0001750 00000005425 11026462102 016045 0 ustar zmoelnig zmoelnig #N canvas 580 256 530 325 12;
#X obj 8 136 cd4008 4 bit full adder;
#X obj 8 33 tgl 15 0 empty empty Carry_In 17 7 0 10 -44926 -258699
-1 0 1;
#X obj 30 64 tgl 15 0 empty empty A1 17 7 0 10 -44926 -258699 -1 1
1;
#X obj 52 80 tgl 15 0 empty empty A2 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 75 96 tgl 15 0 empty empty A3 17 7 0 10 -44926 -258699 -1 1
1;
#X obj 97 111 tgl 15 0 empty empty A4 17 7 0 10 -44926 -258699 -1 1
1;
#X obj 119 63 tgl 15 0 empty empty B1 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 142 79 tgl 15 0 empty empty B2 17 7 0 10 -44926 -258699 -1 1
1;
#X obj 164 95 tgl 15 0 empty empty B3 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 187 110 tgl 15 0 empty empty B4 17 7 0 10 -44926 -258699 -1
1 1;
#X obj 8 174 tgl 15 0 empty empty S1 17 7 0 10 -258699 -241291 -1 1
1;
#X obj 52 174 tgl 15 0 empty empty S2 17 7 0 10 -258699 -241291 -1
1 1;
#X obj 97 174 tgl 15 0 empty empty S3 17 7 0 10 -258699 -241291 -1
1 1;
#X obj 142 174 tgl 15 0 empty empty S4 17 7 0 10 -258699 -241291 -1
0 1;
#X obj 187 190 tgl 15 0 empty empty Carry_Out 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 214 170 cd4008 4 bit full adder;
#X obj 236 98 tgl 15 0 empty empty A1 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 258 114 tgl 15 0 empty empty A2 17 7 0 10 -44926 -258699 -1
1 1;
#X obj 281 130 tgl 15 0 empty empty A3 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 303 145 tgl 15 0 empty empty A4 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 325 97 tgl 15 0 empty empty B1 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 348 113 tgl 15 0 empty empty B2 17 7 0 10 -44926 -258699 -1
1 1;
#X obj 370 129 tgl 15 0 empty empty B3 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 393 144 tgl 15 0 empty empty B4 17 7 0 10 -44926 -258699 -1
1 1;
#X obj 214 208 tgl 15 0 empty empty S1 17 7 0 10 -258699 -241291 -1
1 1;
#X obj 258 208 tgl 15 0 empty empty S2 17 7 0 10 -258699 -241291 -1
0 1;
#X obj 303 208 tgl 15 0 empty empty S3 17 7 0 10 -258699 -241291 -1
1 1;
#X obj 348 208 tgl 15 0 empty empty S4 17 7 0 10 -258699 -241291 -1
1 1;
#X obj 393 208 tgl 15 0 empty empty Carry_Out 17 7 0 10 -258699 -241291
-1 0 1;
#X text 87 9 cd4008 emulates the CMOS 4-bit full adder.;
#X text 194 279 20070315_MartinPeach;
#X connect 0 0 10 0;
#X connect 0 1 11 0;
#X connect 0 2 12 0;
#X connect 0 3 13 0;
#X connect 0 4 14 0;
#X connect 0 4 15 0;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
#X connect 3 0 0 2;
#X connect 4 0 0 3;
#X connect 5 0 0 4;
#X connect 6 0 0 5;
#X connect 7 0 0 6;
#X connect 8 0 0 7;
#X connect 9 0 0 8;
#X connect 15 0 24 0;
#X connect 15 1 25 0;
#X connect 15 2 26 0;
#X connect 15 3 27 0;
#X connect 15 4 28 0;
#X connect 16 0 15 1;
#X connect 17 0 15 2;
#X connect 18 0 15 3;
#X connect 19 0 15 4;
#X connect 20 0 15 5;
#X connect 21 0 15 6;
#X connect 22 0 15 7;
#X connect 23 0 15 8;
mrpeach/cmos/cd4071-help.pd 0000644 0001750 0001750 00000000671 11026462102 016043 0 ustar zmoelnig zmoelnig #N canvas 670 174 458 212 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 129 83 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X text 167 138 20070308_Martin_Peach;
#X text 18 47 cd4071 emulates 1/4 of the CMOS OR gate;
#X obj 86 107 cd4071;
#X connect 0 0 5 0;
#X connect 1 0 5 1;
#X connect 5 0 2 0;
mrpeach/cmos/cd4011-help.pd 0000644 0001750 0001750 00000000712 11026462102 016031 0 ustar zmoelnig zmoelnig #N canvas 670 174 490 244 12;
#X obj 86 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 169 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X text 210 170 20070315_Martin_Peach;
#X text 16 29 cd4011 emulates 1/4 of the CMOS two-input NAND gate;
#X obj 86 106 cd4011 nand;
#X connect 0 0 5 0;
#X connect 1 0 5 1;
#X connect 5 0 2 0;
mrpeach/cmos/cd4072-help.pd 0000644 0001750 0001750 00000001210 11026462102 016032 0 ustar zmoelnig zmoelnig #N canvas 670 174 470 224 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 121 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 0 1;
#X obj 157 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 193 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X text 210 170 20070312_Martin_Peach;
#X text 18 47 cd4072 emulates 1/2 of the CMOS quad OR gate;
#X obj 86 106 cd4072 quad or;
#X connect 0 0 7 0;
#X connect 1 0 7 1;
#X connect 3 0 7 2;
#X connect 4 0 7 3;
#X connect 7 0 2 0;
mrpeach/cmos/cd40193.c 0000644 0001750 0001750 00000017000 12430236316 015021 0 ustar zmoelnig zmoelnig /* cd40193.c MP 20070312 */
/* Emulate a cd40193b */
#include "m_pd.h"
typedef struct _cd40193
{
t_object x_obj;
t_outlet *x_QAOut;
t_outlet *x_QBOut;
t_outlet *x_QCOut;
t_outlet *x_QDOut;
t_outlet *x_CarryOut;
t_outlet *x_BorrowOut;
int x_countUp;
int x_countDown;
int x_dataA;
int x_dataB;
int x_dataC;
int x_dataD;
int x_load;
int x_clear;
int x_count;
t_inlet *x_CountDownIn;/* All inlets take one or zero as acceptable inputs. */
t_inlet *x_ClearIn;
t_inlet *x_LoadIn;
t_inlet *x_DataAIn;
t_inlet *x_DataBIn;
t_inlet *x_DataCIn;
t_inlet *x_DataDIn;
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd40193;
static t_class *cd40193_class;
void cd40193_setup(void);
static void *cd40193_new(t_symbol *s, int argc, t_atom *argv);
static void cd40193_free(t_cd40193 *x);
static void cd40193_bang(t_cd40193 *x);
static void cd40193_float(t_cd40193 *x, t_float f);
static void cd40193_clear(t_cd40193 *x, t_float f);
static void cd40193_load(t_cd40193 *x, t_float f);
static void cd40193_count_down(t_cd40193 *x, t_float f);
static void cd40193_data_A(t_cd40193 *x, t_float f);
static void cd40193_data_B(t_cd40193 *x, t_float f);
static void cd40193_data_C(t_cd40193 *x, t_float f);
static void cd40193_data_D(t_cd40193 *x, t_float f);
static void cd40193_update_outlets(t_cd40193 *x);
static void cd40193_float(t_cd40193 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, count up. */
if ((x->x_countUp == 0)&&(x->x_countDown == 1)&&(x->x_clear == 0)&&(x->x_load == 1))
{
x->x_countUp = 1;
x->x_count = (x->x_count + 1)%16;
cd40193_update_outlets(x);
}
}
else if (f == 0)
{
if ((x->x_countUp == 1) && (x->x_count == 15)) outlet_float(x->x_CarryOut, 0);
x->x_countUp = 0;
}
else post("cd40193 accepts bang, 1 or 0.");
}
static void cd40193_bang(t_cd40193 *x)
{
if ((x->x_countDown == 1)&&(x->x_clear == 0)&&(x->x_load == 1))
{
x->x_countUp = 1;
x->x_count = (x->x_count + 1)%16;
cd40193_update_outlets(x);
if (x->x_count == 15) outlet_float(x->x_CarryOut, 0);
}
}
static void cd40193_clear(t_cd40193 *x, t_float f)
{
if (f == 1)
{
if (x->x_clear == 0)
{
x->x_count = 0;
cd40193_update_outlets(x);
x->x_clear = 1;
}
}
else if (f == 0)
{
x->x_clear = 0;
if (x->x_load == 0)
{ /* the strange case of a low-going clear enabling an already low load */
x->x_count = x->x_dataA + 2*x->x_dataB + 4*x->x_dataC + 8*x->x_dataD;
cd40193_update_outlets(x);
}
}
else
{
post("cd40193 clear takes 1 or 0 only.");
return;
}
}
static void cd40193_load(t_cd40193 *x, t_float f)
{
if (f == 1)
{
x->x_load = 1;
}
else if (f == 0)
{
if (x->x_load == 1)
{
x->x_load = 0;
if (x->x_clear == 0)
{
x->x_count = x->x_dataA + 2*x->x_dataB + 4*x->x_dataC + 8*x->x_dataD;
cd40193_update_outlets(x);
}
}
}
else
{
post("cd40193 load takes 1 or 0 only.");
return;
}
}
static void cd40193_count_down(t_cd40193 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, count down. */
if (x->x_countDown == 0)
{
x->x_countDown = 1;
if((x->x_countUp == 1)&&(x->x_clear == 0)&&(x->x_load = 1))
{
x->x_count = (x->x_count - 1)%16;
cd40193_update_outlets(x);
}
}
}
else if (f == 0)
{
if ((x->x_countDown == 1) && (x->x_count == 0)) outlet_float(x->x_BorrowOut, 0);
x->x_countDown = 0;
}
else post("cd40193 count down accepts bang, 1 or 0.");
}
static void cd40193_data_A(t_cd40193 *x, t_float f)
{
if (f == 1) x->x_dataA = 1;
else if (f == 0) x->x_dataA = 0;
else
{
post("cd40193 data A takes 1 or 0 only.");
return;
}
}
static void cd40193_data_B(t_cd40193 *x, t_float f)
{
if (f == 1) x->x_dataB = 1;
else if (f == 0) x->x_dataB = 0;
else
{
post("cd40193 data B takes 1 or 0 only.");
return;
}
}
static void cd40193_data_C(t_cd40193 *x, t_float f)
{
if (f == 1) x->x_dataC = 1;
else if (f == 0) x->x_dataC = 0;
else
{
post("cd40193 data C takes 1 or 0 only.");
return;
}
}
static void cd40193_data_D(t_cd40193 *x, t_float f)
{
if (f == 1) x->x_dataD = 1;
else if (f == 0) x->x_dataD = 0;
else
{
post("cd40193 data D takes 1 or 0 only.");
return;
}
}
static void cd40193_update_outlets(t_cd40193 *x)
{
outlet_float(x->x_BorrowOut, 1);
outlet_float(x->x_CarryOut, 1);
outlet_float(x->x_QDOut, ((x->x_count & 8) != 0)?1:0);
outlet_float(x->x_QCOut, ((x->x_count & 4) != 0)?1:0);
outlet_float(x->x_QBOut, ((x->x_count & 2) != 0)?1:0);
outlet_float(x->x_QAOut, ((x->x_count & 1) != 0)?1:0);
}
static void cd40193_free(t_cd40193 *x)
{
return;
}
static void *cd40193_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd40193 *x;
x = (t_cd40193 *)pd_new(cd40193_class);
if (x == NULL) return (x);
x->x_QAOut = outlet_new((t_object *)x, &s_float);
x->x_QBOut = outlet_new((t_object *)x, &s_float);
x->x_QCOut = outlet_new((t_object *)x, &s_float);
x->x_QDOut = outlet_new((t_object *)x, &s_float);
x->x_CarryOut = outlet_new((t_object *)x, &s_float);
x->x_BorrowOut = outlet_new((t_object *)x, &s_float);
x->x_CountDownIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("countdown"));
x->x_ClearIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("clear"));
x->x_LoadIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("load"));
x->x_DataAIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dataA"));
x->x_DataBIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dataB"));
x->x_DataCIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dataC"));
x->x_DataDIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("dataD"));
return (x);
}
void cd40193_setup(void)
{
cd40193_class = class_new(gensym("cd40193"),
(t_newmethod)cd40193_new,
(t_method)cd40193_free,
sizeof(t_cd40193), 0, 0); /* no arguments */
class_addbang(cd40193_class, cd40193_bang);
class_addfloat(cd40193_class, cd40193_float);
class_addmethod(cd40193_class, (t_method)cd40193_count_down, gensym("countdown"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_load, gensym("load"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_clear, gensym("clear"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_data_A, gensym("dataA"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_data_B, gensym("dataB"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_data_C, gensym("dataC"), A_FLOAT, 0);
class_addmethod(cd40193_class, (t_method)cd40193_data_D, gensym("dataD"), A_FLOAT, 0);
}
/* end cd40193.c */
mrpeach/cmos/cd4013.c 0000644 0001750 0001750 00000012325 12430236316 014735 0 ustar zmoelnig zmoelnig /* cd4013.c MP 20070306 */
/* Emulate a cd4013b */
#include "m_pd.h"
typedef struct _cd4013
{
t_object x_obj;
int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */
t_outlet *x_Q;
t_outlet *x_notQ;
t_inlet *x_set;/* set takes one or zero as acceptable inputs. */
t_inlet *x_reset;/* reset takes one or zero as acceptable inputs. */
t_inlet *x_d;/* d takes one or zero as acceptable inputs. */
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4013;
#define SET_4013 1
#define CLOCK_4013 2
#define RESET_4013 4
#define D_4013 8
#define Q_4013 16
#define UPDATING_4013 32
#define CHANGED_4013 64
static t_class *cd4013_class;
void cd4013_setup(void);
static void *cd4013_new(t_symbol *s, int argc, t_atom *argv);
static void cd4013_free(t_cd4013 *x);
static void cd4013_bang(t_cd4013 *x);
static void cd4013_float(t_cd4013 *x, t_float f);
static void cd4013_set(t_cd4013 *x, t_float f);
static void cd4013_reset(t_cd4013 *x, t_float f);
static void cd4013_d(t_cd4013 *x, t_float f);
static void cd4013_update_outlets(t_cd4013 *x);
static void cd4013_printstate (t_cd4013 *x);
static void cd4013_float(t_cd4013 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, clock it. */
if ((x->x_state & CLOCK_4013) == 0) cd4013_bang(x);
x->x_state |= CLOCK_4013;
}
else if (f == 0) x->x_state &= ~CLOCK_4013;
else post("cd4013 accepts bang, 1 or 0.");
}
static void cd4013_printstate (t_cd4013 *x)
{
post ("SET %d RESET %d D %d Q %d", ((x->x_state & SET_4013) != 0)?1:0
, ((x->x_state & RESET_4013) != 0)?1:0
, ((x->x_state & D_4013) != 0)?1:0
, ((x->x_state & Q_4013) != 0)?1:0);
}
static void cd4013_bang(t_cd4013 *x)
{
if ((x->x_state & (SET_4013 | RESET_4013)) == 0)
{ /* if set is low and reset is low, clock forward */
if ((x->x_state & D_4013) != 0) x->x_state |= Q_4013;
else x->x_state &= ~Q_4013;
cd4013_update_outlets(x);
}
}
static void cd4013_set(t_cd4013 *x, t_float f)
{
if (f == 1)
{
x->x_state |= SET_4013; /* set = 1 */
}
else if (f == 0)
{
x->x_state &= ~SET_4013; /* set = 0 */
}
else
{
post("cd4013 set takes 1 or 0 only.");
return;
}
/* update outlets if not already doing that */
if ((x->x_state & UPDATING_4013) == 0)
{
cd4013_update_outlets(x);
}
else
{
x->x_state |= CHANGED_4013;
}
return;
}
static void cd4013_reset(t_cd4013 *x, t_float f)
{
if (f == 1)
{
x->x_state |= RESET_4013; /* reset = 1 */
}
else if (f == 0)
{
x->x_state &= ~RESET_4013; /* reset = 0 */
}
else
{
return;
}
/* update outlets if not already doing that */
if ((x->x_state & UPDATING_4013) == 0)
{
cd4013_update_outlets(x);
}
else
{
x->x_state |= CHANGED_4013;
}
return;
}
static void cd4013_d(t_cd4013 *x, t_float f)
{
if (f == 1)
{
x->x_state |= D_4013; /* d = 1 */
}
else if (f == 0)
{
x->x_state &= ~D_4013; /* d = 0 */
}
else post("cd4013 d takes 1 or 0 only.");
return;
}
static void cd4013_update_outlets(t_cd4013 *x)
{
/* cd4013_printstate (x); */
x->x_state |= UPDATING_4013;/* updating outlets */
reset:
if ((x->x_state & SET_4013) != 0) x->x_state |= Q_4013;
else if ((x->x_state & RESET_4013) != 0) x->x_state &= ~Q_4013;
x->x_state &= ~CHANGED_4013; /* prepare to flag any changes that occur during outlet_update */
outlet_float(x->x_notQ, ((x->x_state & Q_4013) == 0)?1:0);
/* we might get set or reset as a result of feedback from one of these outlets. */
if ((x->x_state & CHANGED_4013) != 0) goto reset;
outlet_float(x->x_Q, ((x->x_state & Q_4013) != 0)?1:0);
if ((x->x_state & CHANGED_4013) != 0) goto reset;
x->x_state &= ~UPDATING_4013;/* finished updating outlets */
}
static void cd4013_free(t_cd4013 *x)
{
return;
}
static void *cd4013_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4013 *x;
x = (t_cd4013 *)pd_new(cd4013_class);
if (x == NULL) return (x);
x->x_Q = outlet_new((t_object *)x, &s_float);
x->x_notQ = outlet_new((t_object *)x, &s_float);
x->x_set = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("set"));
x->x_reset = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("reset"));
x->x_d = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("d"));
return (x);
}
void cd4013_setup(void)
{
cd4013_class = class_new(gensym("cd4013"),
(t_newmethod)cd4013_new,
(t_method)cd4013_free,
sizeof(t_cd4013), 0, 0); /* no arguments */
class_addbang(cd4013_class, cd4013_bang);
class_addfloat(cd4013_class, cd4013_float);
class_addmethod(cd4013_class, (t_method)cd4013_reset, gensym("reset"), A_FLOAT, 0);
class_addmethod(cd4013_class, (t_method)cd4013_set, gensym("set"), A_FLOAT, 0);
class_addmethod(cd4013_class, (t_method)cd4013_d, gensym("d"), A_FLOAT, 0);
}
/* end cd4013.c */
mrpeach/cmos/cd4001.c 0000644 0001750 0001750 00000004111 12430236316 014724 0 ustar zmoelnig zmoelnig /* cd4001.c MP 20070312 */
/* Emulate a cd4001b */
#include "m_pd.h"
typedef struct _cd4001
{
t_object x_obj;
int x_in1;
int x_in2;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
} t_cd4001;
static t_class *cd4001_class;
void cd4001_setup(void);
static void *cd4001_new(t_symbol *s, int argc, t_atom *argv);
static void cd4001_free(t_cd4001 *x);
static void cd4001_bang(t_cd4001 *x);
static void cd4001_float(t_cd4001 *x, t_float f);
static void cd4001_inlet2(t_cd4001 *x, t_float f);
static void cd4001_update_outlets(t_cd4001 *x);
static void cd4001_float(t_cd4001 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4001 inlet 2 accepts 1 or 0.");
return;
}
cd4001_update_outlets(x);
}
static void cd4001_bang(t_cd4001 *x)
{
cd4001_update_outlets(x);
}
static void cd4001_inlet2(t_cd4001 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4001 inlet 2 accepts 1 or 0.");
return;
}
cd4001_update_outlets(x);
}
static void cd4001_update_outlets(t_cd4001 *x)
{ /* Double NOR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2) != 0)?0:1);
}
static void cd4001_free(t_cd4001 *x)
{
return;
}
static void *cd4001_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4001 *x;
x = (t_cd4001 *)pd_new(cd4001_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
return (x);
}
void cd4001_setup(void)
{
cd4001_class = class_new(gensym("cd4001"),
(t_newmethod)cd4001_new,
(t_method)cd4001_free,
sizeof(t_cd4001), 0, 0); /* no arguments */
class_addbang(cd4001_class, cd4001_bang);
class_addfloat(cd4001_class, cd4001_float);
class_addmethod(cd4001_class, (t_method)cd4001_inlet2, gensym("inlet2"), A_FLOAT, 0);
}
/* end cd4001.c */
mrpeach/cmos/cd4002-help.pd 0000644 0001750 0001750 00000001213 11026462102 016026 0 ustar zmoelnig zmoelnig #N canvas 670 174 490 244 12;
#X obj 86 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 111 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X text 210 170 20070315_Martin_Peach;
#X obj 86 106 cd4002 nor;
#X obj 136 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 161 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X text 16 29 cd4002 emulates 1/2 of the CMOS four-input NOR gate;
#X connect 0 0 4 0;
#X connect 1 0 4 1;
#X connect 4 0 2 0;
#X connect 5 0 4 2;
#X connect 6 0 4 3;
mrpeach/cmos/cd40193-help.pd 0000644 0001750 0001750 00000005632 11026462102 016132 0 ustar zmoelnig zmoelnig #N canvas 406 127 739 406 12;
#X obj 75 5 cd40193 up down counter;
#X obj 75 -53 tgl 15 1 empty empty up_clock 17 7 0 10 -44926 -258699
-1 1 1;
#X obj 100 -37 tgl 15 1 empty empty down_clock 17 7 0 10 -44926 -258699
-1 1 1;
#X obj 126 -88 tgl 15 1 empty empty clear 17 7 0 10 -44926 -258699
-1 0 1;
#X obj 151 -111 tgl 15 1 empty empty load 17 7 0 10 -44926 -258699
-1 1 1;
#X obj 177 -24 tgl 15 0 empty empty A 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 202 -24 tgl 15 0 empty empty B 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 228 -24 tgl 15 0 empty empty C 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 254 -24 tgl 15 0 empty empty D 17 7 0 10 -260818 -258699 -1
0 1;
#X obj 75 47 tgl 15 0 empty empty QA 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 110 47 tgl 15 0 empty empty QB 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 146 47 tgl 15 0 empty empty QC 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 182 47 tgl 15 0 empty empty QD 17 7 0 10 -24198 -258699 -1 1
1;
#X obj 218 29 tgl 15 0 empty empty Carry 17 7 0 10 -62784 -258699 -1
1 1;
#X obj 254 47 tgl 15 0 empty empty Borrow 17 7 0 10 -62784 -258699
-1 1 1;
#X obj 349 106 cd40193 up down counter;
#X obj 451 77 tgl 15 0 empty empty A 17 7 0 10 -260818 -258699 -1 0
1;
#X obj 476 77 tgl 15 0 empty empty B 17 7 0 10 -260818 -258699 -1 0
1;
#X obj 502 77 tgl 15 0 empty empty C 17 7 0 10 -260818 -258699 -1 0
1;
#X obj 528 77 tgl 15 0 empty empty D 17 7 0 10 -260818 -258699 -1 0
1;
#X obj 349 148 tgl 15 0 empty empty QA 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 384 148 tgl 15 0 empty empty QB 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 420 148 tgl 15 0 empty empty QC 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 456 148 tgl 15 0 empty empty QD 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 492 130 tgl 15 0 empty empty Carry 17 7 0 10 -62784 -258699
-1 1 1;
#X obj 528 148 tgl 15 0 empty empty Borrow 17 7 0 10 -62784 -258699
-1 1 1;
#X text 32 -155 cd40193 emulates the CMOS synchronous up/down counter
;
#X text 212 -113 0 loads data into counter;
#X text 197 -90 1 clears counter;
#X text 202 -65 0 to 1 transition on a clock counts only if the other
clock = 1 and clear = 0 and load = 1;
#X text 285 204 20070314_MartinPeach;
#X obj 9 -121 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
#X obj 9 -89 metro 100;
#X connect 0 0 9 0;
#X connect 0 1 10 0;
#X connect 0 2 11 0;
#X connect 0 3 12 0;
#X connect 0 4 13 0;
#X connect 0 4 15 0;
#X connect 0 5 14 0;
#X connect 0 5 15 1;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
#X connect 3 0 0 2;
#X connect 3 0 15 2;
#X connect 4 0 0 3;
#X connect 4 0 15 3;
#X connect 5 0 0 4;
#X connect 6 0 0 5;
#X connect 7 0 0 6;
#X connect 8 0 0 7;
#X connect 15 0 20 0;
#X connect 15 1 21 0;
#X connect 15 2 22 0;
#X connect 15 3 23 0;
#X connect 15 4 24 0;
#X connect 15 5 25 0;
#X connect 16 0 15 4;
#X connect 17 0 15 5;
#X connect 18 0 15 6;
#X connect 19 0 15 7;
#X connect 31 0 32 0;
#X connect 32 0 1 0;
mrpeach/cmos/cd4014.c 0000644 0001750 0001750 00000015734 12430236316 014745 0 ustar zmoelnig zmoelnig /* cd4014.c MP 20070315 */
/* Emulate a cd4014b */
#include "m_pd.h"
typedef struct _cd4014
{
t_object x_obj;
int x_P1;
int x_P2;
int x_P3;
int x_P4;
int x_P5;
int x_P6;
int x_P7;
int x_P8;
int x_SerialIn;
int x_Clk;
int x_Q;
int x_ParallelSerial;
t_outlet *x_outQ6;
t_outlet *x_outQ7;
t_outlet *x_outQ8;
t_inlet *x_inP1;/* extra inlets are 'live' like the first */
t_inlet *x_inP2;
t_inlet *x_inP3;
t_inlet *x_inP4;
t_inlet *x_inP5;
t_inlet *x_inP6;
t_inlet *x_inP7;
t_inlet *x_inP8;
t_inlet *x_inParallelSerial;
t_inlet *x_inSerial;
} t_cd4014;
static t_class *cd4014_class;
void cd4014_setup(void);
static void *cd4014_new(t_symbol *s, int argc, t_atom *argv);
static void cd4014_free(t_cd4014 *x);
static void cd4014_float(t_cd4014 *x, t_float f);
static void cd4014_bang(t_cd4014 *x);
static void cd4014_inP1(t_cd4014 *x, t_float f);
static void cd4014_inP2(t_cd4014 *x, t_float f);
static void cd4014_inP3(t_cd4014 *x, t_float f);
static void cd4014_inP4(t_cd4014 *x, t_float f);
static void cd4014_inP5(t_cd4014 *x, t_float f);
static void cd4014_inP6(t_cd4014 *x, t_float f);
static void cd4014_inP7(t_cd4014 *x, t_float f);
static void cd4014_inP8(t_cd4014 *x, t_float f);
static void cd4014_inParallelSerial(t_cd4014 *x, t_float f);
static void cd4014_inSerial(t_cd4014 *x, t_float f);
static void cd4014_update_outlets(t_cd4014 *x);
static void cd4014_float(t_cd4014 *x, t_float f)
{
if (f == 1)
{
if (x->x_Clk == 0)
{
x->x_Clk = 1;
cd4014_bang(x);
}
}
else if (f == 0) x->x_Clk = 0;
else
{
post("cd4014 Clock inlet accepts 1 or 0.");
return;
}
}
static void cd4014_bang(t_cd4014 *x)
{
if (x->x_ParallelSerial == 0)
{ /* shift left by one */
x->x_Q <<= 1;
x->x_Q |= x->x_SerialIn;
}
else
{ /* parallel load */
x->x_Q = 128*x->x_P8 + 64*x->x_P7 + 32*x->x_P6 + 16*x->x_P5 + 8*x->x_P4 + 4*x->x_P3 + 2*x->x_P2 + x->x_P1;
}
cd4014_update_outlets(x);
}
static void cd4014_inP1(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P1 = 1;
else if (f == 0) x->x_P1 = 0;
else
{
post("cd4014 inlet P1 accepts 1 or 0.");
return;
}
}
static void cd4014_inP2(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P2 = 2;
else if (f == 0) x->x_P2 = 0;
else
{
post("cd4014 inlet P2 accepts 1 or 0.");
return;
}
}
static void cd4014_inP3(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P3 = 1;
else if (f == 0) x->x_P3 = 0;
else
{
post("cd4014 inlet P3 accepts 1 or 0.");
return;
}
}
static void cd4014_inP4(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P4 = 1;
else if (f == 0) x->x_P4 = 0;
else
{
post("cd4014 inlet P4 accepts 1 or 0.");
return;
}
}
static void cd4014_inP5(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P5 = 1;
else if (f == 0) x->x_P5 = 0;
else
{
post("cd4014 inlet P5 accepts 1 or 0.");
return;
}
}
static void cd4014_inP6(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P6 = 1;
else if (f == 0) x->x_P6 = 0;
else
{
post("cd4014 inlet P6 accepts 1 or 0.");
return;
}
}
static void cd4014_inP7(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P7 = 1;
else if (f == 0) x->x_P7 = 0;
else
{
post("cd4014 inlet P7 accepts 1 or 0.");
return;
}
}
static void cd4014_inP8(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_P8 = 1;
else if (f == 0) x->x_P8 = 0;
else
{
post("cd4014 inlet P8 accepts 1 or 0.");
return;
}
}
static void cd4014_inParallelSerial(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_ParallelSerial = 1;
else if (f == 0) x->x_ParallelSerial = 0;
else
{
post("cd4014 inlet ParallelSerial accepts 1 or 0.");
return;
}
}
static void cd4014_inSerial(t_cd4014 *x, t_float f)
{
if (f == 1) x->x_SerialIn = 1;
else if (f == 0) x->x_SerialIn = 0;
else
{
post("cd4014 inlet Serial accepts 1 or 0.");
return;
}
}
static void cd4014_update_outlets(t_cd4014 *x)
{ /* Output Q8, Q7, Q6 */
outlet_float(x->x_outQ8, ((x->x_Q & 128) != 0)?1:0);
outlet_float(x->x_outQ7, ((x->x_Q & 64) != 0)?1:0);
outlet_float(x->x_outQ6, ((x->x_Q & 32) != 0)?1:0);
}
static void cd4014_free(t_cd4014 *x)
{
return;
}
static void *cd4014_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4014 *x;
x = (t_cd4014 *)pd_new(cd4014_class);
if (x == NULL) return (x);
x->x_outQ6 = outlet_new((t_object *)x, &s_float);
x->x_outQ7 = outlet_new((t_object *)x, &s_float);
x->x_outQ8 = outlet_new((t_object *)x, &s_float);
x->x_inP1 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P1"));
x->x_inP2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P2"));
x->x_inP3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P3"));
x->x_inP4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P4"));
x->x_inP5 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P5"));
x->x_inP6 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P6"));
x->x_inP7 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P7"));
x->x_inP8 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("P8"));
x->x_inParallelSerial = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ParallelSerial"));
x->x_inSerial = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("Serial"));
return (x);
}
void cd4014_setup(void)
{
cd4014_class = class_new(gensym("cd4014"),
(t_newmethod)cd4014_new,
(t_method)cd4014_free,
sizeof(t_cd4014), 0, 0); /* no arguments */
class_addfloat(cd4014_class, cd4014_float);
class_addbang(cd4014_class, cd4014_bang);
class_addmethod(cd4014_class, (t_method)cd4014_inP1, gensym("P1"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP2, gensym("P2"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP3, gensym("P3"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP4, gensym("P4"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP5, gensym("P5"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP6, gensym("P6"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP7, gensym("P7"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inP8, gensym("P8"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inParallelSerial, gensym("ParallelSerial"), A_FLOAT, 0);
class_addmethod(cd4014_class, (t_method)cd4014_inSerial, gensym("Serial"), A_FLOAT, 0);
}
/* end cd4014.c */
mrpeach/cmos/cd4015.c 0000644 0001750 0001750 00000006164 12430236316 014743 0 ustar zmoelnig zmoelnig /* cd4015.c MP 20070315 */
/* Emulate a cd4015b */
#include "m_pd.h"
typedef struct _cd4015
{
t_object x_obj;
int x_D;
int x_R;
int x_Clk;
int x_Q;
t_outlet *x_outQ1;
t_outlet *x_outQ2;
t_outlet *x_outQ3;
t_outlet *x_outQ4;
t_inlet *x_inD;/* extra inlets are 'live' like the first */
t_inlet *x_inR;
} t_cd4015;
static t_class *cd4015_class;
void cd4015_setup(void);
static void *cd4015_new(t_symbol *s, int argc, t_atom *argv);
static void cd4015_free(t_cd4015 *x);
static void cd4015_float(t_cd4015 *x, t_float f);
static void cd4015_bang(t_cd4015 *x);
static void cd4015_inD(t_cd4015 *x, t_float f);
static void cd4015_inR(t_cd4015 *x, t_float f);
static void cd4015_update_outlets(t_cd4015 *x);
static void cd4015_float(t_cd4015 *x, t_float f)
{
if (f == 1)
{
if (x->x_Clk == 0)
{
x->x_Clk = 1;
cd4015_bang(x);
}
}
else if (f == 0) x->x_Clk = 0;
else
{
post("cd4015 Clock inlet accepts 1 or 0.");
return;
}
}
static void cd4015_bang(t_cd4015 *x)
{
if (x->x_R == 0)
{ /* shift left by one */
x->x_Q <<= 1;
x->x_Q |= x->x_D;
cd4015_update_outlets(x);
}
}
static void cd4015_inD(t_cd4015 *x, t_float f)
{
if (f == 1) x->x_D = 1;
else if (f == 0) x->x_D = 0;
else
{
post("cd4015 D inlet accepts 1 or 0.");
return;
}
}
static void cd4015_inR(t_cd4015 *x, t_float f)
{
if (f == 1)
{
x->x_R = 1;
x->x_Q = 0;
cd4015_update_outlets(x);
}
else if (f == 0) x->x_R = 0;
else
{
post("cd4015 R inlet accepts 1 or 0.");
return;
}
}
static void cd4015_update_outlets(t_cd4015 *x)
{
outlet_float(x->x_outQ4, ((x->x_Q & 8) != 0)?1:0);
outlet_float(x->x_outQ3, ((x->x_Q & 4) != 0)?1:0);
outlet_float(x->x_outQ2, ((x->x_Q & 2) != 0)?1:0);
outlet_float(x->x_outQ1, ((x->x_Q & 1) != 0)?1:0);
}
static void cd4015_free(t_cd4015 *x)
{
return;
}
static void *cd4015_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4015 *x;
x = (t_cd4015 *)pd_new(cd4015_class);
if (x == NULL) return (x);
x->x_outQ1 = outlet_new((t_object *)x, &s_float);
x->x_outQ2 = outlet_new((t_object *)x, &s_float);
x->x_outQ3 = outlet_new((t_object *)x, &s_float);
x->x_outQ4 = outlet_new((t_object *)x, &s_float);
x->x_inD = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("D"));
x->x_inR = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("R"));
return (x);
}
void cd4015_setup(void)
{
cd4015_class = class_new(gensym("cd4015"),
(t_newmethod)cd4015_new,
(t_method)cd4015_free,
sizeof(t_cd4015), 0, 0); /* no arguments */
class_addfloat(cd4015_class, cd4015_float);
class_addbang(cd4015_class, cd4015_bang);
class_addmethod(cd4015_class, (t_method)cd4015_inD, gensym("D"), A_FLOAT, 0);
class_addmethod(cd4015_class, (t_method)cd4015_inR, gensym("R"), A_FLOAT, 0);
}
/* end cd4015.c */
mrpeach/cmos/cd4024.c 0000644 0001750 0001750 00000007400 12430236316 014735 0 ustar zmoelnig zmoelnig /* cd4024.c MP 20070319 */
/* Emulate a cd4024b */
#include "m_pd.h"
typedef struct _cd4024
{
t_object x_obj;
int x_reset;
int x_clock;
int x_count;
int x_updating;
t_outlet *x_Q1;
t_outlet *x_Q2;
t_outlet *x_Q3;
t_outlet *x_Q4;
t_outlet *x_Q5;
t_outlet *x_Q6;
t_outlet *x_Q7;
t_inlet *x_resetIn;/* reset */
/* The main inlet (clcok) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4024;
static t_class *cd4024_class;
void cd4024_setup(void);
static void *cd4024_new(t_symbol *s, int argc, t_atom *argv);
static void cd4024_free(t_cd4024 *x);
static void cd4024_bang(t_cd4024 *x);
static void cd4024_float(t_cd4024 *x, t_float f);
static void cd4024_reset(t_cd4024 *x, t_float f);
static void cd4024_update_outlets(t_cd4024 *x);
static void cd4024_float(t_cd4024 *x, t_float f)
{
if (f == 0)
{ /* if clock is low and was high, clock it. */
if (x->x_clock == 1)
{
x->x_clock = 0;
cd4024_bang(x);
}
}
else if (f == 1) x->x_clock = 1;
else post("cd4024 clock accepts bang, 1 or 0.");
}
static void cd4024_bang(t_cd4024 *x)
{
if (x->x_reset == 0)
{ /* if reset is low, clock forward */
x->x_count = (x->x_count + 1)%128;
cd4024_update_outlets(x);
}
}
static void cd4024_reset(t_cd4024 *x, t_float f)
{
if (f == 1)
{
x->x_count = 0;
x->x_reset = 1;
if (x->x_updating != 0) x->x_updating |= 2;
else cd4024_update_outlets(x);
}
else if (f == 0) x->x_reset = 0;
}
static void cd4024_update_outlets(t_cd4024 *x)
{
reset:
x->x_updating = 1;/* updating outlets */
outlet_float(x->x_Q7, ((x->x_count & 64) != 0)?1:0);
/* we might get reset as a result of feedback from one of these outlets. */
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q6, ((x->x_count & 32) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q5, ((x->x_count & 16) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q4, ((x->x_count & 8) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q3, ((x->x_count & 4) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q2, ((x->x_count & 2) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
outlet_float(x->x_Q1, ((x->x_count & 1) != 0)?1:0);
if ((x->x_updating & 2) != 0) goto reset;
x->x_updating = 0; /* finished updating outlets */
}
static void cd4024_free(t_cd4024 *x)
{
return;
}
static void *cd4024_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4024 *x;
x = (t_cd4024 *)pd_new(cd4024_class);
if (x == NULL) return (x);
x->x_Q1 = outlet_new((t_object *)x, &s_float);
x->x_Q2 = outlet_new((t_object *)x, &s_float);
x->x_Q3 = outlet_new((t_object *)x, &s_float);
x->x_Q4 = outlet_new((t_object *)x, &s_float);
x->x_Q5 = outlet_new((t_object *)x, &s_float);
x->x_Q6 = outlet_new((t_object *)x, &s_float);
x->x_Q7 = outlet_new((t_object *)x, &s_float);
x->x_resetIn = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("reset"));
return (x);
}
void cd4024_setup(void)
{
cd4024_class = class_new(gensym("cd4024"),
(t_newmethod)cd4024_new,
(t_method)cd4024_free,
sizeof(t_cd4024), 0, 0); /* no arguments */
class_addbang(cd4024_class, cd4024_bang);
class_addfloat(cd4024_class, cd4024_float);
class_addmethod(cd4024_class, (t_method)cd4024_reset, gensym("reset"), A_FLOAT, 0);
}
/* end cd4024.c */
mrpeach/cmos/cd4071.c 0000644 0001750 0001750 00000004101 12430236316 014732 0 ustar zmoelnig zmoelnig /* cd4071.c MP 20070308 */
/* Emulate a cd4071b */
#include "m_pd.h"
typedef struct _cd4071
{
t_object x_obj;
int x_in1;
int x_in2;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
} t_cd4071;
static t_class *cd4071_class;
void cd4071_setup(void);
static void *cd4071_new(t_symbol *s, int argc, t_atom *argv);
static void cd4071_free(t_cd4071 *x);
static void cd4071_bang(t_cd4071 *x);
static void cd4071_float(t_cd4071 *x, t_float f);
static void cd4071_inlet2(t_cd4071 *x, t_float f);
static void cd4071_update_outlets(t_cd4071 *x);
static void cd4071_float(t_cd4071 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4071 inlet 2 accepts 1 or 0.");
return;
}
cd4071_update_outlets(x);
}
static void cd4071_bang(t_cd4071 *x)
{
cd4071_update_outlets(x);
}
static void cd4071_inlet2(t_cd4071 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4071 inlet 2 accepts 1 or 0.");
return;
}
cd4071_update_outlets(x);
}
static void cd4071_update_outlets(t_cd4071 *x)
{ /* OR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2) != 0)?1:0);
}
static void cd4071_free(t_cd4071 *x)
{
return;
}
static void *cd4071_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4071 *x;
x = (t_cd4071 *)pd_new(cd4071_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
return (x);
}
void cd4071_setup(void)
{
cd4071_class = class_new(gensym("cd4071"),
(t_newmethod)cd4071_new,
(t_method)cd4071_free,
sizeof(t_cd4071), 0, 0); /* no arguments */
class_addbang(cd4071_class, cd4071_bang);
class_addfloat(cd4071_class, cd4071_float);
class_addmethod(cd4071_class, (t_method)cd4071_inlet2, gensym("inlet2"), A_FLOAT, 0);
}
/* end cd4071.c */
mrpeach/cmos/cd4076.c 0000644 0001750 0001750 00000017642 12430236316 014755 0 ustar zmoelnig zmoelnig /* cd4076.c MP 20070312 */
/* Emulate a cd4076b */
#include "m_pd.h"
typedef struct _cd4076
{
t_object x_obj;
t_outlet *x_output_A;
t_outlet *x_output_B;
t_outlet *x_output_C;
t_outlet *x_output_D;
int x_clock;
int x_QA;
int x_QB;
int x_QC;
int x_QD;
int x_inA;
int x_inB;
int x_inC;
int x_inD;
int x_InDis1;
int x_InDis2;
int x_OutDis1;
int x_OutDis2;
int x_Clear;
t_inlet *x_clear;/* clear takes one or zero as acceptable inputs. */
t_inlet *x_input_disable_1;/* input_disable_1 takes one or zero as acceptable inputs. */
t_inlet *x_input_disable_2;/* input_disable_2 takes one or zero as acceptable inputs. */
t_inlet *x_output_disable_1;/* output_disable_1 takes one or zero as acceptable inputs. */
t_inlet *x_output_disable_2;/* output_disable_2 takes one or zero as acceptable inputs. */
t_inlet *x_input_A;/* input_A takes one or zero as acceptable inputs. */
t_inlet *x_input_B;/* input_B takes one or zero as acceptable inputs. */
t_inlet *x_input_C;/* input_C takes one or zero as acceptable inputs. */
t_inlet *x_input_D;/* input_D takes one or zero as acceptable inputs. */
/* The main inlet (clock) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4076;
static t_class *cd4076_class;
void cd4076_setup(void);
static void *cd4076_new(t_symbol *s, int argc, t_atom *argv);
static void cd4076_free(t_cd4076 *x);
static void cd4076_bang(t_cd4076 *x);
static void cd4076_float(t_cd4076 *x, t_float f);
static void cd4076_clear(t_cd4076 *x, t_float f);
static void cd4076_input_disable_1(t_cd4076 *x, t_float f);
static void cd4076_input_disable_2(t_cd4076 *x, t_float f);
static void cd4076_output_disable_1(t_cd4076 *x, t_float f);
static void cd4076_output_disable_2(t_cd4076 *x, t_float f);
static void cd4076_input_a(t_cd4076 *x, t_float f);
static void cd4076_input_b(t_cd4076 *x, t_float f);
static void cd4076_input_c(t_cd4076 *x, t_float f);
static void cd4076_input_d(t_cd4076 *x, t_float f);
static void cd4076_update_outlets(t_cd4076 *x);
static void cd4076_float(t_cd4076 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, clock it. */
if ((x->x_clock) == 0) cd4076_bang(x);
x->x_clock = 1;
}
else if (f == 0) x->x_clock = 0;
else post("cd4076 accepts bang, 1 or 0.");
}
static void cd4076_bang(t_cd4076 *x)
{
if ((x->x_InDis1 + x->x_InDis2 + x->x_Clear) == 0)
{
x->x_QA = x->x_inA;
x->x_QB = x->x_inB;
x->x_QC = x->x_inC;
x->x_QD = x->x_inD;
}
cd4076_update_outlets(x);
}
static void cd4076_clear(t_cd4076 *x, t_float f)
{
if (f == 1)
{
x->x_Clear = 1;
x->x_QA = 0;
x->x_QB = 0;
x->x_QC = 0;
x->x_QD = 0;
cd4076_update_outlets(x);
}
else if (f == 0)
{
x->x_Clear = 0;
}
else
{
post("cd4076 clear takes 1 or 0 only.");
return;
}
}
static void cd4076_input_disable_1(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_InDis1 = 1;
else if (f == 0) x->x_InDis1 = 0;
else
{
post("cd4076 input disable 1 takes 1 or 0 only.");
return;
}
}
static void cd4076_input_disable_2(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_InDis2 = 1;
else if (f == 0) x->x_InDis2 = 0;
else
{
post("cd4076 input disable 2 takes 1 or 0 only.");
return;
}
}
static void cd4076_output_disable_1(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_OutDis1 = 1;
else if (f == 0)
{
x->x_OutDis1 = 0;
cd4076_update_outlets(x);
}
else
{
post("cd4076 output disable 1 takes 1 or 0 only.");
return;
}
}
static void cd4076_output_disable_2(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_OutDis2 = 1;
else if (f == 0)
{
x->x_OutDis2 = 0;
cd4076_update_outlets(x);
}
else
{
post("cd4076 output disable 2 takes 1 or 0 only.");
return;
}
}
static void cd4076_input_a(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_inA = 1;
else if (f == 0) x->x_inA = 0;
else
{
post("cd4076 input A takes 1 or 0 only.");
return;
}
}
static void cd4076_input_b(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_inB = 1;
else if (f == 0) x->x_inB = 0;
else
{
post("cd4076 input B takes 1 or 0 only.");
return;
}
}
static void cd4076_input_c(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_inC = 1;
else if (f == 0) x->x_inC = 0;
else
{
post("cd4076 input C takes 1 or 0 only.");
return;
}
}
static void cd4076_input_d(t_cd4076 *x, t_float f)
{
if (f == 1) x->x_inD = 1;
else if (f == 0) x->x_inD = 0;
else
{
post("cd4076 input D takes 1 or 0 only.");
return;
}
}
static void cd4076_update_outlets(t_cd4076 *x)
{
if (x->x_OutDis1 + x->x_OutDis2 == 0)
{
outlet_float(x->x_output_D, ((x->x_QD) == 1)?1:0);
outlet_float(x->x_output_C, ((x->x_QC) == 1)?1:0);
outlet_float(x->x_output_B, ((x->x_QB) == 1)?1:0);
outlet_float(x->x_output_A, ((x->x_QA) == 1)?1:0);
}
}
static void cd4076_free(t_cd4076 *x)
{
return;
}
static void *cd4076_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4076 *x;
x = (t_cd4076 *)pd_new(cd4076_class);
if (x == NULL) return (x);
x->x_output_A = outlet_new((t_object *)x, &s_float);
x->x_output_B = outlet_new((t_object *)x, &s_float);
x->x_output_C = outlet_new((t_object *)x, &s_float);
x->x_output_D = outlet_new((t_object *)x, &s_float);
x->x_clear = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("clear"));
x->x_input_disable_1 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputdisable1"));
x->x_input_disable_2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputdisable2"));
x->x_output_disable_1 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("outputdisable1"));
x->x_output_disable_2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("outputdisable2"));
x->x_input_A = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputA"));
x->x_input_B = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputB"));
x->x_input_C = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputC"));
x->x_input_D = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inputD"));
return (x);
}
void cd4076_setup(void)
{
cd4076_class = class_new(gensym("cd4076"),
(t_newmethod)cd4076_new,
(t_method)cd4076_free,
sizeof(t_cd4076), 0, 0); /* no arguments */
class_addbang(cd4076_class, cd4076_bang);
class_addfloat(cd4076_class, cd4076_float);
class_addmethod(cd4076_class, (t_method)cd4076_clear, gensym("clear"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_disable_1, gensym("inputdisable1"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_disable_2, gensym("inputdisable2"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_output_disable_1, gensym("outputdisable1"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_output_disable_2, gensym("outputdisable2"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_a, gensym("inputA"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_b, gensym("inputB"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_c, gensym("inputC"), A_FLOAT, 0);
class_addmethod(cd4076_class, (t_method)cd4076_input_d, gensym("inputD"), A_FLOAT, 0);
}
/* end cd4076.c */
mrpeach/cmos/cd4024-help.pd 0000644 0001750 0001750 00000002027 11026462102 016036 0 ustar zmoelnig zmoelnig #N canvas 627 296 564 304 12;
#X obj 138 127 cd4024 7-stage counter;
#X obj 138 103 tgl 15 0 empty empty Clk 17 7 0 10 -44926 -258699 -1
1 1;
#X obj 309 103 tgl 15 0 empty empty Reset 17 7 0 10 -44926 -258699
-1 0 1;
#X obj 138 174 tgl 15 0 empty empty Q1 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 170 174 tgl 15 0 empty empty Q2 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 202 174 tgl 15 0 empty empty Q3 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 234 174 tgl 15 0 empty empty Q4 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 267 174 tgl 15 0 empty empty Q5 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 300 174 tgl 15 0 empty empty Q6 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 334 174 tgl 15 0 empty empty Q7 17 7 0 10 -24198 -258699 -1
0 1;
#X text 15 16 cd4024 emulates the CMOS 7-stage ripple carry binary
counter;
#X text 242 250 20070319_MartinPeach;
#X connect 0 0 3 0;
#X connect 0 1 4 0;
#X connect 0 2 5 0;
#X connect 0 3 6 0;
#X connect 0 4 7 0;
#X connect 0 5 8 0;
#X connect 0 6 9 0;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
mrpeach/cmos/cd4023.c 0000644 0001750 0001750 00000005206 12430236316 014736 0 ustar zmoelnig zmoelnig /* cd4023.c MP 20070312 */
/* Emulate a cd4023b */
#include "m_pd.h"
typedef struct _cd4023
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
} t_cd4023;
static t_class *cd4023_class;
void cd4023_setup(void);
static void *cd4023_new(t_symbol *s, int argc, t_atom *argv);
static void cd4023_free(t_cd4023 *x);
static void cd4023_bang(t_cd4023 *x);
static void cd4023_float(t_cd4023 *x, t_float f);
static void cd4023_inlet2(t_cd4023 *x, t_float f);
static void cd4023_inlet3(t_cd4023 *x, t_float f);
static void cd4023_update_outlets(t_cd4023 *x);
static void cd4023_float(t_cd4023 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4023 inlet 2 accepts 1 or 0.");
return;
}
cd4023_update_outlets(x);
}
static void cd4023_bang(t_cd4023 *x)
{
cd4023_update_outlets(x);
}
static void cd4023_inlet2(t_cd4023 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4023 inlet 2 accepts 1 or 0.");
return;
}
cd4023_update_outlets(x);
}
static void cd4023_inlet3(t_cd4023 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4023 inlet 3 accepts 1 or 0.");
return;
}
cd4023_update_outlets(x);
}
static void cd4023_update_outlets(t_cd4023 *x)
{ /* Triple NAND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3) == 3)?0:1);
}
static void cd4023_free(t_cd4023 *x)
{
return;
}
static void *cd4023_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4023 *x;
x = (t_cd4023 *)pd_new(cd4023_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
return (x);
}
void cd4023_setup(void)
{
cd4023_class = class_new(gensym("cd4023"),
(t_newmethod)cd4023_new,
(t_method)cd4023_free,
sizeof(t_cd4023), 0, 0); /* no arguments */
class_addbang(cd4023_class, cd4023_bang);
class_addfloat(cd4023_class, cd4023_float);
class_addmethod(cd4023_class, (t_method)cd4023_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4023_class, (t_method)cd4023_inlet3, gensym("inlet3"), A_FLOAT, 0);
}
/* end cd4023.c */
mrpeach/cmos/cd4012.c 0000644 0001750 0001750 00000006162 12430236316 014736 0 ustar zmoelnig zmoelnig /* cd4012.c MP 20070315 */
/* Emulate a cd4012b */
#include "m_pd.h"
typedef struct _cd4012
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
int x_in4;
t_outlet *x_out;
t_inlet *x_inlet2;/* extra inlets are 'live' like the first */
t_inlet *x_inlet3;
t_inlet *x_inlet4;
} t_cd4012;
static t_class *cd4012_class;
void cd4012_setup(void);
static void *cd4012_new(t_symbol *s, int argc, t_atom *argv);
static void cd4012_free(t_cd4012 *x);
static void cd4012_bang(t_cd4012 *x);
static void cd4012_float(t_cd4012 *x, t_float f);
static void cd4012_inlet2(t_cd4012 *x, t_float f);
static void cd4012_inlet3(t_cd4012 *x, t_float f);
static void cd4012_inlet4(t_cd4012 *x, t_float f);
static void cd4012_update_outlets(t_cd4012 *x);
static void cd4012_float(t_cd4012 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4012 inlet 2 accepts 1 or 0.");
return;
}
cd4012_update_outlets(x);
}
static void cd4012_bang(t_cd4012 *x)
{
cd4012_update_outlets(x);
}
static void cd4012_inlet2(t_cd4012 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4012 inlet 2 accepts 1 or 0.");
return;
}
cd4012_update_outlets(x);
}
static void cd4012_inlet3(t_cd4012 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4012 inlet 3 accepts 1 or 0.");
return;
}
cd4012_update_outlets(x);
}
static void cd4012_inlet4(t_cd4012 *x, t_float f)
{
if (f == 1) x->x_in4 = 1;
else if (f == 0) x->x_in4 = 0;
else
{
post("cd4012 inlet 4 accepts 1 or 0.");
return;
}
cd4012_update_outlets(x);
}
static void cd4012_update_outlets(t_cd4012 *x)
{ /* Quadruple NAND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3 + x->x_in4) == 4)?0:1);
}
static void cd4012_free(t_cd4012 *x)
{
return;
}
static void *cd4012_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4012 *x;
x = (t_cd4012 *)pd_new(cd4012_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
x->x_inlet4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet4"));
return (x);
}
void cd4012_setup(void)
{
cd4012_class = class_new(gensym("cd4012"),
(t_newmethod)cd4012_new,
(t_method)cd4012_free,
sizeof(t_cd4012), 0, 0); /* no arguments */
class_addbang(cd4012_class, cd4012_bang);
class_addfloat(cd4012_class, cd4012_float);
class_addmethod(cd4012_class, (t_method)cd4012_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4012_class, (t_method)cd4012_inlet3, gensym("inlet3"), A_FLOAT, 0);
class_addmethod(cd4012_class, (t_method)cd4012_inlet4, gensym("inlet4"), A_FLOAT, 0);
}
/* end cd4012.c */
mrpeach/cmos/cd4000-help.pd 0000644 0001750 0001750 00000001135 11026462102 016027 0 ustar zmoelnig zmoelnig #N canvas 670 174 482 236 12;
#X obj 86 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 151 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 217 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 106 cd4000 triple nor;
#X text 16 29 cd4000 emulates 1/2 of the CMOS three-input NOR gate
;
#X text 210 170 20070315_Martin_Peach;
#X text 170 48 (inverter not included);
#X connect 0 0 4 0;
#X connect 1 0 4 1;
#X connect 3 0 4 2;
#X connect 4 0 2 0;
mrpeach/cmos/cd4025-help.pd 0000644 0001750 0001750 00000001055 11026462102 016037 0 ustar zmoelnig zmoelnig #N canvas 670 174 478 232 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 151 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 217 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X text 210 170 20070319_Martin_Peach;
#X text 18 47 cd4025 emulates 1/3 of the CMOS triple NOR gate;
#X obj 86 106 cd4025 triple nor;
#X connect 0 0 6 0;
#X connect 1 0 6 1;
#X connect 3 0 6 2;
#X connect 6 0 2 0;
mrpeach/cmos/cd4017.c 0000644 0001750 0001750 00000012347 12430236316 014745 0 ustar zmoelnig zmoelnig /* cd4017.c MP 20070305 */
/* Emulate a cd4017b */
#include "m_pd.h"
typedef struct _cd4017
{
t_object x_obj;
int x_state;/* clock_inhibit value in bit 0, clock level in bit 1, reset level in bit 2 */
int x_count;
t_outlet *x_0;
t_outlet *x_1;
t_outlet *x_2;
t_outlet *x_3;
t_outlet *x_4;
t_outlet *x_5;
t_outlet *x_6;
t_outlet *x_7;
t_outlet *x_8;
t_outlet *x_9;
t_outlet *x_carry_out;/* Outputs 1 when any of outlets 0-3 is one */
t_inlet *x_clock_inhibit;/* clock_inhibit takes one or zero as acceptable inputs. 1 inhibits the clock. */
t_inlet *x_reset;/* reset */
/* The main inlet (clcok) should accept a bang or a one as valid clocks. */
/* If a one is received, it must be followed by a zero before the clock will work again. */
} t_cd4017;
static t_class *cd4017_class;
void cd4017_setup(void);
static void *cd4017_new(t_symbol *s, int argc, t_atom *argv);
static void cd4017_free(t_cd4017 *x);
static void cd4017_bang(t_cd4017 *x);
static void cd4017_float(t_cd4017 *x, t_float f);
static void cd4017_clock_inhibit(t_cd4017 *x, t_float f);
static void cd4017_reset(t_cd4017 *x, t_float f);
static void cd4017_update_outlets(t_cd4017 *x);
static void cd4017_float(t_cd4017 *x, t_float f)
{
if (f == 1)
{ /* if clock is high and was low, clock it. */
if ((x->x_state & 2) == 0) cd4017_bang(x);
x->x_state |= 2;
}
else if (f == 0) x->x_state &= ~2;
else post("cd4017 accepts bang, 1 or 0.");
}
static void cd4017_bang(t_cd4017 *x)
{
if ((x->x_state & 5) == 0)
{ /* if clock inhibit is low and reset is low, clock forward */
x->x_count = ((x->x_count + 1)%10);
cd4017_update_outlets(x);
}
}
static void cd4017_clock_inhibit(t_cd4017 *x, t_float f)
{
if (f == 1) x->x_state |= 1; /* clock inhibited */
else if (f == 0) x->x_state &= ~1; /* clock uninhibited */
else post("cd4017 clock inhibit takes 1 or 0 only.");
return;
}
static void cd4017_reset(t_cd4017 *x, t_float f)
{
if (f == 1)
{
x->x_count = 0;
x->x_state |= 4; /* reset */
if ((x->x_state & 8) == 0) /* don't reenter any update_oulets in progress */
{
cd4017_update_outlets(x);
}
else x->x_state |= 16; /* reset during outlet_update */
}
else if (f == 0) x->x_state &= ~4; /* no reset */
}
static void cd4017_update_outlets(t_cd4017 *x)
{
x->x_state |= 8;/* updating outlets */
reset:
x->x_state &= ~16; /* clear reset during outlet_update */
outlet_float(x->x_0, (x->x_count == 0)?1:0);
/* we might get reset as a result of feedback from one of these outlets. */
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_1, (x->x_count == 1)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_2, (x->x_count == 2)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_3, (x->x_count == 3)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_4, (x->x_count == 4)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_5, (x->x_count == 5)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_6, (x->x_count == 6)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_7, (x->x_count == 7)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_8, (x->x_count == 8)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_9, (x->x_count == 9)?1:0);
if ((x->x_state & 16) != 0) goto reset;
outlet_float(x->x_carry_out, (x->x_count < 5)?1:0);
if ((x->x_state & 16) != 0) goto reset;
x->x_state &= ~8;/* finished updating outlets */
}
static void cd4017_free(t_cd4017 *x)
{
return;
}
static void *cd4017_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4017 *x;
x = (t_cd4017 *)pd_new(cd4017_class);
if (x == NULL) return (x);
x->x_0 = outlet_new((t_object *)x, &s_float);
x->x_1 = outlet_new((t_object *)x, &s_float);
x->x_2 = outlet_new((t_object *)x, &s_float);
x->x_3 = outlet_new((t_object *)x, &s_float);
x->x_4 = outlet_new((t_object *)x, &s_float);
x->x_5 = outlet_new((t_object *)x, &s_float);
x->x_6 = outlet_new((t_object *)x, &s_float);
x->x_7 = outlet_new((t_object *)x, &s_float);
x->x_8 = outlet_new((t_object *)x, &s_float);
x->x_9 = outlet_new((t_object *)x, &s_float);
x->x_carry_out = outlet_new((t_object *)x, &s_float);
x->x_clock_inhibit = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("clock_inhibit"));
x->x_reset = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("reset"));
return (x);
}
void cd4017_setup(void)
{
cd4017_class = class_new(gensym("cd4017"),
(t_newmethod)cd4017_new,
(t_method)cd4017_free,
sizeof(t_cd4017), 0, 0); /* no arguments */
class_addbang(cd4017_class, cd4017_bang);
class_addfloat(cd4017_class, cd4017_float);
class_addmethod(cd4017_class, (t_method)cd4017_reset, gensym("reset"), A_FLOAT, 0);
class_addmethod(cd4017_class, (t_method)cd4017_clock_inhibit, gensym("clock_inhibit"), A_FLOAT, 0);
}
/* end cd4017.c */
mrpeach/cmos/Makefile 0000644 0001750 0001750 00000041477 12571126767 015363 0 ustar zmoelnig zmoelnig ## Pd library template version 1.0.14
# For instructions on how to use this template, see:
# http://puredata.info/docs/developer/MakefileTemplate
LIBRARY_NAME = cmos
# add your .c source files, one object per file, to the SOURCES
# variable, help files will be included automatically, and for GUI
# objects, the matching .tcl file too
SOURCES = \
cd4000.c cd4008.c cd4013.c cd4017.c cd4024.c cd4070.c cd4073.c \
cd4081.c cd4516.c cd4001.c cd4011.c cd4014.c cd40193.c cd4025.c \
cd4071.c cd4075.c cd4082.c cd4002.c cd4012.c cd4015.c cd4023.c \
cd4027.c cd4072.c cd4076.c cd4094.c
# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
# be included automatically
PDOBJECTS =
# example patches and related files, in the 'examples' subfolder
EXAMPLES =
# manuals and related files, in the 'manual' subfolder
MANUAL =
# if you want to include any other files in the source and binary tarballs,
# list them here. This can be anything from header files, test patches,
# documentation, etc. README.txt and LICENSE.txt are required and therefore
# automatically included
EXTRA_DIST =
# unit tests and related files here, in the 'unittests' subfolder
UNITTESTS =
#------------------------------------------------------------------------------#
#
# things you might need to edit if you are using other C libraries
#
#------------------------------------------------------------------------------#
ALL_CFLAGS = -I"$(PD_INCLUDE)"
ALL_LDFLAGS =
SHARED_LDFLAGS =
ALL_LIBS =
#------------------------------------------------------------------------------#
#
# you shouldn't need to edit anything below here, if we did it right :)
#
#------------------------------------------------------------------------------#
# these can be set from outside without (usually) breaking the build
CFLAGS = -Wall -W -g
LDFLAGS =
LIBS =
# get library version from meta file
LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd)
ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"'
PD_INCLUDE = $(PD_PATH)/include/pd
# where to install the library, overridden below depending on platform
prefix = /usr/local
libdir = $(prefix)/lib
pkglibdir = $(libdir)/pd-externals
objectsdir = $(pkglibdir)
INSTALL = install
INSTALL_PROGRAM = $(INSTALL) -p -m 644
INSTALL_DATA = $(INSTALL) -p -m 644
INSTALL_DIR = $(INSTALL) -p -m 755 -d
ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
$(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION)
UNAME := $(shell uname -s)
ifeq ($(UNAME),Darwin)
CPU := $(shell uname -p)
ifeq ($(CPU),arm) # iPhone/iPod Touch
SOURCES += $(SOURCES_iphoneos)
EXTENSION = pd_darwin
SHARED_EXTENSION = dylib
OS = iphoneos
PD_PATH = /Applications/Pd-extended.app/Contents/Resources
IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
CC=$(IPHONE_BASE)/gcc
CPP=$(IPHONE_BASE)/cpp
CXX=$(IPHONE_BASE)/g++
ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS)
ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT)
ALL_LIBS += -lc $(LIBS_iphoneos)
STRIP = strip -x
DISTBINDIR=$(DISTDIR)-$(OS)
else # Mac OS X
SOURCES += $(SOURCES_macosx)
EXTENSION = pd_darwin
SHARED_EXTENSION = dylib
OS = macosx
PD_PATH = /Applications/Pd-extended.app/Contents/Resources
OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
# build universal 32-bit on 10.4 and 32/64 on newer
ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8)
FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4
else
SOURCES += $(SOURCES_iphoneos)
# Starting with Xcode 4.0, the PowerPC compiler is not installed by default
ifeq ($(wildcard /usr/llvm-gcc-4.2/libexec/gcc/powerpc*), )
FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.5
else
FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
endif
endif
ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include
# if the 'pd' binary exists, check the linking against it to aid with stripping
BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd)
ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -bundle $(BUNDLE_LOADER) \
-undefined dynamic_lookup -L/sw/lib
SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \
-install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0
ALL_LIBS += -lc $(LIBS_macosx)
STRIP = strip -x
DISTBINDIR=$(DISTDIR)-$(OS)
# install into ~/Library/Pd on Mac OS X since /usr/local isn't used much
pkglibdir=$(HOME)/Library/Pd
endif
endif
# Tho Android uses Linux, we use this fake uname to provide an easy way to
# setup all this things needed to cross-compile for Android using the NDK
ifeq ($(UNAME),ANDROID)
CPU := arm
SOURCES += $(SOURCES_android)
EXTENSION = so
SHARED_EXTENSION = so
OS = android
PD_PATH = /usr
NDK_BASE := /opt/android-ndk
NDK_PLATFORM_LEVEL ?= 5
NDK_ABI=arm
NDK_COMPILER_VERSION = 4.6
NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_LEVEL)/arch-$(NDK_ABI)
NDK_UNAME:=$(shell uname -s | tr '[A-Z]' '[a-z]')
ifeq ($(NDK_ABI),x86)
HOST = i686-linux-android
NDK_TOOLCHAIN = $(NDK_ABI)-$(NDK_COMPILER_VERSION)
else
HOST = $(NDK_ABI)-linux-androideabi
NDK_TOOLCHAIN = $(HOST)-$(NDK_COMPILER_VERSION)
endif
NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/$(NDK_TOOLCHAIN)/prebuilt/$(NDK_UNAME)-$(NDK_PROCESSOR)
CC := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-gcc --sysroot=$(NDK_SYSROOT)
LD := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-ld
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
CFLAGS +=
LDFLAGS += -rdynamic -shared
SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
LIBS += -lc $(LIBS_android)
STRIP := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-strip) \
--strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),Linux)
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
SHARED_EXTENSION = so
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
ALL_LIBS += -lc $(LIBS_linux)
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),GNU)
# GNU/Hurd, should work like GNU/Linux for basically all externals
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
SHARED_EXTENSION = so
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
ALL_LIBS += -lc $(LIBS_linux)
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq ($(UNAME),GNU/kFreeBSD)
# Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals
CPU := $(shell uname -m)
SOURCES += $(SOURCES_linux)
EXTENSION = pd_linux
SHARED_EXTENSION = so
OS = linux
PD_PATH = /usr
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -fPIC
ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
ALL_LIBS += -lc $(LIBS_linux)
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
endif
ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
CPU := $(shell uname -m)
SOURCES += $(SOURCES_cygwin)
EXTENSION = dll
SHARED_EXTENSION = dll
OS = cygwin
PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd
OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS +=
ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin"
SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
ALL_LIBS += -lc -lpd $(LIBS_cygwin)
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)
endif
ifeq (MINGW,$(findstring MINGW,$(UNAME)))
CPU := $(shell uname -m)
SOURCES += $(SOURCES_windows)
EXTENSION = dll
SHARED_EXTENSION = dll
OS = windows
PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd)
# MinGW doesn't seem to include cc so force gcc
CC=gcc
OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
ALL_CFLAGS += -mms-bitfields
ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import
SHARED_LDFLAGS += -shared
ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \
-lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows)
STRIP = strip --strip-unneeded -R .note -R .comment
DISTBINDIR=$(DISTDIR)-$(OS)
endif
# in case somebody manually set the HELPPATCHES above
HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS)
ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS)
ALL_LIBS := $(LIBS) $(ALL_LIBS)
SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c)
SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h)
SHARED_LIB ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION))
SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl)
.PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME)
all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB)
%.o: %.c
$(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c"
%.$(EXTENSION): %.o $(SHARED_LIB)
$(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB)
chmod a-x "$*.$(EXTENSION)"
# this links everything into a single binary file
$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o
$(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \
$(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS)
chmod a-x $(LIBRARY_NAME).$(EXTENSION)
$(SHARED_LIB): $(SHARED_SOURCE:.c=.o)
$(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_LIBS)
install: libdir_install
# The meta and help files are explicitly installed to make sure they are
# actually there. Those files are not optional, then need to be there.
libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(SOURCES))" || (\
$(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
$(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
test -z "$(strip $(SHARED_LIB))" || \
$(INSTALL_DATA) $(SHARED_LIB) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \
$(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(PDOBJECTS))" || \
$(INSTALL_DATA) $(PDOBJECTS) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(SHARED_TCL_LIB))" || \
$(INSTALL_DATA) $(SHARED_TCL_LIB) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
# install library linked as single binary
single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
install-doc:
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \
$(INSTALL_DATA) $(HELPPATCHES) \
$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
$(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt
$(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt
install-examples:
test -z "$(strip $(EXAMPLES))" || \
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
for file in $(EXAMPLES); do \
$(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \
done
install-manual:
test -z "$(strip $(MANUAL))" || \
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \
for file in $(MANUAL); do \
$(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \
done
install-unittests:
test -z "$(strip $(UNITTESTS))" || \
$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \
for file in $(UNITTESTS); do \
$(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \
done
clean:
-rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o)
-rm -f -- $(SOURCES:.c=.$(EXTENSION))
-rm -f -- $(LIBRARY_NAME).o
-rm -f -- $(LIBRARY_NAME).$(EXTENSION)
-rm -f -- $(SHARED_LIB)
distclean: clean
-rm -f -- $(DISTBINDIR).tar.gz
-rm -rf -- $(DISTBINDIR)
-rm -f -- $(DISTDIR).tar.gz
-rm -rf -- $(DISTDIR)
-rm -f -- $(ORIGDIR).tar.gz
-rm -rf -- $(ORIGDIR)
$(DISTBINDIR):
$(INSTALL_DIR) $(DISTBINDIR)
libdir: all $(DISTBINDIR)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR)
$(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR)
$(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR)
test -z "$(strip $(EXTRA_DIST))" || \
$(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR)
# tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
$(DISTDIR):
$(INSTALL_DIR) $(DISTDIR)
$(ORIGDIR):
$(INSTALL_DIR) $(ORIGDIR)
dist: $(DISTDIR)
$(INSTALL_DATA) Makefile $(DISTDIR)
$(INSTALL_DATA) README.txt $(DISTDIR)
$(INSTALL_DATA) LICENSE.txt $(DISTDIR)
$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR)
test -z "$(strip $(ALLSOURCES))" || \
$(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR)
test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \
$(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR)
test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \
$(INSTALL_DATA) $(LIBRARY_NAME).c $(DISTDIR)
test -z "$(strip $(SHARED_HEADER))" || \
$(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR)
test -z "$(strip $(SHARED_SOURCE))" || \
$(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR)
test -z "$(strip $(SHARED_TCL_LIB))" || \
$(INSTALL_DATA) $(SHARED_TCL_LIB) $(DISTDIR)
test -z "$(strip $(PDOBJECTS))" || \
$(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR)
test -z "$(strip $(HELPPATCHES))" || \
$(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR)
test -z "$(strip $(EXTRA_DIST))" || \
$(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR)
test -z "$(strip $(EXAMPLES))" || \
$(INSTALL_DIR) $(DISTDIR)/examples && \
for file in $(EXAMPLES); do \
$(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \
done
test -z "$(strip $(MANUAL))" || \
$(INSTALL_DIR) $(DISTDIR)/manual && \
for file in $(MANUAL); do \
$(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \
done
test -z "$(strip $(UNITTESTS))" || \
$(INSTALL_DIR) $(DISTDIR)/unittests && \
for file in $(UNITTESTS); do \
$(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \
done
tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
# make a Debian source package
dpkg-source:
debclean
make distclean dist
mv $(DISTDIR) $(ORIGDIR)
tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR)
rm -f -- $(DISTDIR).tar.gz
rm -rf -- $(DISTDIR) $(ORIGDIR)
cd .. && dpkg-source -b $(LIBRARY_NAME)
etags: TAGS
TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER)
etags $(wildcard $(PD_INCLUDE)/*.h)
etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER)
etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
showsetup:
@echo "CC: $(CC)"
@echo "CFLAGS: $(CFLAGS)"
@echo "LDFLAGS: $(LDFLAGS)"
@echo "LIBS: $(LIBS)"
@echo "ALL_CFLAGS: $(ALL_CFLAGS)"
@echo "ALL_LDFLAGS: $(ALL_LDFLAGS)"
@echo "ALL_LIBS: $(ALL_LIBS)"
@echo "PD_INCLUDE: $(PD_INCLUDE)"
@echo "PD_PATH: $(PD_PATH)"
@echo "objectsdir: $(objectsdir)"
@echo "LIBRARY_NAME: $(LIBRARY_NAME)"
@echo "LIBRARY_VERSION: $(LIBRARY_VERSION)"
@echo "SOURCES: $(SOURCES)"
@echo "SHARED_HEADER: $(SHARED_HEADER)"
@echo "SHARED_SOURCE: $(SHARED_SOURCE)"
@echo "SHARED_LIB: $(SHARED_LIB)"
@echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)"
@echo "PDOBJECTS: $(PDOBJECTS)"
@echo "ALLSOURCES: $(ALLSOURCES)"
@echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))"
@echo "UNAME: $(UNAME)"
@echo "CPU: $(CPU)"
@echo "pkglibdir: $(pkglibdir)"
@echo "DISTDIR: $(DISTDIR)"
@echo "ORIGDIR: $(ORIGDIR)"
@echo "NDK_TOOLCHAIN: $(NDK_TOOLCHAIN)"
@echo "NDK_BASE: $(NDK_BASE)"
@echo "NDK_SYSROOT: $(NDK_SYSROOT)"
mrpeach/cmos/cd4027-help.pd 0000644 0001750 0001750 00000002355 11026462102 016045 0 ustar zmoelnig zmoelnig #N canvas 581 224 647 312 12;
#X obj 79 38 tgl 15 0 empty empty CLK 17 7 0 10 -24198 -62784 -1 1
1;
#X obj 93 53 tgl 15 0 empty empty SET 17 7 0 10 -24198 -62784 -1 0
1;
#X obj 108 68 tgl 15 0 empty empty RESET 17 7 0 10 -24198 -62784 -1
0 1;
#X obj 123 83 tgl 15 0 empty empty J 17 7 0 10 -24198 -62784 -1 1 1
;
#X obj 138 98 tgl 15 0 empty empty K 17 7 0 10 -24198 -62784 -1 1 1
;
#X obj 79 146 cd4027 v;
#X obj 138 172 tgl 15 0 empty empty /Q 17 7 0 10 -143491 -241291 -1
0 1;
#X obj 79 172 tgl 15 0 empty empty Q 17 7 0 10 -143491 -241291 -1 1
1;
#X text 173 65 Sets Q=0. Overrides Clock;
#X text 133 35 A 0-1 transition or a bang clocks the flipflop.;
#X text 142 50 Sets Q=1. Overrides Reset and Clock;
#X text 237 264 20070307MartinPeach;
#X text 27 5 cd4027 emulates one half of the CMOS logic J/K flipflop.
;
#X text 157 80 When Q=0 and J=1 \, Q will change on next clock.;
#X text 168 96 When Q=1 and K=1 \, Q will change on next clock.;
#X obj 6 89 metro 100;
#X obj 6 67 tgl 15 0 empty empty empty 17 7 0 10 -44926 -90881 -1 0
1;
#X connect 0 0 5 0;
#X connect 1 0 5 1;
#X connect 2 0 5 2;
#X connect 3 0 5 3;
#X connect 4 0 5 4;
#X connect 5 0 7 0;
#X connect 5 1 6 0;
#X connect 15 0 5 0;
#X connect 16 0 15 0;
mrpeach/cmos/cd4073.c 0000644 0001750 0001750 00000005205 12430236316 014742 0 ustar zmoelnig zmoelnig /* cd4073.c MP 20070312 */
/* Emulate a cd4073b */
#include "m_pd.h"
typedef struct _cd4073
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
} t_cd4073;
static t_class *cd4073_class;
void cd4073_setup(void);
static void *cd4073_new(t_symbol *s, int argc, t_atom *argv);
static void cd4073_free(t_cd4073 *x);
static void cd4073_bang(t_cd4073 *x);
static void cd4073_float(t_cd4073 *x, t_float f);
static void cd4073_inlet2(t_cd4073 *x, t_float f);
static void cd4073_inlet3(t_cd4073 *x, t_float f);
static void cd4073_update_outlets(t_cd4073 *x);
static void cd4073_float(t_cd4073 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4073 inlet 2 accepts 1 or 0.");
return;
}
cd4073_update_outlets(x);
}
static void cd4073_bang(t_cd4073 *x)
{
cd4073_update_outlets(x);
}
static void cd4073_inlet2(t_cd4073 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4073 inlet 2 accepts 1 or 0.");
return;
}
cd4073_update_outlets(x);
}
static void cd4073_inlet3(t_cd4073 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4073 inlet 3 accepts 1 or 0.");
return;
}
cd4073_update_outlets(x);
}
static void cd4073_update_outlets(t_cd4073 *x)
{ /* Triple AND function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3) == 3)?1:0);
}
static void cd4073_free(t_cd4073 *x)
{
return;
}
static void *cd4073_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4073 *x;
x = (t_cd4073 *)pd_new(cd4073_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
return (x);
}
void cd4073_setup(void)
{
cd4073_class = class_new(gensym("cd4073"),
(t_newmethod)cd4073_new,
(t_method)cd4073_free,
sizeof(t_cd4073), 0, 0); /* no arguments */
class_addbang(cd4073_class, cd4073_bang);
class_addfloat(cd4073_class, cd4073_float);
class_addmethod(cd4073_class, (t_method)cd4073_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4073_class, (t_method)cd4073_inlet3, gensym("inlet3"), A_FLOAT, 0);
}
/* end cd4073.c */
mrpeach/cmos/cd4000.c 0000644 0001750 0001750 00000005205 12430236171 014727 0 ustar zmoelnig zmoelnig /* cd4000.c MP 20070312 */
/* Emulate a cd4000b */
#include "m_pd.h"
typedef struct _cd4000
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
} t_cd4000;
static t_class *cd4000_class;
void cd4000_setup(void);
static void *cd4000_new(t_symbol *s, int argc, t_atom *argv);
static void cd4000_free(t_cd4000 *x);
static void cd4000_bang(t_cd4000 *x);
static void cd4000_float(t_cd4000 *x, t_float f);
static void cd4000_inlet2(t_cd4000 *x, t_float f);
static void cd4000_inlet3(t_cd4000 *x, t_float f);
static void cd4000_update_outlets(t_cd4000 *x);
static void cd4000_float(t_cd4000 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4000 inlet 2 accepts 1 or 0.");
return;
}
cd4000_update_outlets(x);
}
static void cd4000_bang(t_cd4000 *x)
{
cd4000_update_outlets(x);
}
static void cd4000_inlet2(t_cd4000 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4000 inlet 2 accepts 1 or 0.");
return;
}
cd4000_update_outlets(x);
}
static void cd4000_inlet3(t_cd4000 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4000 inlet 3 accepts 1 or 0.");
return;
}
cd4000_update_outlets(x);
}
static void cd4000_update_outlets(t_cd4000 *x)
{ /* Triple NOR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3) != 0)?0:1);
}
static void cd4000_free(t_cd4000 *x)
{
return;
}
static void *cd4000_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4000 *x;
x = (t_cd4000 *)pd_new(cd4000_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
return (x);
}
void cd4000_setup(void)
{
cd4000_class = class_new(gensym("cd4000"),
(t_newmethod)cd4000_new,
(t_method)cd4000_free,
sizeof(t_cd4000), 0, 0); /* no arguments */
class_addbang(cd4000_class, cd4000_bang);
class_addfloat(cd4000_class, cd4000_float);
class_addmethod(cd4000_class, (t_method)cd4000_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4000_class, (t_method)cd4000_inlet3, gensym("inlet3"), A_FLOAT, 0);
}
/* end cd4000.c */
mrpeach/cmos/cd4072.c 0000644 0001750 0001750 00000006277 12430236316 014753 0 ustar zmoelnig zmoelnig /* cd4072.c MP 20070312 */
/* Emulate a cd4072b */
#include "m_pd.h"
typedef struct _cd4072
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
int x_in4;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
t_inlet *x_inlet4;/* Fourth inlet is 'live' like the first */
} t_cd4072;
static t_class *cd4072_class;
void cd4072_setup(void);
static void *cd4072_new(t_symbol *s, int argc, t_atom *argv);
static void cd4072_free(t_cd4072 *x);
static void cd4072_bang(t_cd4072 *x);
static void cd4072_float(t_cd4072 *x, t_float f);
static void cd4072_inlet2(t_cd4072 *x, t_float f);
static void cd4072_inlet3(t_cd4072 *x, t_float f);
static void cd4072_inlet4(t_cd4072 *x, t_float f);
static void cd4072_update_outlets(t_cd4072 *x);
static void cd4072_float(t_cd4072 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4072 inlet 2 accepts 1 or 0.");
return;
}
cd4072_update_outlets(x);
}
static void cd4072_bang(t_cd4072 *x)
{
cd4072_update_outlets(x);
}
static void cd4072_inlet2(t_cd4072 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4072 inlet 2 accepts 1 or 0.");
return;
}
cd4072_update_outlets(x);
}
static void cd4072_inlet3(t_cd4072 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4072 inlet 3 accepts 1 or 0.");
return;
}
cd4072_update_outlets(x);
}
static void cd4072_inlet4(t_cd4072 *x, t_float f)
{
if (f == 1) x->x_in4 = 1;
else if (f == 0) x->x_in4 = 0;
else
{
post("cd4072 inlet 4 accepts 1 or 0.");
return;
}
cd4072_update_outlets(x);
}
static void cd4072_update_outlets(t_cd4072 *x)
{ /* QUAD OR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3 + x->x_in4) != 0)?1:0);
}
static void cd4072_free(t_cd4072 *x)
{
return;
}
static void *cd4072_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4072 *x;
x = (t_cd4072 *)pd_new(cd4072_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
x->x_inlet4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet4"));
return (x);
}
void cd4072_setup(void)
{
cd4072_class = class_new(gensym("cd4072"),
(t_newmethod)cd4072_new,
(t_method)cd4072_free,
sizeof(t_cd4072), 0, 0); /* no arguments */
class_addbang(cd4072_class, cd4072_bang);
class_addfloat(cd4072_class, cd4072_float);
class_addmethod(cd4072_class, (t_method)cd4072_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4072_class, (t_method)cd4072_inlet3, gensym("inlet3"), A_FLOAT, 0);
class_addmethod(cd4072_class, (t_method)cd4072_inlet4, gensym("inlet4"), A_FLOAT, 0);
}
/* end cd4072.c */
mrpeach/cmos/cd4070.c 0000644 0001750 0001750 00000004051 12430236316 014735 0 ustar zmoelnig zmoelnig /* cd4070.c MP 20070305 */
/* Emulate a cd4070b */
#include "m_pd.h"
typedef struct _cd4070
{
t_object x_obj;
int x_in1;
int x_in2;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
} t_cd4070;
static t_class *cd4070_class;
void cd4070_setup(void);
static void *cd4070_new(t_symbol *s, int argc, t_atom *argv);
static void cd4070_free(t_cd4070 *x);
static void cd4070_bang(t_cd4070 *x);
static void cd4070_float(t_cd4070 *x, t_float f);
static void cd4070_inlet2(t_cd4070 *x, t_float f);
static void cd4070_update_outlets(t_cd4070 *x);
static void cd4070_float(t_cd4070 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4070 inlet 2 accepts 1 or 0.");
return;
}
cd4070_update_outlets(x);
}
static void cd4070_bang(t_cd4070 *x)
{
cd4070_update_outlets(x);
}
static void cd4070_inlet2(t_cd4070 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4070 inlet 2 accepts 1 or 0.");
return;
}
cd4070_update_outlets(x);
}
static void cd4070_update_outlets(t_cd4070 *x)
{
outlet_float(x->x_out, (x->x_in1 != x->x_in2)?1:0);
}
static void cd4070_free(t_cd4070 *x)
{
return;
}
static void *cd4070_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4070 *x;
x = (t_cd4070 *)pd_new(cd4070_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
return (x);
}
void cd4070_setup(void)
{
cd4070_class = class_new(gensym("cd4070"),
(t_newmethod)cd4070_new,
(t_method)cd4070_free,
sizeof(t_cd4070), 0, 0); /* no arguments */
class_addbang(cd4070_class, cd4070_bang);
class_addfloat(cd4070_class, cd4070_float);
class_addmethod(cd4070_class, (t_method)cd4070_inlet2, gensym("inlet2"), A_FLOAT, 0);
}
/* end cd4070.c */
mrpeach/cmos/cd4015-help.pd 0000644 0001750 0001750 00000001506 11026462102 016037 0 ustar zmoelnig zmoelnig #N canvas 693 303 454 304 12;
#X obj 125 135 cd4015 4bit shift register;
#X obj 125 84 tgl 15 0 empty empty Clk 17 7 0 10 -44926 -258699 -1
0 1;
#X obj 226 84 tgl 15 0 empty empty D 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 328 84 tgl 15 0 empty empty R 17 7 0 10 -44926 -258699 -1 0
1;
#X obj 125 183 tgl 15 0 empty empty Q1 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 192 183 tgl 15 0 empty empty Q2 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 260 183 tgl 15 0 empty empty Q3 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 328 183 tgl 15 0 empty empty Q4 17 7 0 10 -24198 -258699 -1
0 1;
#X text 32 22 cd4016 emulates 1/2 of the CMOS shift register;
#X text 165 239 20070319_MartinPeach;
#X connect 0 0 4 0;
#X connect 0 1 5 0;
#X connect 0 2 6 0;
#X connect 0 3 7 0;
#X connect 1 0 0 0;
#X connect 2 0 0 1;
#X connect 3 0 0 2;
mrpeach/cmos/cd4008.c 0000644 0001750 0001750 00000013756 12430236316 014752 0 ustar zmoelnig zmoelnig /* cd4008.c MP 20070315 */
/* Emulate a cd4008b */
#include "m_pd.h"
typedef struct _cd4008
{
t_object x_obj;
int x_A1;
int x_A2;
int x_A3;
int x_A4;
int x_B1;
int x_B2;
int x_B3;
int x_B4;
int x_CarryIn;
t_outlet *x_outS1;
t_outlet *x_outS2;
t_outlet *x_outS3;
t_outlet *x_outS4;
t_outlet *x_outC;
t_inlet *x_inA1;/* extra inlets are 'live' like the first */
t_inlet *x_inA2;
t_inlet *x_inA3;
t_inlet *x_inA4;
t_inlet *x_inB1;
t_inlet *x_inB2;
t_inlet *x_inB3;
t_inlet *x_inB4;
} t_cd4008;
static t_class *cd4008_class;
void cd4008_setup(void);
static void *cd4008_new(t_symbol *s, int argc, t_atom *argv);
static void cd4008_free(t_cd4008 *x);
static void cd4008_float(t_cd4008 *x, t_float f);
static void cd4008_inA1(t_cd4008 *x, t_float f);
static void cd4008_inA2(t_cd4008 *x, t_float f);
static void cd4008_inA3(t_cd4008 *x, t_float f);
static void cd4008_inA4(t_cd4008 *x, t_float f);
static void cd4008_inB1(t_cd4008 *x, t_float f);
static void cd4008_inB2(t_cd4008 *x, t_float f);
static void cd4008_inB3(t_cd4008 *x, t_float f);
static void cd4008_inB4(t_cd4008 *x, t_float f);
static void cd4008_update_outlets(t_cd4008 *x);
static void cd4008_float(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_CarryIn = 1;
else if (f == 0) x->x_CarryIn = 0;
else
{
post("cd4008 Carry inlet accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inA1(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_A1 = 1;
else if (f == 0) x->x_A1 = 0;
else
{
post("cd4008 inlet A1 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inA2(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_A2 = 1;
else if (f == 0) x->x_A2 = 0;
else
{
post("cd4008 inlet A2 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inA3(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_A3 = 1;
else if (f == 0) x->x_A3 = 0;
else
{
post("cd4008 inlet A3 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inA4(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_A4 = 1;
else if (f == 0) x->x_A4 = 0;
else
{
post("cd4008 inlet A4 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inB1(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_B1 = 1;
else if (f == 0) x->x_B1 = 0;
else
{
post("cd4008 inlet B1 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inB2(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_B2 = 1;
else if (f == 0) x->x_B2 = 0;
else
{
post("cd4008 inlet B2 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inB3(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_B3 = 1;
else if (f == 0) x->x_B3 = 0;
else
{
post("cd4008 inlet B3 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_inB4(t_cd4008 *x, t_float f)
{
if (f == 1) x->x_B4 = 1;
else if (f == 0) x->x_B4 = 0;
else
{
post("cd4008 inlet B4 accepts 1 or 0.");
return;
}
cd4008_update_outlets(x);
}
static void cd4008_update_outlets(t_cd4008 *x)
{ /* Quadruple add function */
t_int sum;
sum = x->x_CarryIn + x->x_A1 + x->x_B1 + 2*(x->x_A2 + x->x_B2) + 4*(x->x_A3 + x->x_B3) + 8*(x->x_A4 + x->x_B4);
outlet_float(x->x_outC, ((sum & 16) != 0)?1:0);
outlet_float(x->x_outS4, ((sum & 8) != 0)?1:0);
outlet_float(x->x_outS3, ((sum & 4) != 0)?1:0);
outlet_float(x->x_outS2, ((sum & 2) != 0)?1:0);
outlet_float(x->x_outS1, ((sum & 1) != 0)?1:0);
}
static void cd4008_free(t_cd4008 *x)
{
return;
}
static void *cd4008_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4008 *x;
x = (t_cd4008 *)pd_new(cd4008_class);
if (x == NULL) return (x);
x->x_outS1 = outlet_new((t_object *)x, &s_float);
x->x_outS2 = outlet_new((t_object *)x, &s_float);
x->x_outS3 = outlet_new((t_object *)x, &s_float);
x->x_outS4 = outlet_new((t_object *)x, &s_float);
x->x_outC = outlet_new((t_object *)x, &s_float);
x->x_inA1 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("A1"));
x->x_inA2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("A2"));
x->x_inA3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("A3"));
x->x_inA4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("A4"));
x->x_inB1 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B1"));
x->x_inB2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B2"));
x->x_inB3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B3"));
x->x_inB4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("B4"));
return (x);
}
void cd4008_setup(void)
{
cd4008_class = class_new(gensym("cd4008"),
(t_newmethod)cd4008_new,
(t_method)cd4008_free,
sizeof(t_cd4008), 0, 0); /* no arguments */
class_addfloat(cd4008_class, cd4008_float);
class_addmethod(cd4008_class, (t_method)cd4008_inA1, gensym("A1"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inA2, gensym("A2"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inA3, gensym("A3"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inA4, gensym("A4"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inB1, gensym("B1"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inB2, gensym("B2"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inB3, gensym("B3"), A_FLOAT, 0);
class_addmethod(cd4008_class, (t_method)cd4008_inB4, gensym("B4"), A_FLOAT, 0);
}
/* end cd4008.c */
mrpeach/cmos/cd4023-help.pd 0000644 0001750 0001750 00000001057 11026462102 016037 0 ustar zmoelnig zmoelnig #N canvas 670 174 478 232 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 155 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 225 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 106 cd4023 triple nand;
#X text 18 47 cd4023 emulates 1/3 of the CMOS triple NAND gate;
#X text 210 170 20070319_Martin_Peach;
#X connect 0 0 4 0;
#X connect 1 0 4 1;
#X connect 3 0 4 2;
#X connect 4 0 2 0;
mrpeach/cmos/cd4082-help.pd 0000644 0001750 0001750 00000001212 11026462102 016035 0 ustar zmoelnig zmoelnig #N canvas 670 174 466 220 12;
#X obj 86 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 124 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X obj 162 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 201 82 tgl 15 0 empty empty empty 17 7 0 10 -24198 -258699 -1
1 1;
#X obj 86 106 cd4082 quad and;
#X text 18 47 cd4082 emulates 1/2 of the CMOS quad AND gate;
#X text 210 170 20070312_Martin_Peach;
#X connect 0 0 5 0;
#X connect 1 0 5 1;
#X connect 3 0 5 2;
#X connect 4 0 5 3;
#X connect 5 0 2 0;
mrpeach/cmos/cd4012-help.pd 0000644 0001750 0001750 00000001217 11026462102 016033 0 ustar zmoelnig zmoelnig #N canvas 670 174 494 248 12;
#X obj 86 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 113 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 86 137 tgl 15 0 empty empty empty 17 7 0 10 -258699 -241291
-1 1 1;
#X text 210 170 20070315_Martin_Peach;
#X obj 141 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X obj 169 82 tgl 15 1 empty empty empty 17 7 0 10 -24198 -258699 -1
0 1;
#X text 18 31 cd4012 emulates 1/2 of the CMOS four-input NAND gate
;
#X obj 86 106 cd4012 nand;
#X connect 0 0 7 0;
#X connect 1 0 7 1;
#X connect 4 0 7 2;
#X connect 5 0 7 3;
#X connect 7 0 2 0;
mrpeach/cmos/cd4094-help.pd 0000644 0001750 0001750 00000003160 11026462102 016044 0 ustar zmoelnig zmoelnig #N canvas 657 97 532 308 12;
#X obj 130 135 cd4094 shift register;
#X obj 130 173 tgl 15 0 empty empty Q1 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 148 189 tgl 15 0 empty empty Q2 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 166 173 tgl 15 0 empty empty Q3 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 184 189 tgl 15 0 empty empty Q4 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 202 173 tgl 15 0 empty empty Q5 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 220 189 tgl 15 0 empty empty Q6 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 238 173 tgl 15 0 empty empty Q7 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 256 189 tgl 15 0 empty empty Q8 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 274 173 tgl 15 0 empty empty QS 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 292 189 tgl 15 0 empty empty Q'S 17 7 0 10 -24198 -123526 -1
0 1;
#X obj 130 51 tgl 15 0 empty empty CLOCK 17 7 0 10 -258699 -42246 -1
1 1;
#X obj 184 73 tgl 15 0 empty empty STROBE 17 7 0 10 -24198 -143491
-1 1 1;
#X obj 238 93 tgl 15 0 empty empty DATA 17 7 0 10 -24198 -143491 -1
0 1;
#X obj 293 110 tgl 15 0 empty empty OUTPUT_ENABLE 17 7 0 10 -24198
-143491 -1 1 1;
#X text 52 10 cd4094 emulates the CMOS shift register;
#X text 166 239 20030313_MartinPeach;
#X text 200 48 0 to 1 transition clocks data...;
#X text 255 70 ...only if strobe is 1;
#X text 316 121 enables outputs Q1-Q8.;
#X connect 0 0 1 0;
#X connect 0 1 2 0;
#X connect 0 2 3 0;
#X connect 0 3 4 0;
#X connect 0 4 5 0;
#X connect 0 5 6 0;
#X connect 0 6 7 0;
#X connect 0 7 8 0;
#X connect 0 8 9 0;
#X connect 0 9 10 0;
#X connect 11 0 0 0;
#X connect 12 0 0 1;
#X connect 13 0 0 2;
#X connect 14 0 0 3;
mrpeach/cmos/README.txt 0000644 0001750 0001750 00000000240 12571126767 015400 0 ustar zmoelnig zmoelnig CMOS digital logic emulation objects
===
This is a collection of small objects that emulate
logic CMOS components.
The emulation assumes idealized components.
mrpeach/cmos/cd4076-help.pd 0000644 0001750 0001750 00000004012 11026462102 016041 0 ustar zmoelnig zmoelnig #N canvas 581 224 661 399 12;
#X obj 49 39 tgl 15 0 empty empty CP 17 7 0 10 -24198 -62784 -1 0 1
;
#X obj 68 54 tgl 15 0 empty empty CLEAR 17 7 0 10 -24198 -62784 -1
0 1;
#X obj 87 70 tgl 15 0 empty empty Input_Disable_1 17 7 0 10 -24198
-62784 -1 0 1;
#X obj 106 88 tgl 15 0 empty empty Input_Disable_2 17 7 0 10 -24198
-62784 -1 0 1;
#X obj 106 304 tgl 15 0 empty empty B 17 7 0 10 -143491 -241291 -1
0 1;
#X obj 49 304 tgl 15 0 empty empty A 17 7 0 10 -143491 -241291 -1 0
1;
#X obj 26 157 tgl 15 0 empty empty empty 17 7 0 10 -44926 -90881 -1
0 1;
#X text 89 36 A 0-1 transition or a bang clocks D to the outlets.;
#X obj 26 221 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -241291
-1;
#X obj 26 187 metro 500;
#X text 27 5 cd4076 emulates the CMOS quad D flipflop.;
#X obj 220 304 tgl 15 0 empty empty D 17 7 0 10 -143491 -241291 -1
0 1;
#X obj 163 304 tgl 15 0 empty empty C 17 7 0 10 -143491 -241291 -1
0 1;
#X text 131 50 Sets outputs to 0 Overrides CP.;
#X text 250 74 Prevents input from being clocked to output.;
#X obj 125 106 tgl 15 0 empty empty Output_Disable_1 17 7 0 10 -24198
-62784 -1 0 1;
#X obj 144 124 tgl 15 0 empty empty Output_Disable_1 17 7 0 10 -24198
-62784 -1 0 1;
#X text 291 107 Inhibits output.;
#X text 74 341 20070312_Martin_Peach;
#X obj 163 141 tgl 15 0 empty empty InA 17 7 0 10 -260818 -143491 -1
0 1;
#X obj 182 158 tgl 15 0 empty empty InB 17 7 0 10 -260818 -143491 -1
0 1;
#X obj 201 177 tgl 15 0 empty empty InC 17 7 0 10 -260818 -143491 -1
0 1;
#X obj 220 194 tgl 15 0 empty empty InD 17 7 0 10 -260818 -143491 -1
0 1;
#X text 236 142 Data inputs;
#X obj 49 263 cd4076 quad d flipflop;
#X connect 0 0 24 0;
#X connect 1 0 24 1;
#X connect 2 0 24 2;
#X connect 3 0 24 3;
#X connect 6 0 9 0;
#X connect 8 0 24 0;
#X connect 9 0 8 0;
#X connect 15 0 24 4;
#X connect 16 0 24 5;
#X connect 19 0 24 6;
#X connect 20 0 24 7;
#X connect 21 0 24 8;
#X connect 22 0 24 9;
#X connect 24 0 5 0;
#X connect 24 1 4 0;
#X connect 24 2 12 0;
#X connect 24 3 11 0;
mrpeach/cmos/cd4025.c 0000644 0001750 0001750 00000005205 12430236316 014737 0 ustar zmoelnig zmoelnig /* cd4025.c MP 20070312 */
/* Emulate a cd4025b */
#include "m_pd.h"
typedef struct _cd4025
{
t_object x_obj;
int x_in1;
int x_in2;
int x_in3;
t_outlet *x_out;
t_inlet *x_inlet2;/* Second inlet is 'live' like the first */
t_inlet *x_inlet3;/* Third inlet is 'live' like the first */
} t_cd4025;
static t_class *cd4025_class;
void cd4025_setup(void);
static void *cd4025_new(t_symbol *s, int argc, t_atom *argv);
static void cd4025_free(t_cd4025 *x);
static void cd4025_bang(t_cd4025 *x);
static void cd4025_float(t_cd4025 *x, t_float f);
static void cd4025_inlet2(t_cd4025 *x, t_float f);
static void cd4025_inlet3(t_cd4025 *x, t_float f);
static void cd4025_update_outlets(t_cd4025 *x);
static void cd4025_float(t_cd4025 *x, t_float f)
{
if (f == 1) x->x_in1 = 1;
else if (f == 0) x->x_in1 = 0;
else
{
post("cd4025 inlet 2 accepts 1 or 0.");
return;
}
cd4025_update_outlets(x);
}
static void cd4025_bang(t_cd4025 *x)
{
cd4025_update_outlets(x);
}
static void cd4025_inlet2(t_cd4025 *x, t_float f)
{
if (f == 1) x->x_in2 = 1;
else if (f == 0) x->x_in2 = 0;
else
{
post("cd4025 inlet 2 accepts 1 or 0.");
return;
}
cd4025_update_outlets(x);
}
static void cd4025_inlet3(t_cd4025 *x, t_float f)
{
if (f == 1) x->x_in3 = 1;
else if (f == 0) x->x_in3 = 0;
else
{
post("cd4025 inlet 3 accepts 1 or 0.");
return;
}
cd4025_update_outlets(x);
}
static void cd4025_update_outlets(t_cd4025 *x)
{ /* Triple NOR function */
outlet_float(x->x_out, ((x->x_in1 + x->x_in2 + x->x_in3) != 0)?0:1);
}
static void cd4025_free(t_cd4025 *x)
{
return;
}
static void *cd4025_new(t_symbol *s, int argc, t_atom *argv)
{
t_cd4025 *x;
x = (t_cd4025 *)pd_new(cd4025_class);
if (x == NULL) return (x);
x->x_out = outlet_new((t_object *)x, &s_float);
x->x_inlet2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet2"));
x->x_inlet3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("inlet3"));
return (x);
}
void cd4025_setup(void)
{
cd4025_class = class_new(gensym("cd4025"),
(t_newmethod)cd4025_new,
(t_method)cd4025_free,
sizeof(t_cd4025), 0, 0); /* no arguments */
class_addbang(cd4025_class, cd4025_bang);
class_addfloat(cd4025_class, cd4025_float);
class_addmethod(cd4025_class, (t_method)cd4025_inlet2, gensym("inlet2"), A_FLOAT, 0);
class_addmethod(cd4025_class, (t_method)cd4025_inlet3, gensym("inlet3"), A_FLOAT, 0);
}
/* end cd4025.c */
mrpeach/midifile/ 0000755 0001750 0001750 00000000000 14110766276 014523 5 ustar zmoelnig zmoelnig mrpeach/midifile/I_Wanna_Be_Sedated.mid 0000644 0001750 0001750 00000135610 13153266454 020576 0 ustar zmoelnig zmoelnig MThd xMTrk B X Y Qt %Sequenced by sargpepp67@earthlink.net / MTrk ! Drums
@ ] [@c$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ (((( (!$( (( $ *( (,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y $y$ $ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$ $4$ $ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( J$4$ B(,( M$$ #$y$ %(+( I$4,4 $ / MTrk ! Cymbals/Percussionc4| 5;5 4 .r;. .o;. .;. .;. .;. .;. .{;. .|;. .r;. .;. .;. .;. .o;. .;. .;. 4;4 .;. .u;. .|;. .;. .o;. .};. .|;. .;. .;. .i;. .o;. .;. .;. .;. .;. 4;4 .c;. .};. .;. .;. .;. .;. .o;. .;. .Y;. .o;. .Y;. .;. .;. .|;. .;. 4f;4 .;. .;. .;. .;. .;. .;. .;. .;. .{;. .;. .c;. .;. .;. .u;. .;. 4;4 .;. .;. .;. .u;. .;. .;. .;. .u;. .u;. .i;. .Y;. .;. .{;. .;. .;. 4|;4 .u;. .;. .;. .;. .o;. .;. .c;. .;. .;. .;. .;. .;. .;. .;. .o;. 4;4 3;3 3;3 3l;3 3;3 3;3 3;3 3o;3 4;4 3M;3 3Y;3 3x;3 3|;3 3V;3 3o;3 3o;3 4|;4 3i;3 3{;3 3;3 3];3 3u;3 3Y;3 3i;3 4c;4 3o;3 3];3 3;3 3i;3 3x;3 3x;3 3i;3 4;4 3|;3 3;3 3c;3 3V;3 3u;3 3;3 3;3 4;4 3;3 3;3 3;3 3;3 3;3 3u;3 3;3 4x;4 3o;3 3{;3 3u;3 3u;3 3;3 3;3 3c;3 4{;4 3`;3 3{;3 3{;3 3u;3 3};3 3l;3 3];3 .. '.E. '.. #.M. (.. #.[. +.c. '.V. -.o. .f. .T. .V. ".Y". .r. .. .u. .V . .Y!. .}#. .u!. .. .!. . . .`. .Q. .x. .". .r. . . . . .|. .o . 4*4 L.. .l. .i. .|. .}. .H. !.!. .. .o. .u . .x . .. .i. .|. .. .. .. .. .`. .i. .Y. .|. .. .r. .. .`. .". .~. .. .$. 4%4 S.. .T. ".{ . .=. .i. ".i. %.]. #.`. #.`. ".o. #.T. #.V. &.]. (.c. "4|#4 S.V. &.r. #.|. ".o. #.. #.. !4"4 .u. (.O. $.o. ".c. ".|. .. !.O. "4}"4 .l. #.Q. #.x. ".l. ".]. .o. .l. 4{$4 .i. &.. ".}. .Q. ".Q. ".`. .i. 4"4 .]. ).]. #.|. !.Q. !.`. .|. #.. 4i 4 .O. '.Q. $.u. ".~. !.l. %.Q. ".. 4!4 .]. &.u. .~. ".o. .u. $.. %.. 4c!4 .u. ).. !.{. .u. .Q. ".}. .. %6H*6 * *H 6Q
6
* #'*}66 ' * *T6c6 * "*Q6]6 * *6c6 * $*l'Y6' * 6 'x6o*Y6 ' * *6Q6 * *| 6M
6 * #*'~6' 6 * *]6H6 * "*Y 6@6 * 6E*l6 * 6*'|' * 6 6T'c*x6 ' * !6x*~6 * 6`*x6 * !6'{ *6 * ' 6O*c6 * 6o*x6 * 6H*6 * '*{6' *
6 *'x6x6 ' * *c 6[6 * *}6H6 * $'*6' 6 * *H6J6 * $6B*~6 * *u6Q6 * "'*{6' * 6 * '6H6 ' * *o6O6 * *|6Y6 * %* '6' 6 * *|6f6 * *|6f6 * *i6J6 * "6'V*{' * 6 6x' *`6 ' * 6x*o6 * 6=*
6
* 6* '' 6 * 6E*6 * !6o*6 * 6Y*|6 * 6'*' 6 * 6*o'6
' * 6r*o6 * 6M*6 * ' *6' * 6 *l 6V6 * *6Q6 * *6T6 * '*r6' *
6 *'x6T' 6 * *6x* 6 *6=6 * !'*u6' * 6 *6=6 * *6Q6 * *O6B6 * #* '6' * 6 *{ '~6u6 ' * 11 '.E. '.. #.M. (.. #.[. +.c. '.V. -.o. .f. .T. .V. ".Y". .r. .. .u. .V . .Y!. .}#. .u!. .. .!. . . .`. .Q. .x. .". .r. . . . . .|. .o . 4*4 L.. .l. .i. .|. .}. .H. !.!. .. .o. .u . .x . .. .i. .|. .. .. .. .. .`. .i. .Y. .|. .. .r. .. .`. .". .~. .. .$. 4%4 S.. .T. ".{ . .=. .i. ".i. %.]. #.`. #.`. ".o. #.T. #.V. &.]. (.c. "4|#4 S.V. &.r. #.|. ".o. #.. #.. !4"4 .u. (.O. $.o. ".c. ".|. .. !.O. "4}"4 .l. #.Q. #.x. ".l. ".]. .o. .l. 4{$4 .i. &.. ".}. .Q. ".Q. ".`. .i. 4"4 .]. ).]. #.|. !.Q. !.`. .|. #.. 4i 4 .O. '.Q. $.u. ".~. !.l. %.Q. ".. 4!4 .]. &.u. .~. ".o. .u. $.. %.. 4c!4 .u. ).. !.{. .u. .Q. ".}. .. !.. '.E. '.. #.M. (.. #.[. +.c. '.V. -.o. .f. .T. .V. ".Y". .r. .. .u. .V . .Y!. .}#. .u!. .. .!. . . .`. .Q. .x. .". .r. . . . . .|. .o . 4*4 L.. .l. .i. .|. .}. .H. !.!. .. .o. .u . .x . .. .i. .|. .. .. .. .. .`. .i. .Y. .|. .. .r. .. .`. .". .~. .. .$. 4%4 S.. .T. ".{ . .=. .i. ".i. %.]. #.`. #.`. ".o. #.T. #.V. &.]. (.c. "4|#4 S.V. &.r. #.|. ".o. #.. #.. !4"4 .u. (.O. $.o. ".c. ".|. .. !.O. "4}"4 .l. #.Q. #.x. ".l. ".]. .o. .l. 4{$4 .i. &.. ".}. .Q. ".Q. ".`. .i. 4"4 .]. ).]. #.|. !.Q. !.`. .|. #.. 4i 4 .O. '.Q. $.u. ".~. !.l. %.Q. ".. 4!4 .]. &.u. .~. ".o. .u. $.. %.. 4c!4 .u. ).. !.{. .u. .Q. ".}. .. %6H*6 * *H 6Q
6
* #'*}66 ' * *T6c6 * "*Q6]6 * *6c6 * $*l'Y6' * 6 'x6o*Y6 ' * *6Q6 * *| 6M
6 * #*'~6' 6 * *]6H6 * "*Y 6@6 * 6E*l6 * 6*'|' * 6 6T'c*x6 ' * !6x*~6 * 6`*x6 * !6'{ *6 * ' 6O*c6 * 6o*x6 * 6H*6 * '*{6' *
6 *'x6x6 ' * *c 6[6 * *}6H6 * $'*6' 6 * *H6J6 * $6B*~6 * *u6Q6 * "'*{6' * 6 * '6H6 ' * $6H*6 * *H 6Q
6
* #'*}66 ' * *T6c6 * "*Q6]6 * *6c6 * $*l'Y6' * 6 'x6o*Y6 ' * *6Q6 * *| 6M
6 * #*'~6' 6 * *]6H6 * "*Y 6@6 * 6E*l6 * 6*'|' * 6 6T'c*x6 ' * !6x*~6 * 6`*x6 * !6'{ *6 * ' 6O*c6 * 6o*x6 * 6H*6 * '*{6' *
6 *'x6x6 ' * *c 6[6 * *}6H6 * $'*6' 6 * *H6J6 * $6B*~6 * *u6Q6 * "'*{6' * 6 * '6H6 ' * $6H*6 * *H 6Q
6
* #'*}66 ' * *T6c6 * "*Q6]6 * *6c6 * $*l'Y6' * 6 'x6o*Y6 ' * *6Q6 * *| 6M
6 * #*'~6' 6 * *]6H6 * "*Y 6@6 * 6E*l6 * 6*'|' * 6 6T'c*x6 ' * !6x*~6 * 6`*x6 * !6'{ *6 * ' 6O*c6 * 6o*x6 * 6H*6 * '*{6' *
6 *'x6x6 ' * *c 6[6 * *}6H6 * $'*6' 6 * *H6J6 * $6B*~6 * *u6Q6 * "'*{6' * 6 * '6H6 ' * $6H*6 * *H 6Q
6
* #'*}66 ' * *T6c6 * "*Q6]6 * *6c6 * $*l'Y6' * 6 'x6o*Y6 ' * *6Q6 * *| 6M
6 * #*'~6' 6 * *]6H6 * "*Y 6@6 * 6E*l6 * 6*'|' * 6 6T'c*x6 ' * !6x*~6 * 6`*x6 * !6'{ *6 * ' 6O*c6 * 6o*x6 * 6H*6 * '*{6' *
6 *'x6x6 ' * / MTrk ! Bass " d
@ ] [ `r; c; V@4 Q; J; H; T; J; B; B; T; H; J; J; J; B%@ `; f5@ M; Q; `; `; `; Y; H; E; O; T; M; O; ]; T; @ o; :; @ J; O; H; T; E; @; J; J; E; Y; T; O; J; O.@
!|'@! =!T;! !M;! !O;! !J;! !T;! !Y"@ ! f @ H; J; J; H; O; M; =; x @ 2 O@4 Y; O; T; J; O; O; T; O; @; H; E; M; Y; f8@ !o*@! !O;! !O;! !M;! !T;! !J;! !O;! !V&@ ! l@" M; O; J; Y; T; H; V)@ #Y@# #B;# #B;# #T;# #H;# #E;# #E;# #E-@ # f!@ V; f; O; E; T; r; `,@ #`@!# #T;# #O;# #Y;# #`;# #Y;# #Q;# #f@