Skip to content

Commit

Permalink
P25 Trunking Message Improvements (#820)
Browse files Browse the repository at this point in the history
* trying to debug

* Update main.cc

* Update main.cc

* Only stop recording when control channel timesout too

* Update p25_parser.cc

Default encrypted to false - needed if we are going to treat updates as call starts

* Turn off excessive logging

* Update p25_parser.cc

* Update transmission_sink.cc

* Updated the Mermaid charts

* REmoved COMPLETED

* MORE RESETS!

* Cleaned up setting GRP ID

* Update p25_frame_assembler_impl.cc

* error messages

* Update p25p2_tdma.cc

* streamline grp src ID

* add message back

* Update p25p2_tdma.cc

* SRC ID from MAC_END_PTT appears to be broken

* Trying some MUTEX in the Gardner to get rid of the SegFault

* Update p25_parser.cc

* Bigger buffers for smoother writing

Let's see if this helps network drive writes
  • Loading branch information
robotastic authored Jun 3, 2023
1 parent 5fde381 commit a8d1a2a
Show file tree
Hide file tree
Showing 18 changed files with 268 additions and 259 deletions.
56 changes: 15 additions & 41 deletions docs/notes/CALL-HANDLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,48 @@ Use [Mermaid Live](https://mermaid.live/) to edit the charts.

```mermaid
flowchart TD
A[Control Channel] -->|GRANT| B["handle_call_grant()"]
A[Control Channel] -->|GRANT or UPDATE| B["handle_call_grant()"]
B --> C{Existing Call on Freq?}
C -.->|Yes| D{Same Talkgroup?}
C -.->|No| G["new Call()"]
D -.->|Yes| E["call->set_record_more_transmissions(True)"]
D -.->|No| F[Delete Existing Call]
F -.-> G
D -.->|Yes| E["call->update()"]
D -.->|No| F[Do nothing.\n The Recorder will notice the \ndifferent Talkgroup and stop]
G -.-> H["start_recording()"]
```

```mermaid
flowchart TD
A1[Voice Channel] --> B1[Transmission Sink]
B1 -.->|Samples| C1{State}
B1 -.->|GROUP ID| V1{GROUP ID \n==\nCALL TG}
V1 -.->|Mismatch|Q1{Sample\nCount}
Q1 -.->|0| R1[state = IGNORE]
Q1 -.->|>0| S1[End Transmission]
S1 --> T1[state = STOPPED]
C1 -.->|STOPPED| D1[Drop Samples]
C1 -.->|IDLE| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;\nstate = RECORDING"]
C1 -.->|IGNORE| D1
C1 -.->|IDLE| F1["Setup files\nstate = RECORDING"]
C1 -.->|RECORDING| G1[Write Samples]
G1 --> U1[Update d_last_write_time]
F1 -.-> G1
B1 -.->|TERMINATOR| H1["End Transmission"]
H1 -.-> I1{"record_more_transmissions"}
I1 -.->|False| J1["state = STOPPED"]
I1 -.->|True| K1["state = IDLE"]
L1["set_record_more_transmissions(True)"] -.-> N1{state == STOPPED}
N1 -.->|True| O1["state == IDLE"]
N1 -.->|False| P1["record_mode_transmissions = True"]
O1 -.-> P1
H1 -.-> K1["state = IDLE"]
```




```mermaid
flowchart TD
A[Control Channel] -->|UPDATE| B["handle_call_update()"]
B -.-> C[Find Call]
C -.-> D{"call->state"}
D -.->|COMPLETED| E[Do Nothing]
D -.->|INACTIVE| F["call->state==RECORDING"]
F -.-> G["call->update()"]
D -.->|RECORDING| G
G -.-> H["call->set_record_more_transmissions(True)"]
```


```mermaid
flowchart TD
A[For Each Call] -->|Call| B{state}
B -.->|RECORDING| C{"last_update > 1.0"}
C -.->|True| E["call->set_record_more_transmissions(false)\nstate = INACTIVE"]
B -.->|RECORDING| C{call->last_update > 3.0 &&\nrecroder->d_last_write_time > 3.0}
C -.->|True| H["Conclude Call"]
C -.->|False| D[Next]
E -.-> D
B -.->|MONITORING| F{"last_update > 1.0"}
B -.->|MONITORING| F{"last_update > 3.0"}
F -.->|True| G["Delete Call"]
G -.-> D
F -.->|False| D
B -.->|COMPLETED| H["Conclude Call"]
H -.-> Z["Delete Call"]
Z -.-> D
B -.->|INACTIVE| I{"since last_update > 5.0"}
I -.->|True| J[state = COMPLETED]
J -.-> K[Conclude Call]
K -.-> L[Delete Call]
I -.->|False| D
L -.-> D
```
3 changes: 3 additions & 0 deletions lib/op25_repeater/lib/gardner_cc_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ gardner_cc_impl::~gardner_cc_impl()
void
gardner_cc_impl::reset()
{
gr::thread::scoped_lock lock(d_mutex);
d_phase = 0;
d_update_request = 0;
d_last_sample = 0;
Expand All @@ -109,6 +110,7 @@ gardner_cc_impl::reset()
void
gardner_cc_impl::set_omega (float omega)
{
gr::thread::scoped_lock lock(d_mutex);
assert (omega >= 2.0);
d_omega = omega;
d_min_omega = omega*(1.0 - d_omega_rel);
Expand Down Expand Up @@ -136,6 +138,7 @@ gardner_cc_impl::general_work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
gr::thread::scoped_lock lock(d_mutex);
const gr_complex *in = (const gr_complex *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];

Expand Down
2 changes: 2 additions & 0 deletions lib/op25_repeater/lib/gardner_cc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <gnuradio/math.h>

#include <gnuradio/filter/mmse_fir_interpolator_cc.h>
#include <boost/thread/mutex.hpp>
// class gr::filter::mmse_fir_interpolator_cc;

namespace gr {
Expand Down Expand Up @@ -101,6 +102,7 @@ class gardner_cc_impl : public gardner_cc
float d_gain_mu;
float d_lock_threshold;
id_avg d_lock_accum;
boost::mutex d_mutex;

gr_complex d_last_sample;
gr::filter::mmse_fir_interpolator_cc *d_interp;
Expand Down
69 changes: 48 additions & 21 deletions lib/op25_repeater/lib/p25_frame_assembler_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ static const int MAX_IN = 1; // maximum number of input streams
output_queue(),
op25audio(udp_host, port, debug),
d_input_rate(4800),
d_tag_key(pmt::intern("src_id")),
d_tag_src(pmt::intern(name())),
d_silence_frames(silence_frames)
{
Expand All @@ -126,9 +125,53 @@ static const int MAX_IN = 1; // maximum number of input streams


void p25_frame_assembler_impl::clear() {
// clear out the SRC and GRP IDs
long clear;
clear = p1fdma.get_curr_src_id();
clear = p1fdma.get_curr_grp_id();
clear = p2tdma.get_ptt_src_id();
clear = p2tdma.get_ptt_grp_id();
p1fdma.clear();
}

void p25_frame_assembler_impl::send_grp_src_id() {
long tdma_src_id = -1;
long tdma_grp_id = -1;
long fdma_src_id = -1;
long fdma_grp_id = -1;

tdma_src_id = p2tdma.get_ptt_src_id();
tdma_grp_id = p2tdma.get_ptt_grp_id();
fdma_src_id = p1fdma.get_curr_src_id();
fdma_grp_id = p1fdma.get_curr_grp_id();

// If a SRC wasn't received on the voice channel since the last check, it will be -1
if (fdma_src_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("src_id"), pmt::from_long(fdma_src_id), d_tag_src);
}

if (tdma_src_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("src_id"), pmt::from_long(tdma_src_id), d_tag_src);
}

if ((tdma_src_id > 0) && (fdma_src_id > 0)) {
BOOST_LOG_TRIVIAL(info) << " Both TDMA and FDMA SRC IDs are set. TDMA: " << tdma_src_id << " FDMA: " << fdma_src_id;
}

if (fdma_grp_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("grp_id"), pmt::from_long(fdma_grp_id), d_tag_src);
}

if (tdma_grp_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("grp_id"), pmt::from_long(tdma_grp_id), d_tag_src);
}

if ((tdma_grp_id > 0) && (fdma_grp_id > 0)) {
BOOST_LOG_TRIVIAL(info) << " Both TDMA and FDMA GRP IDs are set. TDMA: " << tdma_grp_id << " FDMA: " << fdma_grp_id;
}
}


int
p25_frame_assembler_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
Expand All @@ -138,8 +181,7 @@ p25_frame_assembler_impl::general_work (int noutput_items,

const uint8_t *in = (const uint8_t *) input_items[0];
bool terminate_call = false;
long p2_ptt_src_id = -1;
long p2_ptt_grp_id = -1;

p1fdma.rx_sym(in, ninput_items[0]);
if(d_do_phase2_tdma) {
for (int i = 0; i < ninput_items[0]; i++) {
Expand All @@ -149,9 +191,6 @@ p25_frame_assembler_impl::general_work (int noutput_items,
terminate_call = true;
p2tdma.reset_call_terminated();
}

p2_ptt_src_id = p2tdma.get_ptt_src_id();
p2_ptt_grp_id = p2tdma.get_ptt_grp_id();

if (rc > -1) {
p25p2_queue_msg(rc);
Expand Down Expand Up @@ -181,27 +220,13 @@ p25_frame_assembler_impl::general_work (int noutput_items,

amt_produce = 32767; // buffer limit is 32768, see gnuradio/gnuradio-runtime/lib/../include/gnuradio/buffer.h:186
}
long src_id = p1fdma.get_curr_src_id();
long grp_id = p1fdma.get_curr_grp_id();
// If a SRC wasn't received on the voice channel since the last check, it will be -1
if (src_id > 0) {
add_item_tag(0, nitems_written(0), d_tag_key, pmt::from_long(src_id), d_tag_src);
}

if (p2_ptt_src_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("ptt_src_id"), pmt::from_long(p2_ptt_src_id), d_tag_src);
//BOOST_LOG_TRIVIAL(info) << "PTT Src: " << p2_ptt_src_id << " amt_produced: " << amt_produce << std::endl;
}

if (grp_id > 0) {
add_item_tag(0, nitems_written(0), pmt::intern("grp_id"), pmt::from_long(grp_id), d_tag_src);
}

for (int i = 0; i < amt_produce; i++) {
out[i] = output_queue[i];
}
output_queue.erase(output_queue.begin(), output_queue.begin() + amt_produce);

send_grp_src_id();

BOOST_LOG_TRIVIAL(trace) << "setting silence_frame_count " << silence_frame_count << " to d_silence_frames: " << d_silence_frames << std::endl;
silence_frame_count = d_silence_frames;
Expand All @@ -218,6 +243,8 @@ p25_frame_assembler_impl::general_work (int noutput_items,
p1fdma.reset_rx_status();
}

send_grp_src_id();

std::fill(out, out + 1, 0);
amt_produce = 1;
}
Expand Down
1 change: 1 addition & 0 deletions lib/op25_repeater/lib/p25_frame_assembler_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace gr {
pmt::pmt_t d_tag_src;
// internal functions

void send_grp_src_id();
void set_xormask(const char*p) ;
void set_nac(int nac) ;
void set_slotid(int slotid) ;
Expand Down
13 changes: 8 additions & 5 deletions lib/op25_repeater/lib/p25p2_tdma.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ p25p2_tdma::p25p2_tdma(const op25_audio& udp, log_ts& logger, int slotid, int de
bool p25p2_tdma::rx_sym(uint8_t sym)
{
symbols_received++;
terminate_call = false;
src_id = -1;
grp_id = -1;
return p2framer.rx_sym(sym);
}

Expand All @@ -154,13 +151,15 @@ bool p25p2_tdma::get_call_terminated() {
}

long p25p2_tdma::get_ptt_src_id() {
return src_id;
long id = src_id;
src_id = -1;
return id;
}

long p25p2_tdma::get_ptt_grp_id() {
long addr = grp_id;
grp_id = -1;
return grp_id;
return addr;
}

p25p2_tdma::~p25p2_tdma() // destructor
Expand Down Expand Up @@ -261,6 +260,7 @@ void p25p2_tdma::handle_mac_ptt(const uint8_t byte_buf[], const unsigned int len

src_id = srcaddr;
grp_id = grpaddr;

std::string s = "{\"srcaddr\" : " + std::to_string(srcaddr) + ", \"grpaddr\": " + std::to_string(grpaddr) + "}";
send_msg(s, -3);
reset_vb();
Expand All @@ -280,6 +280,9 @@ void p25p2_tdma::handle_mac_end_ptt(const uint8_t byte_buf[], const unsigned int
uint32_t srcaddr = (byte_buf[13] << 16) + (byte_buf[14] << 8) + byte_buf[15];
uint16_t grpaddr = (byte_buf[16] << 8) + byte_buf[17];

//src_id = srcaddr; // the decode for Source Address is not correct
grp_id = grpaddr;

if (d_debug >= 10)
fprintf(stderr, "%s MAC_END_PTT: colorcd=0x%03x, srcaddr=%u, grpaddr=%u, rs_errs=%d\n", logts.get(d_msgq_id), colorcd, srcaddr, grpaddr, rs_errs);

Expand Down
14 changes: 3 additions & 11 deletions trunk-recorder/call_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ void Call_impl::stop_call() {
// If the call is being recorded, check to see if the recorder is currently in an INACTIVE state. This means that the recorder is not
// doing anything and can be stopped.
if ((state == RECORDING) && this->get_recorder()->is_idle()) {
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tStopping Recorded Call_impl, setting call state to COMPLETED - Last Update: " << this->since_last_update() << "s";
this->set_state(COMPLETED);
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tStopping Recorded Call_impl - Last Update: " << this->since_last_update() << "s";
}
}
}
Expand All @@ -113,13 +112,13 @@ void Call_impl::conclude_call() {
// BOOST_LOG_TRIVIAL(info) << "conclude_call()";
stop_time = time(NULL);

if (state == COMPLETED || (state == MONITORING && monitoringState == SUPERSEDED)) {
if (state == RECORDING || (state == MONITORING && monitoringState == SUPERSEDED)) {
final_length = recorder->get_current_length();

if (!recorder) {
BOOST_LOG_TRIVIAL(error) << "Call_impl::end_call() State is recording, but no recorder assigned!";
}
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\t\u001b[33mConcluding Recorded Call\u001b[0m - Last Update: " << this->since_last_update() << "s\tCall Elapsed: " << this->elapsed();
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\t\u001b[33mConcluding Recorded Call\u001b[0m - Last Update: " << this->since_last_update() << "s\tRecorder last write:" << recorder->since_last_write() << "\tCall Elapsed: " << this->elapsed();

if (was_update) {
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\t\u001b[33mCall was UPDATE not GRANT\u001b[0m";
Expand All @@ -136,9 +135,6 @@ void Call_impl::conclude_call() {

Call_Concluder::conclude_call(this, sys, config);
}
else {
BOOST_LOG_TRIVIAL(error) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "Concluding call, but call state is not COMPLETED!";
}
}

void Call_impl::set_sigmf_recorder(Recorder *r) {
Expand Down Expand Up @@ -321,16 +317,12 @@ bool Call_impl::add_source(long src) {
}

bool Call_impl::update(TrunkMessage message) {
if ((state == INACTIVE) || (state == COMPLETED)) {
BOOST_LOG_TRIVIAL(error) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tCall_impl Update, but state is: " << state << " - Call_impl TG: " << get_talkgroup() << "\t Call_impl Freq: " << get_freq() << "\tMsg Tg: " << message.talkgroup << "\tMsg Freq: " << message.freq;
} else {
last_update = time(NULL);
if ((message.freq != this->curr_freq) || (message.talkgroup != this->talkgroup)) {
BOOST_LOG_TRIVIAL(error) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tCall_impl Update, message mismatch - Call_impl TG: " << get_talkgroup() << "\t Call_impl Freq: " << get_freq() << "\tMsg Tg: " << message.talkgroup << "\tMsg Freq: " << message.freq;
} else {
return add_source(message.source);
}
}
return false;
}

Expand Down
4 changes: 0 additions & 4 deletions trunk-recorder/formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ std::string format_state(State state) {
return "active";
else if (state == IDLE)
return "idle";
else if (state == COMPLETED)
return "completed";
else if (state == STOPPED)
return "stopped";
else if (state == AVAILABLE)
Expand Down Expand Up @@ -85,8 +83,6 @@ std::string format_state(State state, MonitoringState monitoringState) {
return "active";
else if (state == IDLE)
return "idle";
else if (state == COMPLETED)
return "completed";
else if (state == STOPPED)
return "stopped";
else if (state == AVAILABLE)
Expand Down
Loading

0 comments on commit a8d1a2a

Please sign in to comment.