/* 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 */