Merge pull request #354 from alanbjohnston/fc-2

FunCube changes
fc-jy-1
Alan Johnston 11 months ago committed by GitHub
commit a45a72d624
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -43,7 +43,7 @@ cubesatsim: afsk/ax5043.o
cubesatsim: TelemEncoding.o cubesatsim: TelemEncoding.o
cubesatsim: main.o cubesatsim: main.o
cubesatsim: codecAO40.o cubesatsim: codecAO40.o
g++ -std=c++14 $(DEBUG_BEHAVIOR) -o cubesatsim -Wall -Wextra -L./ afsk/ax25.o afsk/ax5043.o TelemEncoding.o codecAO40.o main.o -lwiringPi -lax5043 -lm gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o cubesatsim -Wall -Wextra -L./ afsk/ax25.o afsk/ax5043.o TelemEncoding.o codecAO40.o main.o -lwiringPi -lax5043 -lm
telem: telem.o telem: telem.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o telem -Wall -Wextra -L./ telem.o -lwiringPi gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o telem -Wall -Wextra -L./ telem.o -lwiringPi
@ -52,10 +52,9 @@ TelemEncoding.o: TelemEncoding.c
TelemEncoding.o: TelemEncoding.h TelemEncoding.o: TelemEncoding.h
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -Wall -Wextra -c TelemEncoding.c gcc -std=gnu99 $(DEBUG_BEHAVIOR) -Wall -Wextra -c TelemEncoding.c
codecAO40.o: codecAO40.cpp codecAO40.o: codecAO40.c
codecAO40.o: codecAO40.h codecAO40.o: codecAO40.h
codecAO40.o: fecConstants.h gcc -std=gnu99 $(DEBUG_BEHAVIOR) -Wall -Wextra -c codecAO40.c
g++ -std=c++14 $(DEBUG_BEHAVIOR) -Wall -Wextra -c codecAO40.cpp
ax5043/generated/configcommon.o: ax5043/generated/configcommon.c ax5043/generated/configcommon.o: ax5043/generated/configcommon.c
ax5043/generated/configcommon.o: ax5043/generated/configrx.h ax5043/generated/configcommon.o: ax5043/generated/configrx.h

@ -46,6 +46,7 @@
#define min(a,b) ((a) < (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b))
#endif #endif
/*
CCodecAO40::CCodecAO40(void) CCodecAO40::CCodecAO40(void)
{ {
} }
@ -55,8 +56,9 @@ CCodecAO40::~CCodecAO40(void)
{ {
} }
*/
int CCodecAO40::mod255(int x) { //int CCodecAO40::mod255(int x) {
int mod255(int x) {
while (x >= 255) { while (x >= 255) {
x -= 255; x -= 255;
x = (x >> 8) + (x & 255); x = (x >> 8) + (x & 255);
@ -64,7 +66,8 @@ int CCodecAO40::mod255(int x) {
return x; return x;
} }
int CCodecAO40::decode_rs_8(char *data, int *eras_pos, int no_eras){ //int CCodecAO40::decode_rs_8(char *data, int *eras_pos, int no_eras){
int decode_rs_8(char *data, int *eras_pos, int no_eras){
int deg_lambda, el, deg_omega; int deg_lambda, el, deg_omega;
int i, j, r,k; int i, j, r,k;
@ -268,7 +271,8 @@ finish:
/* Write one binary channel symbol into the interleaver frame and update the pointers */ /* Write one binary channel symbol into the interleaver frame and update the pointers */
void CCodecAO40::interleave_symbol(int c) //void CCodecAO40::interleave_symbol(int c)
void interleave_symbol(int c)
{ {
int row,col; int row,col;
col=m_ileaver_index/COLUMNS; col=m_ileaver_index/COLUMNS;
@ -281,7 +285,8 @@ void CCodecAO40::interleave_symbol(int c)
} }
/* Convolutionally encode and interleave one byte */ /* Convolutionally encode and interleave one byte */
void CCodecAO40::encode_and_interleave(unsigned char c,int cnt){ //void CCodecAO40::encode_and_interleave(unsigned char c,int cnt){
void encode_and_interleave(unsigned char c,int cnt){
while(cnt-- != 0) while(cnt-- != 0)
{ {
m_conv_sr = (m_conv_sr << 1) | (c >> 7); m_conv_sr = (m_conv_sr << 1) | (c >> 7);
@ -292,7 +297,8 @@ void CCodecAO40::encode_and_interleave(unsigned char c,int cnt){
} }
/* Scramble a byte, convolutionally encode and interleave into frame */ /* Scramble a byte, convolutionally encode and interleave into frame */
void CCodecAO40::scramble_and_encode(unsigned char c){ //void CCodecAO40::scramble_and_encode(unsigned char c){
void scramble_and_encode(unsigned char c){
c ^= Scrambler[m_encoded_bytes]; /* Scramble byte */ c ^= Scrambler[m_encoded_bytes]; /* Scramble byte */
encode_and_interleave(c,8); /* RS encode and place into reencode buffer */ encode_and_interleave(c,8); /* RS encode and place into reencode buffer */
} }
@ -301,7 +307,8 @@ void CCodecAO40::scramble_and_encode(unsigned char c){
* results stored in m_encoded. * results stored in m_encoded.
* On success encoded buffer is returned, an zeroed buffer on failure * On success encoded buffer is returned, an zeroed buffer on failure
*/ */
const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count) //const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count)
const unsigned char *encode(unsigned char *source_bytes, int byte_count)
{ {
if(BLOCKSIZE != byte_count || NULL == source_bytes ) if(BLOCKSIZE != byte_count || NULL == source_bytes )
{ {
@ -333,7 +340,8 @@ encode_parity() Called 64 times to finish off
*/ */
/* This function initializes the encoder. */ /* This function initializes the encoder. */
void CCodecAO40::init_encoder(void){ //void CCodecAO40::init_encoder(void){
void init_encoder(void){
int i,j,sr; int i,j,sr;
m_encoded_bytes = 0; m_encoded_bytes = 0;
@ -370,7 +378,8 @@ void CCodecAO40::init_encoder(void){
* current frame. It should be called in sequence 256 times per frame, followed * current frame. It should be called in sequence 256 times per frame, followed
* by 64 calls to encode_parity(). * by 64 calls to encode_parity().
*/ */
void CCodecAO40::encode_byte(unsigned char c){ //void CCodecAO40::encode_byte(unsigned char c){
void encode_byte(unsigned char c){
unsigned char *rp; /* RS block pointer */ unsigned char *rp; /* RS block pointer */
int i; int i;
unsigned char feedback; unsigned char feedback;
@ -417,7 +426,8 @@ void CCodecAO40::encode_byte(unsigned char c){
* have been passed to update_encoder. Each call scrambles, encodes and * have been passed to update_encoder. Each call scrambles, encodes and
* interleaves one byte of Reed-Solomon parity. * interleaves one byte of Reed-Solomon parity.
*/ */
void CCodecAO40::encode_parity(void) { //void CCodecAO40::encode_parity(void) {
void encode_parity(void) {
unsigned char c; unsigned char c;
c = m_RS_block[m_encoded_bytes & 1][(m_encoded_bytes-256)>>1]; c = m_RS_block[m_encoded_bytes & 1][(m_encoded_bytes-256)>>1];
@ -430,7 +440,8 @@ void CCodecAO40::encode_parity(void) {
void CCodecAO40::descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT], char rsblocks[RSBLOCKS][NN]) //void CCodecAO40::descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT], char rsblocks[RSBLOCKS][NN])
void descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT], char rsblocks[RSBLOCKS][NN])
{ {
/* interleave into Reed Solomon codeblocks */ /* interleave into Reed Solomon codeblocks */
memset(rsblocks,0,RSBLOCKS*NN); /* Zero rsblocks array */ memset(rsblocks,0,RSBLOCKS*NN); /* Zero rsblocks array */
@ -465,7 +476,8 @@ void CCodecAO40::descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT]
* rserrs[x] contains -1 * rserrs[x] contains -1
* Data output should not be used. * Data output should not be used.
*/ */
int CCodecAO40::decode(unsigned char vitdecdata[NBITS_OUT], unsigned char *decoded_data) //int CCodecAO40::decode(unsigned char vitdecdata[NBITS_OUT], unsigned char *decoded_data)
int decode(unsigned char vitdecdata[NBITS_OUT], unsigned char *decoded_data)
{ {
int row, col, row_errors, total_errors; int row, col, row_errors, total_errors;
char rsblocks[RSBLOCKS][NN]; char rsblocks[RSBLOCKS][NN];
@ -502,7 +514,8 @@ int CCodecAO40::decode(unsigned char vitdecdata[NBITS_OUT], unsigned char *decod
} }
/* Compairs raw input symbols to current buffer of encoded symbols and counts the errors */ /* Compairs raw input symbols to current buffer of encoded symbols and counts the errors */
int CCodecAO40::count_errors(unsigned char *raw_symbols) //int CCodecAO40::count_errors(unsigned char *raw_symbols)
int count_errors(unsigned char *raw_symbols)
{ {
int error_count = 0; int error_count = 0;
for(int i=0;i<SYMPBLOCK;i++) for(int i=0;i<SYMPBLOCK;i++)

@ -22,13 +22,63 @@
#pragma once #pragma once
#include "fecConstants.h" //#include "fecConstants.h"
class CCodecAO40
{ /*
public: Amsat P3 FEC Encoder/decoder system. Look-up tables
CCodecAO40(void); Created by Phil Karn KA9Q and James Miller G3RUH
virtual ~CCodecAO40(void); Last modified 2003 Jun 20
*/
/* Defines for Viterbi Decoder for r=1/2 k=7 (to CCSDS convention) */
#define K 7 /* Constraint length */
#define N 2 /* Number of symbols per data bit */
#define CPOLYA 0x4f /* First convolutional encoder polynomial */
#define CPOLYB 0x6d /* Second convolutional encoder polynomial */
#define SYNC_POLY 0x48 /* Sync vector PN polynomial */
#define NN 255
#define KK 223
#define NROOTS 32 /* NN-KK */
#define A0 (NN)
#define FCR 112
#define PRIM 11
#define IPRIM 116
#define BLOCKSIZE 256 /* Data bytes per frame */
#define RSBLOCKS 2 /* Number of RS decoder blocks */
#define RSPAD 95 /* Unused bytes in block (KK-BLOCKSIZE/RSBLOCKS) */
/* Defines for Interleaver */
#define ROWS 80 /* Block interleaver rows */
#define COLUMNS 65 /* Block interleaver columns */
#define SYMPBLOCK (ROWS*COLUMNS) /* Encoded symbols per block */
/* Number of symbols in an FEC block that are */
/* passed to the Viterbi decoder (320*8 + 6) */
#define NBITS ((BLOCKSIZE+NROOTS*RSBLOCKS)*8+K-1)
/* Number of bits obtained from Viterbi decoder */
#define NBITS_OUT (BLOCKSIZE+NROOTS*RSBLOCKS)
extern unsigned char m_RS_block[RSBLOCKS][NROOTS]; /* RS parity blocks */
extern unsigned char m_encoded[SYMPBLOCK] ; /* encoded symbols */
extern int m_encoded_bytes; /* Byte counter for encode_data() */
extern int m_ileaver_index; /* Byte counter for interleaver */
extern unsigned char m_conv_sr; /* Convolutional encoder shift register state */
extern const unsigned char RS_poly[];
extern const unsigned char ALPHA_TO[];
extern const unsigned char INDEX_OF[];
extern const unsigned char Partab[];
extern const unsigned char Scrambler[];
//class CCodecAO40
//{
//public:
// CCodecAO40(void);
// virtual ~CCodecAO40(void);
int decode(unsigned char viterbi_decoded[NBITS_OUT], unsigned char *decoded_data); int decode(unsigned char viterbi_decoded[NBITS_OUT], unsigned char *decoded_data);
@ -40,7 +90,7 @@ public:
/* Compares raw input symbols to current buffer of encoded symbols and counts the errors */ /* Compares raw input symbols to current buffer of encoded symbols and counts the errors */
int count_errors( unsigned char *raw_symbols); int count_errors( unsigned char *raw_symbols);
private: //private:
int mod255(int x); int mod255(int x);
int decode_rs_8(char *data, int *eras_pos, int no_eras); int decode_rs_8(char *data, int *eras_pos, int no_eras);
void scramble_and_encode(unsigned char c); void scramble_and_encode(unsigned char c);
@ -56,10 +106,5 @@ private:
void interleave_symbol(int c); void interleave_symbol(int c);
int m_encoded_bytes; /* Byte counter for encode_data() */
int m_ileaver_index; /* Byte counter for interleaver */
unsigned char m_conv_sr; /* Convolutional encoder shift register state */
unsigned char m_RS_block[RSBLOCKS][NROOTS]; /* RS parity blocks */ //};
unsigned char m_encoded[SYMPBLOCK] ; /* encoded symbols */
};

@ -249,6 +249,8 @@ if [ "$1" = "" ]; then
echo "Mode is SSTV" echo "Mode is SSTV"
elif [ "$1" = "e" ]; then elif [ "$1" = "e" ]; then
echo "Mode is Repeater" echo "Mode is Repeater"
elif [ "$1" = "j" ]; then
echo "Mode is FunCube"
elif [ "$1" = "n" ]; then elif [ "$1" = "n" ]; then
echo -n "Mode is Transmit Commands with " echo -n "Mode is Transmit Commands with "
FILE=/home/pi/CubeSatSim/transmit_dtmf FILE=/home/pi/CubeSatSim/transmit_dtmf
@ -1403,6 +1405,22 @@ elif [ "$1" = "-g" ]; then
echo "Not resetting" echo "Not resetting"
fi fi
elif [ "$1" = "-j" ]; then
value=`cat /home/pi/CubeSatSim/.mode`
echo "$value" > /dev/null
set -- $value
# if [ "$1" == "n" ]; then
# transmit_command_bpsk
# else
echo "changing CubeSatSim to FunCube mode"
sudo echo "j" > /home/pi/CubeSatSim/.mode
restart=1
# fi
elif [ "$1" = "-h" ]; then elif [ "$1" = "-h" ]; then
@ -1416,7 +1434,8 @@ elif [ "$1" = "-h" ]; then
echo " -f Change to FSK/DUV mode" echo " -f Change to FSK/DUV mode"
echo " -b Change to BPSK mode" echo " -b Change to BPSK mode"
echo " -s Change to SSTV mode" echo " -s Change to SSTV mode"
echo " -n Change to Transmit Commands mode" echo " -j Change to FunCube mode"
echo " -n Change to Transmit Commands mode"
echo " -e Change to Repeater mode" echo " -e Change to Repeater mode"
echo " -i Restart CubeSatsim software" echo " -i Restart CubeSatsim software"
echo " -c Change the CALLSIGN in the configuration file sim.cfg" echo " -c Change the CALLSIGN in the configuration file sim.cfg"

288
main.c

@ -190,6 +190,9 @@ int main(int argc, char * argv[]) {
} else if ( * argv[1] == 'm') { } else if ( * argv[1] == 'm') {
mode = CW; mode = CW;
printf("Mode is CW\n"); printf("Mode is CW\n");
} else if ( * argv[1] == 'j') {
mode = FC;
printf("Mode is FunCube\n");
} else { } else {
printf("Mode is BPSK\n"); printf("Mode is BPSK\n");
} }
@ -228,6 +231,9 @@ int main(int argc, char * argv[]) {
} else if ( mode_string == 'm') { } else if ( mode_string == 'm') {
mode = CW; mode = CW;
printf("Mode is CW\n"); printf("Mode is CW\n");
} else if ( mode_string == 'j') {
mode = FC;
printf("Mode is FunCube\n");
} else if ( mode_string == 'e') { } else if ( mode_string == 'e') {
mode = REPEATER; mode = REPEATER;
printf("Mode is Repeater\n"); printf("Mode is Repeater\n");
@ -455,6 +461,7 @@ int main(int argc, char * argv[]) {
printf("\n FSK Mode, %d bits per frame, %d bits per second, %d ms per frame, %d ms sample period\n", printf("\n FSK Mode, %d bits per frame, %d bits per second, %d ms per frame, %d ms sample period\n",
bufLen / (samples * frameCnt), bitRate, frameTime, samplePeriod); bufLen / (samples * frameCnt), bitRate, frameTime, samplePeriod);
} else if (mode == BPSK) { } else if (mode == BPSK) {
bitRate = 1200; bitRate = 1200;
rsFrames = 3; rsFrames = 3;
@ -487,6 +494,40 @@ int main(int argc, char * argv[]) {
// printf(" %d", sin_map[j]); // printf(" %d", sin_map[j]);
} }
printf("\n"); printf("\n");
} else if (mode == FC) { // for now copy BPSK settings
bitRate = 1200;
// rsFrames = 3;
// payloads = 6;
// rsFrameLen = 159;
headerLen = 768; // 8;
dataLen = 5200; // 78;
syncBits = 32; // 31;
syncWord = 0x1acffc1d; // 0b1000111110011010010000101011101;
// parityLen = 32;
amplitude = 32767;
samples = S_RATE / bitRate;
// bufLen = (frameCnt * (syncBits + 10 * (headerLen + rsFrames * (rsFrameLen + parityLen))) * samples);
bufLen = (headerLen + syncBits + dataLen)/8;
// samplePeriod = ((float)((syncBits + 10 * (headerLen + rsFrames * (rsFrameLen + parityLen))))/(float)bitRate) * 1000 - 1800;
samplePeriod = 5000;
// samplePeriod = 3000;
// sleepTime = 3.0;
//samplePeriod = 2200; // reduce dut to python and sensor querying delays
// sleepTime = 2.2f;
// frameTime = ((float)((float)bufLen / (samples * frameCnt * bitRate))) * 1000; // frame time in ms
frameTime = 5000;
printf("\n FC Mode, bufLen: %d, %d bits per frame, %d bits per second, %d ms per frame %d ms sample period\n",
bufLen, bufLen / samples, bitRate, frameTime, samplePeriod);
sin_samples = S_RATE/freq_Hz;
for (int j = 0; j < sin_samples; j++) {
sin_map[j] = (short int)(amplitude * sin((float)(2 * M_PI * j / sin_samples)));
}
printf("\n");
} }
memset(voltage, 0, sizeof(voltage)); memset(voltage, 0, sizeof(voltage));
@ -496,6 +537,9 @@ int main(int argc, char * argv[]) {
if (((mode == FSK) || (mode == BPSK))) // && !sim_mode) if (((mode == FSK) || (mode == BPSK))) // && !sim_mode)
get_tlm_fox(); // fill transmit buffer with reset count 0 packets that will be ignored get_tlm_fox(); // fill transmit buffer with reset count 0 packets that will be ignored
else if (((mode == FC))) // && !sim_mode)
get_tlm_fc(); // fill transmit buffer with reset count 0 packets that will be ignored
firstTime = 1; firstTime = 1;
// if (!sim_mode) // always read sensors, even in sim mode // if (!sim_mode) // always read sensors, even in sim mode
@ -869,6 +913,8 @@ int main(int argc, char * argv[]) {
} else if ((mode == FSK) || (mode == BPSK)) {// FSK or BPSK } else if ((mode == FSK) || (mode == BPSK)) {// FSK or BPSK
get_tlm_fox(); get_tlm_fox();
} else if ((mode == FC)) {
get_tlm_fc();
} else { // SSTV } else { // SSTV
// fprintf(stderr, "Sleeping\n"); // fprintf(stderr, "Sleeping\n");
sleep(30); sleep(30);
@ -879,7 +925,7 @@ int main(int argc, char * argv[]) {
#endif #endif
} }
if (mode == BPSK) { if ((mode == BPSK) || (mode == FC)) {
// digitalWrite(txLed, txLedOn); // digitalWrite(txLed, txLedOn);
#ifdef DEBUG_LOGGING #ifdef DEBUG_LOGGING
// printf("Tx LED On 1\n"); // printf("Tx LED On 1\n");
@ -1663,7 +1709,7 @@ void get_tlm_fox() {
val = sync; val = sync;
data = val & 1 << (bit - 1); data = val & 1 << (bit - 1);
// printf ("%d i: %d new frame %d sync bit %d = %d \n", // printf ("%d i: %d new frame %d sync bit %d = %d \n",
// ctr/SAMPLES, i, frames, bit, (data > 0) ); // ctr/, i, frames, bit, (data > 0) );
if (mode == FSK) { if (mode == FSK) {
phase = ((data != 0) * 2) - 1; phase = ((data != 0) * 2) - 1;
// printf("Sending a %d\n", phase); // printf("Sending a %d\n", phase);
@ -1691,7 +1737,7 @@ void get_tlm_fox() {
val = data10[symbol]; val = data10[symbol];
data = val & 1 << (bit - 1); data = val & 1 << (bit - 1);
// printf ("%d i: %d new frame %d data10[%d] = %x bit %d = %d \n", // printf ("%d i: %d new frame %d data10[%d] = %x bit %d = %d \n",
// ctr/SAMPLES, i, frames, symbol, val, bit, (data > 0) ); // ctr/, i, frames, symbol, val, bit, (data > 0) );
if (mode == FSK) { if (mode == FSK) {
phase = ((data != 0) * 2) - 1; phase = ((data != 0) * 2) - 1;
// printf("Sending a %d\n", phase); // printf("Sending a %d\n", phase);
@ -1928,13 +1974,16 @@ void write_wave(int i, short int *buffer)
} }
else else
{ {
if ((ctr - flip_ctr) < smaller) if ((ctr - flip_ctr) < smaller) {
// buffer[ctr++] = (short int)(amplitude * 0.4 * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE))); buffer[ctr++] = (short int)(amplitude * 0.4 * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE))); // buffer[ctr++] = (short int)(amplitude * 0.4 * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE)));
buffer[ctr++] = (short int)(phase * sin_map[ctr % sin_samples] / 2); buffer[ctr++] = (short int)(phase * sin_map[ctr % sin_samples] / 2);
// if (ctr < 1000) printf("*");
}
else else
// buffer[ctr++] = (short int)(amplitude * 0.4 * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE))); buffer[ctr++] = (short int)(amplitude * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE))); // buffer[ctr++] = (short int)(amplitude * 0.4 * phase * sin((float)(2*M_PI*i*freq_Hz/S_RATE)));
buffer[ctr++] = (short int)(phase * sin_map[ctr % sin_samples]); } buffer[ctr++] = (short int)(phase * sin_map[ctr % sin_samples]);
// printf("%d %d \n", i, buffer[ctr - 1]); }
// if (ctr < 1000) printf("%d %d %d \n", ctr, i, buffer[ctr - 1]);
} }
@ -2244,33 +2293,226 @@ void get_tlm_fc() {
/* create data, stream, and waveform buffers */ /* create data, stream, and waveform buffers */
unsigned char source_bytes[256]; unsigned char source_bytes[256];
unsigned char encoded_bytes[650]; // unsigned char encoded_bytes[650];
int byte_count = 256; int byte_count = 256;
memset(source_bytes, 0xa5, sizeof(source_bytes));
/* write telemetry into data buffer */ /* write telemetry into data buffer */
/* convert data buffer into stream buffer */ // printf("\nBLOCKSIZE = %d\n", BLOCKSIZE);
// printf("\nSYMPBLOCK = %d\n", SYMPBLOCK);
// const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count) memset(source_bytes, 0x00, sizeof(source_bytes));
source_bytes[10] = (uint8_t) rnd_float(0,255);
/*
printf("\nsource_bytes\n");
for (int i=0; i<256; i++)
printf("%d ", source_bytes[i]);
printf("\n\n");
*/
CCodecAO40 ao40; /* convert data buffer into stream buffer */
encoded_bytes = ao40.encode((unsigned char*)source_bytes, byte_count);
const unsigned char* encoded_bytes = encode(source_bytes, byte_count);
/*
printf("\nencoded_bytes\n");
for (int i=0; i<5200; i++)
printf("%d", encoded_bytes[i]);
printf("\n\n");
*/
/* convert to waveform buffer */ /* convert to waveform buffer */
/* open socket */ int data;
int val;
int i;
ctr = 0;
smaller = (int) (S_RATE / (2 * freq_Hz));
// printf("\n\nsmaller = %d \n\n",smaller);
for (i = 1; i <= headerLen * samples; i++) {
write_wave(ctr, buffer);
if ((i % samples) == 0) {
phase *= -1;
if ((ctr - smaller) > 0) {
int j;
for (j = 1; j <= smaller; j++) {
buffer[ctr - j] = buffer[ctr - j] * 0.5;
// if (ctr < 1000) printf("# %d %d\n", ctr - j, buffer[ctr - j]);
}
}
flip_ctr = ctr;
}
}
for (i = 1; i <= syncBits * samples; i++) {
write_wave(ctr, buffer);
// printf("%d ",ctr);
if ((i % samples) == 0) {
int bit = syncBits - i / samples + 1;
val = syncWord;
data = val & 1 << (bit - 1);
// printf ("%d i: %d sync bit %d = %d \n",
// ctr, i, bit, (data > 0) );
if (data == 0) {
phase *= -1;
if ((ctr - smaller) > 0) {
int j;
for (j = 1; j <= smaller; j++)
buffer[ctr - j] = buffer[ctr - j] * 0.5;
}
flip_ctr = ctr;
}
}
}
for (i = 1; i <= (dataLen * samples); i++) // 5200
{
write_wave(ctr, buffer);
if ((i % samples) == 0) {
// int symbol = (int)((i - 1) / (samples * 8));
// int bit = 8 - (i - symbol * samples * 8) / samples + 1;
// val = encoded_bytes[symbol];
// data = val & 1 << (bit - 1);
// printf ("%d i: %d new frame %d data10[%d] = %x bit %d = %d \n",
// ctr/SAMPLES, i, frames, symbol, val, bit, (data > 0) );
int symbol = i / samples;
data = encoded_bytes[symbol];
if (data == 0) {
phase *= -1;
if ((ctr - smaller) > 0) {
int j;
for (j = 1; j <= smaller; j++) {
buffer[ctr - j] = buffer[ctr - j] * 0.5;
// if (ctr < 1000) printf("# %d %d\n", ctr - j, buffer[ctr - j]);
}
}
flip_ctr = ctr;
}
}
}
printf("\nctr = %d\n\n", ctr);
/* open socket */
int error = 0;
// int count;
// for (count = 0; count < dataLen; count++) {
// printf("%02X", b[count]);
// }
// printf("\n");
// socket write
if (!socket_open && transmit) {
printf("Opening socket!\n");
// struct sockaddr_in address;
// int valread;
struct sockaddr_in serv_addr;
// char *hello = "Hello from client";
// char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
error = 1;
}
memset( & serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", & serv_addr.sin_addr) <= 0) {
printf("\nInvalid address/ Address not supported \n");
error = 1;
}
if (connect(sock, (struct sockaddr * ) & serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
printf("Error: %s\n", strerror(errno));
error = 1;
// try again
error = 0;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
error = 1;
}
memset( & serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", & serv_addr.sin_addr) <= 0) {
printf("\nInvalid address/ Address not supported \n");
error = 1;
}
if (connect(sock, (struct sockaddr * ) & serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
printf("Error: %s\n", strerror(errno));
error = 1;
}
}
if (error == 1) {
printf("Socket error count: %d\n", error_count);
// ; //transmitStatus = -1;
if (error_count++ > 5) {
printf("Restarting transmit\n");
FILE * transmit_restartf = popen("sudo systemctl restart transmit", "r");
pclose(transmit_restartf);
sleep(10); // was 5 // sleep if socket connection refused
}
}
else {
socket_open = 1;
error_count = 0;
}
}
/* write waveform buffer over socket */
int length = (headerLen + syncBits + dataLen) * samples;
if (!error && transmit) {
// digitalWrite (0, LOW);
// printf("Sending %d buffer bytes over socket after %d ms!\n", ctr, (long unsigned int)millis() - start);
start = millis();
int sock_ret = send(sock, buffer, length, 0);
// printf("socket send 1 %d ms bytes: %d \n\n", (unsigned int)millis() - start, sock_ret);
// fflush(stdout);
if (sock_ret < length) {
// printf("Not resending\n");
sleep(0.5);
sock_ret = send(sock, &buffer[sock_ret], length - sock_ret, 0);
// printf("socket send 2 %d ms bytes: %d \n\n", millis() - start, sock_ret);
}
/* write waveform buffer over socket */ loop_count++;
/* from funcubeLib/common/testFec.cpp if (sock_ret == -1) {
printf("Error: %s \n", strerror(errno));
socket_open = 0;
}
}
if (!transmit) {
fprintf(stderr, "\nNo CubeSatSim Band Pass Filter detected. No transmissions after the CW ID.\n");
fprintf(stderr, " See http://cubesatsim.org/wiki for info about building a CubeSatSim\n\n");
}
U8 sourceBytes[BLOCK_SIZE]; int startSleep = millis();
memset(sourceBytes, 42, BLOCK_SIZE); if ((millis() - sampleTime) < ((unsigned int)frameTime)) // - 750 + pi_zero_2_offset))
sleep(1.0);
while ((millis() - sampleTime) < ((unsigned int)frameTime)) // - 750 + pi_zero_2_offset))
sleep(0.1);
printf("Start sleep %d Sleep period: %d while period: %d\n", startSleep, millis() - startSleep, millis() - sampleTime);
sampleTime = (unsigned int) millis(); // resetting time for sleeping
fflush(stdout);
CCodecAO40 ao40; if (socket_open == 1)
const U8* encoded = ao40.encode((unsigned char*)sourceBytes, BLOCK_SIZE); firstTime = 0;
*/
return;
} }

102
main.h

@ -88,6 +88,7 @@ void update_rs(unsigned char parity[32], unsigned char c);
void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file); void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file);
static int init_rf(); static int init_rf();
extern int Encode_8b10b[][256]; extern int Encode_8b10b[][256];
extern const unsigned char ALPHA_TO[];
// const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count); // const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count);
void program_radio(); void program_radio();
@ -111,6 +112,7 @@ FILE *telem_file;
#define BPSK 3 #define BPSK 3
#define SSTV 4 #define SSTV 4
#define CW 5 #define CW 5
#define FC 7
#define REPEATER 11 #define REPEATER 11
#define TXCOMMAND 12 #define TXCOMMAND 12
@ -206,3 +208,103 @@ long int loopTime;
int error_count = 0; int error_count = 0;
int groundCommandCount = 0; int groundCommandCount = 0;
unsigned char m_RS_block[RSBLOCKS][NROOTS]; /* RS parity blocks */
unsigned char m_encoded[SYMPBLOCK] ; /* encoded symbols */
int m_encoded_bytes; /* Byte counter for encode_data() */
int m_ileaver_index; /* Byte counter for interleaver */
unsigned char m_conv_sr; /* Convolutional encoder shift register state */
// from funcubeLib/common/fecConstants.h
const unsigned char RS_poly[] = {
249, 59, 66, 4, 43,126,251, 97, 30, 3,213, 50, 66,170, 5, 24
};
/* Tables for RS decoder */
/* Galois field log/antilog tables */
const unsigned char ALPHA_TO[] =
{
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4,
0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb, 0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd,
0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31, 0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67,
0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc, 0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b,
0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4, 0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26,
0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21, 0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba,
0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0,
0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3, 0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a,
0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9, 0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44,
0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef, 0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85,
0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6, 0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf,
0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff, 0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58,
0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24,
0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8, 0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64,
0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2, 0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda,
0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77, 0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x00,
};
const unsigned char INDEX_OF[]=
{
0xff, 0x00, 0x01, 0x63, 0x02, 0xc6, 0x64, 0x6a, 0x03, 0xcd, 0xc7, 0xbc, 0x65, 0x7e, 0x6b, 0x2a,
0x04, 0x8d, 0xce, 0x4e, 0xc8, 0xd4, 0xbd, 0xe1, 0x66, 0xdd, 0x7f, 0x31, 0x6c, 0x20, 0x2b, 0xf3,
0x05, 0x57, 0x8e, 0xe8, 0xcf, 0xac, 0x4f, 0x83, 0xc9, 0xd9, 0xd5, 0x41, 0xbe, 0x94, 0xe2, 0xb4,
0x67, 0x27, 0xde, 0xf0, 0x80, 0xb1, 0x32, 0x35, 0x6d, 0x45, 0x21, 0x12, 0x2c, 0x0d, 0xf4, 0x38,
0x06, 0x9b, 0x58, 0x1a, 0x8f, 0x79, 0xe9, 0x70, 0xd0, 0xc2, 0xad, 0xa8, 0x50, 0x75, 0x84, 0x48,
0xca, 0xfc, 0xda, 0x8a, 0xd6, 0x54, 0x42, 0x24, 0xbf, 0x98, 0x95, 0xf9, 0xe3, 0x5e, 0xb5, 0x15,
0x68, 0x61, 0x28, 0xba, 0xdf, 0x4c, 0xf1, 0x2f, 0x81, 0xe6, 0xb2, 0x3f, 0x33, 0xee, 0x36, 0x10,
0x6e, 0x18, 0x46, 0xa6, 0x22, 0x88, 0x13, 0xf7, 0x2d, 0xb8, 0x0e, 0x3d, 0xf5, 0xa4, 0x39, 0x3b,
0x07, 0x9e, 0x9c, 0x9d, 0x59, 0x9f, 0x1b, 0x08, 0x90, 0x09, 0x7a, 0x1c, 0xea, 0xa0, 0x71, 0x5a,
0xd1, 0x1d, 0xc3, 0x7b, 0xae, 0x0a, 0xa9, 0x91, 0x51, 0x5b, 0x76, 0x72, 0x85, 0xa1, 0x49, 0xeb,
0xcb, 0x7c, 0xfd, 0xc4, 0xdb, 0x1e, 0x8b, 0xd2, 0xd7, 0x92, 0x55, 0xaa, 0x43, 0x0b, 0x25, 0xaf,
0xc0, 0x73, 0x99, 0x77, 0x96, 0x5c, 0xfa, 0x52, 0xe4, 0xec, 0x5f, 0x4a, 0xb6, 0xa2, 0x16, 0x86,
0x69, 0xc5, 0x62, 0xfe, 0x29, 0x7d, 0xbb, 0xcc, 0xe0, 0xd3, 0x4d, 0x8c, 0xf2, 0x1f, 0x30, 0xdc,
0x82, 0xab, 0xe7, 0x56, 0xb3, 0x93, 0x40, 0xd8, 0x34, 0xb0, 0xef, 0x26, 0x37, 0x0c, 0x11, 0x44,
0x6f, 0x78, 0x19, 0x9a, 0x47, 0x74, 0xa7, 0xc1, 0x23, 0x53, 0x89, 0xfb, 0x14, 0x5d, 0xf8, 0x97,
0x2e, 0x4b, 0xb9, 0x60, 0x0f, 0xed, 0x3e, 0xe5, 0xf6, 0x87, 0xa5, 0x17, 0x3a, 0xa3, 0x3c, 0xb7,
};
/* 8-bit parity table */
const unsigned char Partab[] = {
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
};
/* Scramble byte table */
const unsigned char Scrambler[]=
{
0xff, 0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce,
0x5a, 0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1,
0xfe, 0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c,
0xb5, 0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63,
0xfd, 0x20, 0x3b, 0x02, 0x68, 0x35, 0xc2, 0xf2, 0x38, 0xb2, 0x4e, 0xb6, 0x9e, 0xdd, 0x1b, 0x39,
0x6a, 0x5d, 0xf7, 0x30, 0xca, 0x8a, 0xfc, 0xf8, 0x28, 0x43, 0xc6, 0x22, 0x53, 0x37, 0xaa, 0xc7,
0xfa, 0x40, 0x76, 0x04, 0xd0, 0x6b, 0x85, 0xe4, 0x71, 0x64, 0x9d, 0x6d, 0x3d, 0xba, 0x36, 0x72,
0xd4, 0xbb, 0xee, 0x61, 0x95, 0x15, 0xf9, 0xf0, 0x50, 0x87, 0x8c, 0x44, 0xa6, 0x6f, 0x55, 0x8f,
0xf4, 0x80, 0xec, 0x09, 0xa0, 0xd7, 0x0b, 0xc8, 0xe2, 0xc9, 0x3a, 0xda, 0x7b, 0x74, 0x6c, 0xe5,
0xa9, 0x77, 0xdc, 0xc3, 0x2a, 0x2b, 0xf3, 0xe0, 0xa1, 0x0f, 0x18, 0x89, 0x4c, 0xde, 0xab, 0x1f,
0xe9, 0x01, 0xd8, 0x13, 0x41, 0xae, 0x17, 0x91, 0xc5, 0x92, 0x75, 0xb4, 0xf6, 0xe8, 0xd9, 0xcb,
0x52, 0xef, 0xb9, 0x86, 0x54, 0x57, 0xe7, 0xc1, 0x42, 0x1e, 0x31, 0x12, 0x99, 0xbd, 0x56, 0x3f,
0xd2, 0x03, 0xb0, 0x26, 0x83, 0x5c, 0x2f, 0x23, 0x8b, 0x24, 0xeb, 0x69, 0xed, 0xd1, 0xb3, 0x96,
0xa5, 0xdf, 0x73, 0x0c, 0xa8, 0xaf, 0xcf, 0x82, 0x84, 0x3c, 0x62, 0x25, 0x33, 0x7a, 0xac, 0x7f,
0xa4, 0x07, 0x60, 0x4d, 0x06, 0xb8, 0x5e, 0x47, 0x16, 0x49, 0xd6, 0xd3, 0xdb, 0xa3, 0x67, 0x2d,
0x4b, 0xbe, 0xe6, 0x19, 0x51, 0x5f, 0x9f, 0x05, 0x08, 0x78, 0xc4, 0x4a, 0x66, 0xf5, 0x58, 0xff,
0x48, 0x0e, 0xc0, 0x9a, 0x0d, 0x70, 0xbc, 0x8e, 0x2c, 0x93, 0xad, 0xa7, 0xb7, 0x46, 0xce, 0x5a,
0x97, 0x7d, 0xcc, 0x32, 0xa2, 0xbf, 0x3e, 0x0a, 0x10, 0xf1, 0x88, 0x94, 0xcd, 0xea, 0xb1, 0xfe,
0x90, 0x1d, 0x81, 0x34, 0x1a, 0xe1, 0x79, 0x1c, 0x59, 0x27, 0x5b, 0x4f, 0x6e, 0x8d, 0x9c, 0xb5,
0x2e, 0xfb, 0x98, 0x65, 0x45, 0x7e, 0x7c, 0x14, 0x21, 0xe3, 0x11, 0x29, 0x9b, 0xd5, 0x63, 0xfd,
};

@ -383,7 +383,7 @@ if __name__ == "__main__":
# if (mode != ) and (command_tx == True): # if (mode != ) and (command_tx == True):
# if (command_tx == True): # if (command_tx == True):
if ((mode == 'a') or (mode == 'b') or (mode == 'f') or (mode == 's')) and (command_tx == True) and (skip == False): if ((mode == 'a') or (mode == 'b') or (mode == 'f') or (mode == 's') or (mode == 'j')) and (command_tx == True) and (skip == False):
# battery_saver_mode # battery_saver_mode
GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4 GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi Zero 2 and Pi 4
GPIO.setup(txLed, GPIO.OUT) GPIO.setup(txLed, GPIO.OUT)
@ -739,9 +739,12 @@ if __name__ == "__main__":
# output(pd, 0) # output(pd, 0)
sleep(10) sleep(10)
elif (mode == 'b'): elif (mode == 'b') or (mode == 'j'):
# command_control_check() # command_control_check()
print("BPSK") if (mode == 'b'):
print("BPSK")
else:
print("FunCube")
print("turn on FM rx") print("turn on FM rx")
output(pd, 1) output(pd, 1)
output(ptt, 1) output(ptt, 1)
@ -768,7 +771,10 @@ if __name__ == "__main__":
output(txLed, txLedOn) output(txLed, txLedOn)
# print(txLed) # print(txLed)
# print(txLedOn) # print(txLedOn)
sleep(4.2) if (mode == 'b'):
sleep(4.2)
else:
sleep(4.6)
elif (mode == 'e'): # code based on https://zr6aic.blogspot.com/2016/11/creating-2m-fm-repeater-with-raspberry.html elif (mode == 'e'): # code based on https://zr6aic.blogspot.com/2016/11/creating-2m-fm-repeater-with-raspberry.html
print("Repeater") print("Repeater")
print("Stopping command and control") print("Stopping command and control")

Loading…
Cancel
Save

Powered by TurnKey Linux.