1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
/* slipdec.c 20100513 Martin Peach */
/* decode a list of SLIP-encoded bytes */
#include "m_pd.h"
/* -------------------------- slipdec -------------------------- */
#ifndef _SLIPCODES
/* SLIP special character codes */
#define SLIP_END 0300 /* decimal 192 indicates end of packet */
#define SLIP_ESC 0333 /* decimal 219 indicates byte stuffing */
#define SLIP_ESC_END 0334 /* decimal 220 SLIP_ESC_END means SLIP_END as data byte */
#define SLIP_ESC_ESC 0335 /* decimal 221 SLIP_ESC_ESC means SLIP_ESC as data byte */
#define MAX_SLIP 1006 /* maximum SLIP packet size */
#define _SLIPCODES
#endif /* _SLIPCODES */
static t_class *slipdec_class;
typedef struct _slipdec
{
t_object x_obj;
t_outlet *x_slipdec_out;
t_outlet *x_status_out;
t_atom *x_slip_buf;
int x_slip_length;
int x_slip_max_length;
int x_valid_SLIP;
int x_esced;
int x_verbose;
} t_slipdec;
static void *slipdec_new(t_symbol *s, int argc, t_atom *argv);
static void slipdec_dump(t_slipdec *x, int dosend);
static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av);
static void slipdec_float(t_slipdec *x, t_float f);
static void slipdec_verbosity(t_slipdec *x, t_float f);
static void slipdec_free(t_slipdec *x);
void slipdec_setup(void);
static void *slipdec_new(t_symbol *s, int argc, t_atom *argv)
{
int i;
t_slipdec *x = (t_slipdec *)pd_new(slipdec_class);
if (x == NULL) return x;
x->x_slip_max_length = MAX_SLIP;// default unless a float argument is given
for (i = 0; i < argc; ++i)
{
if (argv[i].a_type == A_FLOAT)
{
x->x_slip_max_length = atom_getfloat(&argv[i]);
post("slipdec: maximum packet length is %d", x->x_slip_max_length);
break;
}
}
x->x_slip_buf = (t_atom *)getbytes(sizeof(t_atom)*x->x_slip_max_length);
if(x->x_slip_buf == NULL)
{
pd_error(x, "slipdec: unable to allocate %lu bytes for x_slip_buf", (long)sizeof(t_atom)*x->x_slip_max_length);
return NULL;
}
/* init the slip buf atoms to float type */
for (i = 0; i < x->x_slip_max_length; ++i) x->x_slip_buf[i].a_type = A_FLOAT;
x->x_slipdec_out = outlet_new(&x->x_obj, &s_list);
x->x_status_out = outlet_new(&x->x_obj, &s_anything);
x->x_valid_SLIP = 1;
return (x);
}
static void slipdec_dump(t_slipdec *x, int dosend)
{
outlet_float(x->x_status_out, x->x_valid_SLIP);
if(dosend)
{
if ((0 != x->x_valid_SLIP) && (x->x_slip_length > 0))
outlet_list(x->x_slipdec_out, &s_list, x->x_slip_length, x->x_slip_buf);
}
x->x_slip_length = x->x_esced = 0;
x->x_valid_SLIP = 1;
}
static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av)
{
/* SLIP decode a list of bytes */
float f;
int i, c;
if (x->x_verbose) post ("slipdec_list: buffer length %d, esc = %d", x->x_slip_length, x->x_esced);
/* x_slip_length will be non-zero if an incomplete packet is in the buffer */
if ((ac + x->x_slip_length) > x->x_slip_max_length)
{
pd_error (x, "slipdec_list: input packet longer than %d", x->x_slip_max_length);
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);// reset
return;
}
/* for each byte in the packet, send the appropriate character sequence */
for(i = 0; ((i < ac) && (x->x_slip_length < x->x_slip_max_length)); ++i)
{
/* check each atom for byteness */
f = atom_getfloat(&av[i]);
c = (((int)f) & 0x0FF);
if (c != f)
{
/* abort, input list needs to be fixed before this is gonna wuk */
pd_error (x, "slipdec: input %f out of range [0..255]", f);
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);// reset
return;
}
if(SLIP_END == c)
{
if (x->x_verbose) post ("slipdec_list: SLIP_END at %d", x->x_slip_length);
/* If it's the beginning of a packet, ignore it */
if (x->x_slip_length)
{
if (x->x_verbose) post ("slipdec_list: end of packet");
/* send the packet */
slipdec_dump(x, 1);
}
continue;
}
if (SLIP_ESC == c)
{
if (x->x_verbose) post ("slipdec_list: SLIP_ESC %f = %d", f, c);
x->x_esced = 1;
continue;
}
if (1 == x->x_esced)
{
if (SLIP_ESC_END == c) c = SLIP_END;
else if (SLIP_ESC_ESC == c) c = SLIP_ESC;
else
{
pd_error (x, "slipdec_list: SLIP_ESC not followed by 220 or 221 (%d)", c);
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);/* reset */
return;
}
x->x_esced = 0;
}
/* Add the character to the buffer */
if (x->x_verbose) post ("slipdec_list: adding character %d to buffer[%d]", c, x->x_slip_length);
x->x_slip_buf[x->x_slip_length++].a_w.w_float = c;
}
}
static void slipdec_float(t_slipdec *x, t_float f)
{
/* SLIP decode a byte */
int c;
if (x->x_verbose) post ("slipdec_float: buffer length %d, esc = %d", x->x_slip_length, x->x_esced);
/* for each byte in the packet, send the appropriate character sequence */
/* check each atom for byteness */
c = (((int)f) & 0x0FF);
if (c != f)
{
/* abort, input list needs to be fixed before this is gonna wuk */
pd_error (x, "slipdec: input %f out of range [0..255]", f);
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);/* reset */
return;
}
if(SLIP_END == c)
{
if (x->x_verbose) post ("slipdec_float: SLIP_END at %d", x->x_slip_length);
/* If it's the beginning of a packet, ignore it */
if (0 == x->x_slip_length) return;
/* send the packet */
else
{
if (x->x_verbose) post ("slipdec_float: end of packet");
slipdec_dump(x, 1);
return;
}
}
if (SLIP_ESC == c)
{
if (x->x_verbose) post ("slipdec_float: SLIP_ESC %f = %d", f, c);
x->x_esced = 1;
return;
}
if (1 == x->x_esced)
{
if (SLIP_ESC_END == c) c = SLIP_END;
else if (SLIP_ESC_ESC == c) c = SLIP_ESC;
else
{
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);/* reset */
pd_error (x, "slipdec_float: SLIP_ESC not followed by 220 or 221 (%d)", c);
return;
}
if (x->x_verbose) post ("slipdec_float: ESCED %f = %d", f, c);
x->x_esced = 0;
}
/* Add the character to the buffer */
if (x->x_slip_length < x->x_slip_max_length)
{
if (x->x_verbose) post ("slipdec_float: adding character %d to buffer[%d]", c, x->x_slip_length);
x->x_slip_buf[x->x_slip_length++].a_w.w_float = c;
}
else
{
pd_error (x, "slipdec: input packet longer than %d", x->x_slip_length);
x->x_valid_SLIP = 0; /* not valid SLIP */
slipdec_dump(x,0);/* reset */
}
}
static void slipdec_verbosity(t_slipdec *x, t_float f)
{
x->x_verbose = (0 != f)?1:0;
}
static void slipdec_free(t_slipdec *x)
{
if (x->x_slip_buf != NULL) freebytes((void *)x->x_slip_buf, sizeof(t_atom)*x->x_slip_max_length);
}
void slipdec_setup(void)
{
slipdec_class = class_new(gensym("slipdec"),
(t_newmethod)slipdec_new, (t_method)slipdec_free,
sizeof(t_slipdec), 0, A_GIMME, 0);
class_addlist(slipdec_class, slipdec_list);
class_addfloat(slipdec_class, slipdec_float);
class_addmethod(slipdec_class, (t_method)slipdec_verbosity, gensym("verbosity"), A_FLOAT, 0);
}
/* fin slipdec.c */
|