aboutsummaryrefslogtreecommitdiff
path: root/slipenc
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-05-03 23:23:46 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-05-03 23:23:46 +0000
commitd12a97f73664e552caec2010a3405b3a381076a1 (patch)
treeb002d482365abf844a78932c99350741f27d3544 /slipenc
parent34a543355e6dd46d36a600a4ff082558e626bf7a (diff)
slipenc encodes an input list of bytes-as-floats with the Serial Line Internet Protocol, suitable for transmission over a serial link. This is used in OSC 1.1.
svn path=/trunk/externals/mrpeach/; revision=13487
Diffstat (limited to 'slipenc')
-rw-r--r--slipenc/slipenc-help.pd36
-rw-r--r--slipenc/slipenc.c144
2 files changed, 180 insertions, 0 deletions
diff --git a/slipenc/slipenc-help.pd b/slipenc/slipenc-help.pd
new file mode 100644
index 0000000..d32ebfc
--- /dev/null
+++ b/slipenc/slipenc-help.pd
@@ -0,0 +1,36 @@
+#N canvas 631 295 583 358 10;
+#X obj -98 158 slipenc;
+#X obj -98 83 packOSC;
+#X msg -98 58 /test 1 2 3 192 218 219 220 221 222;
+#X obj -98 277 slipdec;
+#X text -36 159 Encodes a list of bytes for transmission through a
+serial link using SLIP (RFC1055). Useful for sending OSC through [comport].
+;
+#X text 76 315 Author: Martin Peach \, 2010/05/04;
+#X floatatom 35 142 5 0 0 0 - - -;
+#X text -35 77 SLIP is a simple encoding that prefixes each packet
+with 192 \, and replaces any occurence of 192 by the sequence 219 \,
+220 Also any occurrence of 219 will be replaced by 219 \, 221 The packet
+is ended with a final 192;
+#X text -100 0 [slipenc]: Encode a list of bytes using Serial Line
+Internet Protocol (SLIP);
+#X text -81 234 Note that SLIP limits the maximum packet size to 1006
+;
+#X obj -71 210 print encoded;
+#X obj -71 135 print original;
+#X obj -98 317 print decoded;
+#X obj -98 113 t a a;
+#X obj -98 186 t a a;
+#X text -47 279 Decodes a list of bytes that were encoded with SLIP.
+;
+#X text -100 28 [slipdec]: Decode a list of bytes using Serial Line
+Internet Protocol (SLIP);
+#X connect 0 0 14 0;
+#X connect 1 0 13 0;
+#X connect 2 0 1 0;
+#X connect 3 0 12 0;
+#X connect 6 0 0 0;
+#X connect 13 0 0 0;
+#X connect 13 1 11 0;
+#X connect 14 0 3 0;
+#X connect 14 1 10 0;
diff --git a/slipenc/slipenc.c b/slipenc/slipenc.c
new file mode 100644
index 0000000..fc2747b
--- /dev/null
+++ b/slipenc/slipenc.c
@@ -0,0 +1,144 @@
+/* slipenc.c 20070711 Martin Peach */
+/**encode a list of bytes as SLIP /
+/*
+/*
+From RFC 1055:
+PROTOCOL
+
+ The SLIP protocol defines two special characters: SLIP_END and SLIP_ESC. SLIP_END is
+ octal 300 (decimal 192) and SLIP_ESC is octal 333 (decimal 219) not to be
+ confused with the ASCII ESCape character; for the purposes of this
+ discussion, SLIP_ESC will indicate the SLIP SLIP_ESC character. To send a
+ packet, a SLIP host simply starts sending the data in the packet. If
+ a data byte is the same code as SLIP_END character, a two byte sequence of
+ SLIP_ESC and octal 334 (decimal 220) is sent instead. If it the same as
+ an SLIP_ESC character, an two byte sequence of SLIP_ESC and octal 335 (decimal
+ 221) is sent instead. When the last byte in the packet has been
+ sent, an SLIP_END character is then transmitted.
+
+ Phil Karn suggests a simple change to the algorithm, which is to
+ begin as well as end packets with an SLIP_END character. This will flush
+ any erroneous bytes which have been caused by line noise. In the
+ normal case, the receiver will simply see two back-to-back SLIP_END
+ characters, which will generate a bad IP packet. If the SLIP
+ implementation does not throw away the zero-length IP packet, the IP
+ implementation certainly will. If there was line noise, the data
+ received due to it will be discarded without affecting the following
+ packet.
+
+ Because there is no 'standard' SLIP specification, there is no real
+ defined maximum packet size for SLIP. It is probably best to accept
+ the maximum packet size used by the Berkeley UNIX SLIP drivers: 1006
+ bytes including the IP and transport protocol headers (not including
+ the framing characters). Therefore any new SLIP implementations
+ should be prepared to accept 1006 byte datagrams and should not send
+ more than 1006 bytes in a datagram.
+*/
+
+#include "m_pd.h"
+
+/* -------------------------- slipenc -------------------------- */
+#ifndef _SLIPCODES
+/* SLIP special character codes */
+#define SLIP_END 0300 /* indicates end of packet */
+#define SLIP_ESC 0333 /* indicates byte stuffing */
+#define SLIP_ESC_END 0334 /* SLIP_ESC SLIP_ESC_END means SLIP_END data byte */
+#define SLIP_ESC_ESC 0335 /* SLIP_ESC SLIP_ESC_ESC means SLIP_ESC data byte */
+#define MAX_SLIP 1006 /* maximum SLIP packet size */
+#define _SLIPCODES
+#endif // _SLIPCODES
+
+static t_class *slipenc_class;
+
+typedef struct _slipenc
+{
+ t_object x_obj;
+ t_outlet *x_slipenc_out;
+ t_atom *x_slip_buf;
+ t_int x_slip_length;
+} t_slipenc;
+
+static void *slipenc_new(t_symbol *s, int argc, t_atom *argv);
+static void slipenc_list(t_slipenc *x, t_symbol *s, int ac, t_atom *av);
+static void slipenc_free(t_slipenc *x);
+void slipenc_setup(void);
+
+static void *slipenc_new(t_symbol *s, int argc, t_atom *argv)
+{
+ int i;
+ t_slipenc *x = (t_slipenc *)pd_new(slipenc_class);
+
+ x->x_slip_buf = (t_atom *)getbytes(sizeof(t_atom)*MAX_SLIP);
+ if(x->x_slip_buf == NULL)
+ {
+ error("slipenc: unable to allocate %lu bytes for x_slip_buf", (long)sizeof(t_atom)*MAX_SLIP);
+ return NULL;
+ }
+ /* Initialize all the slip buf atoms to float type */
+ for (i = 0; i < MAX_SLIP; ++i) x->x_slip_buf[i].a_type = A_FLOAT;
+ x->x_slipenc_out = outlet_new(&x->x_obj, &s_list);
+ return (x);
+}
+
+static void slipenc_list(t_slipenc *x, t_symbol *s, int ac, t_atom *av)
+{
+ /* SLIP encode a list of bytes */
+ float f;
+ int i, c;
+
+ i = x->x_slip_length = 0;
+ /* send an initial SLIP_END character to flush out any data that may */
+ /* have accumulated in the receiver due to line noise */
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_END;
+
+ /* for each byte in the packet, send the appropriate character sequence */
+ while((i < ac) && (x->x_slip_length < (MAX_SLIP-1)))
+ {
+ /* check each atom for byteness */
+ f = atom_getfloat(&av[i++]);
+ c = (((int)f) & 0x0FF);
+ if (c != f)
+ {
+ /* abort, bad input character */
+ pd_error (x, "slipenc: input %d out of range [0..255]", f);
+ return;
+ }
+ if(SLIP_END == c)
+ {
+ /* If it's the same code as a SLIP_END character, replace it with a */
+ /* special two-character code so as not to make the receiver think we sent SLIP_END */
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_ESC;
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_ESC_END;
+ }
+ else if (SLIP_ESC == c)
+ {
+ /* If it's the same code as a SLIP_ESC character, replace it with a special two-character code */
+ /* so as not to make the receiver think we sent SLIP_ESC */
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_ESC;
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_ESC_ESC;
+ }
+ else
+ {
+ /* Otherwise, pass the character */
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = c;
+ }
+ }
+ /* Add the SLIP_END code to tell the receiver that the packet is complete */
+ x->x_slip_buf[x->x_slip_length++].a_w.w_float = SLIP_END;
+ outlet_list(x->x_slipenc_out, &s_list, x->x_slip_length, x->x_slip_buf);
+}
+
+static void slipenc_free(t_slipenc *x)
+{
+ if (x->x_slip_buf != NULL) freebytes((void *)x->x_slip_buf, sizeof(t_atom)*MAX_SLIP);
+}
+
+void slipenc_setup(void)
+{
+ slipenc_class = class_new(gensym("slipenc"),
+ (t_newmethod)slipenc_new, (t_method)slipenc_free,
+ sizeof(t_slipenc), 0, A_GIMME, 0);
+ class_addlist(slipenc_class, slipenc_list);
+}
+
+/* fin slipenc.c*/