示例#1
0
static VALUE
step_initialize( int argc, VALUE *argv, VALUE self )
{
    VALUE a, b=Qnil, c=Qnil, d=Qnil, e=Qnil;

    rb_scan_args(argc, argv, "13", &a, &b, &c, &d);
    /* Selfs are immutable, so that they should be initialized only once. */
    if (rb_ivar_defined(self, id_beg)) {
        rb_name_error(rb_intern("initialize"), "`initialize' called twice");
    }
    if (rb_obj_is_kind_of(a,rb_cRange)) {
        if (argc>3) {
            rb_raise(rb_eArgError, "extra argument");
        }
        d = c;
        c = b;
        e = rb_funcall(a, rb_intern("exclude_end?"), 0);
        //b = rb_ivar_get(a, id_end);
        b = rb_funcall(a, id_end, 0);
        //a = rb_ivar_get(a, id_beg);
        a = rb_funcall(a, id_beg, 0);
    }
    step_init(self, a, b, c, d, e);
    return Qnil;
}
示例#2
0
void Yao::proc_gen_out()
{
	step_init();

	double start;

	EVL_BEGIN
		start = MPI_Wtime();
			m_gen_out = m_ccts[0].m_gen_out;
		m_timer_evl += MPI_Wtime() - start;

		start = MPI_Wtime();
			EVL_SEND(m_gen_out);
		m_timer_com += MPI_Wtime() - start;
	EVL_END

	GEN_BEGIN
		start = MPI_Wtime();
			m_gen_out = GEN_RECV();
		m_timer_com += MPI_Wtime() - start;
	GEN_END

	m_comm_sz += m_gen_out.size();

	step_report("chk-gen-out");
}
示例#3
0
void Yao::proc_evl_out()
{
	EVL_BEGIN
		step_init();

		double start = MPI_Wtime();
			m_evl_out = m_ccts[0].m_evl_out;
		m_timer_evl += MPI_Wtime() - start;

		step_report("chk-evl-out");
	EVL_END
}
示例#4
0
VALUE
nary_step_new(
  VALUE beg,
  VALUE end,
  VALUE step,
  VALUE len,
  VALUE excl
)
{
    VALUE self = rb_obj_alloc(na_cStep);

    step_init(self, beg, end, step, len, excl);
    return self;
}
void BetterYao2::proc_gen_out()
{
	step_init();

	// TODO: implement Ki08
	m_gen_out = m_ccts[0].m_gen_out;

	EVL_BEGIN
		send_data(Env::world_rank()-1, m_gen_out);
	EVL_END

	GEN_BEGIN
		m_gen_out = recv_data(Env::world_rank()+1);
	GEN_END

	step_report("chk-gen-out");
}
void BetterYao2::proc_evl_out()
{
	EVL_BEGIN
		step_init();

		double start;
		Bytes send, recv;

		start = MPI_Wtime();
			const Bytes ZEROS((Env::circuit().evl_out_cnt()+7)/8, 0);

			for (size_t ix = 0; ix < m_ccts.size(); ix++) // fill zeros for uniformity (convenient to MPIs)
			{
				send += (m_chks[ix])? ZEROS : m_ccts[ix].m_evl_out;
			}

			if (Env::group_rank() == 0)
			{
				recv.resize(send.size()*Env::node_amnt());
			}
		m_timer_evl += MPI_Wtime() - start;

		start = MPI_Wtime();
			MPI_Gather(&send[0], send.size(), MPI_BYTE, &recv[0], send.size(), MPI_BYTE, 0, m_mpi_comm);
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			if (Env::is_root())
			{
				size_t chks_total = 0;
				for (size_t ix = 0; ix < m_all_chks.size(); ix++)
					chks_total += m_all_chks[ix];

				// find majority by locating the median of output from evaluation-circuits
				std::vector<Bytes> vec = recv.split((Env::circuit().evl_out_cnt()+7)/8);
				size_t median_ix = (chks_total+vec.size())/2;
				std::nth_element(vec.begin(), vec.begin()+median_ix, vec.end());

				m_evl_out = *(vec.begin()+median_ix);
			}
		m_timer_evl += MPI_Wtime() - start;

		step_report("chk-evl-out");
	EVL_END
}
示例#7
0
VALUE
nary_step_new2(
  VALUE range,
  VALUE step,
  VALUE len
)
{
    VALUE beg, end, excl;
    VALUE self = rb_obj_alloc(na_cStep);

    //beg = rb_ivar_get(range, id_beg);
    beg = rb_funcall(range, id_beg, 0);
    //end = rb_ivar_get(range, id_end);
    end = rb_funcall(range, id_end, 0);
    excl = rb_funcall(range, rb_intern("exclude_end?"), 0);

    step_init(self, beg, end, step, len, excl);
    return self;
}
示例#8
0
void Yao::oblivious_transfer()
{
	step_init();

	double start; // time marker

	Bytes send, recv, bufr(Env::elm_size_in_bytes()*4);
	std::vector<Bytes> bufr_chunks, recv_chunks;

	G X[2], Y[2], gr, hr;
    Z s[2], t[2],  y,  a,  r;

	// step 1: generating the CRS: g[0], h[0], g[1], h[1]
	if (Env::is_root())
	{
		EVL_BEGIN
			start = MPI_Wtime();
				y.random();
				a.random();

				m_ot_g[0].random();
				m_ot_g[1] = m_ot_g[0]^y;          // g[1] = g[0]^y

				m_ot_h[0] = m_ot_g[0]^a;          // h[0] = g[0]^a
				m_ot_h[1] = m_ot_g[1]^(a + Z(1)); // h[1] = g[1]^(a+1)

				bufr.clear();
				bufr += m_ot_g[0].to_bytes();
				bufr += m_ot_g[1].to_bytes();
				bufr += m_ot_h[0].to_bytes();
				bufr += m_ot_h[1].to_bytes();
			m_timer_evl += MPI_Wtime() - start;

			start = MPI_Wtime(); // send to Gen's root process
				EVL_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		EVL_END

		GEN_BEGIN
			start = MPI_Wtime();
				bufr = GEN_RECV();
			m_timer_com += MPI_Wtime() - start;
		GEN_END

	    m_comm_sz += bufr.size();
	}

	// send g[0], g[1], h[0], h[1] to slave processes
	start = MPI_Wtime();
		MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm);
	m_timer_mpi += MPI_Wtime() - start;

	start = MPI_Wtime();
		bufr_chunks = bufr.split(Env::elm_size_in_bytes());

		m_ot_g[0].from_bytes(bufr_chunks[0]);
		m_ot_g[1].from_bytes(bufr_chunks[1]);
		m_ot_h[0].from_bytes(bufr_chunks[2]);
		m_ot_h[1].from_bytes(bufr_chunks[3]);

		// pre-processing
		m_ot_g[0].fast_exp();
		m_ot_g[1].fast_exp();
		m_ot_h[0].fast_exp();
		m_ot_h[1].fast_exp();

		// allocate memory for m_keys
		m_ot_keys.resize(Env::node_load());
		for (size_t ix = 0; ix < m_ot_keys.size(); ix++)
		{
			m_ot_keys[ix].reserve(Env::circuit().evl_inp_cnt()*2);
		}
	m_timer_evl += MPI_Wtime() - start;
	m_timer_gen += MPI_Wtime() - start;

	// Step 2: ZKPoK of (g[0], g[1], h[0], h[1])
	// TODO

	// Step 3: gr=g[b]^r, hr=h[b]^r, where b is the evaluator's bit
	if (Env::is_root())
	{
		EVL_BEGIN
			start = MPI_Wtime();
				bufr.clear(); bufr.reserve(Env::exp_size_in_bytes()*Env::circuit().evl_inp_cnt());
				send.clear(); send.reserve(Env::elm_size_in_bytes()*Env::circuit().evl_inp_cnt()*2);
				for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++)
				{
					r.random();
					bufr += r.to_bytes();  // to be shared with slave evaluators

					byte bit_value = m_evl_inp.get_ith_bit(bix);
					send += (m_ot_g[bit_value]^r).to_bytes(); // gr
					send += (m_ot_h[bit_value]^r).to_bytes(); // hr
				}
			m_timer_evl += MPI_Wtime() - start;

			start = MPI_Wtime();
				EVL_SEND(send); // send (gr, hr)'s
			m_timer_com += MPI_Wtime() - start;

			m_comm_sz += send.size();
		EVL_END

		GEN_BEGIN
			start = MPI_Wtime();
				bufr = GEN_RECV(); // receive (gr, hr)'s
			m_timer_com += MPI_Wtime() - start;

			m_comm_sz += bufr.size();
		GEN_END
	}

	EVL_BEGIN // forward rs to slave evaluators
		start = MPI_Wtime();
			bufr.resize(Env::exp_size_in_bytes()*Env::circuit().evl_inp_cnt());
		m_timer_evl += MPI_Wtime() - start;

		start = MPI_Wtime();
			MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); // now every evaluator has r's
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			bufr_chunks = bufr.split(Env::exp_size_in_bytes());
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	GEN_BEGIN // forward (gr, hr)s to slave generators
		start = MPI_Wtime();
			bufr.resize(Env::elm_size_in_bytes()*Env::circuit().evl_inp_cnt()*2);
		m_timer_gen += MPI_Wtime() - start;

		start = MPI_Wtime();
			MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); // now every Bob has bufr
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			bufr_chunks = bufr.split(Env::elm_size_in_bytes());
		m_timer_gen += MPI_Wtime() - start;
	GEN_END

	// Step 4: the generator computes X[0], Y[0], X[1], Y[1]
	GEN_BEGIN
		for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++)
		{
			start = MPI_Wtime();
				gr.from_bytes(bufr_chunks[2*bix+0]);
				hr.from_bytes(bufr_chunks[2*bix+1]);

				if (m_ot_keys.size() > 2)
				{
					gr.fast_exp();
					hr.fast_exp();
				}
			m_timer_gen += MPI_Wtime() - start;

			for (size_t cix = 0; cix < m_ot_keys.size(); cix++)
			{
				start = MPI_Wtime();
					Y[0].random(); // K[0]
					Y[1].random(); // K[1]

					m_ot_keys[cix].push_back(Y[0].to_bytes().hash(Env::k()));
					m_ot_keys[cix].push_back(Y[1].to_bytes().hash(Env::k()));

					s[0].random(); s[1].random();
					t[0].random(); t[1].random();

					// X[b] = ( g[b]^s[b] ) * ( h[b]^t[b] ), where b = 0, 1
					X[0] = m_ot_g[0]^s[0]; X[0] *= m_ot_h[0]^t[0];
					X[1] = m_ot_g[1]^s[1]; X[1] *= m_ot_h[1]^t[1];

					// Y[b] = ( gr^s[b] ) * ( hr^t[b] ) * K[b], where b = 0, 1
					Y[0] *= gr^s[0]; Y[0] *= hr^t[0];
					Y[1] *= gr^s[1]; Y[1] *= hr^t[1];

					send.clear();
					send += X[0].to_bytes(); send += X[1].to_bytes();
					send += Y[0].to_bytes(); send += Y[1].to_bytes();
				m_timer_gen += MPI_Wtime() - start;

				start = MPI_Wtime();
					GEN_SEND(send);
				m_timer_com += MPI_Wtime() - start;

				m_comm_sz += send.size();
			}
		}

		for (size_t ix = 0; ix < m_ot_keys.size(); ix++)
		{
			assert(m_ot_keys[ix].size() == Env::circuit().evl_inp_cnt()*2);
		}
	GEN_END

	// Step 5: the evaluator computes K = Y[b]/X[b]^r
	EVL_BEGIN
		for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++)
		{
			start = MPI_Wtime();
				int bit_value = m_evl_inp.get_ith_bit(bix);
				r.from_bytes(bufr_chunks[bix]);
			m_timer_evl += MPI_Wtime() - start;

			for (size_t cix = 0; cix < m_ot_keys.size(); cix++)
			{
				start = MPI_Wtime();
					recv = EVL_RECV(); // receive X[0], X[1], Y[0], Y[1]
				m_timer_com += MPI_Wtime() - start;

				m_comm_sz += recv.size();

				start = MPI_Wtime();
					recv_chunks = recv.split(Env::elm_size_in_bytes());

					X[bit_value].from_bytes(recv_chunks[    bit_value]); // X[b]
					Y[bit_value].from_bytes(recv_chunks[2 + bit_value]); // Y[b]

					// K = Y[b]/(X[b]^r)
					Y[bit_value] /= X[bit_value]^r;
					m_ot_keys[cix].push_back(Y[bit_value].to_bytes().hash(Env::k()));
				m_timer_evl += MPI_Wtime() - start;
			}
		}

		for (size_t ix = 0; ix < m_ot_keys.size(); ix++)
		{
			assert(m_ot_keys[ix].size() == Env::circuit().evl_inp_cnt());
		}
	EVL_END

	step_report("ob-transfer");
}
示例#9
0
void Yao::circuit_evaluate()
{
	step_init();

	double start;

	Bytes bufr;
	vector<Bytes> bufr_chunks;

	G M;

	for (size_t ix = 0; ix < m_ccts.size(); ix++)
	{
		GEN_BEGIN
			start = MPI_Wtime();
				m_rnds[ix] = m_prng.rand(Env::k());
				m_gen_inp_masks[ix] = m_prng.rand(Env::circuit().gen_inp_cnt());
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(m_gen_inp_masks[ix] ^ m_gen_inp); // send the masked gen_inp
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]);
			m_timer_gen += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				m_gen_inp_masks[ix] = EVL_RECV(); // receive the masked gen_inp
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				m_ccts[ix].evl_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_evl_inp);
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += m_gen_inp_masks[ix].size();
	}

	GEN_BEGIN
		start = MPI_Wtime();
			bufr.clear();
			for (int ix = 0; ix < Env::circuit().gen_inp_cnt(); ix++)
			{
				bool bit_value = m_gen_inp.get_ith_bit(ix);
				bufr += m_ccts[0].m_M[2*ix+bit_value].to_bytes();
			}
		m_timer_gen += MPI_Wtime() - start;

		start = MPI_Wtime();
			GEN_SEND(bufr);
		m_timer_com += MPI_Wtime() - start;
	GEN_END

	EVL_BEGIN
		start = MPI_Wtime();
			bufr = EVL_RECV();
		m_timer_com += MPI_Wtime() - start;

		start = MPI_Wtime();
			bufr_chunks = bufr.split(Env::elm_size_in_bytes());
			for (size_t ix = 0, kx = 0; ix < Env::circuit().gen_inp_cnt(); ix++)
			{
				M.from_bytes(bufr_chunks[ix]);

				for (size_t jx = 0; jx < m_ccts.size(); jx++)
				{
					m_ccts[jx].m_M.push_back(M);
				}
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	m_comm_sz += bufr.size();

	step_report("pre-cir-evl");
	step_init();

	GEN_BEGIN // generate and send the circuit gate-by-gate
		start = MPI_Wtime();
			while (Env::circuit().more_gate_binary())
			{
				const Gate &g = Env::circuit().next_gate_binary();

				for (size_t ix = 0; ix < m_ccts.size(); ix++)
				{
						m_ccts[ix].gen_next_gate(g);
						bufr = m_ccts[ix].send();
					m_timer_gen += MPI_Wtime() - start;

					start = MPI_Wtime();
						GEN_SEND(bufr);
					m_timer_com += MPI_Wtime() - start;

					m_comm_sz += bufr.size();

					start = MPI_Wtime(); // start m_timer_gen
				}
			}
		m_timer_gen += MPI_Wtime() - start;
	GEN_END

	EVL_BEGIN // receive and evaluate the circuit gate-by-gate
		start = MPI_Wtime();
			while (Env::circuit().more_gate_binary())
			{
				const Gate &g = Env::circuit().next_gate_binary();

				for (size_t ix = 0; ix < m_ccts.size(); ix++)
				{
					m_timer_evl += MPI_Wtime() - start;

					start = MPI_Wtime();
						bufr = EVL_RECV();
					m_timer_com += MPI_Wtime() - start;

					m_comm_sz += bufr.size();

					start = MPI_Wtime();
						m_ccts[ix].recv(bufr);
						m_ccts[ix].evl_next_gate(g);
				}
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	step_report("circuit-evl");

	if (Env::circuit().evl_out_cnt() != 0)
		proc_evl_out();

    if (Env::circuit().gen_out_cnt() != 0)
        proc_gen_out();
}
void BetterYao2::circuit_evaluate()
{
	step_init();

	double start;

	int verify = 1;
	Bytes bufr;

	EVL_BEGIN
		start = MPI_Wtime();
			for (size_t ix = 0; ix < m_ccts.size(); ix++)
			{
				if (m_chks[ix]) // check-circuits
				{
					m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]);
				}
				else // evaluation-circuits
				{
					m_ccts[ix].evl_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_evl_inp);
				}
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	step_report("pre-cir-evl");
	step_init();

	GEN_BEGIN // start generating circuits gate-by-gate
		start = MPI_Wtime();
			while (Env::circuit().more_gate_binary())
			{
				const Gate &g = Env::circuit().next_gate_binary();

				for (size_t ix = 0; ix < m_ccts.size(); ix++)
				{
						m_ccts[ix].gen_next_gate(g);
						bufr = m_ccts[ix].send();
					m_timer_gen += MPI_Wtime() - start;

					start = MPI_Wtime();
						GEN_SEND(bufr);
					m_timer_com += MPI_Wtime() - start;

					m_comm_sz += bufr.size();

					start = MPI_Wtime(); // start m_timer_gen
				}
			}
		m_timer_gen += MPI_Wtime() - start;
	GEN_END

	EVL_BEGIN
		start = MPI_Wtime();
			int gate_ix = 0;
			while (Env::circuit().more_gate_binary())
			{
				const Gate &g = Env::circuit().next_gate_binary();

				for (size_t ix = 0; ix < m_ccts.size(); ix++)
				{
					m_timer_evl += MPI_Wtime() - start;

					start = MPI_Wtime();
						bufr = EVL_RECV();
					m_timer_com += MPI_Wtime() - start;

					m_comm_sz += bufr.size();

					start = MPI_Wtime();
						if (m_chks[ix]) // check-circuits
						{
							m_ccts[ix].gen_next_gate(g);
							verify &= (m_ccts[ix].send() == bufr);
						}
						else // evaluation-circuits
						{
							m_ccts[ix].recv(bufr);
							m_ccts[ix].evl_next_gate(g);
						}
				}
				gate_ix ++;
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	EVL_BEGIN // check the hash of all the garbled circuits
		int all_verify = 0;

		start = MPI_Wtime();
			MPI_Reduce(&verify, &all_verify, 1, MPI_INT, MPI_LAND, 0, m_mpi_comm);
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			if (Env::is_root() && !all_verify)
			{
				LOG4CXX_FATAL(logger, "Verification failed");
				MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	step_report("circuit-evl");

	if (Env::circuit().evl_out_cnt() != 0)
		proc_evl_out();

    if (Env::circuit().gen_out_cnt() != 0)
        proc_gen_out();
}
void BetterYao2::consistency_check()
{
	step_init();

	Bytes send, recv, bufr;
	std::vector<Bytes> recv_chunks, bufr_chunks;

	double start;

	Z m;

	if (Env::is_root())
	{
		GEN_BEGIN // give away the generator's input M_{0,j}
			start = MPI_Wtime();
				bufr.clear();
				for (int jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++)
				{
					bool bit_value = m_gen_inp.get_ith_bit(jx);
					bufr += m_ccts[0].m_M[2*jx+bit_value].to_bytes();
				}
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();
	}

	EVL_BEGIN // forward the generator's input M_{0,j} to slave evaluators
		start = MPI_Wtime();
			bufr.resize(Env::elm_size_in_bytes()*Env::circuit().gen_inp_cnt());
		m_timer_evl += MPI_Wtime() - start;

		start = MPI_Wtime();
			MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm);
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			bufr_chunks = bufr.split(Env::elm_size_in_bytes());
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	GEN_BEGIN // give away m_{i,j}-m_{0,j} so that M_{i,j} can be reconstructed
		start = MPI_Wtime();
			if (Env::is_root()) // forward m_{0,j} to slave generators
			{
				bufr.clear();
				for (size_t jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++)
				{
					bool bit_value = m_gen_inp.get_ith_bit(jx);
					bufr += m_ccts[0].m_m[2*jx+bit_value].to_bytes();
				}
			}
			bufr.resize(Env::exp_size_in_bytes()*Env::circuit().gen_inp_cnt());
		m_timer_gen += MPI_Wtime() - start;

		start = MPI_Wtime();
			MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm);
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			bufr_chunks = bufr.split(Env::exp_size_in_bytes());

			send.clear();
			send.reserve(Env::exp_size_in_bytes()*Env::circuit().gen_inp_cnt()*m_ccts.size());
			for (size_t jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++)
			{
				m.from_bytes(bufr_chunks[jx]); // retrieve m_{0,j}
				bool bit_value = m_gen_inp.get_ith_bit(jx);

				for (size_t ix = 0; ix < m_ccts.size(); ix++)
				{
					if (m_chks[ix]) // no data for check-circuits
						continue;
					send += (m_ccts[ix].m_m[2*jx+bit_value]-m).to_bytes(); // m_{i,j}-m_{0,j}
				}
			}
		m_timer_gen += MPI_Wtime() - start;

		start = MPI_Wtime();
			GEN_SEND(send);
		m_timer_com += MPI_Wtime() - start;

		m_comm_sz += send.size();
	GEN_END

	int verify = 1;
	G M;

	EVL_BEGIN
		start = MPI_Wtime();
			recv = EVL_RECV();
		m_timer_com += MPI_Wtime() - start;

		m_comm_sz += recv.size();

		start = MPI_Wtime();
			recv_chunks = recv.split(Env::exp_size_in_bytes());
			for (size_t ix = 0, kx = 0; ix < Env::circuit().gen_inp_cnt(); ix++)
			{
				M.from_bytes(bufr_chunks[ix]);

				for (size_t jx = 0; jx < m_ccts.size(); jx++)
				{
					if (m_chks[jx])
						continue;

					// reconstruct M_{i,j}
					m.from_bytes(recv_chunks[kx++]);                // m = m_{i,j}-m_{0,j}
					M *= Env::clawfree().R(m);                      // M_{i,j} = h^m * M_{0,j}
					verify &= (m_ccts[jx].m_M[ix] == M);
				}
			}
		m_timer_evl += MPI_Wtime() - start;

		int all_verify = 0;

		start = MPI_Wtime();
			MPI_Reduce(&verify, &all_verify, 1, MPI_INT, MPI_LAND, 0, m_mpi_comm);
		m_timer_mpi += MPI_Wtime() - start;

		start = MPI_Wtime();
			if (Env::is_root() && !all_verify)
			{
				LOG4CXX_FATAL(logger, "consistency check failed");
				MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	step_report("const-check");
}
void BetterYao2::cut_and_choose2()
{
	step_init();
	double start;

	Bytes bufr;
	vector<Bytes> bufr_chunks;

	m_ot_bit_cnt = Env::node_load();

	EVL_BEGIN
		start = MPI_Wtime();
			m_ot_recv_bits.resize((m_ot_bit_cnt+7)/8);
			for (size_t ix = 0; ix < m_chks.size(); ix++)
			{
				m_ot_recv_bits.set_ith_bit(ix, m_chks[ix]);
			}
		m_timer_evl += MPI_Wtime() - start;
	EVL_END

	ot_init();
	ot_random();

	GEN_BEGIN
		start = MPI_Wtime();
			for (size_t ix = 0; ix < m_ccts.size(); ix++)
			{
				m_rnds[ix] = m_prng.rand(Env::k());
				m_gen_inp_masks[ix] = m_prng.rand(Env::circuit().gen_inp_cnt());
				m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]);
			}
		m_timer_gen += MPI_Wtime() - start;
	GEN_END

	Prng prng;
	G M;

	for (size_t ix = 0; ix < m_ccts.size(); ix++)
	{
		// evaluation-circuit branch of OT
		GEN_BEGIN
			start = MPI_Wtime(); // send group elements representing m_gen_inp
				bufr.clear();
				prng.srand(m_ot_out[2*ix+0]);
				for (size_t bix = 0; bix < Env::circuit().gen_inp_cnt(); bix++)
				{
					byte bit_value = m_gen_inp.get_ith_bit(bix);
					bufr += m_ccts[ix].m_M[2*bix+bit_value].to_bytes();
				}
				bufr ^= prng.rand(bufr.size()*8);
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (m_chks[ix] == 0)
				{
					prng.srand(m_ot_out[ix]);
					bufr ^= prng.rand(bufr.size()*8);
					bufr_chunks = bufr.split(Env::elm_size_in_bytes());
					for (size_t bix = 0; bix < bufr_chunks.size(); bix++)
					{
						M.from_bytes(bufr_chunks[bix]);
						m_ccts[ix].m_M.push_back(M);
					}
				}
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();

		GEN_BEGIN
			start = MPI_Wtime(); // send the masked m_gen_inp
				bufr = m_gen_inp_masks[ix] ^ m_gen_inp;
				bufr ^= prng.rand(bufr.size()*8);
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (m_chks[ix] == 0)
				{
					bufr ^= prng.rand(bufr.size()*8);
					m_gen_inp_masks[ix] = bufr;
				}
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();

		// check-circuit branch of OT
		GEN_BEGIN
			start = MPI_Wtime(); // send the m_gen_inp_masks[ix]
				prng.srand(m_ot_out[2*ix+1]);
				bufr = m_gen_inp_masks[ix];
				bufr ^= prng.rand(bufr.size()*8);
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (m_chks[ix])
				{
					prng.srand(m_ot_out[ix]);
					bufr ^= prng.rand(bufr.size()*8);
					m_gen_inp_masks[ix] = bufr;
				}
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();

		GEN_BEGIN
			start = MPI_Wtime(); // send the masked m_gen_inp
				bufr = m_rnds[ix];
				bufr ^= prng.rand(bufr.size()*8);
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (m_chks[ix])
				{
					bufr ^= prng.rand(bufr.size()*8);
					m_rnds[ix] = bufr;
				}
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();

		GEN_BEGIN
			start = MPI_Wtime(); // send the m_ot_keys
				bufr = Bytes(m_ot_keys[ix]);
				bufr ^= prng.rand(bufr.size()*8);
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(bufr);
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		EVL_BEGIN
			start = MPI_Wtime();
				bufr = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (m_chks[ix])
				{
					bufr ^= prng.rand(bufr.size()*8);
					m_ot_keys[ix] = bufr.split(Env::key_size_in_bytes());
				}
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		m_comm_sz += bufr.size();
	}

	step_report("cut-'n-chk2");
}
void BetterYao2::cut_and_choose()
{
	step_init();

	double start;

	if (Env::is_root())
	{
		Bytes coins = m_prng.rand(Env::k());          // Step 0: flip coins
		Bytes remote_coins, comm, open;

		EVL_BEGIN
			start = MPI_Wtime();
				comm = EVL_RECV();                    // Step 1: receive bob's commitment
				EVL_SEND(coins);                      // Step 2: send coins to bob
				open = EVL_RECV();
			m_timer_com += MPI_Wtime() - start;

			start = MPI_Wtime();
				if (!(open.hash(Env::s()) == comm))   // Step 3: check bob's decommitment
				{
					LOG4CXX_FATAL(logger, "commitment to coins can't be properly opened");
					MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
				}
				remote_coins = Bytes(open.begin()+Env::k()/8, open.end());
			m_timer_evl += MPI_Wtime() - start;
		EVL_END

		GEN_BEGIN
			start = MPI_Wtime();
				open = m_prng.rand(Env::k()) + coins; // Step 1: commit to coins
				comm = open.hash(Env::s());
			m_timer_gen += MPI_Wtime() - start;

			start = MPI_Wtime();
				GEN_SEND(comm);
				remote_coins = GEN_RECV();            // Step 2: receive alice's coins
				GEN_SEND(open);                       // Step 3: decommit to the coins
			m_timer_com += MPI_Wtime() - start;
		GEN_END

		m_comm_sz = comm.size() + remote_coins.size() + open.size();

		start = MPI_Wtime();
			coins ^= remote_coins;
			Prng prng;
			prng.srand(coins); // use the coins to generate more random bits

			// make 60-40 check-vs-evaluateion circuit ratio
			m_all_chks.assign(Env::s(), 1);

			// FisherÐYates shuffle
			std::vector<uint16_t> indices(m_all_chks.size());
			for (size_t ix = 0; ix < indices.size(); ix++) { indices[ix] = ix; }

			// starting from 1 since the 0-th circuit is always evaluation-circuit
			for (size_t ix = 1; ix < indices.size(); ix++)
			{
				int rand_ix = prng.rand_range(indices.size()-ix);
				std::swap(indices[ix], indices[ix+rand_ix]);
			}

			int num_of_evls;
			switch(m_all_chks.size())
			{
			case 0: case 1:
				LOG4CXX_FATAL(logger, "there isn't enough circuits for cut-and-choose");
				MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
				break;

			case 2: case 3:
				num_of_evls = 1;
				break;

			case 4:
				num_of_evls = 2;
				break;

			default:
				num_of_evls = m_all_chks.size()*2/5;
				break;
			}

			for (size_t ix = 0; ix < num_of_evls; ix++) { m_all_chks[indices[ix]] = 0; }
		m_timer_evl += MPI_Wtime() - start;
		m_timer_gen += MPI_Wtime() - start;
	}

	start = MPI_Wtime();
		m_chks.resize(Env::node_load());
	m_timer_evl += MPI_Wtime() - start;
	m_timer_gen += MPI_Wtime() - start;

	start = MPI_Wtime();
		MPI_Scatter(&m_all_chks[0], m_chks.size(), MPI_BYTE, &m_chks[0], m_chks.size(), MPI_BYTE, 0, m_mpi_comm);
	m_timer_mpi += MPI_Wtime() - start;

	step_report("cut-&-check");
}
示例#14
0
文件: emulator.c 项目: rpedde/6502
int main(int argc, char *argv[]) {
    char *configfile = DEFAULT_CONFIG_FILE;
    char *base_path = DEFAULT_DEBUG_FIFO;
    int option;
    int step = 0;
    int debuglevel = 2;
    pthread_t run_tid;
    int running=1;

    while((option = getopt(argc, argv, "d:sc:b:")) != -1) {
        switch(option) {
        case 'd':
            debuglevel = atoi(optarg);
            break;

        case 'c':
            configfile = optarg;
            break;

        case 'b':
            base_path = optarg;
            break;

        case 's':
            step = 1;
            break;

        default:
            fprintf(stderr,"Srsly?");
            exit(EXIT_FAILURE);
        }
    }

    debug_level(debuglevel);

    config_init(&main_config);
    if(config_read_file(&main_config, configfile) != CONFIG_TRUE) {
        FATAL("Can't read config file (%s, line %d): %s",
              configfile, config_error_line(&main_config),
              config_error_text(&main_config));
        exit(EXIT_FAILURE);
    }

    if(step)
        step_init(NULL);

    memory_init();
    if(!load_memory())
        exit(EXIT_FAILURE);

    cpu_init();

    if(step) {
        if(pthread_create(&run_tid, NULL, stepwise_proc, &running) < 0) {
            perror("pthread_create");
            exit(EXIT_FAILURE);
        }
    } else {
    }

    /* here, we should run the event loop required by any drivers.
     * really, this means the SDL video driver.  for osx, all
     * event polling/pumping has to be done in the main thread,
     * not background threads.  that's kind of a fail.
     */
    while(running) {
        memory_run_eventloop();
    }

    exit(EXIT_SUCCESS);
}
示例#15
0
文件: step.c 项目: AndySze/OpenServo
void step_update(uint16_t position, int16_t step_in)
//  Update the timer delay that trigers a step.  The delay time is determined by the step value, which represents a value of the maximum delay.
//  The farther the step value is from zero, the longer the delay.
{
    uint16_t min_position;
    uint16_t max_position;
    uint8_t step_mode;
    static uint8_t prev_step_mode;
    static uint16_t prev_pwm_div;
    static int16_t prev_seek_position;
    static uint8_t step_accel_idx = 0;
    uint16_t duty_cycle;
    uint16_t pwm_div_hi;
    uint16_t pwm_div_lo;

    // Read the high and low values for the PWM frequencies. pwm_div_hi is the top frequency and
    // pwm_div_lo is the bottom frequency
    pwm_div_hi = (uint16_t)banks_read_byte(CONFIG_BANK, REG_PWM_FREQ_DIVIDER_HI);
    pwm_div_lo = (uint16_t)banks_read_byte(CONFIG_BANK, REG_PWM_FREQ_DIVIDER_LO);

    // Store these in the correct 16 bit size 
    pwm_div_hi = (uint8_t)pwm_div_hi << 8;
    pwm_div_lo = (uint8_t)pwm_div_lo << 8;

    // Set up for the configured step mode
    step_mode = banks_read_byte(CONFIG_BANK, REG_STEP_MODE);

    // Check to see if the step mode has changed in the registers on the fly
    if (prev_step_mode != step_mode)
        step_init();

    prev_step_mode = step_mode;

    min_position = banks_read_word(CONFIG_BANK, REG_MIN_SEEK_HI, REG_MIN_SEEK_LO);
    max_position = banks_read_word(CONFIG_BANK, REG_MAX_SEEK_HI, REG_MAX_SEEK_LO);

    // Make sure these values are sane 10-bit values.
    if (min_position > 0x3ff) min_position = 0x3ff;
    if (max_position > 0x3ff) max_position = 0x3ff;

    // Disable clockwise movements when position is below the minimum position.
    if ((position < min_position) && (step_in < 0)) step_in = 0;

    // Disable counter-clockwise movements when position is above the maximum position.
    if ((position > max_position) && (step_in > 0)) step_in = 0;

    // Determine if Stepping is disabled in the registers.
    // TODO cheeck for braking and disable bridge
    if (!(registers_read_byte(REG_FLAGS_LO) & (1<<FLAGS_LO_PWM_ENABLED))) step_in = 0;

    // Determine and set the direction: Stop (0), Clockwise (1), Counter-Clockwise (2).
    if (step_in < -5)
    {
        // Less than zero. Set the direction to clockwise.
        direction |=  R_COUNTER_CLOCKWISE;
        direction &=  ~R_CLOCKWISE;

        // Calculate our duty cycle value
        duty_cycle = PWM_OCRN_VALUE(pwm_div_hi, pwm_div_lo, -step_in);
    }
    else if (step_in > 5)
    {
        // More than zero. Set the direction to counter-clockwise.
        direction |= R_CLOCKWISE; //DIRECTION = 2
        direction &= ~R_COUNTER_CLOCKWISE;

        // Calculate our duty cycle value
        duty_cycle = PWM_OCRN_VALUE(pwm_div_hi, pwm_div_lo, step_in);
    }
    else
    {
        // Stop all stepping output to the motor by setting motor outputs to low.
        step_stop();
        return;
    }

    // If acceleration mode is set, the current speed is divided to all incremental
    // speed. This function also waits for the R_ACCEL_CLEAR flag from the timer interrupt
    // before starting the next increment. It should take 10 pulses to get up to speed.
    if ((direction & R_ACCEL) && (direction & R_ACCEL_CLEAR))
    {
        // Scale the current duty cycle by 64 and increment over a loop
        duty_cycle = (duty_cycle/64)*(step_accel_idx+1);
        step_accel_idx++;
        if (step_accel_idx >= 64)
        {
            step_accel_idx = 0;
            direction &= ~R_ACCEL;
        }
        // clear the acceleration flag ready for next toggle
        direction &= ~R_ACCEL_CLEAR;
    }

    // If the motor changes direction we need to wait a small amount of time to discharge,
    // and then start accelerating in the new direction.
    uint16_t seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO);
    if (seek_position != prev_seek_position)
    {
        direction |= R_ACCEL;
        step_accel_idx = 0;
        OCR1A = 6500;  // Wait 1ms (at 20mhz)
    }
    else
    {
        // A slower speed is a larger delay, so calculate the top pwm frequency, and take away the step delay.
        OCR1A =  65535 - pwm_div_lo - duty_cycle; //Update the CTC compare value with the modified value of step.
    }

    prev_seek_position = seek_position;

    // Enable the timer mask
    TIMSK1 |= (1 << OCIE1A);
}
示例#16
0
文件: main.c 项目: AndySze/OpenServo
int main (void)
{
    // Configure pins to the default states.
    config_pin_defaults();

    // Initialize the watchdog module.
    watchdog_init();

    // First, initialize registers that control servo operation.
    registers_init();

#if PWM_STD_ENABLED || PWM_ENH_ENABLED
    // Initialize the PWM module.
    pwm_init();
#endif

#if STEP_ENABLED
    // Initialise the stepper motor
    step_init();
#endif
    
    // Initialize the ADC module.
    adc_init();

    // Initialise the Heartbeart
    heartbeat_init();

    // Initialize the PID algorithm module.
    pid_init();

#if CURVE_MOTION_ENABLED
    // Initialize curve motion module.
    motion_init();
#endif

    // Initialize the power module.
    power_init();

#if PULSE_CONTROL_ENABLED
    pulse_control_init();
#endif

#if BACKEMF_ENABLED
    // Initialise the back emf module
    backemf_init();
#endif

#if ALERT_ENABLED
    //initialise the alert registers
    alert_init();
#endif

    // Initialize the TWI slave module.
    twi_slave_init(banks_read_byte(POS_PID_BANK, REG_TWI_ADDRESS));

    // Finally initialize the timer.
    timer_set(0);

    // Enable interrupts.
    sei();

    // Trigger the adc sampling hardware
    adc_start(ADC_CHANNEL_POSITION);

    // Wait until initial position value is ready.
    while (!adc_position_value_is_ready());

#if CURVE_MOTION_ENABLED
    // Reset the curve motion with the current position of the servo.
    motion_reset(adc_get_position_value());
#endif

    // Set the initial seek position and velocity.
    registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value());
    registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0);

    // XXX Enable PWM and writing.  I do this for now to make development and
    // XXX tuning a bit easier.  Constantly manually setting these values to
    // XXX turn the servo on and write the gain values get's to be a pain.
