Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P25 Trunking Message Improvements #820

Merged
merged 22 commits into from
Jun 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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