Skip to content

Commit

Permalink
Add MA3 (all digital) service mode
Browse files Browse the repository at this point in the history
  • Loading branch information
argilo committed May 5, 2024
1 parent e3b30c3 commit 2371df6
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void acquire_process(acquire_t *st)

if (st->input->sync_state != SYNC_STATE_FINE)
{
for (j = CENTER_AM - PIDS_2_INDEX_AM; j <= CENTER_AM + PIDS_2_INDEX_AM; j++)
for (j = CENTER_AM - PIDS_OUTER_INDEX_AM; j <= CENTER_AM + PIDS_OUTER_INDEX_AM; j++)
{
mag_sums[j] += cabsf(st->fftout[j]);
}
Expand All @@ -215,7 +215,7 @@ void acquire_process(acquire_t *st)
{
float max_mag = -1.0f;
int max_index = -1;
for (j = CENTER_AM - PIDS_2_INDEX_AM; j <= CENTER_AM + PIDS_2_INDEX_AM; j++)
for (j = CENTER_AM - PIDS_OUTER_INDEX_AM; j <= CENTER_AM + PIDS_OUTER_INDEX_AM; j++)
{
if (mag_sums[j] > max_mag)
{
Expand Down
145 changes: 115 additions & 30 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,48 @@ static void interleaver_ma1(decode_t *st)
p = 3 + (n % 3);
st->mu[DIVERSITY_DELAY_AM + n] = bit_map(st->buffer_pu, b, k, p);
}
for (int n = 0; n < 12000; n++)

if (st->input->sync.psmi != SERVICE_MODE_MA3)
{
b = (3*n + n/3000) % 8;
k = (n + (n/6000)) % 750;
p = n % 2;
st->el[n] = bit_map(st->buffer_t, b, k, p);
for (int n = 0; n < 12000; n++)
{
b = (3*n + n/3000) % 8;
k = (n + (n/6000)) % 750;
p = n % 2;
st->el[n] = bit_map(st->buffer_t, b, k, p);
}
for (int n = 0; n < 24000; n++)
{
b = (3*n + n/3000 + 2*(n/12000)) % 8;
k = (n + (n/6000)) % 750;
p = n % 4;
st->eu[n] = bit_map(st->buffer_s, b, k, p);
}
}
for (int n = 0; n < 24000; n++)
else
{
b = (3*n + n/3000 + 2*(n/12000)) % 8;
k = (n + (n/6000)) % 750;
p = n % 4;
st->eu[n] = bit_map(st->buffer_s, b, k, p);
for (int n = 0; n < 18000; n++)
{
b = (3*n + 3) % 8;
k = (n + n/3000 + 3) % 750;
p = n % 3;
st->ebl[n] = bit_map(st->buffer_t, b, k, p);

b = (3*n + 3) % 8;
k = (n + n/3000 + 3) % 750;
p = 3 + (n % 3);
st->eml[DIVERSITY_DELAY_AM + n] = bit_map(st->buffer_t, b, k, p);

b = (3*n) % 8;
k = (n + n/3000 + 2) % 750;
p = n % 3;
st->ebu[n] = bit_map(st->buffer_s, b, k, p);

b = (3*n) % 8;
k = (n + n/3000 + 2) % 750;
p = 3 + (n % 3);
st->emu[DIVERSITY_DELAY_AM + n] = bit_map(st->buffer_s, b, k, p);
}
}

for (int i = 0; i < 6000; i++)
Expand All @@ -89,18 +118,36 @@ static void interleaver_ma1(decode_t *st)
st->p1_am[i*12 + bu_delay[j]] = st->bu[i*3 + j];
st->p1_am[i*12 + mu_delay[j]] = st->mu[i*3 + j];
}
for (int j = 0; j < 2; j++)
if (st->input->sync.psmi != SERVICE_MODE_MA3)
{
st->p3_am[i*6 + el_delay[j]] = st->el[i*2 + j];
for (int j = 0; j < 2; j++)
{
st->p3_am[i*6 + el_delay[j]] = st->el[i*2 + j];
}
for (int j = 0; j < 4; j++)
{
st->p3_am[i*6 + eu_delay[j]] = st->eu[i*4 + j];
}
}
for (int j = 0; j < 4; j++)
else
{
st->p3_am[i*6 + eu_delay[j]] = st->eu[i*4 + j];
for (int j = 0; j < 3; j++)
{
st->p3_am[i*12 + bl_delay[j]] = st->ebl[i*3 + j];
st->p3_am[i*12 + ml_delay[j]] = st->eml[i*3 + j];
st->p3_am[i*12 + bu_delay[j]] = st->ebu[i*3 + j];
st->p3_am[i*12 + mu_delay[j]] = st->emu[i*3 + j];
}
}
}

memmove(st->ml, st->ml + 18000, DIVERSITY_DELAY_AM);
memmove(st->mu, st->mu + 18000, DIVERSITY_DELAY_AM);
if (st->input->sync.psmi == SERVICE_MODE_MA3)
{
memmove(st->eml, st->eml + 18000, DIVERSITY_DELAY_AM);
memmove(st->emu, st->emu + 18000, DIVERSITY_DELAY_AM);
}

int offset = 0;
for (int i = 0; i < 8 * P1_FRAME_LEN_AM * 3; i++)
Expand All @@ -118,17 +165,36 @@ static void interleaver_ma1(decode_t *st)
}

