aboutsummaryrefslogtreecommitdiff
path: root/cmos/cd40193.c
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2007-03-20 16:06:17 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2007-03-20 16:06:17 +0000
commit8a36990c0305ea2effba5e869351b902ecb429b0 (patch)
tree01aa72be2cddadbe1f26db56ce17c84f3bf99127 /cmos/cd40193.c
parentaf3619555f5c60450da97c74ec3c1f9c14f3133d (diff)
CMOS digital logic emulation objects
svn path=/trunk/externals/mrpeach/; revision=7509
Diffstat (limited to 'cmos/cd40193.c')
-rwxr-xr-xcmos/cd40193.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/cmos/cd40193.c b/cmos/cd40193.c
new file mode 100755
index 0000000..22bdcbc
--- /dev/null
+++ b/cmos/cd40193.c
@@ -0,0 +1,250 @@
+/* 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;
+ t_int x_countUp;
+ t_int x_countDown;
+ t_int x_dataA;
+ t_int x_dataB;
+ t_int x_dataC;
+ t_int x_dataD;
+ t_int x_load;
+ t_int x_clear;
+ t_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 */
+