#if PWM_STD_ENABLED || PWM_ENH_ENABLED
    pwm_enable();
#endif
#if STEP_ENABLED
    step_enable();
#endif

    registers_write_enable();

    // This is the main processing loop for the servo.  It basically looks
    // for new position, power or TWI commands to be processed.
    for (;;)
    {
        static uint8_t emf_motor_is_coasting = 0;

        // Is the system heartbeat ready?
        if (heartbeat_is_ready())
        {
            static int16_t last_seek_position;
            static int16_t wait_seek_position;
            static int16_t new_seek_position;

            // Clear the heartbeat flag
            heartbeat_value_clear_ready();

#if PULSE_CONTROL_ENABLED
            // Give pulse control a chance to update the seek position.
            pulse_control_update();
#endif

#if CURVE_MOTION_ENABLED
            // Give the motion curve a chance to update the seek position and velocity.
            motion_next(10);
#endif

            // General call support
            // Check to see if we have the wait flag enabled. If so save the new position, and write in the
            // old position until we get the move command
            if (general_call_enabled()) 
            {
                //we need to wait for the go command before moving
                if (general_call_wait())
                {
                    // store the new position, but let the servo lock to the last seek position
                    wait_seek_position = (int16_t) registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO);
                    if (wait_seek_position != last_seek_position) // do we have a new position?
                    {
                        new_seek_position = wait_seek_position;
                        registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, last_seek_position);
                    }
                }
                last_seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO);

                //check to make sure that we can start the move.
                if (general_call_start() || 
                    ( registers_read_byte(REG_GENERAL_CALL_GROUP_START) == banks_read_byte(CONFIG_BANK, REG_GENERAL_CALL_GROUP)))
                {
                    // write the new position with the previously saved position
                    registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, new_seek_position);  
                    general_call_start_wait_reset();  // reset the wait flag
                    general_call_start_reset();  // reset the start flag
                }
            }