offset = 0;
for (int i = 0; i < P3_FRAME_LEN_AM * 3; i++)
if (st->input->sync.psmi != SERVICE_MODE_MA3)
{
switch (i % 6)
for (int i = 0; i < P3_FRAME_LEN_MA1 * 3; i++)
{
case 1:
case 4:
case 5:
st->viterbi_p3_am[i] = 0;
break;
default:
st->viterbi_p3_am[i] = st->p3_am[offset++] ? 1 : -1;
switch (i % 6)
{
case 1:
case 4:
case 5:
st->viterbi_p3_am[i] = 0;
break;
default:
st->viterbi_p3_am[i] = st->p3_am[offset++] ? 1 : -1;
}
}
}
else
{
for (int i = 0; i < P3_FRAME_LEN_MA3 * 3; i++)
{
switch (i % 15)
{
case 1:
case 4:
case 7:
st->viterbi_p3_am[i] = 0;
break;
default:
st->viterbi_p3_am[i] = st->p3_am[offset++] ? 1 : -1;
}
}
}
}
Expand Down Expand Up @@ -173,10 +239,16 @@ static int bit_errors_p1_am(int8_t *coded, uint8_t *decoded)
return bit_errors(coded, decoded, 9, P1_FRAME_LEN_AM, 0561, 0657, 0711, puncture, 15);
}

static int bit_errors_p3_am(int8_t *coded, uint8_t *decoded)
static int bit_errors_p3_ma1(int8_t *coded, uint8_t *decoded)
{
uint8_t puncture[] = {1, 0, 1, 1, 0, 0};
return bit_errors(coded, decoded, 9, P3_FRAME_LEN_AM, 0561, 0753, 0711, puncture, 6);
return bit_errors(coded, decoded, 9, P3_FRAME_LEN_MA1, 0561, 0753, 0711, puncture, 6);
}

static int bit_errors_p3_ma3(int8_t *coded, uint8_t *decoded)
{
uint8_t puncture[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1};
return bit_errors(coded, decoded, 9, P3_FRAME_LEN_MA3, 0561, 0657, 0711, puncture, 15);
}

static void descramble(uint8_t *buf, unsigned int length)
Expand Down Expand Up @@ -336,12 +408,25 @@ void decode_process_p1_p3_am(decode_t *st)
descramble(st->scrambler_p1_am, P1_FRAME_LEN_AM);
frame_push(&st->input->frame, st->scrambler_p1_am, P1_FRAME_LEN_AM, P1_LOGICAL_CHANNEL);
}
nrsc5_conv_decode_e2(st->viterbi_p3_am, st->scrambler_p3_am, P3_FRAME_LEN_AM);
total_errors += bit_errors_p3_am(st->viterbi_p3_am, st->scrambler_p3_am);
descramble(st->scrambler_p3_am, P3_FRAME_LEN_AM);
frame_push(&st->input->frame, st->scrambler_p3_am, P3_FRAME_LEN_AM, P3_LOGICAL_CHANNEL);

nrsc5_report_ber(st->input->radio, (float) total_errors / (8 * P1_FRAME_LEN_ENCODED_AM + P3_FRAME_LEN_ENCODED_AM));
if (st->input->sync.psmi != SERVICE_MODE_MA3)
{
nrsc5_conv_decode_e2(st->viterbi_p3_am, st->scrambler_p3_am, P3_FRAME_LEN_MA1);
total_errors += bit_errors_p3_ma1(st->viterbi_p3_am, st->scrambler_p3_am);
descramble(st->scrambler_p3_am, P3_FRAME_LEN_MA1);
frame_push(&st->input->frame, st->scrambler_p3_am, P3_FRAME_LEN_MA1, P3_LOGICAL_CHANNEL);

nrsc5_report_ber(st->input->radio, (float) total_errors / (8 * P1_FRAME_LEN_ENCODED_AM + P3_FRAME_LEN_ENCODED_MA1));
}
else
{
nrsc5_conv_decode_e1(st->viterbi_p3_am, st->scrambler_p3_am, P3_FRAME_LEN_MA3);
total_errors += bit_errors_p3_ma3(st->viterbi_p3_am, st->scrambler_p3_am);
descramble(st->scrambler_p3_am, P3_FRAME_LEN_MA3);
frame_push(&st->input->frame, st->scrambler_p3_am, P3_FRAME_LEN_MA3, P3_LOGICAL_CHANNEL);

nrsc5_report_ber(st->input->radio, (float) total_errors / (8 * P1_FRAME_LEN_ENCODED_AM + P3_FRAME_LEN_ENCODED_MA3));
}
}

