kopia lustrzana https://github.com/M17-Project/M17_Implementations
Add files via upload
rodzic
5eca167967
commit
ae53fe6636
|
@ -0,0 +1,228 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "golay.h"
|
||||
|
||||
const uint16_t encode_matrix[12]=
|
||||
{
|
||||
0x8eb, 0x93e, 0xa97, 0xdc6, 0x367, 0x6cd,
|
||||
0xd99, 0x3da, 0x7b4, 0xf68, 0x63b, 0xc75
|
||||
};
|
||||
|
||||
const uint16_t decode_matrix[12]=
|
||||
{
|
||||
0xc75, 0x49f, 0x93e, 0x6e3, 0xdc6, 0xf13,
|
||||
0xab9, 0x1ed, 0x3da, 0x7b4, 0xf68, 0xa4f
|
||||
};
|
||||
|
||||
//0 index - LSB
|
||||
void IntToSoft(uint16_t* out, const uint16_t in, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
(in>>i)&1 ? (out[i]=0xFFFF) : (out[i]=0);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t SoftToInt(const uint16_t* in, uint8_t len)
|
||||
{
|
||||
uint16_t tmp=0;
|
||||
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
if(in[i]>0x7FFF)
|
||||
tmp|=(1<<i);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//Quadrant I fixed point division with saturation
|
||||
//result=a/b
|
||||
uint16_t Div16(uint16_t a, uint16_t b)
|
||||
{
|
||||
uint32_t aa=a<<16;
|
||||
uint32_t r=aa/b;
|
||||
|
||||
if(r<=0xFFFF)
|
||||
return r;
|
||||
else
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
//Quadrant I fixed point multiplication
|
||||
//result=a/b
|
||||
uint16_t Mul16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return (uint16_t)(((uint32_t)a*b)>>16);
|
||||
}
|
||||
|
||||
//use bilinear interpolation for XOR
|
||||
uint16_t SoftBitXOR(const uint16_t a, const uint16_t b)
|
||||
{
|
||||
return Mul16(Div16(0xFFFF-b, 0xFFFF), Div16(a, 0xFFFF)) + Mul16(Div16(b, 0xFFFF), Div16(0xFFFF-a, 0xFFFF));
|
||||
}
|
||||
|
||||
//soft XOR
|
||||
void SoftXOR(uint16_t* out, const uint16_t* a, const uint16_t* b, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
out[i]=SoftBitXOR(a[i], b[i]);
|
||||
}
|
||||
|
||||
//soft equivalent of popcount
|
||||
uint32_t spopcount(const uint16_t* in, uint8_t siz)
|
||||
{
|
||||
uint32_t tmp=0;
|
||||
|
||||
for(uint8_t i=0; i<siz; i++)
|
||||
tmp+=in[i];
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void calcChecksumS(uint16_t* out, const uint16_t* value)
|
||||
{
|
||||
uint16_t checksum[12];
|
||||
uint16_t soft_em[12]; //soft valued encoded matrix entry
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
checksum[i]=0;
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
IntToSoft(soft_em, encode_matrix[i], 12);
|
||||
|
||||
if(value[i]>0x7FFF)
|
||||
{
|
||||
SoftXOR(checksum, checksum, soft_em, 12);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((uint8_t*)out, (uint8_t*)checksum, 12*2);
|
||||
}
|
||||
|
||||
uint32_t SdetectErrors(const uint16_t* codeword)
|
||||
{
|
||||
uint16_t data[12];
|
||||
uint16_t parity[12];
|
||||
uint16_t cksum[12];
|
||||
uint16_t syndrome[12];
|
||||
uint32_t weight; //for soft popcount
|
||||
|
||||
memcpy((uint8_t*)data, (uint8_t*)&codeword[12], 2*12);
|
||||
memcpy((uint8_t*)parity, (uint8_t*)&codeword[0], 2*12);
|
||||
|
||||
calcChecksumS(cksum, data);
|
||||
SoftXOR(syndrome, parity, cksum, 12);
|
||||
|
||||
weight=spopcount(syndrome, 12);
|
||||
|
||||
//all (less than 4) errors in the parity part
|
||||
if(weight < 4*0xFFFE)
|
||||
{
|
||||
//printf("1: %1.2f\n", (float)weight/0xFFFF);
|
||||
return SoftToInt(syndrome, 12);
|
||||
}
|
||||
|
||||
//one of the errors in data part, up to 3 in parity
|
||||
for(uint8_t i = 0; i<12; i++)
|
||||
{
|
||||
uint16_t e = 1<<i;
|
||||
uint16_t coded_error = encode_matrix[i];
|
||||
uint16_t scoded_error[12]; //soft coded_error
|
||||
uint16_t sc[12]; //syndrome^coded_error
|
||||
|
||||
IntToSoft(scoded_error, coded_error, 12);
|
||||
SoftXOR(sc, syndrome, scoded_error, 12);
|
||||
weight=spopcount(sc, 12);
|
||||
|
||||
if(weight < 3*0xFFFE)
|
||||
{
|
||||
//printf("2: %1.2f\n", (float)weight/0xFFFF+1);
|
||||
uint16_t s=SoftToInt(syndrome, 12);
|
||||
return (e << 12) | (s ^ coded_error);
|
||||
}
|
||||
}
|
||||
|
||||
//two of the errors in data part and up to 2 in parity
|
||||
for(uint8_t i = 0; i<11; i++)
|
||||
{
|
||||
for(uint8_t j = i+1; j<12; j++)
|
||||
{
|
||||
uint16_t e = (1<<i) | (1<<j);
|
||||
uint16_t coded_error = encode_matrix[i]^encode_matrix[j];
|
||||
uint16_t scoded_error[12]; //soft coded_error
|
||||
uint16_t sc[12]; //syndrome^coded_error
|
||||
|
||||
IntToSoft(scoded_error, coded_error, 12);
|
||||
SoftXOR(sc, syndrome, scoded_error, 12);
|
||||
weight=spopcount(sc, 12);
|
||||
|
||||
if(weight < 2*0xFFFF)
|
||||
{
|
||||
//printf("3: %1.2f\n", (float)weight/0xFFFF+2);
|
||||
uint16_t s=SoftToInt(syndrome, 12);
|
||||
return (e << 12) | (s ^ coded_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//algebraic decoding magic
|
||||
uint16_t inv_syndrome[12]={0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint16_t dm[12]; //soft decode matrix
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
if(syndrome[i] > 0x7FFF)
|
||||
{
|
||||
IntToSoft(dm, decode_matrix[i], 12);
|
||||
SoftXOR(inv_syndrome, inv_syndrome, dm, 12);
|
||||
}
|
||||
}
|
||||
|
||||
//all (less than 4) errors in the data part
|
||||
weight=spopcount(inv_syndrome, 12);
|
||||
if(weight < 4*0xFFFF)
|
||||
{
|
||||
//printf("4: %1.2f\n", (float)weight/0xFFFF);
|
||||
return SoftToInt(inv_syndrome, 12) << 12;
|
||||
}
|
||||
|
||||
//one error in parity bits, up to 3 in data - this part has some quirks, the reason remains unknown
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
uint16_t e = 1<<i;
|
||||
uint16_t coding_error = decode_matrix[i];
|
||||
|
||||
uint16_t ce[12]; //soft coding error
|
||||
uint16_t tmp[12];
|
||||
|
||||
IntToSoft(ce, coding_error, 12);
|
||||
SoftXOR(tmp, inv_syndrome, ce, 12);
|
||||
weight=spopcount(tmp, 12);
|
||||
|
||||
if(weight < 3*(0xFFFF+2))
|
||||
{
|
||||
//printf("5: %1.2f\n", (float)weight/0xFFFF+1);
|
||||
return ((SoftToInt(inv_syndrome, 12) ^ coding_error) << 12) | e;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//soft decode
|
||||
uint16_t golay24_sdecode(const uint16_t* codeword)
|
||||
{
|
||||
//match the bit order in M17
|
||||
uint16_t cw[24];
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
cw[i]=codeword[23-i];
|
||||
|
||||
uint32_t errors = SdetectErrors(cw);
|
||||
|
||||
if(errors == 0xFFFFFFFF)
|
||||
return 0xFFFF;
|
||||
|
||||
return (((SoftToInt(&cw[0], 16) | (SoftToInt(&cw[16], 8) << 16)) ^ errors) >> 12) & 0x0FFF;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef GOLAY_H
|
||||
#define GOLAY_H
|
||||
|
||||
void IntToSoft(uint16_t* out, const uint16_t in, uint8_t len);
|
||||
uint16_t SoftToInt(const uint16_t* in, uint8_t len);
|
||||
uint16_t Div16(uint16_t a, uint16_t b);
|
||||
uint16_t Mul16(uint16_t a, uint16_t b);
|
||||
uint16_t SoftBitXOR(const uint16_t a, const uint16_t b);
|
||||
void SoftXOR(uint16_t* out, const uint16_t* a, const uint16_t* b, uint8_t len);
|
||||
uint32_t spopcount(const uint16_t* in, uint8_t siz);
|
||||
void calcChecksumS(uint16_t* out, const uint16_t* value);
|
||||
uint32_t SdetectErrors(const uint16_t* codeword);
|
||||
uint16_t golay24_sdecode(const uint16_t* codeword);
|
||||
|
||||
#endif
|
|
@ -2,9 +2,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "m17.h"
|
||||
#include "golay.h"
|
||||
|
||||
float sample;
|
||||
float last[8];
|
||||
|
@ -12,11 +13,39 @@ float xcorr;
|
|||
float pld[SYM_PER_PLD];
|
||||
uint16_t soft_bit[2*SYM_PER_PLD];
|
||||
uint16_t d_soft_bit[2*SYM_PER_PLD]; //deinterleaved soft bits
|
||||
uint16_t lich_chunk[96];
|
||||
|
||||
uint8_t lsf[30]; //complete LSF
|
||||
uint16_t lich_chunk[96]; //raw, soft LSF chunk extracted from the LICH
|
||||
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
|
||||
|
||||
//soft decodes LICH into a 6-byte array
|
||||
//input - soft bits
|
||||
//output - an array of packed bits
|
||||
void decode_LICH(uint8_t* outp, const uint16_t* inp)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
memset(outp, 0, 5);
|
||||
|
||||
tmp=golay24_sdecode(&inp[0]);
|
||||
outp[0]=(tmp>>4)&0xFF;
|
||||
outp[1]|=(tmp&0xF)<<4;
|
||||
tmp=golay24_sdecode(&inp[1*24]);
|
||||
outp[1]|=(tmp>>8)&0xF;
|
||||
outp[2]=tmp&0xFF;
|
||||
tmp=golay24_sdecode(&inp[2*24]);
|
||||
outp[3]=(tmp>>4)&0xFF;
|
||||
outp[4]|=(tmp&0xF)<<4;
|
||||
tmp=golay24_sdecode(&inp[3*24]);
|
||||
outp[4]|=(tmp>>8)&0xF;
|
||||
outp[5]=tmp&0xFF;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
while(1)
|
||||
|
@ -41,7 +70,9 @@ int main(void)
|
|||
xcorr+=last[i]*str_sync[i];
|
||||
}
|
||||
|
||||
if(xcorr>8.0)
|
||||
//printf("%f\n", xcorr);
|
||||
|
||||
if(xcorr>62.0)
|
||||
{
|
||||
syncd=1;
|
||||
pushed=0;
|
||||
|
@ -112,8 +143,15 @@ int main(void)
|
|||
lich_chunk[i]=d_soft_bit[i];
|
||||
}
|
||||
|
||||
//Golay decoder goes here
|
||||
decode_LICH(lich_b, lich_chunk);
|
||||
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X ", lich_b[i]);
|
||||
printf("\n");
|
||||
|
||||
//debug - dump LICH
|
||||
uint8_t tmp;
|
||||
/*uint8_t tmp;
|
||||
for(uint16_t i=0; i<96; i++)
|
||||
{
|
||||
if(!(i%8))
|
||||
|
@ -123,9 +161,9 @@ int main(void)
|
|||
if(!((i+1)%8))
|
||||
write(STDOUT_FILENO, &tmp, 1);
|
||||
}
|
||||
tmp=0;
|
||||
tmp=0; //padding
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
write(STDOUT_FILENO, &tmp, 1);
|
||||
write(STDOUT_FILENO, &tmp, 1);*/
|
||||
|
||||
//job done
|
||||
syncd=0;
|
||||
|
|
Ładowanie…
Reference in New Issue