#if BACKEMF_ENABLED
            // Quick and dirty check to see if pwm is active. This is done to make sure the motor doesn't
            // whine in the audible range while idling.
            uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA);
            uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB);
            if (pwm_a || pwm_b)
            {
                // Disable PWM
                backemf_coast_motor();
                emf_motor_is_coasting = 1;
            }
            else
            {
                // reset the back EMF value to 0
                banks_write_word(INFORMATION_BANK, REG_BACKEMF_HI, REG_BACKEMF_LO, 0);
                emf_motor_is_coasting = 0;
            }
#endif

#if ADC_ENABLED
            // Trigger the adc sampling hardware. This triggers the position and temperature sample
            adc_start(ADC_FIRST_CHANNEL);
#endif

        }
    
    
        // Wait for the samples to complete
#if TEMPERATURE_ENABLED
        if (adc_temperature_value_is_ready())
        {
            // Save temperature value to registers
            registers_write_word(REG_TEMPERATURE_HI, REG_TEMPERATURE_LO, (uint16_t)adc_get_temperature_value());
        }
#endif
#if CURRENT_ENABLED
        if (adc_power_value_is_ready())
        {

            // Get the new power value.
            uint16_t power = adc_get_power_value();

            // Update the power value for reporting.
            power_update(power);
        }
#endif
#if ADC_POSITION_ENABLED
        if (adc_position_value_is_ready())
        {
            int16_t position;
            // Get the new position value from the ADC module.
            position = (int16_t) adc_get_position_value();
#else
        if (position_value_is_ready())
        {
            int16_t position;
            // Get the position value from an external module.
            position = (int16_t) get_position_value();
#endif
            int16_t pwm;
#if BACKEMF_ENABLED
            if (emf_motor_is_coasting == 1)
            {
                uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA);
                uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB);

                // Quick and dirty check to see if pwm is active
                if (pwm_a || pwm_b)
                {
                    // Get the backemf sample.
                    backemf_get_sample();

                    // Turn the motor back on
                    backemf_restore_motor();
		    emf_motor_is_coasting = 0;
                }
            }
#endif

            // Call the PID algorithm module to get a new PWM value.
            pwm = pid_position_to_pwm(position);

#if ALERT_ENABLED
            // Update the alert status registers and do any throttling
            alert_check();
#endif

            // Allow any alerts to modify the PWM value.
            pwm = alert_pwm_throttle(pwm);

#if PWM_STD_ENABLED || PWM_ENH_ENABLED
            // Update the servo movement as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            pwm_update(position, pwm);
#endif

#if STEP_ENABLED
            // Update the stepper motor as indicated by the PWM value.
            // Sanity checks are performed against the position value.
            step_update(position, pwm);
#endif
        }
    
        // Was a command recieved?
        if (twi_data_in_receive_buffer())
        {
            // Handle any TWI command.
            handle_twi_command();
        }

        // Update the bank register operations
        banks_update_registers();

#if MAIN_MOTION_TEST_ENABLED
        // This code is in place for having the servo drive itself between
        // two positions to aid in the servo tuning process.  This code
        // should normally be disabled in config.h.
#if CURVE_MOTION_ENABLED
        if (motion_time_left() == 0)
        {
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300);
            motion_append();
            registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000);
            registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100);
            motion_append();
        }
#else
        {
            // Get the timer.
            uint16_t timer = timer_get();

            // Reset the timer if greater than 800.
            if (timer > 800) timer_set(0);

            // Look for specific events.
            if (timer == 0)
            {
                registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0100);
            }
            else if (timer == 400)
            {
                registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0300);
            }
        }
#endif
#endif
    }

    return 0;
}