static void interleaver_iv_reset(interleaver_iv_t *interleaver)
Expand Down
10 changes: 7 additions & 3 deletions src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ typedef struct
uint8_t mu[18000 + DIVERSITY_DELAY_AM];
uint8_t el[12000];
uint8_t eu[24000];
uint8_t ebl[18000];
uint8_t ebu[18000];
uint8_t eml[18000 + DIVERSITY_DELAY_AM];
uint8_t emu[18000 + DIVERSITY_DELAY_AM];

int8_t viterbi_p1[P1_FRAME_LEN_FM * 3];
uint8_t scrambler_p1[P1_FRAME_LEN_FM];
Expand All @@ -51,9 +55,9 @@ typedef struct
uint8_t p1_am[8 * P1_FRAME_LEN_ENCODED_AM];
int8_t viterbi_p1_am[8 * P1_FRAME_LEN_AM * 3];
uint8_t scrambler_p1_am[P1_FRAME_LEN_AM];
uint8_t p3_am[P3_FRAME_LEN_ENCODED_AM];
int8_t viterbi_p3_am[P3_FRAME_LEN_AM * 3];
uint8_t scrambler_p3_am[P3_FRAME_LEN_AM];
uint8_t p3_am[P3_FRAME_LEN_ENCODED_MA3];
int8_t viterbi_p3_am[P3_FRAME_LEN_MA3 * 3];
uint8_t scrambler_p3_am[P3_FRAME_LEN_MA3];

pids_t pids;
} decode_t;
Expand Down
19 changes: 12 additions & 7 deletions src/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@
#define CENTER_AM (FFT_AM / 2)
// indexes of AM subcarriers
#define REF_INDEX_AM 1
#define PIDS_1_INDEX_AM 27
#define PIDS_2_INDEX_AM 53
#define TERTIARY_INDEX_AM 2
#define SECONDARY_INDEX_AM 28
#define PRIMARY_INDEX_AM 57
#define PIDS_INNER_INDEX_AM 27
#define PIDS_OUTER_INDEX_AM 53
#define INNER_PARTITION_START_AM 2
#define MIDDLE_PARTITION_START_AM 28
#define OUTER_PARTITION_START_AM 57
#define MAX_INDEX_AM 81
// AM service modes
#define SERVICE_MODE_MA1 1
#define SERVICE_MODE_MA3 2
// bits per P1 frame
#define P1_FRAME_LEN_FM 146176
#define P1_FRAME_LEN_AM 3750
Expand All @@ -49,10 +52,12 @@
#define PIDS_FRAME_LEN_ENCODED_AM (PIDS_FRAME_LEN * 3)
// bits per P3 frame
#define P3_FRAME_LEN_FM 4608
#define P3_FRAME_LEN_AM 24000
#define P3_FRAME_LEN_MA1 24000
#define P3_FRAME_LEN_MA3 30000
// bits per encoded P3 frame
#define P3_FRAME_LEN_ENCODED_FM (P3_FRAME_LEN_FM * 2)
#define P3_FRAME_LEN_ENCODED_AM (P3_FRAME_LEN_AM * 3 / 2)
#define P3_FRAME_LEN_ENCODED_MA1 (P3_FRAME_LEN_MA1 * 3 / 2)
#define P3_FRAME_LEN_ENCODED_MA3 (P3_FRAME_LEN_MA3 * 12 / 5)
// bits per L2 PCI
#define PCI_LEN 24
// bytes per L2 PDU (max)
Expand Down
7 changes: 6 additions & 1 deletion src/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,11 +614,16 @@ void frame_push(frame_t *st, uint8_t *bits, size_t length, logical_channel_t lc)
offset = 160;
pci_len = 22;
break;
case P3_FRAME_LEN_AM:
case P3_FRAME_LEN_MA1:
start = 120;
offset = 992;
pci_len = 24;
break;
case P3_FRAME_LEN_MA3:
start = 120;
offset = 1240;
pci_len = 24;
break;
default:
log_error("Unknown frame length: %u", (unsigned int)length);
return;
Expand Down
Loading

0 comments on commit 2371df6

Please sign in to comment.