3
* Copyright 2007,2008 Free Software Foundation, Inc.
5
* This file is part of GNU Radio
7
* GNU Radio is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 3, or (at your option)
12
* GNU Radio is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
#include <mblock/mblock.h>
26
#include <mblock/protocol_class.h>
27
#include <mblock/message.h>
28
#include <mblock/class_registry.h>
34
static pmt_t s_in = pmt_intern("in");
35
static pmt_t s_out = pmt_intern("out");
36
static pmt_t s_data = pmt_intern("data");
37
static pmt_t s_ack = pmt_intern("ack");
38
static pmt_t s_select_pipe = pmt_intern("select-pipe");
39
static pmt_t s_long0 = pmt_from_long(0);
40
static pmt_t s_sys_port = pmt_intern("%sys-port");
41
static pmt_t s_shutdown = pmt_intern("%shutdown");
43
class qa_disconnect_mux : public mb_mblock
50
qa_disconnect_mux(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
51
void initial_transition();
52
void handle_message(mb_message_sptr msg);
55
qa_disconnect_mux::qa_disconnect_mux(mb_runtime *runtime,
56
const std::string &instance_name,
58
: mb_mblock(runtime, instance_name, user_arg)
60
d_in = define_port("in", "qa-bitset", false, mb_port::RELAY);
61
d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
62
d_cs = define_port("cs", "qa-disconnect-cs", true, mb_port::EXTERNAL);
64
define_component("pipeline0", "qa_bitset8", pmt_from_long(0));
65
define_component("pipeline1", "qa_bitset8", pmt_from_long(8));
69
qa_disconnect_mux::initial_transition(){}
72
qa_disconnect_mux::handle_message(mb_message_sptr msg)
74
if (pmt_eq(msg->port_id(), d_cs->port_symbol()) // select-pipe on cs
75
&& pmt_eq(msg->signal(), s_select_pipe)){
77
long which_pipe = pmt_to_long(pmt_nth(0, msg->data()));
79
disconnect_component("pipeline0");
80
disconnect_component("pipeline1");
85
connect("self", "in", "pipeline0", "in");
86
connect("self", "out", "pipeline0", "out");
90
connect("self", "in", "pipeline1", "in");
91
connect("self", "out", "pipeline1", "out");
95
d_cs->send(s_ack, msg->data());
100
REGISTER_MBLOCK_CLASS(qa_disconnect_mux);
102
// ------------------------------------------------------------------------
104
class qa_disconnect_top : public mb_mblock
120
void check_pipe_send_next_msg();
121
void send_next_msg();
122
void select_pipe(int n);
124
// alternate pipes every 128 messages
125
static int which_pipe(int msg_number) { return (msg_number >> 7) & 0x1; }
126
bool time_to_switch() { return (d_msg_number & 0x7f) == 0; }
129
qa_disconnect_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
130
void initial_transition();
131
void handle_message(mb_message_sptr msg);
134
qa_disconnect_top::qa_disconnect_top(mb_runtime *runtime,
135
const std::string &instance_name,
137
: mb_mblock(runtime, instance_name, user_arg),
138
d_state(UNINITIALIZED), d_msg_number(0)
140
d_nmsgs_to_send = pmt_to_long(pmt_nth(0, user_arg));
142
d_in = define_port("in", "qa-bitset", false, mb_port::INTERNAL);
143
d_out = define_port("out", "qa-bitset", true, mb_port::INTERNAL);
144
d_cs = define_port("cs", "qa-disconnect-cs", false, mb_port::INTERNAL);
146
define_component("mux", "qa_disconnect_mux", PMT_F);
148
connect("self", "cs", "mux", "cs");
149
connect("self", "out", "mux", "in");
150
connect("self", "in", "mux", "out");
154
qa_disconnect_top::initial_transition()
156
check_pipe_send_next_msg();
160
qa_disconnect_top::handle_message(mb_message_sptr msg)
163
std::cerr << "qa_disconnect_top::handle_msg state = "
164
<< d_state << "\n msg = " << msg << std::endl;
166
if (pmt_eq(msg->port_id(), d_cs->port_symbol()) // ack on cs
167
&& pmt_eq(msg->signal(), s_ack)
168
&& d_state == WAIT_FOR_ACK){
174
if (pmt_eq(msg->port_id(), d_in->port_symbol()) // data on in
175
&& pmt_eq(msg->signal(), s_data)
176
&& d_state == WAIT_FOR_DATA){
179
* Confirm that msg passed through the pipe that we expect...
181
static const long expected_mask[2] = { 0x000000ff, 0x0000ff00 };
183
long msg_number = pmt_to_long(pmt_car(msg->data()));
184
long mask = pmt_to_long(pmt_cdr(msg->data()));
186
if (mask != expected_mask[which_pipe(msg_number)]){
187
fprintf(stderr, "\nqa_disconnect_top: wrong mask in msg_number = 0x%08lx\n",
189
fprintf(stderr, " expected = 0x%08lx, actual = 0x%08lx\n",
190
expected_mask[which_pipe(msg_number)], mask);
195
if (msg_number == d_nmsgs_to_send - 1){ // we're done (and were successful)
200
check_pipe_send_next_msg();
204
if (pmt_eq(msg->port_id(), s_sys_port) // ignore %shutdown on %sys-port
205
&& pmt_eq(msg->signal(), s_shutdown))
208
std::cerr << "qa_disconnect_top: unhandled msg: state = "
209
<< d_state << "\n msg = " << msg << std::endl;
213
qa_disconnect_top::select_pipe(int n)
215
d_cs->send(s_select_pipe, pmt_list1(pmt_from_long(n)));
216
d_state = WAIT_FOR_ACK;
220
qa_disconnect_top::send_next_msg()
222
d_state = WAIT_FOR_DATA;
223
if (d_msg_number == d_nmsgs_to_send) // we've sent all we're supposed to
226
d_out->send(s_data, pmt_cons(pmt_from_long(d_msg_number), s_long0));
231
qa_disconnect_top::check_pipe_send_next_msg()
233
if (time_to_switch())
234
select_pipe(which_pipe(d_msg_number));
239
REGISTER_MBLOCK_CLASS(qa_disconnect_top);