T: make number of subframes per frame a configurable item

Think: NR with different number of slots per frame depending on mu.

The name 'subframes_per_frame' is a bit ambiguous. It is valid for LTE,
but for NR it should be 'slots_per_frame'.

For example, for sub-carrier spacing of 30KHz, we have 20 slots per
frame, so in this case subframes_per_frame = 20. In reality whatever
the numerology, there is always 10 subframes per frame in NR.

But how to name this variable which is used both for LTE and NR cases?
'subframes_or_slots_per_frame'? It's a bit long and also ambiguous.

Conclusion: no big deal I think. 'subframes_per_frame' and so be it.
This commit is contained in:
Cedric Roux
2025-08-18 11:53:54 +02:00
parent 138886ad5e
commit c4acec706d
7 changed files with 86 additions and 58 deletions
+21 -12
View File
@@ -15,10 +15,11 @@ struct scrolltti {
int plot;
float refresh_rate;
pthread_mutex_t lock;
unsigned long data[1000];
unsigned long total; /* sum data[0..999] to have smoother value printed */
float xout[1000];
float yout[1000];
int subframes_per_frame;
unsigned long *data;
unsigned long total; /* sum data[0..n] to have smoother value printed */
float *xout;
float *yout;
int insert_point;
int next_tick_frame;
int next_tick_subframe;
@@ -40,21 +41,21 @@ static void *scrolltti_thread(void *_this)
/* TODO: optimize */
p = this->insert_point;
max = 0;
for (i = 0; i < 1000; i++) {
for (i = 0; i < this->subframes_per_frame * 100; i++) {
this->xout[i] = i;
this->yout[i] = this->data[p];
if (this->data[p] > max) max = this->data[p];
p = (p + 1) % 1000;
p = (p + 1) % (this->subframes_per_frame * 100);
}
bps(o, this->total/1000., "b/s");
bps(o, this->total/(this->subframes_per_frame * 100.), "b/s");
textarea_set_text(this->g, this->throughput_textarea, o);
/* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */
if (max < 1000) max = 1000;
mlog = pow(10, floor(log10(max)));
max = tolog[(int)ceil(max/mlog)] * mlog;
xy_plot_set_range(this->g, this->w, 0, 1000, 0, max);
xy_plot_set_range(this->g, this->w, 0, this->subframes_per_frame * 100, 0, max);
xy_plot_set_points(this->g, this->w, this->plot,
1000, this->xout, this->yout);
this->subframes_per_frame * 100, this->xout, this->yout);
if (pthread_mutex_unlock(&this->lock)) abort();
sleepms(1000/this->refresh_rate);
}
@@ -72,13 +73,13 @@ static void insert(struct scrolltti *this, double value)
this->total -= this->data[this->insert_point];
this->data[this->insert_point] = value;
this->total += this->data[this->insert_point];
this->insert_point = (this->insert_point + 1) % 1000;
this->insert_point = (this->insert_point + 1) % (this->subframes_per_frame * 100);
}
static void next_subframe(struct scrolltti *this)
{
this->next_tick_subframe++;
if (this->next_tick_subframe == 10) {
if (this->next_tick_subframe == this->subframes_per_frame) {
this->next_tick_subframe = 0;
this->next_tick_frame++;
this->next_tick_frame %= 1024;
@@ -100,7 +101,7 @@ static void append(view *_this, int frame, int subframe, double value)
}
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
widget *throughput_textarea)
widget *throughput_textarea, int subframes_per_frame)
{
struct scrolltti *ret = calloc(1, sizeof(struct scrolltti));
if (ret == NULL) abort();
@@ -114,6 +115,14 @@ view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
ret->throughput_textarea = throughput_textarea;
ret->plot = xy_plot_new_plot(g, w, color);
ret->subframes_per_frame = subframes_per_frame;
ret->data = calloc(subframes_per_frame * 100, sizeof(unsigned long));
if (ret->data == NULL) abort();
ret->xout = calloc(subframes_per_frame * 100, sizeof(float));
if (ret->xout == NULL) abort();
ret->yout = calloc(subframes_per_frame * 100, sizeof(float));
if (ret->yout == NULL) abort();
if (pthread_mutex_init(&ret->lock, NULL)) abort();
new_thread(scrolltti_thread, ret);
+27 -13
View File
@@ -16,23 +16,25 @@ struct tti {
int plot;
float refresh_rate;
pthread_mutex_t lock;
float data[1024*10];
int valid[1024*10];
float xout[1024*10];
float yout[1024*10];
float *data;
int *valid;
float *xout;
float *yout;
int last_insert_point;
int subframes_per_frame;
};
static int far_enough(int i, int last_insert, int plot_width)
static int far_enough(int i, int last_insert, int plot_width,
int subframes_per_frame)
{
int p1;
int p2;
int hole_size_px;
int hole_size_tti;
hole_size_px = 10;
hole_size_tti = 10240 * hole_size_px / plot_width;
hole_size_tti = 1024 * subframes_per_frame * hole_size_px / plot_width;
p1 = last_insert;
p2 = (last_insert + hole_size_tti) % (1024*10);
p2 = (last_insert + hole_size_tti) % (1024 * subframes_per_frame);
if (p1 < p2) {
return !(i > p1 && i < p2);
}
@@ -53,10 +55,11 @@ static void *tti_thread(void *_this)
length = 0;
double max = 0;
/* TODO: optimize */
for (i = 0; i < 1024*10; i++)
for (i = 0; i < 1024 * this->subframes_per_frame; i++)
/* do not take points too close after last insertion point */
if (this->valid[i] &&
far_enough(i, this->last_insert_point, plot_width)) {
far_enough(i, this->last_insert_point, plot_width,
this->subframes_per_frame)) {
this->xout[length] = i;
this->yout[length] = this->data[i];
if (this->data[i] > max) max = this->data[i];
@@ -93,7 +96,7 @@ static void append(view *_this, int frame, int subframe, double value)
{
struct tti *this = (struct tti *)_this;
int i;
int index = frame * 10 + subframe;
int index = frame * this->subframes_per_frame + subframe;
if (pthread_mutex_lock(&this->lock)) abort();
@@ -102,10 +105,10 @@ static void append(view *_this, int frame, int subframe, double value)
* this may be wrong if delay between two append is
* greater than 1024 frames (something like that)
*/
i = (this->last_insert_point + 1) % (1024*10);
i = (this->last_insert_point + 1) % (1024 * this->subframes_per_frame);
while (i != index) {
this->valid[i] = 0;
i = (i + 1) % (1024*10);
i = (i + 1) % (1024 * this->subframes_per_frame);
}
this->data[index] = value;
@@ -116,7 +119,8 @@ static void append(view *_this, int frame, int subframe, double value)
if (pthread_mutex_unlock(&this->lock)) abort();
}
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color)
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color,
int subframes_per_frame)
{
struct tti *ret = calloc(1, sizeof(struct tti));
if (ret == NULL) abort();
@@ -133,6 +137,16 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color)
if (pthread_mutex_init(&ret->lock, NULL)) abort();
ret->subframes_per_frame = subframes_per_frame;
ret->data = calloc(subframes_per_frame * 1024, sizeof(float));
if (ret->data == NULL) abort();
ret->valid = calloc(subframes_per_frame * 1024, sizeof(int));
if (ret->valid == NULL) abort();
ret->xout = calloc(subframes_per_frame * 1024, sizeof(float));
if (ret->xout == NULL) abort();
ret->yout = calloc(subframes_per_frame * 1024, sizeof(float));
if (ret->yout == NULL) abort();
new_thread(tti_thread, ret);
return (view *)ret;
+3 -3
View File
@@ -17,10 +17,10 @@ view *new_view_stdout(void);
view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w);
view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
int color, enum xy_mode mode);
view *new_view_tti(float refresh_rate, gui *g, widget *w,
int color);
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color,
int subframes_per_frame);
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w,
int color, widget *throughput_label);
int color, widget *throughput_label, int subframes_per_frame);
view *new_view_time(int number_of_seconds, float refresh_rate,
gui *g, widget *w);
view *new_subview_time(view *time, int line, int color, int size);