Add files via upload

pull/1/head
Wojciech Kaczmarski 2022-12-05 20:01:07 +01:00 zatwierdzone przez GitHub
rodzic 8a22e07f2e
commit bf212ee421
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 334 dodań i 10 usunięć

Wyświetl plik

@ -6,12 +6,13 @@
#include "m17.h"
#include "golay.h"
#include "viterbi.h"
float sample;
float last[8];
float xcorr;
float pld[SYM_PER_PLD];
uint16_t soft_bit[2*SYM_PER_PLD];
float sample; //last raw sample from the stdin
float last[8]; //look-back buffer for finding syncwords
float xcorr; //cross correlation for finding syncwords
float pld[SYM_PER_PLD]; //raw frame symbols
uint16_t soft_bit[2*SYM_PER_PLD]; //raw frame soft bits
uint16_t d_soft_bit[2*SYM_PER_PLD]; //deinterleaved soft bits
uint8_t lsf[30]; //complete LSF
@ -20,8 +21,13 @@ uint8_t lich_b[6]; //48-bit decoded LICH
uint8_t lich_cnt; //LICH_CNT
uint8_t lich_chunks_rcvd=0; //flags set for each LSF chunk received
uint8_t syncd=0;
uint8_t pushed; //pushed symbols
uint16_t enc_data[272]; //raw frame data soft bits
uint8_t frame_data[18]; //decoded frame data, 144 bits (16+128)
uint8_t syncd=0; //syncword found?
uint8_t pushed; //counter for pushed symbols
extern const uint8_t P2_pat[12];
//soft decodes LICH into a 6-byte array
//input - soft bits
@ -77,6 +83,10 @@ int main(void)
syncd=1;
pushed=0;
}
else if(xcorr<-62)
{
printf("LSF\n");
}
}
else
{
@ -152,7 +162,7 @@ int main(void)
//debug - dump LICH
if(lich_chunks_rcvd==0x3F)
{
//DST
/*//DST
printf("DST: ");
for(uint8_t i=0; i<6; i++)
printf("%02X", lsf[i]);
@ -180,11 +190,28 @@ int main(void)
printf("CRC: ");
for(uint8_t i=0; i<2; i++)
printf("%02X", lsf[28+i]);
printf("\n");
printf("\n");*/
lich_chunks_rcvd=0; //reset all flags
}
//extract data
for(uint16_t i=0; i<272; i++)
{
enc_data[i]=d_soft_bit[96+i];
}
//data part
memset((uint8_t*)frame_data, 0, 18);
decodePunctured(frame_data, enc_data, P2_pat, 272, 12);
//dump data
for(uint8_t i=0; i<18; i++)
{
printf("%02X ", frame_data[i]);
}
printf("\n");
//job done
syncd=0;
pushed=0;

Wyświetl plik

@ -0,0 +1,72 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include "m17.h"
int16_t sample; //raw S16_LE baseband sample
int16_t flt_buff[FLT_LEN]; //root-nyquist filter buffer
int16_t sw_buff[SW_LEN]; //syncword detection buffer
int16_t xc_buff[XC_LEN]; //cross-correlation buffer
int16_t mac; //multiply-accumulate
//states
uint8_t pre_syncd=0;
uint8_t syncd=0;
int8_t phase=0;
int main(void)
{
while(1)
{
//wait for another baseband sample
while(read(STDIN_FILENO, (uint8_t*)&sample, 2)<2);
//push the root-nyquist filter's buffer
for(uint8_t i=0; i<FLT_LEN-1; i++)
{
flt_buff[i]=flt_buff[i+1];
}
flt_buff[FLT_LEN-1]=sample;
//calculate the filter's output
mac=0;
for(uint8_t i=0; i<FLT_LEN; i++)
mac+=flt_buff[i]*taps[i];
for(uint8_t i=0; i<FLT_LEN-2; i++)
{
sw_buff[i]=sw_buff[i+1];
}
sw_buff[FLT_LEN-2]=mac;
//detect syncword using cross-correlation
int32_t xcorr=0;
for(uint8_t i=0; i<XC_LEN; i+=10)
{
xcorr+=sw_buff[i]*str_sync[i/10];
}
//push the xcorr value to the buffer
for(uint8_t i=0; i<XC_LEN-1; i++)
{
xc_buff[i]=xc_buff[i+1];
}
xc_buff[XC_LEN-1]=xcorr/24;
//detect peak
if(xc_buff[XC_LEN-1]>0.4*INT16_MAX)
{
uint8_t msg[64];
uint8_t len=sprintf(msg, "SYNC\n");
write(STDERR_FILENO, msg, len);
}
}
return 0;
}

Wyświetl plik

@ -11,7 +11,7 @@ const int8_t str_sync[8]={-3, -3, -3, -3, +3, +3, -3, +3};
const int8_t lsf_sync[8]={+3, +3, +3, +3, -3, -3, +3, -3};
//symbol levels
const float symbs[4]={-3*0.12, -1*0.12, +1*0.12, +3*0.12};
const float symbs[4]={-3.0, -1.0, +1.0, +3.0};
//RRC filter - 10 samples per symbol, 8 symbols span
const float taps[FLT_LEN]=

214
SP5WWP/viterbi.c 100644
Wyświetl plik

@ -0,0 +1,214 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include "viterbi.h"
#define K 5 //constraint length
#define NUM_STATES (1 << (K - 1)) //number of states
const uint8_t P2_pat[12]={1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; //P_2 puncturing pattern for stream frames
//vars
uint32_t prevMetrics[NUM_STATES];
uint32_t currMetrics[NUM_STATES];
uint32_t prevMetricsData[NUM_STATES];
uint32_t currMetricsData[NUM_STATES];
uint16_t history[244];
/**
* Decode unpunctured convolutionally encoded data.
*
* @param out: destination array where decoded data is written.
* @param in: input data.
* @param len: input length in bits
* @return number of bit errors corrected.
*/
uint32_t decode(uint8_t* out, const uint16_t* in, uint16_t len)
{
if(len > 244*2)
fprintf((FILE*)STDERR_FILENO, "Input size exceeds max history\n");
reset();
size_t pos = 0;
for(size_t i = 0; i < len; i += 2)
{
uint16_t s0 = in[i];
uint16_t s1 = in[i + 1];
decodeBit(s0, s1, pos);
pos++;
}
return chainback(out, pos, len/2);
}
/**
* Decode punctured convolutionally encoded data.
*
* @param out: destination array where decoded data is written.
* @param in: input data.
* @param punct: puncturing matrix.
* @param in_len: input data length.
* @param p_len: puncturing matrix length (entries).
* @return number of bit errors corrected.
*/
uint16_t decodePunctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, uint16_t in_len, uint16_t p_len) //input length, puncturing pattern length
{
if(in_len > 244*2)
fprintf((FILE*)STDERR_FILENO, "Input size exceeds max history\n");
uint16_t umsg[244*2]; //unpunctured message
uint8_t p=0; //puncturer matrix entry
uint16_t u=0; //bits count - unpunctured message
uint16_t i=0; //bits read from the input message
while(i<in_len)
{
if(punct[p])
{
umsg[u]=in[i];
i++;
}
else
{
umsg[u]=0x7FFF;
}
u++;
p++;
p%=p_len;
}
return decode(out, umsg, u);
}
/**
* Decode one bit and update trellis.
*
* @param s0: cost of the first symbol.
* @param s1: cost of the second symbol.
* @param pos: bit position in history.
*/
void decodeBit(uint16_t s0, uint16_t s1, size_t pos)
{
static const uint16_t COST_TABLE_0[] = {0, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
static const uint16_t COST_TABLE_1[] = {0, 0xFFFF, 0xFFFF, 0, 0, 0xFFFF, 0xFFFF, 0};
for(uint8_t i = 0; i < NUM_STATES/2; i++)
{
uint32_t metric = q_AbsDiff(COST_TABLE_0[i], s0)
+ q_AbsDiff(COST_TABLE_1[i], s1);
uint32_t m0 = prevMetrics[i] + metric;
uint32_t m1 = prevMetrics[i + NUM_STATES/2] + (0x1FFFE - metric);
uint32_t m2 = prevMetrics[i] + (0x1FFFE - metric);
uint32_t m3 = prevMetrics[i + NUM_STATES/2] + metric;
uint8_t i0 = 2 * i;
uint8_t i1 = i0 + 1;
if(m0 >= m1)
{
history[pos]|=(1<<i0);
currMetrics[i0] = m1;
}
else
{
history[pos]&=~(1<<i0);
currMetrics[i0] = m0;
}
if(m2 >= m3)
{
history[pos]|=(1<<i1);
currMetrics[i1] = m3;
}
else
{
history[pos]&=~(1<<i1);
currMetrics[i1] = m2;
}
}
//swap
uint32_t tmp[NUM_STATES];
for(uint8_t i=0; i<NUM_STATES; i++)
{
tmp[i]=currMetrics[i];
}
for(uint8_t i=0; i<NUM_STATES; i++)
{
currMetrics[i]=prevMetrics[i];
prevMetrics[i]=tmp[i];
}
}
/**
* History chainback to obtain final byte array.
*
* @param out: destination byte array for decoded data.
* @param pos: starting position for the chainback.
* @param len: length of the output in bits.
* @return minimum Viterbi cost at the end of the decode sequence.
*/
uint32_t chainback(uint8_t* out, size_t pos, uint16_t len)
{
uint8_t state = 0;
size_t bitPos = len;
while(bitPos > 0)
{
bitPos--;
pos--;
uint8_t bit = history[pos]&((1<<(state>>4)));
state >>= 1;
if(bit)
{
state |= 0x80;
out[bitPos/8]|=1<<(bitPos%8);
}
}
uint32_t cost = prevMetrics[0];
for(size_t i = 0; i < NUM_STATES; i++)
{
uint32_t m = prevMetrics[i];
if(m < cost) cost = m;
}
return cost;
}
/**
* Utility function to compute the absolute value of a difference between
* two fixed-point values.
*
* @param v1: first value
* @param v2: second value
* @return abs(v1-v2)
*/
uint16_t q_AbsDiff(const uint16_t v1, const uint16_t v2)
{
if(v2 > v1) return v2 - v1;
return v1 - v2;
}
/**
* Reset the decoder state.
*
*/
void reset(void)
{
memset((uint8_t*)history, 0, 2*244);
memset((uint8_t*)currMetrics, 0, 4*NUM_STATES);
memset((uint8_t*)prevMetrics, 0, 4*NUM_STATES);
memset((uint8_t*)currMetricsData, 0, 4*NUM_STATES);
memset((uint8_t*)prevMetricsData, 0, 4*NUM_STATES);
}

11
SP5WWP/viterbi.h 100644
Wyświetl plik

@ -0,0 +1,11 @@
#ifndef VITERBI_H
#define VITERBI_H
uint32_t decode(uint8_t* out, const uint16_t* in, uint16_t len);
uint16_t decodePunctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, uint16_t in_len, uint16_t p_len);
void decodeBit(uint16_t s0, uint16_t s1, size_t pos);
uint32_t chainback(uint8_t* out, size_t pos, uint16_t len);
uint16_t q_AbsDiff(const uint16_t v1, const uint16_t v2);
void reset(void);
#endif