blob: 870b28c51eee29050a679d66f507b4529b756cd7 [file] [log] [blame]
#include <atomic>
#include "radioInterface.h"
#include "Interthread.h"
#include "GSMCommon.h"
//#include "Sockets.h"
#include <sys/types.h>
#include <sys/socket.h>
static const auto tssize = 156.25;
static const auto framee_to_read = 12;
static const auto ts_to_read = framee_to_read * 8;
static const int fbsb_chunk_len = ts_to_read * 2 * tssize; // contiguous fcch+sch guaranteed
static const auto corr_offset = 0;
struct fbsb_par {
enum class fbsb_state {
IDLE,
INIT,
ACQ,
WAIT,
ACQ_COMPL,
DONE
};
int pos;
int time_idx;
std::atomic<fbsb_state> s;
GSM::Time rcvClock[ts_to_read];
complex fbsb_buf[fbsb_chunk_len+corr_offset];
complex conjbuf[fbsb_chunk_len+corr_offset];
complex avgbuf[fbsb_chunk_len+corr_offset];
void addclk(GSM::Time c) { rcvClock[time_idx] = c; time_idx++; return;}
public:
fbsb_par() : s(fbsb_state::IDLE) {
reset();
};
bool done() {return !(time_idx < ts_to_read);}
void take(void* addr, int num_cplx_sps, GSM::Time c) {
memcpy(fbsb_buf+pos+corr_offset,addr, num_cplx_sps * sizeof(complex));
pos += num_cplx_sps;
assert(pos < fbsb_chunk_len);
rcvClock[time_idx] = c;
time_idx++;
}
void reset() {pos = 0;
time_idx = 0;
// s = fbsb_state::IDLE;
memset(fbsb_buf, 0, sizeof(fbsb_buf));
memset(conjbuf, 0, sizeof(conjbuf));
memset(avgbuf, 0, sizeof(avgbuf));
}
int sz () {return fbsb_chunk_len;}
int off () {return corr_offset;}
// from osmotrx sigproc
complex fastPeakDetect(complex* rxBurst, float* index, int N)
{
float val, max = 0.0f;
complex amp;
int _index = -1;
for (size_t i = 0; i < N; i++) {
val = rxBurst[i].abs();
if (val > max) {
max = val;
_index = i;
amp = rxBurst[i];
}
}
if (index)
*index = (float)_index;
return amp;
}
void conj_with_lag(complex* in, complex* out, int lag, int offset, int N) {
int total_offset = offset + lag;
for (int s = 0; s < N; s++)
out[s] = in[s + total_offset] * in[s + total_offset - lag].conj();
}
auto ac_sum_with_lag(complex* in, int lag, int offset, int N) {
complex v(0,0);
auto total_offset = offset + lag;
for (auto s = 0; s < N; s++)
v += in[s + total_offset] * in[s + total_offset - lag].conj();
return atan2(v.imag(), v.real());
}
bool running_avg_opt(complex* in, complex* out, int avg_window, int val_to_find, int* idx, int N) {
bool found = false;
complex avg0 = 0;
complex scale(avg_window, avg_window);
for (auto i = 0; i < avg_window; i++)
avg0 += in[i];
out[0] = avg0 / scale;
//skip first
for (auto i = 1; i < N - avg_window; i++) {
avg0 += in[i-1] - in[i+avg_window];
auto tmp = avg0 / scale;
out[i] = tmp;
if (!found && tmp.abs() > val_to_find) {
found = !found;
*idx = i;
return true;
}
}
return false;
}
int fcch(complex* amp, int* found_idx, bool dump) {
conj_with_lag(fbsb_buf, conjbuf, 3, off(), sz());
running_avg_opt(conjbuf, avgbuf, 48, 1.5e6, found_idx, sz()-off());
float pos;
auto r = fastPeakDetect(avgbuf, &pos, sz()-off());
*found_idx = *found_idx+off();
std::cerr << "fcch found at " << pos << " amp: " << r.abs() << std::endl;
*amp = r;
if(dump) {
{
auto f = fopen("inbuf.cfile", "wb");
fwrite(fbsb_buf, sz(), 1, f);
fclose(f);
}
{
auto f = fopen("conjbuf.cfile", "wb");
fwrite(conjbuf, sz(), 1, f);
fclose(f);
}
{
auto f = fopen("schfcch.cfile", "wb");
fwrite(avgbuf, sz(), 1, f);
fclose(f);
}
exit(0);
}
return pos;
}
};