kopia lustrzana https://github.com/M17-Project/M17_Implementations
PKT Encoder: Add Support for libsndfile .wav output and float symbol output files compatible with packet decoder; Fix terminating byte inclusion;
README to include mentions for m17-fme and cross compatibility use;pull/26/head
rodzic
3bfe8ae61d
commit
1de9d711eb
|
@ -5,3 +5,8 @@
|
|||
/SP5WWP/m17-packet/m17-packet-decode
|
||||
/SP5WWP/.vscode
|
||||
*.json
|
||||
*.rrc
|
||||
*.wav
|
||||
*.bin
|
||||
*.sym
|
||||
*.patch
|
90
README.md
90
README.md
|
@ -12,6 +12,12 @@ Written in C, it has all the components described by the protocol's specificatio
|
|||
|
||||
There's no support for **any** encryption yet.
|
||||
|
||||
### Cloning
|
||||
Be sure to clone with `--recursive` to pull the linked libm17 repository, otherwise, building will fail.
|
||||
```
|
||||
git clone https://github.com/M17-Project/M17_Implementations.git --recursive
|
||||
```
|
||||
|
||||
### Building
|
||||
First, build the shared object `libm17.so`:
|
||||
```
|
||||
|
@ -76,19 +82,91 @@ Packet encoding is available with `m17-packet-encoder`. Its input parameters are
|
|||
-x - binary output (M17 baseband as a packed bitstream)
|
||||
-r - raw audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol)
|
||||
-s - signed 16-bit LE symbols output
|
||||
-f - float symbols output compatible with m17-packet-decode
|
||||
-d - raw audio output - same as -r, but no RRC filtering (debug)
|
||||
-w - libsndfile wav audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol)
|
||||
```
|
||||
|
||||
Input data is passed over stdin. Example command:
|
||||
|
||||
`echo -en "\x05Testing M17 packet mode." | ./m17-packet-encode -S N0CALL -D ALL -C 0 -n 25 -o baseband.rrc`
|
||||
`echo -en "\x05Testing M17 packet mode." | ./m17-packet-encode -S N0CALL -D ALL -C 0 -n 25 -f -o baseband.sym`
|
||||
|
||||
`-en` parameter for `echo` suppresses the trailing newline character and enables the use of `\` within the message.
|
||||
`\x05` sets the packet data content and stands for text message (as per M17 Specification document, chapter 3.2 - Packet Application).
|
||||
If a WAVE file format is required for the baseband, sox can be used:
|
||||
|
||||
`sox -t raw -r 48000 -b 16 -c 1 -L -e signed-integer baseband.rrc baseband.wav`
|
||||
Output:
|
||||
|
||||
This line converts .rrc to .wav. SDRangel successfully decoding a packet:
|
||||

|
||||
```
|
||||
DST: ALL FFFFFFFFFFFF
|
||||
SRC: N0CALL 00004B13D106
|
||||
Data CRC: BFEC
|
||||
LSF CRC: 432A
|
||||
FN:00 (full frame)
|
||||
0554657374696E67204D3137207061636B6574206D6F64652E00
|
||||
FN:-- (ending frame)
|
||||
00BFEC0000000000000000000000000000000000000000000084
|
||||
FULL: 0554657374696E67204D3137207061636B6574206D6F64652E00BFEC
|
||||
SMS: Testing M17 packet mode.
|
||||
```
|
||||
|
||||
The two characters at the end of the message are probably CRC bytes erroneously decoded by SDRangel as a part of the text message.
|
||||
Decode packet created with above sample:
|
||||
|
||||
`cat baseband.sym | ./m17-packet-decode`
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
DST: FFFFFFFFFFFF SRC: 00004B13D106 TYPE: 0002 META: 0000000000000000000000000000 LSF_CRC_OK
|
||||
Testing M17 packet mode.
|
||||
```
|
||||
|
||||
Encode directly as wav format (skip sox):
|
||||
|
||||
`echo -en "\x05Testing M17 packet mode." | ./m17-packet-encode -S N0CALL -D AB1CDE -C 7 -n 25 -w -o baseband.wav`
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
DST: AB1CDE 00001F245D51
|
||||
SRC: N0CALL 00004B13D106
|
||||
Data CRC: BFEC
|
||||
LSF CRC: F754
|
||||
FN:00 (full frame)
|
||||
0554657374696E67204D3137207061636B6574206D6F64652E00
|
||||
FN:-- (ending frame)
|
||||
00BFEC0000000000000000000000000000000000000000000084
|
||||
FULL: 0554657374696E67204D3137207061636B6574206D6F64652E00BFEC
|
||||
SMS: Testing M17 packet mode.
|
||||
```
|
||||
|
||||
Decode with M17-FME:
|
||||
|
||||
`m17-fme -r -w baseband.wav -v 1`
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
M17 Project - Florida Man Edition
|
||||
Build Version: 2024-1-g4f2c15c
|
||||
Session Number: A4F5
|
||||
M17 Project RF Audio Frame Demodulator.
|
||||
SNDFile (.wav, .rrc) Input File: baseband.wav
|
||||
Payload Verbosity: 1;
|
||||
|
||||
|
||||
M17 LSF Frame Sync (08:57:09):
|
||||
DST: AB1CDE SRC: N0CALL CAN: 7; Data Packet
|
||||
LSF: 00 00 1F 24 5D 51 00 00 4B 13 D1 06 03 82 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 F7 54
|
||||
(CRC CHK) E: F754; C: F754;
|
||||
M17 PKT Frame Sync (08:57:09): CNT: 00; PBC: 00; EOT: 0;
|
||||
pkt: 0554657374696E67204D3137207061636B6574206D6F64652E00
|
||||
M17 PKT Frame Sync (08:57:09): CNT: 01; LST: 01; EOT: 1;
|
||||
pkt: 00BFEC0000000000000000000000000000000000000000000084 Protocol: SMS;
|
||||
SMS: Testing M17 packet mode.
|
||||
PKT: 05 54 65 73 74 69 6E 67 20 4D 31 37 20 70 61 63 6B 65 74 20 6D 6F 64 65 2E
|
||||
00 BF EC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
(CRC CHK) E: BFEC; C: BFEC;
|
||||
M17 No Frame Sync (08:57:09):
|
||||
|
||||
```
|
|
@ -1,10 +1,10 @@
|
|||
all: m17-packet-encode m17-packet-decode
|
||||
|
||||
m17-packet-encode: m17-packet-encode.c
|
||||
gcc -I ../../libm17 -O2 -Wall -Wextra m17-packet-encode.c -o m17-packet-encode -lm -lm17
|
||||
gcc -I ../../libm17 -O2 -Wall -Wextra m17-packet-encode.c -o m17-packet-encode -lm -lm17 -lsndfile
|
||||
|
||||
m17-packet-decode: m17-packet-decode.c
|
||||
gcc -I ../../libm17 -O2 -Wall -Wextra m17-packet-decode.c -o m17-packet-decode -lm -lm17
|
||||
gcc -I ../../libm17 -O2 -Wall -Wextra m17-packet-decode.c -o m17-packet-decode -lm -lm17 -lsndfile
|
||||
|
||||
install: all
|
||||
sudo install m17-packet-encode /usr/local/bin
|
||||
|
|
|
@ -207,7 +207,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
uint16_t p_len=strlen((const char*)packet_data);
|
||||
uint16_t p_crc=CRC_M17(packet_data, p_len+1);
|
||||
//fprintf(stderr, "rx=%02X%02X calc=%04X", packet_data[p_len+1], packet_data[p_len+2], p_crc);
|
||||
fprintf(stderr, "Data CRC: rx=%02X%02X calc=%04X\n ", packet_data[p_len+1], packet_data[p_len+2], p_crc);
|
||||
if(p_crc==(uint16_t)packet_data[p_len+1]*256+(uint16_t)packet_data[p_len+2])
|
||||
{
|
||||
fprintf(stderr, "%s\n", &packet_data[1]);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
//libm17
|
||||
#include <m17.h>
|
||||
|
@ -11,6 +12,11 @@
|
|||
|
||||
struct LSF lsf;
|
||||
|
||||
char wav_name[1024]; //name of wav file to output to
|
||||
SNDFILE *wav; //sndfile wav file
|
||||
SF_INFO info; //sndfile parameter struct
|
||||
int len=3; //number of blocks produced via counter +3 for pre,lsf, and eot marker
|
||||
|
||||
uint8_t enc_bits[SYM_PER_PLD*2]; //type-2 bits, unpacked
|
||||
uint8_t rf_bits[SYM_PER_PLD*2]; //type-4 bits, unpacked
|
||||
|
||||
|
@ -21,7 +27,7 @@ uint16_t num_bytes=0; //number of bytes in
|
|||
uint8_t fname[128]={'\0'}; //output file
|
||||
|
||||
FILE* fp;
|
||||
float full_packet[6912+88]; //full packet, symbols as floats - (40+40+32*40+40+40)/1000*4800
|
||||
float full_packet[36*192*10]; //full packet, symbols as floats - 36 "frames" max (incl. preamble, LSF, EoT), 192 symbols each, sps=10:
|
||||
//pream, LSF, 32 frames, ending frame, EOT plus RRC flushing
|
||||
uint16_t pkt_sym_cnt=0; //packet symbol counter, used to fill the packet
|
||||
uint8_t pkt_cnt=0; //packet frame counter (1..32) init'd at 0
|
||||
|
@ -30,6 +36,9 @@ uint8_t full_packet_data[32*25]; //full packet data,
|
|||
uint8_t out_type=0; //output file type - 0 - raw int16 filtered samples (.rrc) - default
|
||||
// 1 - int16 symbol stream
|
||||
// 2 - binary stream (TODO)
|
||||
// 3 - simple 10x upsample no filter
|
||||
// 4 - SB16-LE RRC filtered wav file
|
||||
// 5 - float symbol output for m17-packet-decode
|
||||
|
||||
//type - 0 - preamble before LSF (standard)
|
||||
//type - 1 - preamble before BERT transmission
|
||||
|
@ -152,6 +161,18 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
out_type=2;
|
||||
}
|
||||
else if(argv[i][1]=='d') //-d - raw unfiltered output to wav file
|
||||
{
|
||||
out_type=3;
|
||||
}
|
||||
else if(argv[i][1]=='w') //-w - rrc filtered output to wav file
|
||||
{
|
||||
out_type=4;
|
||||
}
|
||||
else if(argv[i][1]=='f') //-f - float symbol output
|
||||
{
|
||||
out_type=5;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown param detected. Exiting...\n");
|
||||
|
@ -172,6 +193,9 @@ int main(int argc, char* argv[])
|
|||
//fprintf(stderr, "-x - binary output (M17 baseband as a packed bitstream),\n");
|
||||
fprintf(stderr, "-r - raw audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol),\n");
|
||||
fprintf(stderr, "-s - signed 16-bit LE symbols output\n");
|
||||
fprintf(stderr, "-f - float symbols output compatible with m17-packet-decode\n");
|
||||
fprintf(stderr, "-d - raw audio output - same as -r, but no RRC filtering (debug)\n");
|
||||
fprintf(stderr, "-w - libsndfile audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol),\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -199,6 +223,7 @@ int main(int argc, char* argv[])
|
|||
fprintf(stderr, "Packet data too short. Exiting...\n");
|
||||
return -1;
|
||||
}
|
||||
num_bytes++; //increment by one to include the terminating byte
|
||||
uint16_t packet_crc=CRC_M17(full_packet_data, num_bytes);
|
||||
full_packet_data[num_bytes] =packet_crc>>8;
|
||||
full_packet_data[num_bytes+1]=packet_crc&0xFF;
|
||||
|
@ -231,13 +256,13 @@ int main(int argc, char* argv[])
|
|||
uint16_t lsf_crc=LSF_CRC(&lsf);
|
||||
lsf.crc[0]=lsf_crc>>8;
|
||||
lsf.crc[1]=lsf_crc&0xFF;
|
||||
fprintf(stderr, "LSF CRC:\t%04hX\n", lsf_crc);
|
||||
fprintf(stderr, "LSF CRC:\t%04hX\n", lsf_crc);
|
||||
|
||||
//encode LSF data
|
||||
conv_encode_LSF(enc_bits, &lsf);
|
||||
|
||||
//fill preamble
|
||||
memset((uint8_t*)full_packet, 0, sizeof(float)*(6912+88));
|
||||
memset((uint8_t*)full_packet, 0.0f, 36*192*10*sizeof(float));
|
||||
fill_preamble(full_packet, 0);
|
||||
pkt_sym_cnt=SYM_PER_FRA;
|
||||
|
||||
|
@ -344,15 +369,36 @@ int main(int argc, char* argv[])
|
|||
|
||||
num_bytes=tmp; //bring back the num_bytes value
|
||||
|
||||
//fprintf(stderr, "DATA: %s\n", full_packet_data);
|
||||
fprintf (stderr, "FULL: ");
|
||||
for(uint8_t i=0; i<tmp; i++)
|
||||
{
|
||||
fprintf (stderr, "%02X", full_packet_data[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
fprintf(stderr, " SMS: %s\n", full_packet_data);
|
||||
|
||||
//send EOT
|
||||
for(uint8_t i=0; i<SYM_PER_FRA/SYM_PER_SWD; i++) //192/8=24
|
||||
fill_syncword(full_packet, &pkt_sym_cnt, EOT_MRKR);
|
||||
|
||||
//dump baseband to a file
|
||||
fp=fopen((const char*)fname, "wb");
|
||||
|
||||
if (out_type == 3 || out_type == 4) //open wav file out
|
||||
{
|
||||
sprintf (wav_name, "%s", fname);
|
||||
info.samplerate = 48000;
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
wav = sf_open (wav_name, SFM_WRITE, &info); //write only, no append
|
||||
if (wav == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error - could not open raw wav output file %s\n", wav_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else //dump baseband to a file
|
||||
fp=fopen((const char*)fname, "wb");
|
||||
|
||||
//debug mode - symbols multiplied by 7168 scaling factor
|
||||
/*for(uint16_t i=0; i<pkt_sym_cnt; i++)
|
||||
{
|
||||
|
@ -402,7 +448,86 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
//float symbol stream compatible with m17-packet-decode
|
||||
else if(out_type==5)
|
||||
{
|
||||
for(uint16_t i=0; i<pkt_sym_cnt; i++)
|
||||
{
|
||||
float val=full_packet[i];
|
||||
fwrite(&val, 4, 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
//simple 10x upsample * 7168.0f
|
||||
else if (out_type == 3)
|
||||
{
|
||||
|
||||
//array of upsample full_packet
|
||||
float up[1920*35]; memset (up, 0, 1920*35*sizeof(float));
|
||||
|
||||
//10x upsample from full_packet to up
|
||||
for (int i = 0; i < 192*len; i++)
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
up[(i*10)+j] = full_packet[i];
|
||||
}
|
||||
|
||||
//array of shorts for sndfile wav output
|
||||
short bb[1920*35]; memset (bb, 0, 1920*35*sizeof(short));
|
||||
|
||||
//write dead air to sndfile wav
|
||||
sf_write_short(wav, bb, 1920);
|
||||
|
||||
//load bb with upsample, use len to see how many we need to send
|
||||
for (int i = 0; i < 1920*len; i++)
|
||||
bb[i] = (short)(up[i] * 7168.0f);
|
||||
|
||||
//write to sndfile wav
|
||||
sf_write_short(wav, bb, 1920*len);
|
||||
}
|
||||
|
||||
//standard mode - filtered baseband (converted to wav)
|
||||
else if(out_type == 4)
|
||||
{
|
||||
|
||||
float mem[FLT_LEN];
|
||||
float mac=0.0f;
|
||||
memset((uint8_t*)mem, 0, FLT_LEN*sizeof(float));
|
||||
for(uint16_t i=0; i<pkt_sym_cnt; i++)
|
||||
{
|
||||
//push new sample
|
||||
mem[0]=full_packet[i]*RRC_DEV;
|
||||
|
||||
for(uint8_t j=0; j<10; j++)
|
||||
{
|
||||
mac=0.0f;
|
||||
|
||||
//calc the sum of products
|
||||
for(uint16_t k=0; k<FLT_LEN; k++)
|
||||
mac+=mem[k]*rrc_taps_10[k]*sqrtf(10.0); //temporary fix for the interpolation gain error
|
||||
|
||||
//shift the delay line right by 1
|
||||
for(int16_t k=FLT_LEN-1; k>0; k--)
|
||||
{
|
||||
mem[k]=mem[k-1];
|
||||
}
|
||||
mem[0]=0.0f;
|
||||
|
||||
//write to file
|
||||
short tmp[2]; tmp[0]=mac;
|
||||
sf_write_short(wav, tmp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//close file, depending on type opened
|
||||
if (out_type == 3 || out_type == 4)
|
||||
{
|
||||
sf_write_sync(wav);
|
||||
sf_close(wav);
|
||||
}
|
||||
else fclose(fp);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue