Merge pull request #370 from alanbjohnston/fc

Version v2.1 with FunCube Mode and Cross Band Repeater mode
master-ff
Alan Johnston 6 months ago committed by GitHub
commit b4242cce04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -42,7 +42,8 @@ cubesatsim: afsk/ax25.o
cubesatsim: afsk/ax5043.o cubesatsim: afsk/ax5043.o
cubesatsim: TelemEncoding.o cubesatsim: TelemEncoding.o
cubesatsim: main.o cubesatsim: main.o
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -o cubesatsim -Wall -Wextra -L./ afsk/ax25.o afsk/ax5043.o TelemEncoding.o main.o -lwiringPi -lax5043 -lm cubesatsim: codecAO40.o
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
@ -51,6 +52,10 @@ 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.c
codecAO40.o: codecAO40.h
gcc -std=gnu99 $(DEBUG_BEHAVIOR) -Wall -Wextra -c codecAO40.c
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
ax5043/generated/configcommon.o: ax5043/generated/configtx.h ax5043/generated/configcommon.o: ax5043/generated/configtx.h

@ -0,0 +1,46 @@
pcm.!default {
type asym
playback.pcm "softvol"
capture.pcm "shared_mic"
}
ctl.!default {
type hw
card 2
}
# Playback with software volume and mixing
pcm.softvol {
type softvol
slave.pcm "shared_speaker"
control {
name "Master"
card 2
}
}
pcm.shared_speaker {
type dmix
ipc_key 1024
slave {
pcm "hw:2,0"
rate 48000
period_time 0
period_size 1024
buffer_size 4096
}
}
# Recording with input mixing
pcm.shared_mic {
type dsnoop
ipc_key 2048
slave {
pcm "hw:2,0"
# channels 1
rate 48000
period_time 0
period_size 1024
buffer_size 4096
}
}

@ -0,0 +1,529 @@
#include <string.h>
#include "codecAO40.h"
/* ---------------------- */
/* AO40 Encoder - Decoder */
/* ---------------------- */
/* Scramble and RS encode 256 byte blocks of data into 5200 bits
* or Descramble and RS decode 5200 bits into the 256 bytes of data
*
* --------------------------------------------------------------------------
* This decoder has evolved extensively through the work of Phil Karn. It draws
* on his own ideas and optimisations, and on the work of others. The lineage
* is as below, and parts of the authors' notices are included here. (JRM)
* AO40 encoder / decoder
* Copyright 2002 Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
*
* Reed-Solomon coding and decoding
* Phil Karn (karn@ka9q.ampr.org) September 1996
*
* This file is derived from the program "new_rs_erasures.c" by Robert
* Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy
* (harit@spectra.eng.hawaii.edu), Aug 1995
* --------------------------------------------------------------------------
*
* From the RM-Z & HT program:
* The encoding and decoding methods are based on the
* book "Error Control Coding: Fundamentals and Applications",
* by Lin and Costello, Prentice Hall, 1983, ISBN 0-13-283796-X
* Portions of this program are from a Reed-Solomon encoder/decoder
* in C, written by Simon Rockliff (simon@augean.ua.oz.au) on 21/9/89.
* --------------------------------------------------------------------------
*
* From the 1989/1991 SR program (also based on Lin and Costello):
* This program may be freely modified and/or given to whoever wants it.
* A condition of such distribution is that the author's contribution be
* acknowledged by his name being left in the comments heading the program,
* Simon Rockliff, 26th June 1991
*
*/
/* Defines for RS Decoder(s) */
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
/*
CCodecAO40::CCodecAO40(void)
{
}
CCodecAO40::~CCodecAO40(void)
{
}
*/
//int CCodecAO40::mod255(int x) {
int mod255(int x) {
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
//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 i, j, r,k;
unsigned char u,q,tmp,num1,num2,den,discr_r;
unsigned char lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly and syndrome poly */
unsigned char b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1];
unsigned char root[NROOTS], reg[NROOTS+1], loc[NROOTS];
int syn_error, count;
/* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
for(i=0;i<NROOTS;i++)
s[i] = data[0];
for(j=1;j<NN;j++){
for(i=0;i<NROOTS;i++){
if(s[i] == 0){
s[i] = data[j];
} else {
s[i] = data[j] ^ ALPHA_TO[mod255(INDEX_OF[s[i]] + (FCR+i)*PRIM)];
}
}
}
/* Convert syndromes to index form, checking for nonzero condition */
syn_error = 0;
for(i=0;i<NROOTS;i++){
syn_error |= s[i];
s[i] = INDEX_OF[s[i]];
}
if (!syn_error) {
/* if syndrome is zero, data[] is a codeword and there are no
* errors to correct. So return data[] unmodified
*/
count = 0;
goto finish;
}
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
lambda[0] = 1;
if (no_eras > 0) {
/* Init lambda to be the erasure locator polynomial */
lambda[1] = ALPHA_TO[mod255(PRIM*(NN-1-eras_pos[0]))];
for (i = 1; i < no_eras; i++) {
u = mod255(PRIM*(NN-1-eras_pos[i]));
for (j = i+1; j > 0; j--) {
tmp = INDEX_OF[lambda[j - 1]];
if(tmp != A0)
lambda[j] ^= ALPHA_TO[mod255(u + tmp)];
}
}
}
for(i=0;i<NROOTS+1;i++)
b[i] = INDEX_OF[lambda[i]];
/*
* Begin Berlekamp-Massey algorithm to determine error+erasure
* locator polynomial
*/
r = no_eras;
el = no_eras;
while (++r <= NROOTS) { /* r is the step number */
/* Compute discrepancy at the r-th step in poly-form */
discr_r = 0;
for (i = 0; i < r; i++){
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
discr_r ^= ALPHA_TO[mod255(INDEX_OF[lambda[i]] + s[r-i-1])];
}
}
discr_r = INDEX_OF[discr_r]; /* Index form */
if (discr_r == A0) {
/* 2 lines below: B(x) <-- x*B(x) */
memmove(&b[1],b,NROOTS*sizeof(b[0]));
b[0] = A0;
} else {
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
t[0] = lambda[0];
for (i = 0 ; i < NROOTS; i++) {
if(b[i] != A0)
t[i+1] = lambda[i+1] ^ ALPHA_TO[mod255(discr_r + b[i])];
else
t[i+1] = lambda[i+1];
}
if (2 * el <= r + no_eras - 1) {
el = r + no_eras - el;
/*
* 2 lines below: B(x) <-- inv(discr_r) *
* lambda(x)
*/
for (i = 0; i <= NROOTS; i++)
b[i] = (lambda[i] == 0) ? A0 : mod255(INDEX_OF[lambda[i]] - discr_r + NN);
} else {
/* 2 lines below: B(x) <-- x*B(x) */
memmove(&b[1],b,NROOTS*sizeof(b[0]));
b[0] = A0;
}
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
}
}
/* Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0;
for(i=0;i<NROOTS+1;i++){
lambda[i] = INDEX_OF[lambda[i]];
if(lambda[i] != A0)
deg_lambda = i;
}
/* Find roots of the error+erasure locator polynomial by Chien search */
memcpy(&reg[1],&lambda[1],NROOTS*sizeof(reg[0]));
count = 0; /* Number of roots of lambda(x) */
for (i = 1,k=IPRIM-1; i <= NN; i++,k = mod255(k+IPRIM)) {
q = 1; /* lambda[0] is always 0 */
for (j = deg_lambda; j > 0; j--){
if (reg[j] != A0) {
reg[j] = mod255(reg[j] + j);
q ^= ALPHA_TO[reg[j]];
}
}
if (q != 0)
continue; /* Not a root */
/* store root (index-form) and error location number */
root[count] = i;
loc[count] = k;
/* If we've already found max possible roots,
* abort the search to save time
*/
if(++count == deg_lambda)
break;
}
if (deg_lambda != count) {
/*
* deg(lambda) unequal to number of roots => uncorrectable
* error detected
*/
count = -1;
goto finish;
}
/*
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
* x**NROOTS). in index form. Also find deg(omega).
*/
deg_omega = 0;
for (i = 0; i < NROOTS;i++){
tmp = 0;
j = (deg_lambda < i) ? deg_lambda : i;
for(;j >= 0; j--){
if ((s[i - j] != A0) && (lambda[j] != A0))
tmp ^= ALPHA_TO[mod255(s[i - j] + lambda[j])];
}
if(tmp != 0)
deg_omega = i;
omega[i] = INDEX_OF[tmp];
}
omega[NROOTS] = A0;
/*
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
*/
for (j = count-1; j >=0; j--) {
num1 = 0;
for (i = deg_omega; i >= 0; i--) {
if (omega[i] != A0)
num1 ^= ALPHA_TO[mod255(omega[i] + i * root[j])];
}
num2 = ALPHA_TO[mod255(root[j] * (FCR - 1) + NN)];
den = 0;
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
if(lambda[i+1] != A0)
den ^= ALPHA_TO[mod255(lambda[i+1] + i * root[j])];
}
if (den == 0) {
count = -1;
goto finish;
}
/* Apply error to data */
if (num1 != 0) {
data[loc[j]] ^= ALPHA_TO[mod255(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])];
}
}
finish:
if(eras_pos != NULL){
for(i=0;i<count;i++)
eras_pos[i] = loc[i];
}
return count;
}
/* ---------- */
/* Re-encoder */
/* ---------- */
/* Reference encoder for proposed coded AO-40 telemetry format - v1.0 7 Jan 2002
* Copyright 2002, Phil Karn, KA9Q
* This software may be used under the terms of the GNU Public License (GPL)
*/
/* Adapted from the above enc_ref.c as used by the spacecraft (JRM) */
/* Write one binary channel symbol into the interleaver frame and update the pointers */
//void CCodecAO40::interleave_symbol(int c)
void interleave_symbol(int c)
{
int row,col;
col=m_ileaver_index/COLUMNS;
row=m_ileaver_index%COLUMNS;
if(c)
{
m_encoded[row*ROWS+col] = 1;
}
m_ileaver_index++;
}
/* Convolutionally encode and interleave one byte */
//void CCodecAO40::encode_and_interleave(unsigned char c,int cnt){
void encode_and_interleave(unsigned char c,int cnt){
while(cnt-- != 0)
{
m_conv_sr = (m_conv_sr << 1) | (c >> 7);
c <<= 1;
interleave_symbol( Partab[m_conv_sr & CPOLYA]);
interleave_symbol(!Partab[m_conv_sr & CPOLYB]); /* Second encoder symbol is inverted */
}
}
/* Scramble a byte, convolutionally encode and interleave into frame */
//void CCodecAO40::scramble_and_encode(unsigned char c){
void scramble_and_encode(unsigned char c){
c ^= Scrambler[m_encoded_bytes]; /* Scramble byte */
encode_and_interleave(c,8); /* RS encode and place into reencode buffer */
}
/* Encodes the 256 byte source block RSdecdata[] into 5200 byte block of symbols
* results stored in m_encoded.
* 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 *encode(unsigned char *source_bytes, int byte_count)
{
if(BLOCKSIZE != byte_count || NULL == source_bytes )
{
memset(m_encoded, 0, BLOCKSIZE);
return m_encoded;
}
init_encoder();
for(int i=0;i<BLOCKSIZE;i++)
{
encode_byte(source_bytes[i]) ;
}
for(int i=0;i<64;i++)
{
encode_parity();
}
return m_encoded;
}
/* The original three C user's entry points now follow. They are:
init_encoder() Called once before using system.
encode_byte(unsigned char c) Called with each user byte (i.e. 256 calls)
encode_parity() Called 64 times to finish off
*/
/* This function initializes the encoder. */
//void CCodecAO40::init_encoder(void){
void init_encoder(void){
int i,j,sr;
m_encoded_bytes = 0;
m_conv_sr = 0;
m_ileaver_index = COLUMNS; /* Sync vector is in first column; data starts here */
for(j=0;j<RSBLOCKS;j++) /* Flush parity array */
{
for(i=0;i<NROOTS;i++)
{
m_RS_block[j][i] = 0;
}
}
/* Clear re-encoded array */
for(i=0;i<SYMPBLOCK;i++)
{
m_encoded[i] = 0;
}
/* Generate sync vector, interleave into re-encode array, 1st column */
sr = 0x7f;
for(i=0;i<65;i++)
{
if(sr & 64)
{
m_encoded[ROWS*i] = 1; /* Every 80th symbol is a sync bit */
}
sr = (sr << 1) | Partab[sr & SYNC_POLY];
}
}
/* This function is called with each user data byte to be encoded into the
* current frame. It should be called in sequence 256 times per frame, followed
* by 64 calls to encode_parity().
*/
//void CCodecAO40::encode_byte(unsigned char c){
void encode_byte(unsigned char c){
unsigned char *rp; /* RS block pointer */
int i;
unsigned char feedback;
/* Update the appropriate Reed-Solomon codeword */
rp = m_RS_block[m_encoded_bytes & 1];
/* Compute feedback term */
feedback = INDEX_OF[c ^ rp[0]];
/* If feedback is non-zero, multiply by each generator polynomial coefficient and
* add to corresponding shift register elements
*/
if(feedback != A0){
int j;
/* This loop exploits the palindromic nature of the generator polynomial
* to halve the number of discrete multiplications
*/
for(j=0;j<15;j++){
unsigned char t;
t = ALPHA_TO[mod255(feedback + RS_poly[j])];
rp[j+1] ^= t; rp[31-j] ^= t;
}
rp[16] ^= ALPHA_TO[mod255(feedback + RS_poly[15])];
}
/* Shift 32 byte RS register one position down */
for(i=0;i<31;i++)
rp[i] = rp[i+1];
/* Handle highest order coefficient, which is unity */
if(feedback != A0){
rp[31] = ALPHA_TO[feedback];
} else {
rp[31] = 0;
}
scramble_and_encode(c);
m_encoded_bytes++;
}
/* This function should be called 64 times after the 256 data bytes
* have been passed to update_encoder. Each call scrambles, encodes and
* interleaves one byte of Reed-Solomon parity.
*/
//void CCodecAO40::encode_parity(void) {
void encode_parity(void) {
unsigned char c;
c = m_RS_block[m_encoded_bytes & 1][(m_encoded_bytes-256)>>1];
scramble_and_encode(c);
if(++m_encoded_bytes == 320){
/* Tail off the convolutional encoder (flush) */
encode_and_interleave(0,6);
}
}
//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 */
memset(rsblocks,0,RSBLOCKS*NN); /* Zero rsblocks array */
int di = 0;
int si = 0;
for(int col=RSPAD;col<NN;col++)
{
for(int row=0;row<RSBLOCKS;row++)
{
rsblocks[row][col] = viterbi_decoded[di++] ^ Scrambler[si++]; /* Remove scrambling */
}
}
}
/* -------- */
/* Decoder */
/* -------- */
/* ------------------- */
/* There are two RS decoders, processing 128 bytes each.
*
* If both RS decoders are SUCCESSFUL
* On exit:
* rs_failures = 0
* rserrs[x] = number of errors corrected; range 0 to 16 (x= 0 or 1)
* Data output is in array RSdecdata[256].
*
* If an RS decoder FAILS
* On exit:
* rs_failures = 1 or 2 (i.e. != 0)
* rserrs[x] contains -1
* Data output should not be used.
*/
//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;
char rsblocks[RSBLOCKS][NN];
descramble_to_rsblocks(vitdecdata, rsblocks);
/* Run RS-decoder(s) */
row_errors = total_errors = 0;
for(row=0; row<RSBLOCKS && row_errors!= -1; row++)
{
// decode row, returns -1 on failure or number of corrected errors
row_errors = decode_rs_8(rsblocks[row],NULL,0);
total_errors += row_errors;
}
if(row_errors != -1)
{
/* if frame decoded OK, deinterleave data from RS codeword(s) */
int j = 0;
for(col=RSPAD;col<KK;col++)
{
for(row=0;row<RSBLOCKS;row++)
{
decoded_data[j++] = rsblocks[row][col];
}
}
}
else
{
total_errors = -1;
}
return total_errors;
}
/* Compairs raw input symbols to current buffer of encoded symbols and counts the errors */
//int CCodecAO40::count_errors(unsigned char *raw_symbols)
int count_errors(unsigned char *raw_symbols)
{
int error_count = 0;
for(int i=0;i<SYMPBLOCK;i++)
{
if ( m_encoded[i] != (raw_symbols[i]>>7) )
{
error_count++ ;
}
}
return error_count;
}

@ -0,0 +1,110 @@
/* AO40 encoder / decoder
* Copyright 2002 Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
* See CodecAO40.cpp for lineage
*
* This file is part of FUNcubeLib.
*
* FUNcubeLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FUNcubeLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FUNcubeLib If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
//#include "fecConstants.h"
/*
Amsat P3 FEC Encoder/decoder system. Look-up tables
Created by Phil Karn KA9Q and James Miller G3RUH
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);
/* Encodes the 256 byte source block into 5200 byte block of symbols into m_encoded buffer */
const unsigned char *encode(
unsigned char *source_bytes, /* input to encode */
int byte_count); /* input length in bytes */
/* Compares raw input symbols to current buffer of encoded symbols and counts the errors */
int count_errors( unsigned char *raw_symbols);
//private:
int mod255(int x);
int decode_rs_8(char *data, int *eras_pos, int no_eras);
void scramble_and_encode(unsigned char c);
void encode_and_interleave(unsigned char c,int cnt);
void descramble_to_rsblocks(
unsigned char viterbi_decoded[NBITS_OUT],
char rsblocks[RSBLOCKS][NN]);
void init_encoder(void);
void encode_byte(unsigned char c);
void encode_parity(void);
void interleave_symbol(int c);
//};

@ -1,6 +1,8 @@
#!/bin/bash #!/bin/bash
echo -e "\nCommand and Control script for CubeSatSim v2.0\n" echo -e "\nCommand and Control script for CubeSatSim v2.1\n"
sudo modprobe snd-aloop
FILE=/home/pi/CubeSatSim/command_control FILE=/home/pi/CubeSatSim/command_control
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
@ -35,9 +37,17 @@ else
fi fi
uptime=`cat /proc/uptime | awk '{printf "%0.f", $1}'`
echo -n "Uptime since boot is "
echo $uptime
if [[ "$uptime" -lt "60" ]]; then
echo "Waiting 20 seconds for USB" echo "Waiting 20 seconds for USB"
sleep 20 sleep 20
fi
FILE=/home/pi/CubeSatSim/command_control_direwolf FILE=/home/pi/CubeSatSim/command_control_direwolf
if [[ $(arecord -l | grep "USB Audio Device") ]] && [ -f "$FILE" ]; then if [[ $(arecord -l | grep "USB Audio Device") ]] && [ -f "$FILE" ]; then

@ -210,7 +210,7 @@ function transmit_command_beacon {
exit exit
} }
echo "CubeSatSim v2.0 configuration tool" echo "CubeSatSim v2.1 configuration tool"
echo echo
# echo $1 # echo $1
# echo $2 # echo $2
@ -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
@ -366,7 +368,7 @@ elif [ "$1" = "-a" ]; then
echo "changing CubeSatSim to AFSK mode" echo "changing CubeSatSim to AFSK mode"
sudo echo "a" > /home/pi/CubeSatSim/.mode sudo echo "a" > /home/pi/CubeSatSim/.mode
if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] || [ "$1" == "j" ] ; then
FILE=/home/pi/CubeSatSim/battery_saver FILE=/home/pi/CubeSatSim/battery_saver
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
restart=1 restart=1
@ -392,7 +394,7 @@ elif [ "$1" = "-m" ]; then
echo "changing CubeSatSim to CW mode" echo "changing CubeSatSim to CW mode"
sudo echo "m" > /home/pi/CubeSatSim/.mode sudo echo "m" > /home/pi/CubeSatSim/.mode
if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] || [ "$1" == "j" ] ; then
FILE=/home/pi/CubeSatSim/battery_saver FILE=/home/pi/CubeSatSim/battery_saver
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
restart=1 restart=1
@ -452,7 +454,7 @@ elif [ "$1" = "-s" ]; then
echo "changing CubeSatSim to SSTV mode" echo "changing CubeSatSim to SSTV mode"
sudo echo "s" > /home/pi/CubeSatSim/.mode sudo echo "s" > /home/pi/CubeSatSim/.mode
if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] ; then if [ "$1" == "f" ] || [ "$1" == "b" ] || [ "$1" == "e" ] || [ "$1" == "j" ] ; then
FILE=/home/pi/CubeSatSim/battery_saver FILE=/home/pi/CubeSatSim/battery_saver
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
@ -743,6 +745,8 @@ elif [ "$1" = "-T" ]; then
# reboot=1 # reboot=1
echo "restarting command and control" echo "restarting command and control"
sudo systemctl restart command sudo systemctl restart command
echo "restarting transmit"
sudo systemctl restart transmit
## sudo reboot now ## sudo reboot now
fi fi
@ -759,6 +763,8 @@ elif [ "$1" = "-T" ]; then
echo "restarting command and control" echo "restarting command and control"
# reboot=1 # reboot=1
sudo systemctl restart command sudo systemctl restart command
echo "restarting transmit"
sudo systemctl restart transmit
## sudo reboot now ## sudo reboot now
fi fi
@ -1403,6 +1409,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,6 +1438,7 @@ 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 " -j Change to FunCube mode"
echo " -n Change to Transmit Commands 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"

@ -1,2 +1,2 @@
ADEVICE hw:CARD=Device,DEV=0 default ADEVICE shared_mic hw:CARD=Loopback,DEV=1
DTMF DTMF

@ -71,6 +71,25 @@ if __name__ == "__main__":
system("echo '\nCW Mode!!\n'") system("echo '\nCW Mode!!\n'")
mode = 'm' mode = 'm'
change_mode = True change_mode = True
if ((line.find("MODE=e")) > 0):
system("echo '\nRepeater Mode!!\n'")
mode = 'e'
change_mode = True
counter = (counter + 1) % 2
if ((line.find("DTMF>APDW15:t6#")) > 0):
system("echo '\nRepeater Mode!!\n'")
mode = 'e'
change_mode = True
if ((line.find("MODE=j")) > 0):
system("echo '\nFunCube Mode!!\n'")
mode = 'j'
change_mode = True
counter = (counter + 1) % 2
if ((line.find("DTMF>APDW15:t7#")) > 0):
system("echo '\nFunCube Mode!!\n'")
mode = 'j'
change_mode = True
if ((line.find("MODE=n")) > 0): if ((line.find("MODE=n")) > 0):
system("echo '\nTransmit Commands Mode!!\n'") system("echo '\nTransmit Commands Mode!!\n'")
mode = 'n' mode = 'n'
@ -80,7 +99,6 @@ if __name__ == "__main__":
system("echo '\nTransmit Commands Mode!!\n'") system("echo '\nTransmit Commands Mode!!\n'")
mode = 'n' mode = 'n'
change_mode = True change_mode = True
# Currently, C2C does not support Repeater mode e
if ((line.find("MODE=o")) > 0): if ((line.find("MODE=o")) > 0):
system("echo '\nBeacon Mode toggle!!\n'") system("echo '\nBeacon Mode toggle!!\n'")
mode = 'o' mode = 'o'
@ -91,7 +109,8 @@ if __name__ == "__main__":
mode = 'o' mode = 'o'
change_mode = True change_mode = True
if (debug_mode == False) and (change_mode == True) and (counter == 1): # skip every other APRS command since Direwolf prints them twice # if (debug_mode == False) and (change_mode == True) and (counter == 1): # skip every other APRS command since Direwolf prints them twice
if (debug_mode == False) and (change_mode == True): # skip every other APRS command since Direwolf prints them twice
GPIO.setmode(GPIO.BCM) GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False) GPIO.setwarnings(False)
GPIO.setup(powerPin, GPIO.OUT) GPIO.setup(powerPin, GPIO.OUT)
@ -160,6 +179,63 @@ if __name__ == "__main__":
sleep(0.1) sleep(0.1)
GPIO.output(powerPin, 1) GPIO.output(powerPin, 1)
sleep(1) sleep(1)
elif (mode == 'e'):
GPIO.output(powerPin, 0) # blink six times
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1);
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(1)
elif (mode == 'j'):
GPIO.output(powerPin, 0) # blink seven times
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1);
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(1)
elif (mode == 'a'): elif (mode == 'a'):
mode = 'a' mode = 'a'
GPIO.output(powerPin, 0) # blink one time GPIO.output(powerPin, 0) # blink one time

@ -0,0 +1,128 @@
#pragma once
/*
Amsat P3 FEC Encoder/decoder system. Look-up tables
Created by Phil Karn KA9Q and James Miller G3RUH
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)
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,
};

@ -173,7 +173,8 @@
"upper_bound": 440000000, "upper_bound": 440000000,
"frequencies": { "frequencies": {
"packet": 434900000, "packet": 434900000,
"pocsag": 439987500 "pocsag": 439987500,
"sstv": { "frequency": 434900000, "underlying": "nfm" }
} }
}, },
{ {

@ -29,6 +29,8 @@ sudo killall -9 rtl_tcp &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
#sudo kill `ps -aux | grep cubicsdr-packet | grep -v grep | awk '{ print $2 }'` &>/dev/null && killall inotifywait &>/dev/null #sudo kill `ps -aux | grep cubicsdr-packet | grep -v grep | awk '{ print $2 }'` &>/dev/null && killall inotifywait &>/dev/null
#sudo kill `ps -aux | grep packet | grep -v grep | awk '{ print $2 }'` &>/dev/null && killall inotifywait &>/dev/null #sudo kill `ps -aux | grep packet | grep -v grep | awk '{ print $2 }'` &>/dev/null && killall inotifywait &>/dev/null

@ -1 +1 @@
ADEVICE plughw:CARD=Loopback,DEV=1 plughw:CARD=b1,DEV=0 ADEVICE plughw:CARD=Loopback,DEV=1

@ -0,0 +1,211 @@
import sys
from os import system
from time import sleep
import logging
import random
from PIL import Image, ImageDraw, ImageFont, ImageColor
import subprocess
import io
import datetime
logging.basicConfig(format='%(message)s')
# logging.warning('CC-Warning!')
def fstr(template):
return eval(f"f'{template}'")
def system_and_print(string):
print(string)
system(string)
FC_EPS = 1
FC_BOB = 25
FC_SW = 50
FC_PAYLOAD = 55
extended = 1
sequence, image_id, image_count = 0, 0, 0
Vx, Vy, Vz, Vb = 0, 0, 0, 0
Ix, Iy, Iz, Ic, Ib = 0, 0, 0, 0, 0
frame_count, frame_type = 0, " "
frequency_string, frequency, errors, first_byte = " ", 0, 0, 0
#html_dir = "/home/pi/CubeSatSim/groundstation/public_html/"
html_dir = "/home/pi/fctelem/public_html/"
image_dir = "/home/pi/fctelem/"
image = "image_file"
ssdv = "/home/pi/ssdv/ssdv -d -J "
date_time_string = str(datetime.datetime.now())
date_time = date_time_string[:21]
system_and_print("sudo rm " + image_dir + image)
#system_and_print("sudo rm " + html_dir + "*")
system_and_print("sudo rm " + html_dir + "images/*")
try:
with open('/home/pi/fctelem/fctelem.cfg', 'r') as config:
config_string = config.read()
print(config_string)
except:
print("Error loading fctelem.cfg")
#system_and_print("cp /home/pi/CubeSatSim/sstv/sstv_image_1_320_x_256.jpg " + html_dir + "image_file.jpeg")
head_string = '<HEAD><meta http-equiv="refresh" content="5"><title>FunCube CubeSatSim Telemetry</title></HEAD>\n<HTML>\n<H2>FunCube CubeSatSim Telemetry</H2>' + \
'fcdctl ' + config_string + '<p><pre> <img height="256" width="320" src="' + image + \
'.jpeg"><br> <A HREF="images" target="_blank">All images</a><br>'
foot_string = '</HTML>'
telem_string_format = " Image: {image_id:3d} count: {image_count:2d}<p>" + \
" Vx(mV): {Vx:5d} Vy(mV): {Vy:5d} Vz(mV): {Vz:5d}<p>" + \
" Ix(mA): {Ix:5d} Iy(mA): {Iy:5d} Iz(mA): {Iz:5d}<p>" + \
" Vbat(mV): {Vb:5d} Ibat(mA): {Ib:5d}<br><br></pre>" + \
" Freq: {frequency:10.1f} errors: {errors} Seq: {sequence:d} {frame_type} frames: {frame_count:d}"
label_string = "date time , frm, freq off, err, h, seq, frame, img, c, Vx, Vy, Vz, Ix, Iy, Iz, Vb, Ib "
label_string_html = label_string.replace(" ","&nbsp;")
csv_format = "{date_time:21s}, {frame_count:4d}, {frequency:10.1f}, {errors:3d}, {first_byte: 2x}, {sequence:5d}, {frame_type:9s}, {image_id:3d}, {image_count:2d}, " + \
"{Vx:5d}, {Vy:5d}, {Vz:5d}, {Ix:5d}, {Iy:5d}, {Iz:5d}, {Vb:5d}, {Ib:5d}"
telem_string = fstr(telem_string_format)
with open(html_dir + "index.html", "w+") as html_file:
html_file.write(head_string)
html_file.write(telem_string)
html_file.write(foot_string)
with open(html_dir + "images/telem.csv.txt", "w+") as csv_file:
# csv_file.write(csv_format)
csv_file.write(label_string)
csv_file.write("\n")
image_id = 256 # set illegal image ID for null # random.randint(0, 255)
image_count = 1;
# sys.exit()
if __name__ == "__main__":
debug_mode = False
counter = 1
if (len(sys.argv)) > 1:
# print("There are arguments!")
if ('d' == sys.argv[1]):
debug_mode = True
print(debug_mode)
for line in sys.stdin:
if (debug_mode):
print(line, end =" ")
logging.warning(line)
if ((line.find("data: ")) > 0):
print("\ndata block found!\n")
frame_count += 1
data_block_string = line.split()
# print(data_block_string)
frequency_string = data_block_string[2]
print(frequency_string)
frequency = float(frequency_string[:len(frequency_string) - 2])
print(frequency)
errors = int(data_block_string[5])
data_block = [int(number_string,16) for number_string in data_block_string[7:]]
first_byte = data_block[0]
if (first_byte == 0xE0) or (first_byte == 0xE1):
if (data_block[0] == 0xE0):
frame_type = "RT1+IMG1"
if (data_block[0] == 0xE1):
frame_type = "RT2+IMG2"
print(frame_type)
print(data_block[extended + 51], data_block[extended + 50], data_block[extended + 49])
sequence = data_block[extended + 51] + data_block[extended + 50] * 2**8 + data_block[extended + 49] * 2**16
print("Sequence number: {:d}".format(sequence))
Vx = (data_block[extended + FC_EPS + 0] * 2**6) + (data_block[extended + FC_EPS + 1] >> 2)
Vy = (0x03 & data_block[extended + FC_EPS + 1]) * 2**12 + data_block[extended + FC_EPS + 2] * 2**4 + (data_block[extended + FC_EPS + 3] >> 4)
Vz = (0x0f & data_block[extended + FC_EPS + 3]) * 2**10 + data_block[extended + FC_EPS + 4] * 2**2 + (data_block[extended + FC_EPS + 5] >> 6)
Vb = (0x3f & data_block[extended + FC_EPS + 5]) * 2**8 + data_block[extended + FC_EPS + 6]
Ix = data_block[extended + FC_EPS + 7] * 2**2 + (data_block[extended + FC_EPS + 8] >> 6)
Iy = (0x3f & data_block[extended + FC_EPS + 8]) * 2**4 + (data_block[extended + FC_EPS + 9] >> 4)
Iz = (0x0f & data_block[extended + FC_EPS + 9]) * 2**6 + (data_block[extended + FC_EPS + 10] >> 2)
Ic = (0x03 & data_block[extended + FC_EPS + 10]) * 2**8 + data_block[extended + FC_EPS + 11]
Ib = data_block[extended + FC_EPS + 12] * 2**2 + ((0xc0 & data_block[extended + FC_EPS + 13]) >> 6)
if (Ib == 0):
Ib = 0 - Ic
print("Vx: {:d} mV Vy: {:d} mV Vz: {:d} mV".format(Vx, Vy, Vz))
print('Payload {:x} {:x} \n'.format(data_block[FC_PAYLOAD + extended], data_block[FC_PAYLOAD + extended + 1]))
if (data_block[FC_PAYLOAD + extended] == 0x55) and (data_block[FC_PAYLOAD + extended + 1] == 0x68):
try:
print("Writing this image payload block to file " + image + "_payload")
immutable_payload = bytes(bytearray(data_block[(FC_PAYLOAD + extended):])) # payload)
# print(immutable_payload)
with open(image_dir + image + "_payload", "wb") as binary_file:
binary_file.write(immutable_payload)
except:
print("File error")
# try:
print("Processing payload with ssdv, saving image to " + image + "_paylad.jpeg and log to ssdv_output")
system_and_print(ssdv + image_dir + image + "_payload " +
image_dir + image + "_payload.jpeg 2>&1 | sudo tee /home/pi/fctelem/ssdv_output")
print("Parsing ssdv_output")
with open("/home/pi/fctelem/ssdv_output", "r") as file:
for line in file:
# print("line:")
# print(line)
if ((line.find("mage ID:")) > 0):
# print("\nImage ID found!\n")
image_id_string = line.split()
# print(image_id_string)
new_image_id = int(image_id_string[2], 16)
# print(new_image_id)
if (new_image_id != image_id):
print("End of image")
if (image_id != 256):
print("Saving complete image")
system_and_print("cp " + html_dir + "image_file.jpeg " + html_dir + "images/" + image + str(image_id) + "." + str(image_count) + ".jpeg")
system_and_print("sudo rm " + image_dir + image)
else:
system_and_print("sudo rm " + image_dir + image)
print("New Image ID: ")
print(new_image_id)
image_id = new_image_id
image_count = 1
else:
image_count += 1
print("new image_count:")
print(image_count)
print("Appending block to file " + image)
with open(image_dir + image, "ab") as binary_file:
binary_file.write(immutable_payload)
print("Running ssdv with all blocks in file " + image + " saving as " + html_dir + "image_file.jpeg")
system_and_print(ssdv + image_dir + image + " " + html_dir + "image_file.jpeg")
telem_string = fstr(telem_string_format)
print("Writing index.html file")
with open(html_dir + "index.html", "w") as html_file:
html_file.write(head_string)
html_file.write(telem_string)
html_file.write("<br><pre>")
with open(html_dir + "/images/telem.csv.txt", "r") as csv_file:
for line in csv_file:
html_file.write(line)
html_file.write("<br>")
date_time_string = str(datetime.datetime.now())
date_time = date_time_string[:21]
tlm_string = fstr(csv_format)
html_file.write(tlm_string)
html_file.write("</pre><br>")
html_file.write(foot_string)
else:
print("Payload not an image!")
# image_id = 256 # set illegal image_id to force new image
else:
print("Unknown Sat Id or Frame")
sequence, image_id, image_count = 0, 0, 0
Vx, Vy, Vz, Vb = 0, 0, 0, 0
Ix, Iy, Iz, Ic, Ib = 0, 0, 0, 0, 0
frame_count, frame_type = 0, " "
frequency_string, errors = " ", 0
tlm_string = fstr(csv_format)
with open(html_dir + "/images/telem.csv.txt", "a") as csv_file:
csv_file.write(tlm_string)
csv_file.write("\n")

@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
Exec=/home/pi/CubeSatSim/groundstation/fctelem.sh
Name=FunCube Telem
Comment=FunCube Telemetry Web App
Icon=/home/pi/Icons/fc-icon.png
Path=/home/pi
Terminal=true
Categories=HamRadio
Keywords=Ham Radio;SDR

@ -0,0 +1,153 @@
#!/bin/bash
# script to run FunCube Pi Telemetry App
echo "Script to run FunCube CubeSatSim Telemetry"
echo
echo "The Chromium browser will load in a few seconds with fctelem."
echo "You can also use another web browser if you are on the same network as your Pi."
echo
ip=$(hostname -I|cut -f1 -d ' ')
echo "IP Address to use in web browser is: $ip:8000"
echo
ssid=$(iwgetid -r)
echo "Note: you need to be on the Wifi network: $ssid"
echo
sudo killall -9 fctelem &>/dev/null
sudo killall -9 python3 &>/dev/null
#sudo killall -9 java &>/dev/null
#sudo killall -9 rtl_fm &>/dev/null
#pkill -o chromium &>/dev/null
#sudo killall -9 rtl_tcp &>/dev/null
#sudo killall -9 CubicSDR &>/dev/null
#sudo killall -9 qsstv &>/dev/null
#sudo killall -9 aplay &>/dev/null
#sudo killall -9 direwolf &>/dev/null
#sudo killall -9 zenity &>/dev/null
#sudo systemctl stop rtl_tcp
#sudo systemctl stop openwebrx
if [[ $(/home/pi/fcdctl/fcdctl -l | grep "No FCD found") ]]; then
echo "No FunCube Dongle Found!"
echo "Plug in FCD and try running again"
sleep 30
exit
else
echo "FCD Found! Setting Gain"
FILE=/home/pi/fctelem/fctelem.cfg
if [ -f "$FILE" ]; then
# config_string=$(</home/pi/fctelem/fctelem.cfg)
config_string=$(<$FILE)
else
echo "No fctelem.cfg file"
echo "Creating it"
config_string="-g 1 -m 1 -i 0"
echo $config_string >> FILE
fi
/home/pi/fcdctl/fcdctl $config_string
# /home/pi/fcdctl/fcdctl -g 1 -m 1 -i 0
echo
fi
frequency=$(zenity --list 2>/dev/null --width=410 --height=180 --title="FunCube Telem Decoding" --text="Choose the frequency for FunCube decoding:" --column="kHz" --column="Use" 434900 "CubeSatSim" Other "Choose another frequency")
echo $frequency
if [ -z "$frequency" ]; then
echo "No choice made. Exiting."
sleep 3
exit
fi
if [ "$frequency" = "434900" ]; then
frequency=434900000
elif [ "$frequency" = "Other" ]; then
echo
echo "Enter the frequency in kiloHertz"
echo
read -r frequency
frequency=$frequency"000"
fi
echo "Frequency is" $frequency
echo
echo "If your CubeSatSim is transmitting in FunCube mode (mode 7) you should get some frames after 30 seconds"
echo
sleep 3
echo "connectport=64516 connectaddress='localhost' autotuneoffset=100000 outdir='/home/pi/go/app/fctelem/data' frequency=$frequency" > /home/pi/fctelem/fcdecode.conf
# FILE=/home/pi/CubeSatSim/groundstation/public_html
FILE=/home/pi/CubeSatSim/fctelem/public_html
if [ ! -d "$FILE" ]; then
echo "Making public_html directory"
mkdir /home/pi/fctelem/public_html
mkdir /home/pi/fctelem/public_html/images
fi
cd /home/pi/fctelem/public_html
cp /home/pi/CubeSatSim/groundstation/index.html .
cp /home/pi/CubeSatSim/sstv/sstv_image_1_320_x_256.jpg ./image_file.jpeg
python3 -m http.server &
setsid chromium-browser --check-for-update-interval=1 --simulate-critical-update --noerrdialogs --disable-infobars http://127.0.0.1:8000 &>/dev/null &
cd /home/pi/fctelem
sudo ./fctelem | python3 /home/pi/CubeSatSim/groundstation/fc_block_decode.py
# sleep 10
#read val
#sudo killall -9 fctelem &>/dev/null
#sudo killall -9 python3 &>/dev/null
sleep 10
#$SHELL

@ -19,6 +19,8 @@ sudo killall -9 java &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
sudo killall -9 direwolf &>/dev/null sudo killall -9 direwolf &>/dev/null
sudo killall -9 aplay &>/dev/null sudo killall -9 aplay &>/dev/null

@ -0,0 +1,9 @@
<HEAD><meta http-equiv="refresh" content="5"></HEAD>
<HTML>
FunCube CubeSatSim Telemetry
<p>
<img src="image_file.jpeg">
<!--
<img src="image_file.jpeg" id="reloader" onLoad="setTimeout( () => { document.getElementById('reloader').src='image_file.jpeg' + '?' + new Date().getMilliseconds() } ,5000)" />
-->
</p>

@ -5,6 +5,8 @@ sudo killall -9 java &>/dev/null
sudo killall -9 gpredict &>/dev/null sudo killall -9 gpredict &>/dev/null
source /home/pi/venv/bin/activate
python3 /home/pi/CubeSatSim/groundstation/loc-foxtelem.py python3 /home/pi/CubeSatSim/groundstation/loc-foxtelem.py
#/usr/bin/gpredict #/usr/bin/gpredict

@ -24,6 +24,8 @@ sudo killall -9 java &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
sudo killall -9 zenity &>/dev/null sudo killall -9 zenity &>/dev/null
echo echo
@ -175,7 +177,8 @@ else
echo -e "Auto decoding APRS packets on $frequency Hz" echo -e "Auto decoding APRS packets on $frequency Hz"
direwolf -r 48000 -c /home/pi/CubeSatSim/groundstation/direwolf/direwolf.conf -t 0 & # direwolf -r 48000 -c /home/pi/CubeSatSim/groundstation/direwolf/direwolf.conf -t 0 &
direwolf -r 48000 -c /home/pi/CubeSatSim/groundstation/direwolf/direwolf.conf &
fi fi
@ -186,6 +189,6 @@ echo "$value" > /dev/null
set -- $value set -- $value
#rtl_fm -M fm -f 144.39M -s 48k | aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1 #rtl_fm -M fm -f 144.39M -s 48k | aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1
rtl_fm -M fm -f $frequency -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -D hw:0,0 -r 48000 -t raw -f S16_LE -c 1 rtl_fm -M fm -f $frequency -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -r 48000 -t raw -f S16_LE -c 1
sleep 5 sleep 5

@ -37,6 +37,8 @@ sudo killall -9 rtl_fm &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
sudo killall -9 rtl_tcp &>/dev/null sudo killall -9 rtl_tcp &>/dev/null
sudo killall -9 qsstv &>/dev/null sudo killall -9 qsstv &>/dev/null
@ -48,7 +50,7 @@ sudo killall -9 aplay &>/dev/null
sudo killall -9 zenity &>/dev/null sudo killall -9 zenity &>/dev/null
sudo /bin/sh -c '/usr/local/bin/rtl_tcp -a $(hostname -I|cut -f1 -d " ")' sudo /bin/sh -c 'rtl_tcp -a $(hostname -I|cut -f1 -d " ")'
sleep 5 sleep 5

@ -34,6 +34,8 @@ sudo killall -9 rtl_tcp &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
sudo killall -9 qsstv &>/dev/null sudo killall -9 qsstv &>/dev/null
sudo killall -9 aplay &>/dev/null sudo killall -9 aplay &>/dev/null

@ -26,6 +26,8 @@ sudo killall -9 java &>/dev/null
sudo killall -9 CubicSDR &>/dev/null sudo killall -9 CubicSDR &>/dev/null
sudo killall -9 sdrpp &>/dev/null
sudo killall -9 zenity &>/dev/null sudo killall -9 zenity &>/dev/null
#echo "s" >> .mode #echo "s" >> .mode
@ -128,7 +130,7 @@ set -- $value
#rtl_fm -M fm -f 434.9M -s 48k | aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1 #rtl_fm -M fm -f 434.9M -s 48k | aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1
#rtl_fm -M fm -f 434.9M -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -D hw:0,0 -r 48000 -t raw -f S16_LE -c 1 #rtl_fm -M fm -f 434.9M -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -D hw:0,0 -r 48000 -t raw -f S16_LE -c 1
rtl_fm -M fm -f $frequency -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -D hw:0,0 -r 48000 -t raw -f S16_LE -c 1 rtl_fm -M fm -f $frequency -s 48k | tee >(aplay -D hw:${2:0:1},0,0 -r 48000 -t raw -f S16_LE -c 1) | aplay -r 48000 -t raw -f S16_LE -c 1
sleep 5 sleep 5

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
echo -e "\ninstallation script for CubeSatSim v2.0\n" echo -e "\ninstallation script for CubeSatSim v2.1\n"
FILE=/home/pi/CubeSatSim/sim.cfg FILE=/home/pi/CubeSatSim/sim.cfg
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
@ -56,7 +56,7 @@ sudo dpkg -i debian-template/wiringpi-2.61-1.deb
cd cd
#changed to python3-smbus #changed to python3-smbus
sudo apt install -y python3-pip python3-smbus libjpeg-dev zlib1g-dev libfreetype6-dev libopenjp2-7 libtiff5 python3-pil python3-serial sudo apt install -y python3-pip python3-smbus libjpeg-dev zlib1g-dev libfreetype6-dev libopenjp2-7 libtiff5 python3-pil python3-serial libusb-1.0
sudo pip3 install --upgrade setuptools sudo pip3 install --upgrade setuptools
@ -95,13 +95,35 @@ git clone https://github.com/alanbjohnston/pi-power-button.git
cd pi-power-button cd pi-power-button
git checkout master git checkout 7-modes
./script/install ./script/install
cd
echo "Installing SSDV for FunCube mode"
git clone https://github.com/alanbjohnston/ssdv.git # install ssdv for FunCube images
cd ssdv
make
cd cd
echo "Installing fctelem binary v0.2 for FunCube mode"
mkdir /home/pi/fctelem
mkdir /home/pi/fctelem/public_html
cd fctelem
wget https://github.com/alanbjohnston/go/releases/download/v0.2/fctelem.zip
unzip fctelem.zip
cd
echo "Installing fcdctl to set FunCubeDongle Pro gain"
# sudo rm /var/lib/dpkg/info/python3-pip.list
# sudo apt install python3-pip --reinstall
# sudo apt-get install -y python3-smbus libusb-1.0
cd
git clone https://github.com/csete/fcdctl.git
cd fcdctl
make fcdpp
git clone https://github.com/alanbjohnston/PiSSTVpp.git git clone https://github.com/alanbjohnston/PiSSTVpp.git
cd PiSSTVpp cd PiSSTVpp
@ -125,6 +147,10 @@ cd rpitx
cd cd
git clone https://github.com/alanbjohnston/ssdv.git # install ssdv for FunCube images
cd ssdv
make
cd cd
sudo cp ~/CubeSatSim/systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service sudo cp ~/CubeSatSim/systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service
@ -139,6 +165,8 @@ sudo cp ~/CubeSatSim/systemd/command.service /etc/systemd/system/command.service
sudo systemctl enable command sudo systemctl enable command
sudo cp /home/pi/CubeSatSim/asound.conf /etc/asound.conf
sudo cp /boot/config.txt /boot/config.txt.0 sudo cp /boot/config.txt /boot/config.txt.0
sudo cp /boot/cmdline.txt /boot/cmdline.txt.0 sudo cp /boot/cmdline.txt /boot/cmdline.txt.0

551
main.c

@ -25,7 +25,7 @@
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
printf("\n\nCubeSatSim v2.0 starting...\n\n"); printf("\n\nCubeSatSim v2.1 starting...\n\n");
wiringPiSetup(); wiringPiSetup();
@ -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");
@ -408,16 +414,17 @@ int main(int argc, char * argv[]) {
batt = rnd_float(3.8, 4.3); batt = rnd_float(3.8, 4.3);
speed = rnd_float(1.0, 2.5); speed = rnd_float(1.0, 2.5);
eclipse = (rnd_float(-1, +4) > 0) ? 1.0 : 0.0; eclipse = (rnd_float(-1, +4) > 0) ? 1.0 : 0.0;
// eclipse = 1;
period = rnd_float(150, 300); period = rnd_float(150, 300);
tempS = rnd_float(20, 55); tempS = rnd_float(20, 55);
temp_max = rnd_float(50, 70); temp_max = rnd_float(50, 70);
temp_min = rnd_float(10, 20); temp_min = rnd_float(10, 20);
#ifdef DEBUG_LOGGING // #ifdef DEBUG_LOGGING
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
printf("axis: %f angle: %f v: %f i: %f \n", axis[i], angle[i], volts_max[i], amps_max[i]); printf("axis: %f angle: %f v: %f i: %f \n", axis[i], angle[i], volts_max[i], amps_max[i]);
printf("batt: %f speed: %f eclipse_time: %f eclipse: %f period: %f temp: %f max: %f min: %f\n", batt, speed, eclipse_time, eclipse, period, tempS, temp_max, temp_min); printf("batt: %f speed: %f eclipse_time: %f eclipse: %f period: %f temp: %f max: %f min: %f\n", batt, speed, eclipse_time, eclipse, period, tempS, temp_max, temp_min);
#endif // #endif
time_start = (long int) millis(); time_start = (long int) millis();
@ -455,6 +462,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 +495,43 @@ 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)));
FILE * delete_image = popen("sudo rm /home/pi/CubeSatSim/image_file.bin", "r"); // delete any previous camera images
pclose(delete_image);
}
printf("\n");
} }
memset(voltage, 0, sizeof(voltage)); memset(voltage, 0, sizeof(voltage));
@ -496,6 +541,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
@ -581,16 +629,24 @@ int main(int argc, char * argv[]) {
token = strtok(NULL, space); token = strtok(NULL, space);
} }
} }
if (voltage[map[BAT]] == 0.0) if (voltage[map[BAT]] == 0.0) // No BAT Board
if (voltage[map[BAT2]] == 0.0) // No BAT2 Board
batteryVoltage = 4.5; batteryVoltage = 4.5;
else { else {
batteryVoltage = voltage[map[BAT]]; batteryVoltage = voltage[map[BAT2]]; // only BAT2 Board present
if (sim_mode && !sim_config) { // if Voltage sensor on Battery board is present, exit simulated telemetry mode
sim_mode = FALSE;
fprintf(stderr, "Turning off sim_mode since battery sensor 2 is present\n");
}
}
else {
batteryVoltage = voltage[map[BAT]]; // BAT Board present
if (sim_mode && !sim_config) { // if Voltage sensor on Battery board is present, exit simulated telemetry mode if (sim_mode && !sim_config) { // if Voltage sensor on Battery board is present, exit simulated telemetry mode
sim_mode = FALSE; sim_mode = FALSE;
fprintf(stderr, "Turning off sim_mode since battery sensor is present\n"); fprintf(stderr, "Turning off sim_mode since battery sensor is present\n");
} }
} }
batteryCurrent = current[map[BAT]]; batteryCurrent = current[map[BAT]] + current[map[BAT2]]; // Sum BAT and BAT2 currents
} }
@ -699,7 +755,7 @@ int main(int argc, char * argv[]) {
double Yv = eclipse * volts_max[1] * (float) sin((2.0 * 3.14 * time / (46.0 * speed)) + (3.14 / 2.0)) + rnd_float(-0.2, 0.2); double Yv = eclipse * volts_max[1] * (float) sin((2.0 * 3.14 * time / (46.0 * speed)) + (3.14 / 2.0)) + rnd_float(-0.2, 0.2);
double Zv = 2.0 * eclipse * volts_max[2] * (float) sin((2.0 * 3.14 * time / (46.0 * speed)) + 3.14 + angle[2]) + rnd_float(-0.2, 0.2); double Zv = 2.0 * eclipse * volts_max[2] * (float) sin((2.0 * 3.14 * time / (46.0 * speed)) + 3.14 + angle[2]) + rnd_float(-0.2, 0.2);
// printf("Yi: %f Zi: %f %f %f Zv: %f \n", Yi, Zi, amps_max[2], angle[2], Zv); printf("Yi: %f Zi: %f %f %f Zv: %f \n", Yi, Zi, amps_max[2], angle[2], Zv);
current[map[PLUS_X]] = (Xi >= 0) ? Xi : 0; current[map[PLUS_X]] = (Xi >= 0) ? Xi : 0;
current[map[MINUS_X]] = (Xi >= 0) ? 0 : ((-1.0f) * Xi); current[map[MINUS_X]] = (Xi >= 0) ? 0 : ((-1.0f) * Xi);
@ -715,7 +771,7 @@ int main(int argc, char * argv[]) {
voltage[map[PLUS_Z]] = (Zv >= 1) ? Zv : rnd_float(0.9, 1.1); voltage[map[PLUS_Z]] = (Zv >= 1) ? Zv : rnd_float(0.9, 1.1);
voltage[map[MINUS_Z]] = (Zv <= -1) ? ((-1.0f) * Zv) : rnd_float(0.9, 1.1); voltage[map[MINUS_Z]] = (Zv <= -1) ? ((-1.0f) * Zv) : rnd_float(0.9, 1.1);
// printf("temp: %f Time: %f Eclipse: %d : %f %f | %f %f | %f %f\n",tempS, time, eclipse, voltage[map[PLUS_X]], voltage[map[MINUS_X]], voltage[map[PLUS_Y]], voltage[map[MINUS_Y]], current[map[PLUS_Z]], current[map[MINUS_Z]]); printf("temp: %f Time: %f Eclipse: %d : %f %f | %f %f | %f %f\n",tempS, time, eclipse, voltage[map[PLUS_X]], voltage[map[MINUS_X]], voltage[map[PLUS_Y]], voltage[map[MINUS_Y]], current[map[PLUS_Z]], current[map[MINUS_Z]]);
tempS += (eclipse > 0) ? ((temp_max - tempS) / 50.0f) : ((temp_min - tempS) / 50.0f); tempS += (eclipse > 0) ? ((temp_max - tempS) / 50.0f) : ((temp_min - tempS) / 50.0f);
tempS += +rnd_float(-1.0, 1.0); tempS += +rnd_float(-1.0, 1.0);
@ -725,12 +781,13 @@ int main(int argc, char * argv[]) {
voltage[map[BAT2]] = 0.0; // rnd_float(5.0, 5.005); voltage[map[BAT2]] = 0.0; // rnd_float(5.0, 5.005);
current[map[BAT2]] = 0.0; // rnd_float(158, 171); current[map[BAT2]] = 0.0; // rnd_float(158, 171);
// float charging = current[map[PLUS_X]] + current[map[MINUS_X]] + current[map[PLUS_Y]] + current[map[MINUS_Y]] + current[map[PLUS_Z]] + current[map[MINUS_Z]]; float charging = current[map[PLUS_X]] + current[map[MINUS_X]] + current[map[PLUS_Y]] + current[map[MINUS_Y]] + current[map[PLUS_Z]] + current[map[MINUS_Z]];
float charging = eclipse * (fabs(amps_max[0] * 0.707) + fabs(amps_max[1] * 0.707) + rnd_float(-4.0, 4.0)); // float charging = eclipse * (fabs(amps_max[0] * 0.707) + fabs(amps_max[1] * 0.707) + rnd_float(-4.0, 4.0));
current[map[BAT]] = ((current[map[BAT2]] * voltage[map[BAT2]]) / batt) - charging; // current[map[BAT]] = ((current[map[BAT2]] * voltage[map[BAT2]]) / batt) - charging;
current[map[BAT]] = rnd_float(285, 305) - charging;
// printf("charging: %f bat curr: %f bus curr: %f bat volt: %f bus volt: %f \n",charging, current[map[BAT]], current[map[BAT2]], batt, voltage[map[BAT2]]); printf("charging: %f bat curr: %f bus curr: %f bat volt: %f bus volt: %f \n",charging, current[map[BAT]], current[map[BAT2]], batt, voltage[map[BAT2]]);
batt -= (batt > 3.5) ? current[map[BAT]] / 30000 : current[map[BAT]] / 3000; batt -= (batt > 3.5) ? current[map[BAT]] / 30000 : current[map[BAT]] / 3000;
if (batt < 3.0) { if (batt < 3.0) {
@ -766,9 +823,9 @@ int main(int argc, char * argv[]) {
fclose(cpuTempSensor); fclose(cpuTempSensor);
} }
#ifdef DEBUG_LOGGING // #ifdef DEBUG_LOGGING
// fprintf(stderr, "INFO: Battery voltage: %5.2f V Threshold %5.2f V Current: %6.1f mA Threshold: %6.1f mA\n", batteryVoltage, voltageThreshold, batteryCurrent, currentThreshold); fprintf(stderr, "INFO: Battery voltage: %5.2f V Threshold %5.2f V Current: %6.1f mA Threshold: %6.1f mA\n", batteryVoltage, voltageThreshold, batteryCurrent, currentThreshold);
#endif // #endif
if ((batteryCurrent > currentThreshold) && (batteryVoltage < (voltageThreshold + 0.15)) && !sim_mode && !hab_mode) if ((batteryCurrent > currentThreshold) && (batteryVoltage < (voltageThreshold + 0.15)) && !sim_mode && !hab_mode)
{ {
@ -869,6 +926,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 +938,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 +1722,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 +1750,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);
@ -1713,7 +1772,7 @@ void get_tlm_fox() {
// printf("\ctr/samples = %d ctr/(samples*10) = %d\n\n", ctr/samples, ctr/(samples*10)); // printf("\ctr/samples = %d ctr/(samples*10) = %d\n\n", ctr/samples, ctr/(samples*10));
#endif #endif
int error = 0; //int error = 0;
// int count; // int count;
// for (count = 0; count < dataLen; count++) { // for (count = 0; count < dataLen; count++) {
// printf("%02X", b[count]); // printf("%02X", b[count]);
@ -1722,6 +1781,8 @@ void get_tlm_fox() {
// socket write // socket write
socket_send(ctr);
/*
if (!socket_open && transmit) { if (!socket_open && transmit) {
printf("Opening socket!\n"); printf("Opening socket!\n");
// struct sockaddr_in address; // struct sockaddr_in address;
@ -1810,6 +1871,7 @@ void get_tlm_fox() {
sock_ret = send(sock, &buffer[sock_ret], (unsigned int)(ctr * 2 + 2 - sock_ret), 0); sock_ret = send(sock, &buffer[sock_ret], (unsigned int)(ctr * 2 + 2 - sock_ret), 0);
// printf("socket send 2 %d ms bytes: %d \n\n", millis() - start, sock_ret); // printf("socket send 2 %d ms bytes: %d \n\n", millis() - start, sock_ret);
} }
*/
loop_count++; loop_count++;
if ((firstTime == 1) || (((loop_count % 180) == 0) && (mode == FSK)) || (((loop_count % 80) == 0) && (mode == BPSK))) // do first time and was every 180 samples if ((firstTime == 1) || (((loop_count % 180) == 0) && (mode == FSK)) || (((loop_count % 80) == 0) && (mode == BPSK))) // do first time and was every 180 samples
@ -1830,41 +1892,42 @@ void get_tlm_fox() {
for (int times = 0; times < max; times++) for (int times = 0; times < max; times++)
{ {
start = millis(); // send frame until buffer fills /// start = millis(); // send frame until buffer fills
sock_ret = send(sock, buffer, (unsigned int)(ctr * 2 + 2), 0); socket_send(ctr);
/// sock_ret = send(sock, buffer, (unsigned int)(ctr * 2 + 2), 0);
// printf("socket send %d in %d ms bytes: %d \n\n",times + 2, (unsigned int)millis() - start, sock_ret); // printf("socket send %d in %d ms bytes: %d \n\n",times + 2, (unsigned int)millis() - start, sock_ret);
if ((millis() - start) > 500) { /// if ((millis() - start) > 500) {
printf("Buffer over filled!\n"); /// printf("Buffer over filled!\n");
break; /// break;
} /// }
if (sock_ret < (ctr * 2 + 2)) { /// if (sock_ret < (ctr * 2 + 2)) {
// printf("Not resending\n"); // printf("Not resending\n");
sleep(0.5); /// sleep(0.5);
sock_ret = send(sock, &buffer[sock_ret], (unsigned int)(ctr * 2 + 2 - sock_ret), 0); /// sock_ret = send(sock, &buffer[sock_ret], (unsigned int)(ctr * 2 + 2 - sock_ret), 0);
printf("socket resend %d in %d ms bytes: %d \n\n",times, millis() - start, sock_ret); /// printf("socket resend %d in %d ms bytes: %d \n\n",times, millis() - start, sock_ret);
} /// }
} }
sampleTime = (unsigned int) millis(); // resetting time for sleeping sampleTime = (unsigned int) millis(); // resetting time for sleeping
fflush(stdout); // fflush(stdout);
// if (firstTime == 1) // if (firstTime == 1)
// max -= 1; // max -= 1;
} }
if (sock_ret == -1) { /// if (sock_ret == -1) {
printf("Error: %s \n", strerror(errno)); /// printf("Error: %s \n", strerror(errno));
socket_open = 0; /// socket_open = 0;
//transmitStatus = -1; //transmitStatus = -1;
} /// }
} /// }
if (!transmit) { if (!transmit) {
fprintf(stderr, "\nNo CubeSatSim Band Pass Filter detected. No transmissions after the CW ID.\n"); 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"); fprintf(stderr, " See http://cubesatsim.org/wiki for info about building a CubeSatSim\n\n");
} }
if (socket_open == 1) /// if (socket_open == 1)
firstTime = 0; /// firstTime = 0;
// else if (frames_sent > 0) //5) // else if (frames_sent > 0) //5)
// firstTime = 0; // firstTime = 0;
@ -1928,13 +1991,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]);
} }
@ -2205,6 +2271,7 @@ if (setting == ON) {
pclose(command); pclose(command);
fprintf(stderr,"Turning Safe Mode ON\n"); fprintf(stderr,"Turning Safe Mode ON\n");
fprintf(stderr,"Turning Battery saver mode ON\n"); fprintf(stderr,"Turning Battery saver mode ON\n");
battery_saver_mode = ON;
if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) { if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) {
command = popen("echo 'reboot due to turning ON Safe Mode!' | wall", "r"); command = popen("echo 'reboot due to turning ON Safe Mode!' | wall", "r");
pclose(command); pclose(command);
@ -2221,6 +2288,7 @@ if (setting == ON) {
FILE *command = popen("rm /home/pi/CubeSatSim/battery_saver", "r"); FILE *command = popen("rm /home/pi/CubeSatSim/battery_saver", "r");
pclose(command); pclose(command);
fprintf(stderr,"Turning Battery saver mode OFF\n"); fprintf(stderr,"Turning Battery saver mode OFF\n");
battery_saver_mode = OFF;
if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) { if ((mode == AFSK) || (mode == SSTV) || (mode == CW)) {
command = popen("echo 'reboot due to turning OFF Safe Mode!' | wall", "r"); command = popen("echo 'reboot due to turning OFF Safe Mode!' | wall", "r");
pclose(command); pclose(command);
@ -2238,3 +2306,400 @@ if (setting == ON) {
} }
return; return;
} }
void get_tlm_fc() { // FunCube Mode telemetry generation
//# define FC_EM
#define JY_1
/* create data, stream, and waveform buffers */
unsigned char source_bytes[256];
int byte_count = 256;
/* write telemetry into data buffer */
// printf("\nBLOCKSIZE = %d\n", BLOCKSIZE);
// printf("\nSYMPBLOCK = %d\n", SYMPBLOCK);
memset(source_bytes, 0x00, sizeof(source_bytes));
#ifdef FC_EM
source_bytes[0] = 0b00000001 ; // Sat Id is FunCube-EM
#endif
#ifdef JY_1
// source_bytes[0] = 0b11000001 ; // Sat Id is extended, Frame 2 (RT2 + WO2)
source_bytes[0] = 0xE0 | 0x20 | 0x00; // 1; // Sat Id is extended, Frame 34 (RT2 + IMG2)
source_bytes[0] = source_bytes[0] | ( 0x01 & (uint8_t)(sequence % 2)); // alternate last bit for RT1, RT2.
// source_bytes[1] = 0x08 ; // extended Nayify - works per code
source_bytes[1] = 0x10 ; // extended JY-1 - works, no documentation
int extended = 1;
// if (sequence > 10) {
if (image_file == NULL) {
image_file = fopen("/home/pi/CubeSatSim/image_file.bin", "r");
image_id++;
printf("Opening file image_file.bin for image_id: %d\n", image_id);
}
// }
int pos = FC_PAYLOAD + extended;
int value;
if (image_file != NULL) {
printf("Writing image data to payload\n");
while ((pos < 256) && ((value = getc(image_file)) != EOF)) {
source_bytes[pos++] = value;
// printf("%2x ", value);
}
if (value == EOF) {
image_file = NULL;
printf("End of file reached! Delete image_file.bin");
FILE * delete_image = popen("sudo rm /home/pi/CubeSatSim/image_file.bin", "r");
pclose(delete_image);
}
}
#endif
// printf("Volts: %f %f %f %f \n", voltage[map[BAT]], voltage[map[PLUS_X]] , voltage[map[PLUS_Y]], voltage[map[PLUS_Z]]);
// printf("AmpsPlus: %f %f %f %f \n", current[map[BAT]], current[map[PLUS_X]] , current[map[PLUS_Y]], current[map[PLUS_Z]]);
// printf("AmpsMinus: %f %f %f %f \n", current[map[BAT2]], current[map[MINUS_X]] , current[map[MINUS_Y]], current[map[MINUS_Z]]);
float xmax = (voltage[map[PLUS_X]] > voltage[map[MINUS_X]]) ? voltage[map[PLUS_X]] : voltage[map[MINUS_X]];
float ymax = (voltage[map[PLUS_Y]] > voltage[map[MINUS_Y]]) ? voltage[map[PLUS_Y]] : voltage[map[MINUS_Y]];
float zmax = (voltage[map[PLUS_Z]] > voltage[map[MINUS_Z]]) ? voltage[map[PLUS_Z]] : voltage[map[MINUS_Z]];
// printf("Vmax: %f %f %f \n", xmax, ymax, zmax);
uint16_t x = (uint16_t)(xmax * 1000) & 0x3fff; // 14 bits
uint16_t y = (uint16_t)(ymax * 1000) & 0x3fff;
uint16_t z = (uint16_t)(zmax * 1000) & 0x3fff;
uint16_t b = (uint16_t)(voltage[map[BAT]] * 1000) & 0x3fff;
uint16_t ix = (uint16_t)((current[map[PLUS_X]] + current[map[MINUS_X]])) & 0x3ff; // 10 bits
uint16_t iy = (uint16_t)((current[map[PLUS_Y]] + current[map[MINUS_Y]])) & 0x3ff;
uint16_t iz = (uint16_t)((current[map[PLUS_Z]] + current[map[MINUS_Z]])) & 0x3ff;
uint16_t ic = 0;
uint16_t ib = 0;
if (current[map[BAT]] < 0 )
ic = (uint16_t)(current[map[BAT]] * (-1)) & 0x3ff; // charging current
else
ib = (uint16_t)(current[map[BAT]]) & 0x3ff; // supplying current
// printf("X %x Y %x Z %x B %x\n", x, y, z, b);
// printf("iX %x iY %x iZ %x iB %x iC\n", ix, iy, iz, ib, ic);
#ifdef JY_1
source_bytes[extended + FC_EPS + 0] = 0xff & (x >> 6); // Vx
source_bytes[extended + FC_EPS + 1] = 0xfc & (x << 2);
source_bytes[extended + FC_EPS + 1] = source_bytes[extended + FC_EPS + 1] | (0x03 & (y >> 12));
source_bytes[extended + FC_EPS + 2] = 0xff & (y >> 2); // Vy
source_bytes[extended + FC_EPS + 3] = 0xf0 & (y << 4);
source_bytes[extended + FC_EPS + 3] = source_bytes[extended + FC_EPS + 3] | (0x0f & (z >> 10));
source_bytes[extended + FC_EPS + 4] = 0xff & (z >> 2); // Vz
source_bytes[extended + FC_EPS + 5] = 0xc0 & (z << 6);
source_bytes[extended + FC_EPS + 5] = source_bytes[extended + FC_EPS + 5] | (0x3f & (b >> 8));
source_bytes[extended + FC_EPS + 6] = 0xff & (b >> 0); // Vb
source_bytes[extended + FC_EPS + 7] = 0xff & (ix >> 2); // ix
source_bytes[extended + FC_EPS + 8] = 0xc0 & (iy << 6); // iy
source_bytes[extended + FC_EPS + 8] = source_bytes[extended + FC_EPS + 8] | (0x3f & (iy >> 4));
source_bytes[extended + FC_EPS + 9] = 0xf0 & (iy << 4);
source_bytes[extended + FC_EPS + 9] = source_bytes[extended + FC_EPS + 9] | (0x0f & (iz >> 6));
source_bytes[extended + FC_EPS + 10] = 0x3f & (iz << 2); // iz
source_bytes[extended + FC_EPS + 10] = source_bytes[extended + FC_EPS + 10] | (0x03 & (ic >> 8));
source_bytes[extended + FC_EPS + 11] = 0xff & (ic << 0); // ic battery charging curent
source_bytes[extended + FC_EPS + 12] = 0xff & (ib >> 2); // ib battery discharging current
source_bytes[extended + FC_EPS + 13] = 0xc0 & (ib << 6);
source_bytes[extended + FC_EPS + 13] = source_bytes[extended + FC_EPS + 13] | 0x3f & (((unsigned long int)reset_count) >> 2);
source_bytes[extended + FC_EPS + 14] = 0xff & (((unsigned long int)reset_count) << 6); // reset count
uint8_t temp = (int)(other[IHU_TEMP] + 0.5);
source_bytes[extended + FC_EPS + 17] = source_bytes[extended + FC_EPS + 17] | 0x3f & (temp >> 2); // cpu temp
source_bytes[extended + FC_EPS + 18] = 0xff & (temp << 6);
source_bytes[extended + 48] = 0x0c; // Antenna 1 and 2 deployed
source_bytes[extended + 49] = 0xff & ((unsigned long int)sequence >> 16); // sequence number
source_bytes[extended + 50] = 0xff & ((unsigned long int)sequence >> 8);
source_bytes[extended + 51] = 0xff & (unsigned long int)sequence++;
uint16_t groundCommandCount = 0;
FILE * command_count_file = fopen("/home/pi/CubeSatSim/command_count.txt", "r");
if (command_count_file != NULL) {
char count_string[10];
if ( (fgets(count_string, 10, command_count_file)) != NULL)
groundCommandCount = (uint16_t) atoi(count_string);
} else
printf("Error opening command_count.txt!\n");
fclose(command_count_file);
// source_bytes[extended + 52] = 0xfc & (groundCommandCount << 2); // command doesn't work
source_bytes[extended + 53] = 0x0f; // SW valid
source_bytes[extended + 54] = 0xe0; // SW valid
if ((ix + iy + iz) < 4)
source_bytes[extended + 54] = source_bytes[extended + 54] | 0x10; // eclipse
if (SafeMode == 1)
source_bytes[extended + 54] = source_bytes[extended + 54] | 0x08; // safe mode
#endif
#ifdef FC_EM
source_bytes[FC_EPS + 0] = 0xff & (((unsigned int)((voltage[map[PLUS_X]] + voltage[map[MINUS_X]]) * 1000) >> 8)); // mV
source_bytes[FC_EPS + 1] = 0xff & ((unsigned int)((voltage[map[PLUS_X]] + voltage[map[MINUS_X]]) * 1000));
source_bytes[FC_EPS + 2] = 0xff & (((unsigned int)((voltage[map[PLUS_Y]] + voltage[map[MINUS_Y]]) * 1000) >> 8)); // mV
source_bytes[FC_EPS + 3] = 0xff & ((unsigned int)((voltage[map[PLUS_Y]] + voltage[map[MINUS_Y]]) * 1000));
source_bytes[FC_EPS + 4] = 0xff & (((unsigned int)((voltage[map[PLUS_Z]] + voltage[map[MINUS_Z]]) * 1000) >> 8)); // mV
source_bytes[FC_EPS + 5] = 0xff & ((unsigned int)((voltage[map[PLUS_Z]] + voltage[map[MINUS_Z]]) * 1000));
unsigned int total_solar_current = (unsigned int) (current[map[PLUS_X]] + current[map[MINUS_X]]
+ current[map[PLUS_Y]] + current[map[MINUS_Y]]
+ current[map[PLUS_Z]] + current[map[MINUS_Z]]);
source_bytes[FC_EPS + 6] = 0xff & total_solar_current >> 8;
source_bytes[FC_EPS + 7] = 0xff & total_solar_current;
source_bytes[FC_EPS + 8] = 0xff & (((unsigned int)(voltage[map[BAT]] * 1000) >> 8)); // mV
source_bytes[FC_EPS + 9] = 0xff & ((unsigned int)(voltage[map[BAT]] * 1000));
source_bytes[FC_EPS + 10] = 0xff & (((unsigned int)(current[map[BAT]] * 1) >> 8)); // mA
source_bytes[FC_EPS + 11] = 0xff & ((unsigned int)(current[map[BAT]] * 1));
source_bytes[FC_EPS + 12] = 0xff & (((unsigned long int)reset_count >> 8));
source_bytes[FC_EPS + 13] = 0xff & ((unsigned long int)reset_count);
source_bytes[FC_SW + 0] = 0xff & ((unsigned long int)sequence >> 16); // Sequence number
source_bytes[FC_SW + 1] = 0xff & ((unsigned long int)sequence >> 8);
source_bytes[FC_SW + 2] = 0xff & (unsigned long int)sequence++;
#endif
/**/
printf("\nsource_bytes\n");
for (int i=0; i<256; i++)
printf("%x ", source_bytes[i]);
printf("\n\n");
/**/
/* convert data buffer into stream buffer */
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 */
int data;
int val;
int i;
ctr = 0;
int symbol = 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) {
symbol = i / samples - 1;
// if (i < 100) printf("symbol = %d\n",symbol);
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("symbol = %d\n",symbol);
// printf("\nctr = %d\n\n", ctr);
// socket_send((((headerLen + syncBits + dataLen) * samples) * 2) + 2);
socket_send(ctr);
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");
}
int startSleep = millis();
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);
}
void socket_send(int length) {
printf("Socket_send!\n");
int error = 0;
if (!socket_open && transmit) { // open socket if not open
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) * 2) + 2; // ctr * 2 + 2 like bpsk due to 2 bytes per sample.
length = length * 2 + 2; // convert from samples to bytes
// printf("length in bytes: %d\n", length);
if (!error && transmit) {
// 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);
}
// loop_count++;
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");
}
int startSleep = millis();
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);
*/
if (socket_open == 1)
firstTime = 0;
}

113
main.h

@ -13,6 +13,7 @@
#include <time.h> #include <time.h>
#include <math.h> #include <math.h>
//#include "TelemEncoding.h" //#include "TelemEncoding.h"
#include "codecAO40.h"
#include <sys/socket.h> #include <sys/socket.h>
#include <stdlib.h> #include <stdlib.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -52,6 +53,10 @@
#define XS2 21 #define XS2 21
#define XS3 22 #define XS3 22
#define SENSOR_FIELDS 26 #define SENSOR_FIELDS 26
#define FC_EPS 1
#define FC_BOB 25
#define FC_SW 50
#define FC_PAYLOAD 55
#define RSSI 0 #define RSSI 0
#define IHU_TEMP 2 #define IHU_TEMP 2
@ -76,6 +81,7 @@ float toAprsFormat(float input);
float rnd_float(double min, double max); float rnd_float(double min, double max);
void get_tlm(); void get_tlm();
void get_tlm_fox(); void get_tlm_fox();
void get_tlm_fc();
int encodeA(short int * b, int index, int val); int encodeA(short int * b, int index, int val);
int encodeB(short int * b, int index, int val); int encodeB(short int * b, int index, int val);
void config_x25(); void config_x25();
@ -86,7 +92,10 @@ 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);
void program_radio(); void program_radio();
void socket_send(int length);
int socket_open = 0; int socket_open = 0;
int sock = 0; int sock = 0;
@ -100,6 +109,9 @@ FILE * file1;
short int buffer[2336400]; // max size for 10 frames count of BPSK short int buffer[2336400]; // max size for 10 frames count of BPSK
FILE *sopen(const char *program); FILE *sopen(const char *program);
FILE *telem_file; FILE *telem_file;
long int sequence = 0;
int image_id = 0;
FILE *image_file;
#define S_RATE (48000) // (44100) #define S_RATE (48000) // (44100)
@ -108,6 +120,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
@ -203,3 +216,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,
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
} }
} }
printf("CubeSatSim v2.0 INA219 Voltage and Current Telemetry\n"); printf("CubeSatSim v2.1 INA219 Voltage and Current Telemetry\n");
map[MINUS_X] = MINUS_Y; map[MINUS_X] = MINUS_Y;
map[PLUS_Z] = MINUS_X; map[PLUS_Z] = MINUS_X;
map[MINUS_Y] = PLUS_Z; map[MINUS_Y] = PLUS_Z;

@ -3,13 +3,14 @@
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
from RPi.GPIO import output from RPi.GPIO import output
#import subprocess #import subprocess
#import time import time
from time import sleep from time import sleep
#import os #import os
import sys import sys
from os import system from os import system
from PIL import Image, ImageDraw, ImageFont, ImageColor from PIL import Image, ImageDraw, ImageFont, ImageColor
import serial import serial
import random
def battery_saver_check(): def battery_saver_check():
try: try:
@ -23,6 +24,14 @@ def battery_saver_check():
print("battery saver not activated") print("battery saver not activated")
# txc = True # txc = True
def blink(times):
powerPin = 16
for i in range(times):
GPIO.output(powerPin, 0) # blink two times
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
def increment_mode(): def increment_mode():
print("increment mode") print("increment mode")
powerPin = 16 powerPin = 16
@ -38,76 +47,26 @@ def increment_mode():
print(mode) print(mode)
if (mode == 'a'): if (mode == 'a'):
mode = 'f' mode = 'f'
GPIO.output(powerPin, 0) # blink two times blink(2)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(2.5) sleep(2.5)
elif (mode == 'f'): elif (mode == 'f'):
mode = 'b' mode = 'b'
GPIO.output(powerPin, 0) # blink three times blink(3)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(2.5) sleep(2.5)
elif (mode == 'b'): elif (mode == 'b'):
mode = 's' mode = 's'
GPIO.output(powerPin, 0) # blink four times blink(4)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(2.5) sleep(2.5)
elif (mode == 's'): elif (mode == 's'):
mode = 'm' mode = 'm'
GPIO.output(powerPin, 0) # blink five times blink(5)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1);
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(0.1)
GPIO.output(powerPin, 0)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(2.5) sleep(2.5)
else: else:
mode = 'a' mode = 'a'
GPIO.output(powerPin, 0) # blink one time blink(1)
sleep(0.1)
GPIO.output(powerPin, 1)
sleep(2.5) sleep(2.5)
try: try:
@ -135,8 +94,43 @@ def increment_mode():
except: except:
print("can't write to .mode file") print("can't write to .mode file")
def camera_photo():
system("sudo rm /home/pi/CubeSatSim/camera_out.jpg")
stored_image = False
try:
system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") # > /dev/null 2>&1")
f = open("/home/pi/CubeSatSim/camera_out.jpg")
f.close()
print("Photo taken")
except:
system("cp /home/pi/CubeSatSim/sstv//sstv_image_2_320_x_256.jpeg /home/pi/CubeSatSim/camera_out.jpg")
print("Using stored image")
stored_image = True
if (stored_image == False):
file='/home/pi/CubeSatSim/camera_out.jpg'
font1 = ImageFont.truetype('DejaVuSerif.ttf', 20)
font2 = ImageFont.truetype('DejaVuSerif-Bold.ttf', 16)
try:
filep = open("/home/pi/CubeSatSim/telem_string.txt")
telem_string = filep.readline()
except:
telem_string = ""
if (debug_mode == 1):
print("Can't read telem_string.txt")
print(telem_string)
print("CubeSatSim v2.0 transmit.py starting...") img = Image.open(file)
draw = ImageDraw.Draw(img)
# draw.text((10, 10), callsign, font=font2, fill='white')
# draw.text((120, 10), telem_string, font=font2, fill='white')
draw.text((12, 12), callsign, font=font1, fill='black')
draw.text((10, 10), callsign, font=font1, fill='white')
draw.text((122, 12), telem_string, font=font2, fill='black')
draw.text((120, 10), telem_string, font=font2, fill='white')
img.save(file)
print("CubeSatSim v2.1 transmit.py starting...")
pd = 21 pd = 21
ptt = 20 ptt = 20
@ -277,6 +271,7 @@ if __name__ == "__main__":
sq = '0' sq = '0'
tx = '434.9000' tx = '434.9000'
rx = '435.0000' rx = '435.0000'
txr = '144.9000'
try: try:
file = open("/home/pi/CubeSatSim/sim.cfg") file = open("/home/pi/CubeSatSim/sim.cfg")
@ -292,8 +287,13 @@ if __name__ == "__main__":
txf = float(config[6]) txf = float(config[6])
# print(txf) # print(txf)
# print( "{:.4f}".format(txf)) # print( "{:.4f}".format(txf))
if (mode == 'e'):
txr = txf - 290.0 # Cross Band Repeater mode transmit frequency in 2m band
tx = "{:.4f}".format(txr)
else:
tx = "{:.4f}".format(txf) tx = "{:.4f}".format(txf)
print(tx) print("Transmit frequency: ",tx)
if len(config) > 7: if len(config) > 7:
rxf = float(config[7]) rxf = float(config[7])
# print(rxf) # print(rxf)
@ -316,10 +316,10 @@ if __name__ == "__main__":
print print
# print(callsign) # print(callsign)
print(sq) print(sq)
if sq == '8': # if sq == '8':
print("squelch set to 8, no command input!") # print("squelch set to 8, no command input!")
no_command = True # no_command = True
else: # else:
no_command = False no_command = False
print(no_command) print(no_command)
except: except:
@ -355,6 +355,7 @@ if __name__ == "__main__":
card = "Headphones" # default using pcm audio output of Pi Zero card = "Headphones" # default using pcm audio output of Pi Zero
# card = "Device" # using USB sound card for audio output # card = "Device" # using USB sound card for audio output
if (mode != 'e'):
print("Programming FM module!\n"); print("Programming FM module!\n");
output(pd, 1) output(pd, 1)
output (ptt, 1) output (ptt, 1)
@ -383,7 +384,8 @@ 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):
if (((mode == 'a') or (mode == 'b') or (mode == 'f') or (mode == 's') or (mode == 'j')) and (command_tx == True) and (skip == False)) or ((mode == 'e') and (command_tx == True)):
# 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)
@ -397,13 +399,17 @@ if __name__ == "__main__":
# output (ptt, 1) # output (ptt, 1)
# output(pd, 0) # output(pd, 0)
# else: # else:
if (True): if (no_command):
if (debug_mode == 1): if (debug_mode == 1):
# system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f 434.9e3")
system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3") system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3")
else: else:
# system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f 434.9e3 > /dev/null 2>&1")
system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1") system("echo 'hi hi de " + callsign + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1")
else:
if (debug_mode == 1):
system("echo 'hi hi de " + callsign + " C" + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3")
else:
system("echo 'hi hi de " + callsign + " C" + "' > id.txt && gen_packets -M 20 /home/pi/CubeSatSim/id.txt -o /home/pi/CubeSatSim/morse.wav -r 48000 > /dev/null 2>&1 && cat /home/pi/CubeSatSim/morse.wav | csdr convert_i16_f | csdr gain_ff 7000 | csdr convert_f_samplerf 20833 | sudo /home/pi/rpitx/rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1")
output(txLed, txLedOff) output(txLed, txLedOff)
@ -580,32 +586,32 @@ if __name__ == "__main__":
print("image 2 did not load - copy from CubeSatSim/sstv directory") print("image 2 did not load - copy from CubeSatSim/sstv directory")
while 1: while 1:
# command_control_check() # command_control_check()
camera_photo()
system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") # > /dev/null 2>&1") ## system("raspistill -o /home/pi/CubeSatSim/camera_out.jpg -w 320 -h 256") # > /dev/null 2>&1")
print("Photo taken") ## print("Photo taken")
##
file='/home/pi/CubeSatSim/camera_out.jpg' ## file='/home/pi/CubeSatSim/camera_out.jpg'
font1 = ImageFont.truetype('DejaVuSerif.ttf', 20) ## font1 = ImageFont.truetype('DejaVuSerif.ttf', 20)
font2 = ImageFont.truetype('DejaVuSerif-Bold.ttf', 16) ## font2 = ImageFont.truetype('DejaVuSerif-Bold.ttf', 16)
##
try: ## try:
filep = open("/home/pi/CubeSatSim/telem_string.txt") ## filep = open("/home/pi/CubeSatSim/telem_string.txt")
telem_string = filep.readline() ## telem_string = filep.readline()
except: ## except:
telem_string = "" ## telem_string = ""
if (debug_mode == 1): ## if (debug_mode == 1):
print("Can't read telem_string.txt") ## print("Can't read telem_string.txt")
print(telem_string) ## print(telem_string)
##
img = Image.open(file) ## img = Image.open(file)
draw = ImageDraw.Draw(img) ## draw = ImageDraw.Draw(img)
# draw.text((10, 10), callsign, font=font2, fill='white') # draw.text((10, 10), callsign, font=font2, fill='white')
# draw.text((120, 10), telem_string, font=font2, fill='white') # draw.text((120, 10), telem_string, font=font2, fill='white')
draw.text((12, 12), callsign, font=font1, fill='black') ## draw.text((12, 12), callsign, font=font1, fill='black')
draw.text((10, 10), callsign, font=font1, fill='white') ## draw.text((10, 10), callsign, font=font1, fill='white')
draw.text((122, 12), telem_string, font=font2, fill='black') ## draw.text((122, 12), telem_string, font=font2, fill='black')
draw.text((120, 10), telem_string, font=font2, fill='white') ## draw.text((120, 10), telem_string, font=font2, fill='white')
img.save(file) ## img.save(file)
# command_control_check() # command_control_check()
@ -739,9 +745,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()
if (mode == 'b'):
print("BPSK") 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)
@ -753,7 +762,10 @@ if __name__ == "__main__":
# system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f 434.9e6 -t float &") # system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f 434.9e6 -t float &")
system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f " + tx + "e6 -t float &") system("sudo nc -l 8080 | csdr convert_i16_f | csdr fir_interpolate_cc 2 | csdr dsb_fc | csdr bandpass_fir_fft_cc 0.002 0.06 0.01 | csdr fastagc_ff | sudo /home/pi/rpitx/sendiq -i /dev/stdin -s 96000 -f " + tx + "e6 -t float &")
print("Turning LED on/off and listening for carrier") print("Turning LED on/off and listening for carrier")
image_id = random.randint(0, 255)
print("Initial image_id: " + str(image_id) + "\n")
while 1: while 1:
# print ("LED on")
output(txLed, txLedOff) output(txLed, txLedOff)
sleep(0.4) sleep(0.4)
# if (command_tx == False): # if (command_tx == False):
@ -768,45 +780,83 @@ if __name__ == "__main__":
output(txLed, txLedOn) output(txLed, txLedOn)
# print(txLed) # print(txLed)
# print(txLedOn) # print(txLedOn)
if (mode == 'b'):
sleep(4.2) sleep(4.2)
else: # FunCube mode image
for i in range(4):
# print("Checking image_file.bin")
try:
file = open("/home/pi/CubeSatSim/image_file.bin")
file.close()
# image_present = True
sleep(1.0)
except:
# image_present = False
# if (image_present == False):
start = time.perf_counter()
camera_photo()
system("/home/pi/ssdv/ssdv -e -n -i " + str(image_id) + " -q 3 -J /home/pi/CubeSatSim/camera_out.jpg /home/pi/CubeSatSim/image_file.bin")
print("image_id: " + str(image_id) + "\n")
image_id = ( image_id + 1 ) % 256
print("new image_id: " + str(image_id) + "\n")
elapsed_time = time.perf_counter() - start
print("Elapsed time: ")
print(elapsed_time)
if (elapsed_time < 9):
sleep(9 - time.perf_counter() + start)
# else:
sleep(0.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("Cross Band Repeater Mode")
print("Stopping command and control") # print("Stopping command and control")
system("sudo systemctl stop command") # system("sudo systemctl stop command")
print("turn on FM rx") print("turn on FM rx")
output(pd, 1) output(pd, 1)
output(ptt, 1) output(ptt, 1)
GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4 GPIO.setmode(GPIO.BCM) # added to make Tx LED work on Pi 4
GPIO.setup(txLed, GPIO.OUT) GPIO.setup(txLed, GPIO.OUT)
GPIO.setup(powerPin, GPIO.OUT) # GPIO.setup(powerPin, GPIO.OUT)
GPIO.setup(squelch, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## pull up in case pin is not connected GPIO.setup(squelch, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## pull up in case pin is not connected
GPIO.output(powerPin, 0) # GPIO.output(powerPin, 1) # was 0
# txf = float(tx) - 288.9
# print("Transmit frequency: ",txf)
if (command_tx != True):
print("Beacon mode off so no repeater transmission")
print("Ready to detect carrier")
while True: while True:
sleep(0.5) if (GPIO.input(squelch) == False) and (command_tx == True):
if (GPIO.input(squelch) == False):
print("Carrier detected, starting repeater") print("Carrier detected, starting repeater")
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)
output(txLed, txLedOn) output(txLed, txLedOn)
# system("arecord -D plughw:CARD=Device,DEV=0 | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &") # system("arecord -D plughw:CARD=Device,DEV=0 | csdr convert_i16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &")
## system("arecord -D plughw:CARD=Device,DEV=0 -f S16_LE -r 48000 -c 1 | csdr convert_s16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &") ## system("arecord -D plughw:CARD=Device,DEV=0 -f S16_LE -r 48000 -c 1 | csdr convert_s16_f | csdr gain_ff 14000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &")
system("sudo nc -l 8011 | csdr convert_i16_f | csdr gain_ff 16000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 &") system("sudo nc -l 8011 | csdr convert_i16_f | csdr gain_ff 16000 | csdr convert_f_samplerf 20833 | sudo rpitx -i- -m RF -f " + tx + "e3 > /dev/null 2>&1 &")
sleep(1) sleep(1)
system("sudo arecord -D plughw:CARD=Device,DEV=0 -r48000 -fS16_LE -c1 | nc localhost 8011 &") system("sudo arecord -D plughw:CARD=Device,DEV=0 -r48000 -fS16_LE -c1 | nc localhost 8011 &")
GPIO.output(powerPin, 1) GPIO.output(powerPin, 1)
sleep(0.5) sleep(0.5)
GPIO.output(powerPin, 0) # system("sudo arecord -D plughw:1 -r48000 -fS16_LE -c1 | nc localhost 8011 &")
system("sudo arecord -D shared_mic -r48000 -fS16_LE -c1 | nc localhost 8011 &")
# GPIO.output(powerPin, 1)
# sleep(0.5)
# GPIO.output(powerPin, 0)
while (GPIO.input(squelch) == False): while (GPIO.input(squelch) == False):
sleep(1) sleep(1)
print("No carrier detected, stopping repeater") print("No carrier detected, stopping repeater")
output(txLed, txLedOff) output(txLed, txLedOff)
system("sudo killall -9 arecord") system("sudo killall -9 arecord > /dev/null 2>&1")
system("sudo killall -9 nc") system("sudo killall -9 nc > /dev/null 2>&1")
system("sudo killall -9 rpitx") system("sudo killall -9 rpitx > /dev/null 2>&1")
print("Resetting audio") print("Resetting audio")
system("sudo /etc/init.d/alsa-utils stop") system("sudo /etc/init.d/alsa-utils stop")
system("sudo /etc/init.d/alsa-utils start") system("sudo /etc/init.d/alsa-utils start")
print("Finished resetting audio") print("Finished resetting audio")
print("Ready to detect carrier")
else: else:
print("FSK") print("FSK")
print("turn on FM rx") print("turn on FM rx")

@ -1,9 +1,21 @@
#!/bin/bash #!/bin/bash
echo -e "\nupdate script for CubeSatSim v2.0\n" echo -e "\nupdate script for CubeSatSim v2.1\n"
FLAG=0
checkout=0
if [ -z "$1" ] ; then
checkout=0
else
checkout=1
branch="$1"
echo -n "changing to branch "
echo $branch
FLAG=1
fi
if [ "$1" = "n" ] ; then if [ "$1" = "n" ] ; then
# if [ -z "$2" ] ; then
noreboot=1 noreboot=1
else else
noreboot=0 noreboot=0
@ -23,7 +35,7 @@ if [ "$1" = "u" ]; then
fi fi
sudo apt-get install -y python3-smbus # sudo apt-get install -y python3-smbus libusb-1.0
sudo sed -i 's/update.sh/update /g' /etc/motd sudo sed -i 's/update.sh/update /g' /etc/motd
@ -39,6 +51,11 @@ cd /home/pi/CubeSatSim
git pull --no-rebase > .updated git pull --no-rebase > .updated
if [ $checkout -eq 1 ]; then
git checkout $branch
git pull --no-rebase
fi
make debug make debug
FILE=/home/pi/CubeSatSim/command_tx FILE=/home/pi/CubeSatSim/command_tx
@ -57,8 +74,6 @@ else
echo "0\n" > /home/pi/CubeSatSim/command_count.txt echo "0\n" > /home/pi/CubeSatSim/command_count.txt
fi fi
FLAG=0
if [[ $(diff systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service) ]]; then if [[ $(diff systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service) ]]; then
echo "changed cubesatsim.service." echo "changed cubesatsim.service."
sudo cp /home/pi/CubeSatSim/systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service sudo cp /home/pi/CubeSatSim/systemd/cubesatsim.service /etc/systemd/system/cubesatsim.service
@ -104,6 +119,21 @@ else
FLAG=1 FLAG=1
fi fi
FILE=/etc/asound.conf
if [ -f "$FILE" ]; then
if [[ $(diff /home/pi/CubeSatSim/asound.conf /etc/asound.conf) ]]; then
echo "changed /etc/asound.conf."
sudo cp /home/pi/CubeSatSim/asound.conf /etc/asound.conf
FLAG=1
else
echo "no change to /etc/asound.conf."
fi
else
echo "creating /etc/asound.conf."
sudo cp /home/pi/CubeSatSim/asound.conf /etc/asound.conf
FLAG=1
fi
FILE=/home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg FILE=/home/pi/CubeSatSim/sstv_image_1_320_x_256.jpg
if [ ! -f "$FILE" ]; then if [ ! -f "$FILE" ]; then
echo "Copying SSTV image 1." echo "Copying SSTV image 1."
@ -213,10 +243,52 @@ if [ ! -d "/home/pi/WiringPi" ]; then
fi fi
cd /home/pi/pi-power-button if [ ! -d "/home/pi/ssdv" ]; then
echo "Installing SSDV for FunCube mode"
cd
git clone https://github.com/alanbjohnston/ssdv.git # install ssdv for FunCube images
cd ssdv
make
cd
FLAG=1
fi
if [ ! -d "/home/pi/fctelem" ]; then
echo "Installing fctelem binary v0.2 for FunCube mode"
cd
mkdir /home/pi/fctelem
mkdir /home/pi/fctelem/public_html
cd fctelem
wget https://github.com/alanbjohnston/go/releases/download/v0.2/fctelem.zip
unzip fctelem.zip
FLAG=1
elif [ ! -f "/home/pi/fctelem/v0.2" ]; then
echo "Updating fctelem binary to version v0.2 for FunCube mode"
cd
cd /home/pi/fctelem
sudo mv fctelem fctelem.bk
sudo mv fcdecode.conf fcdecode.conf.bk
sudo mv fctelem.zip fctelem.zip.1
wget https://github.com/alanbjohnston/go/releases/download/v0.2/fctelem.zip
unzip fctelem.zip
FLAG=1
fi
git checkout master if [ ! -f "/home/pi/fcdctl/fcdctl" ]; then
echo "Installing fcdctl to set FunCubeDongle Pro gain"
sudo rm /var/lib/dpkg/info/python3-pip.list
sudo apt install python3-pip --reinstall
sudo apt-get install -y python3-smbus libusb-1.0
cd
git clone https://github.com/csete/fcdctl.git
cd fcdctl
make fcdpp
fi
cd /home/pi/pi-power-button
# git checkout master
git pull --no-rebase > .updated_p git pull --no-rebase > .updated_p
@ -225,11 +297,12 @@ git checkout master
echo "updating pi-power-button." echo "updating pi-power-button."
git checkout 7-modes
script/install script/install
FLAG=1 FLAG=1
else else
echo "nothing to do for pi-power-button." echo "nothing to do for pi-power-button."
fi fi
@ -348,7 +421,7 @@ if [ "$noreboot" = "0" ] ; then
fi fi
else else
if [ $FLAG -eq 1 ]; then if [ $FLAG -eq 1 ]; then
echo "reboot needed for changes to take effect" echo "reboot needed for changes to take effect" | wall
fi fi
fi fi

Loading…
Cancel
Save

Powered by TurnKey Linux.