kopia lustrzana https://github.com/mikaelnousiainen/RS41ng
Porównaj commity
3 Commity
b8c88c87a2
...
23ef429eaa
Autor | SHA1 | Data |
---|---|---|
Stephen D | 23ef429eaa | |
Mikael Nousiainen | bcacf17098 | |
Stephen D | 6283d5461f |
12
README.md
12
README.md
|
@ -150,6 +150,16 @@ On an external Si5351 clock generator connected to the external I²C bus of the
|
||||||
* See [horus-gui installation and usage instructions](https://github.com/projecthorus/horusdemodlib/wiki/1.1-Horus-GUI-Reception-Guide-(Windows-Linux-OSX)) and [horusdemodlib](https://github.com/projecthorus/horusdemodlib) library that is responsible for demodulating the signal.
|
* See [horus-gui installation and usage instructions](https://github.com/projecthorus/horusdemodlib/wiki/1.1-Horus-GUI-Reception-Guide-(Windows-Linux-OSX)) and [horusdemodlib](https://github.com/projecthorus/horusdemodlib) library that is responsible for demodulating the signal.
|
||||||
* In order to use Horus 4FSK mode on a flight, you will need to request a new Horus 4FSK payload ID in GitHub according to the instructions at: https://github.com/projecthorus/horusdemodlib/wiki#how-do-i-transmit-it
|
* In order to use Horus 4FSK mode on a flight, you will need to request a new Horus 4FSK payload ID in GitHub according to the instructions at: https://github.com/projecthorus/horusdemodlib/wiki#how-do-i-transmit-it
|
||||||
|
|
||||||
|
#### Notes about CATS (DFM-17 only)
|
||||||
|
|
||||||
|
* CATS is a [modern packet radio standard](https://cats.radio/) designed for communication and telemetry. Due to its increased efficiency over APRS, it allows for fast beacon times (1 Hz or more) without congesting the network.
|
||||||
|
* To receive CATS, you can either use an [I-Gate board](https://www.tindie.com/products/hamcats/cats-i-gate-board/) on a Raspberry Pi, or just a standard RTL-SDR dongle.
|
||||||
|
* See [here](https://gitlab.scd31.com/cats/igate) for the I-Gate board software.
|
||||||
|
* See [here](https://gitlab.scd31.com/cats/sdr-igate) for the SDR software.
|
||||||
|
* In either case, CATS packets that are received get forwarded to FELINET, and relayed to APRS-IS. This means your CATS packets will show up on [aprs.fi](https://aprs.fi)
|
||||||
|
* If you're relying on APRS gating, be sure to set an SSID below 100 or the APRS network may reject it.
|
||||||
|
* For more information, be sure to check [the standard](https://gitlab.scd31.com/cats/cats-standard/-/blob/master/standard.pdf).
|
||||||
|
|
||||||
### External sensors (RS41 only)
|
### External sensors (RS41 only)
|
||||||
|
|
||||||
It is possible to connect external sensors to the I²C bus of the RS41 radiosonde.
|
It is possible to connect external sensors to the I²C bus of the RS41 radiosonde.
|
||||||
|
@ -607,6 +617,8 @@ rtl_fm -f 432500000 -M fm -s 250k -r 48000 -g 22 - | ./aprs -
|
||||||
* Various authors with smaller contributions from GitHub pull requests
|
* Various authors with smaller contributions from GitHub pull requests
|
||||||
* Original codebase: DF8OE and other authors of the [RS41HUP](https://github.com/df8oe/RS41HUP) project
|
* Original codebase: DF8OE and other authors of the [RS41HUP](https://github.com/df8oe/RS41HUP) project
|
||||||
* Horus 4FSK code adapted from [darksidelemm fork of RS41HUP](https://github.com/darksidelemm/RS41HUP) project
|
* Horus 4FSK code adapted from [darksidelemm fork of RS41HUP](https://github.com/darksidelemm/RS41HUP) project
|
||||||
|
* CATS code adapted from [CATS reference implementation](https://gitlab.scd31.com/cats/ham-cats/)
|
||||||
|
* LDPC encoder adapted from [libCATS](https://github.com/CamK06/libCATS)
|
||||||
|
|
||||||
# Additional documentation
|
# Additional documentation
|
||||||
|
|
||||||
|
|
|
@ -11,34 +11,41 @@
|
||||||
|
|
||||||
cats_ldpc_code_t *cats_ldpc_pick_code(int len)
|
cats_ldpc_code_t *cats_ldpc_pick_code(int len)
|
||||||
{
|
{
|
||||||
if(128 <= len)
|
if(len >= 128) {
|
||||||
return &tm2048;
|
return &tm2048;
|
||||||
else if(32 <= len)
|
}
|
||||||
|
else if(len >= 32) {
|
||||||
return &tc512;
|
return &tc512;
|
||||||
else if(16 <= len)
|
}
|
||||||
|
else if(len >= 16) {
|
||||||
return &tc256;
|
return &tc256;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return &tc128;
|
return &tc128;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For more information on this, see the CATS standard
|
||||||
|
// https://gitlab.scd31.com/cats/cats-standard
|
||||||
|
// Section 5.2
|
||||||
// returns # of bytes written to parity_out
|
// returns # of bytes written to parity_out
|
||||||
size_t cats_ldpc_encode_chunk(uint8_t *data, cats_ldpc_code_t *code, uint8_t *parity_out)
|
size_t cats_ldpc_encode_chunk(uint8_t *data, cats_ldpc_code_t *code, uint8_t *parity_out)
|
||||||
{
|
{
|
||||||
// Code parameters
|
// Code parameters
|
||||||
int k = code->k;
|
int data_length_bits = code->data_length_bits;
|
||||||
int r = code->n - code->k;
|
int parity_length_bits = code->code_length_bits - code->data_length_bits;
|
||||||
int b = code->circulant_size;
|
int circ_size = code->circulant_size;
|
||||||
const uint64_t* gc = code->matrix;
|
const uint64_t* gc = code->matrix;
|
||||||
int rowLen = r/64;
|
int row_len = parity_length_bits / 64;
|
||||||
|
|
||||||
memset(parity_out, 0x00, (code->k)/8);
|
memset(parity_out, 0x00, parity_length_bits / 8);
|
||||||
|
|
||||||
for (int offset = 0; offset < b; offset++) {
|
for (int offset = 0; offset < circ_size; offset++) {
|
||||||
for (int crow = 0; crow < k/b; crow++) {
|
for (int crow = 0; crow < data_length_bits / circ_size; crow++) {
|
||||||
int bit = crow*b + offset;
|
int bit = crow * circ_size + offset;
|
||||||
if(GET_BIT(data[bit / 8], bit % 8)) {
|
if(GET_BIT(data[bit / 8], bit % 8)) {
|
||||||
for (int idx = 0; idx < rowLen; idx++) {
|
for (int idx = 0; idx < row_len; idx++) {
|
||||||
uint64_t circ = gc[(crow*rowLen)+idx];
|
uint64_t circ = gc[(crow * row_len) + idx];
|
||||||
for(int j = 0; j < 8; j++) {
|
for(int j = 0; j < 8; j++) {
|
||||||
parity_out[idx*8 + j] ^= (uint8_t)(circ >> ((7 - j) * 8));
|
parity_out[idx*8 + j] ^= (uint8_t)(circ >> ((7 - j) * 8));
|
||||||
}
|
}
|
||||||
|
@ -46,10 +53,10 @@ size_t cats_ldpc_encode_chunk(uint8_t *data, cats_ldpc_code_t *code, uint8_t *pa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int block = 0; block < r/b; block++) {
|
for (int block = 0; block < parity_length_bits / circ_size; block++) {
|
||||||
uint8_t* parityblock = &parity_out[block*b/8];
|
uint8_t* parityblock = &parity_out[block * circ_size / 8];
|
||||||
uint8_t carry = parityblock[0] >> 7;
|
uint8_t carry = parityblock[0] >> 7;
|
||||||
for (int x = (b/8)-1; x >= 0; x--) {
|
for (int x = (circ_size / 8)-1; x >= 0; x--) {
|
||||||
uint8_t c = parityblock[x] >> 7;
|
uint8_t c = parityblock[x] >> 7;
|
||||||
parityblock[x] = (parityblock[x] << 1) | carry;
|
parityblock[x] = (parityblock[x] << 1) | carry;
|
||||||
carry = c;
|
carry = c;
|
||||||
|
@ -57,7 +64,7 @@ size_t cats_ldpc_encode_chunk(uint8_t *data, cats_ldpc_code_t *code, uint8_t *pa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return k / 8;
|
return parity_length_bits / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cats_ldpc_encode(uint8_t *data, size_t len)
|
size_t cats_ldpc_encode(uint8_t *data, size_t len)
|
||||||
|
@ -66,17 +73,19 @@ size_t cats_ldpc_encode(uint8_t *data, size_t len)
|
||||||
// This means we can only encode up to 511 bytes
|
// This means we can only encode up to 511 bytes
|
||||||
assert(len < 512);
|
assert(len < 512);
|
||||||
|
|
||||||
|
// A 128 byte array is needed to support CATS packets up to 511 bytes.
|
||||||
uint8_t parity[128];
|
uint8_t parity[128];
|
||||||
|
|
||||||
// Split data into blocks and encode each block
|
// Split data into blocks and encode each block
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i < len) {
|
while(i < len) {
|
||||||
cats_ldpc_code_t *code = cats_ldpc_pick_code(len - i);
|
cats_ldpc_code_t *code = cats_ldpc_pick_code(len - i);
|
||||||
int k = code->k;
|
int data_length_bits = code->data_length_bits;
|
||||||
|
int data_length = data_length_bits / 8;
|
||||||
|
|
||||||
uint8_t chunk[code->n / 8];
|
uint8_t chunk[code->code_length_bits / 8];
|
||||||
memset(chunk, 0xAA, k/8);
|
memset(chunk, 0xAA, data_length);
|
||||||
memcpy(chunk, data + i, (len-i < k/8) ? (len-i) : (k/8));
|
memcpy(chunk, data + i, (len-i < data_length) ? (len - i) : data_length);
|
||||||
|
|
||||||
size_t parity_len = cats_ldpc_encode_chunk(chunk, code, parity);
|
size_t parity_len = cats_ldpc_encode_chunk(chunk, code, parity);
|
||||||
memcpy(data + len + i, parity, parity_len); // Parity
|
memcpy(data + len + i, parity, parity_len); // Parity
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include "ldpc_matrices.h"
|
#include "ldpc_matrices.h"
|
||||||
|
|
||||||
cats_ldpc_code_t tc128 = {
|
cats_ldpc_code_t tc128 = {
|
||||||
.n = 128,
|
.code_length_bits = 128,
|
||||||
.k = 64,
|
.data_length_bits = 64,
|
||||||
.punctured_bits = 0,
|
.punctured_bits = 0,
|
||||||
.bf_working_len = 128 + 0,
|
.bf_working_len = 128 + 0,
|
||||||
.circulant_size = 128/8,
|
.circulant_size = 128/8,
|
||||||
|
@ -14,8 +14,8 @@ cats_ldpc_code_t tc128 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
cats_ldpc_code_t tc256 = {
|
cats_ldpc_code_t tc256 = {
|
||||||
.n = 256,
|
.code_length_bits = 256,
|
||||||
.k = 128,
|
.data_length_bits = 128,
|
||||||
.punctured_bits = 0,
|
.punctured_bits = 0,
|
||||||
.bf_working_len = 256 + 0,
|
.bf_working_len = 256 + 0,
|
||||||
.circulant_size = 256/8,
|
.circulant_size = 256/8,
|
||||||
|
@ -24,8 +24,8 @@ cats_ldpc_code_t tc256 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
cats_ldpc_code_t tc512 = {
|
cats_ldpc_code_t tc512 = {
|
||||||
.n = 512,
|
.code_length_bits = 512,
|
||||||
.k = 256,
|
.data_length_bits = 256,
|
||||||
.punctured_bits = 0,
|
.punctured_bits = 0,
|
||||||
.bf_working_len = 512 + 0,
|
.bf_working_len = 512 + 0,
|
||||||
.circulant_size = 512/8,
|
.circulant_size = 512/8,
|
||||||
|
@ -34,8 +34,8 @@ cats_ldpc_code_t tc512 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
cats_ldpc_code_t tm2048 = {
|
cats_ldpc_code_t tm2048 = {
|
||||||
.n = 2048,
|
.code_length_bits = 2048,
|
||||||
.k = 1024,
|
.data_length_bits = 1024,
|
||||||
.punctured_bits = 512,
|
.punctured_bits = 512,
|
||||||
.bf_working_len = 2048 + 512,
|
.bf_working_len = 2048 + 512,
|
||||||
.circulant_size = 512/4,
|
.circulant_size = 512/4,
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#define __CATS_LDPC_MATRICES_H
|
#define __CATS_LDPC_MATRICES_H
|
||||||
|
|
||||||
typedef struct cats_ldpc_code {
|
typedef struct cats_ldpc_code {
|
||||||
// Code length (data+parity)
|
// Code length in bits (data+parity)
|
||||||
int n;
|
int code_length_bits;
|
||||||
// Data length in bits
|
// Data length in bits
|
||||||
int k;
|
int data_length_bits;
|
||||||
int punctured_bits;
|
int punctured_bits;
|
||||||
int bf_working_len;
|
int bf_working_len;
|
||||||
size_t circulant_size;
|
size_t circulant_size;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "whisker.h"
|
#include "whisker.h"
|
||||||
|
|
||||||
|
// Hardware IDs defined here: https://cats.radio/pages/hardware-ids.html
|
||||||
|
// It's just a way to tell where CATS packets come from. It doesn't affect anything beyond this
|
||||||
#ifdef RS41
|
#ifdef RS41
|
||||||
#define HARDWARE_ID 0x7d00
|
#define HARDWARE_ID 0x7d00
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,6 +12,24 @@
|
||||||
#define HARDWARE_ID 0x7d01
|
#define HARDWARE_ID 0x7d01
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CATS_IDENT_TYPE 0x00
|
||||||
|
#define CATS_GPS_TYPE 0x02
|
||||||
|
#define CATS_COMMENT_TYPE 0x03
|
||||||
|
#define CATS_NODE_INFO_TYPE 0x09
|
||||||
|
|
||||||
|
#define CATS_NODE_INFO_HARDWARE_ID_PRESENT 1
|
||||||
|
#define CATS_NODE_INFO_SOFTWARE_ID_PRESENT 2
|
||||||
|
#define CATS_NODE_INFO_ANTENNA_GAIN_PRESENT 16
|
||||||
|
#define CATS_NODE_INFO_TX_POWER_PRESENT 32
|
||||||
|
#define CATS_NODE_INFO_VOLTAGE_PRESENT 64
|
||||||
|
#define CATS_NODE_INFO_TX_TEMP_PRESENT 128
|
||||||
|
|
||||||
|
// corresponds to (21 / 4 = 5.25) dBi antenna gain
|
||||||
|
#define CATS_ANTENNA_GAIN 21
|
||||||
|
|
||||||
|
// Software IDs are basically just a version number.
|
||||||
|
// Can increment this whenever something big changes, and then
|
||||||
|
// you can track what version of your software is being used on CATS
|
||||||
#define SOFTWARE_ID 0x00
|
#define SOFTWARE_ID 0x00
|
||||||
|
|
||||||
static inline void cats_push_f16(cats_packet *p, float val)
|
static inline void cats_push_f16(cats_packet *p, float val)
|
||||||
|
@ -64,7 +84,7 @@ static inline void cats_push_u32(cats_packet *p, uint32_t val)
|
||||||
|
|
||||||
void cats_append_identification_whisker(cats_packet *packet, char *callsign, uint8_t ssid, uint16_t icon)
|
void cats_append_identification_whisker(cats_packet *packet, char *callsign, uint8_t ssid, uint16_t icon)
|
||||||
{
|
{
|
||||||
packet->data[packet->len++] = 0x00; // type = identidication
|
packet->data[packet->len++] = CATS_IDENT_TYPE;
|
||||||
size_t callsign_len = strlen(callsign);
|
size_t callsign_len = strlen(callsign);
|
||||||
packet->data[packet->len++] = callsign_len + 3; // len
|
packet->data[packet->len++] = callsign_len + 3; // len
|
||||||
packet->data[packet->len++] = icon & 0xFF; // icon
|
packet->data[packet->len++] = icon & 0xFF; // icon
|
||||||
|
@ -76,7 +96,7 @@ void cats_append_identification_whisker(cats_packet *packet, char *callsign, uin
|
||||||
|
|
||||||
void cats_append_gps_whisker(cats_packet *packet, gps_data gps)
|
void cats_append_gps_whisker(cats_packet *packet, gps_data gps)
|
||||||
{
|
{
|
||||||
packet->data[packet->len++] = 0x02; // type = gps
|
packet->data[packet->len++] = CATS_GPS_TYPE;
|
||||||
packet->data[packet->len++] = 14; // len
|
packet->data[packet->len++] = 14; // len
|
||||||
int32_t lat_converted = gps.latitude_degrees_1000000 * (1LL<<31) / 90LL / 10000000LL;
|
int32_t lat_converted = gps.latitude_degrees_1000000 * (1LL<<31) / 90LL / 10000000LL;
|
||||||
int32_t lon_converted = gps.longitude_degrees_1000000 * (1LL<<31) / 180LL / 10000000LL;
|
int32_t lon_converted = gps.longitude_degrees_1000000 * (1LL<<31) / 180LL / 10000000LL;
|
||||||
|
@ -90,7 +110,7 @@ void cats_append_gps_whisker(cats_packet *packet, gps_data gps)
|
||||||
|
|
||||||
void cats_append_comment_whisker(cats_packet *packet, char *comment)
|
void cats_append_comment_whisker(cats_packet *packet, char *comment)
|
||||||
{
|
{
|
||||||
packet->data[packet->len++] = 0x03; // type = comment
|
packet->data[packet->len++] = CATS_COMMENT_TYPE;
|
||||||
size_t comment_len = strlen(comment);
|
size_t comment_len = strlen(comment);
|
||||||
assert(comment_len <= 255);
|
assert(comment_len <= 255);
|
||||||
packet->data[packet->len++] = comment_len;
|
packet->data[packet->len++] = comment_len;
|
||||||
|
@ -106,16 +126,22 @@ void cats_append_node_info_whisker(cats_packet *packet, telemetry_data *data)
|
||||||
bool has_altitude = GPS_HAS_FIX(data->gps);
|
bool has_altitude = GPS_HAS_FIX(data->gps);
|
||||||
float altitude = data->gps.altitude_mm / 1000.0;
|
float altitude = data->gps.altitude_mm / 1000.0;
|
||||||
|
|
||||||
d[(*l)++] = 0x09; // type = node info
|
d[(*l)++] = CATS_NODE_INFO_TYPE;
|
||||||
d[(*l)++] = has_altitude ? 14 : 10; // len
|
d[(*l)++] = has_altitude ? 14 : 10; // len
|
||||||
// bitmask
|
// bitmask
|
||||||
d[(*l)++] = 0;
|
d[(*l)++] = 0;
|
||||||
d[(*l)++] = (CATS_IS_BALLOON << 2) | (has_altitude << 1);
|
d[(*l)++] = (CATS_IS_BALLOON << 2) | (has_altitude << 1);
|
||||||
d[(*l)++] = 0b11110011;
|
d[(*l)++] =
|
||||||
|
CATS_NODE_INFO_HARDWARE_ID_PRESENT |
|
||||||
|
CATS_NODE_INFO_SOFTWARE_ID_PRESENT |
|
||||||
|
CATS_NODE_INFO_ANTENNA_GAIN_PRESENT |
|
||||||
|
CATS_NODE_INFO_TX_POWER_PRESENT |
|
||||||
|
CATS_NODE_INFO_VOLTAGE_PRESENT |
|
||||||
|
CATS_NODE_INFO_TX_TEMP_PRESENT;
|
||||||
|
|
||||||
cats_push_u16(packet, HARDWARE_ID);
|
cats_push_u16(packet, HARDWARE_ID);
|
||||||
d[(*l)++] = SOFTWARE_ID;
|
d[(*l)++] = SOFTWARE_ID;
|
||||||
d[(*l)++] = 21; // vertical antenna -> ~5.25 dBi gain
|
d[(*l)++] = CATS_ANTENNA_GAIN; // vertical antenna -> ~5.25 dBi gain
|
||||||
d[(*l)++] = CATS_REPORTED_TX_POWER_DBM * 4.0; // TX power
|
d[(*l)++] = CATS_REPORTED_TX_POWER_DBM * 4.0; // TX power
|
||||||
d[(*l)++] = data->battery_voltage_millivolts / 100; // voltage
|
d[(*l)++] = data->battery_voltage_millivolts / 100; // voltage
|
||||||
d[(*l)++] = data->internal_temperature_celsius_100 / 100; // transmitter temperature
|
d[(*l)++] = data->internal_temperature_celsius_100 / 100; // transmitter temperature
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "fifo.h"
|
|
||||||
|
|
||||||
typedef struct _fifo_encoder {
|
|
||||||
uint8_t *data;
|
|
||||||
uint16_t len;
|
|
||||||
} fifo_encoder;
|
|
||||||
|
|
||||||
void fifo_encoder_new(fsk_encoder *encoder)
|
|
||||||
{
|
|
||||||
encoder->priv = malloc(sizeof(fifo_encoder));
|
|
||||||
}
|
|
||||||
|
|
||||||
void fifo_encoder_destroy(fsk_encoder *encoder)
|
|
||||||
{
|
|
||||||
if (encoder->priv != NULL) {
|
|
||||||
free(encoder->priv);
|
|
||||||
encoder->priv = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void fifo_encoder_set_data(fsk_encoder *encoder, uint16_t data_length, uint8_t *data)
|
|
||||||
{
|
|
||||||
fifo_encoder *fifo = (fifo_encoder *) encoder->priv;
|
|
||||||
fifo->data = data;
|
|
||||||
fifo->len = data_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *fifo_encoder_get_data(fsk_encoder *encoder)
|
|
||||||
{
|
|
||||||
fifo_encoder *fifo = (fifo_encoder *) encoder->priv;
|
|
||||||
return fifo->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t fifo_encoder_get_data_len(fsk_encoder *encoder)
|
|
||||||
{
|
|
||||||
fifo_encoder *fifo = (fifo_encoder *) encoder->priv;
|
|
||||||
return fifo->len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fsk_encoder_api fifo_fsk_encoder_api = {
|
|
||||||
.set_data = fifo_encoder_set_data,
|
|
||||||
.get_data = fifo_encoder_get_data,
|
|
||||||
.get_data_len = fifo_encoder_get_data_len,
|
|
||||||
};
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef __FIFO_H
|
|
||||||
#define __FIFO_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "codecs/fsk/fsk.h"
|
|
||||||
|
|
||||||
void fifo_encoder_new(fsk_encoder *encoder);
|
|
||||||
void fifo_encoder_destroy(fsk_encoder *encoder);
|
|
||||||
|
|
||||||
extern fsk_encoder_api fifo_fsk_encoder_api;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "raw.h"
|
||||||
|
|
||||||
|
typedef struct _raw_encoder {
|
||||||
|
uint8_t *data;
|
||||||
|
uint16_t len;
|
||||||
|
} raw_encoder;
|
||||||
|
|
||||||
|
void raw_encoder_new(fsk_encoder *encoder)
|
||||||
|
{
|
||||||
|
encoder->priv = malloc(sizeof(raw_encoder));
|
||||||
|
}
|
||||||
|
|
||||||
|
void raw_encoder_destroy(fsk_encoder *encoder)
|
||||||
|
{
|
||||||
|
if (encoder->priv != NULL) {
|
||||||
|
free(encoder->priv);
|
||||||
|
encoder->priv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void raw_encoder_set_data(fsk_encoder *encoder, uint16_t data_length, uint8_t *data)
|
||||||
|
{
|
||||||
|
raw_encoder *raw = (raw_encoder *) encoder->priv;
|
||||||
|
raw->data = data;
|
||||||
|
raw->len = data_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *raw_encoder_get_data(fsk_encoder *encoder)
|
||||||
|
{
|
||||||
|
raw_encoder *raw = (raw_encoder *) encoder->priv;
|
||||||
|
return raw->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t raw_encoder_get_data_len(fsk_encoder *encoder)
|
||||||
|
{
|
||||||
|
raw_encoder *raw = (raw_encoder *) encoder->priv;
|
||||||
|
return raw->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsk_encoder_api raw_fsk_encoder_api = {
|
||||||
|
.set_data = raw_encoder_set_data,
|
||||||
|
.get_data = raw_encoder_get_data,
|
||||||
|
.get_data_len = raw_encoder_get_data_len,
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef __RAW_H
|
||||||
|
#define __RAW_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "codecs/fsk/fsk.h"
|
||||||
|
|
||||||
|
void raw_encoder_new(fsk_encoder *encoder);
|
||||||
|
void raw_encoder_destroy(fsk_encoder *encoder);
|
||||||
|
|
||||||
|
extern fsk_encoder_api raw_fsk_encoder_api;
|
||||||
|
|
||||||
|
#endif
|
|
@ -341,9 +341,15 @@
|
||||||
/**
|
/**
|
||||||
* CATS mode settings
|
* CATS mode settings
|
||||||
*/
|
*/
|
||||||
|
// CATS is a new digital mode, vaguely meant to be a better APRS (but also much more powerful)
|
||||||
|
// While it offers a number of advantages, probably the best one for balloons is the rapid beacon rate.
|
||||||
|
// The protocol is meant to allow for a much higher channel capacity, so beaconing every second is totally fine.
|
||||||
|
// For more information, see here: https://cats.radio/
|
||||||
#define CATS_CALLSIGN CALLSIGN
|
#define CATS_CALLSIGN CALLSIGN
|
||||||
#define CATS_SSID 29 // 0 - 255
|
#define CATS_SSID 29 // 0 - 255
|
||||||
#define CATS_ICON 13 // Balloon. See the CATS standard for more options
|
// Balloon. See the CATS standard for more options
|
||||||
|
// https://gitlab.scd31.com/cats/cats-standard/-/blob/master/standard.pdf
|
||||||
|
#define CATS_ICON 13
|
||||||
#define CATS_COMMENT "I am a radiosonde. Hear me meow!"
|
#define CATS_COMMENT "I am a radiosonde. Hear me meow!"
|
||||||
#define CATS_REPORTED_TX_POWER_DBM 20
|
#define CATS_REPORTED_TX_POWER_DBM 20
|
||||||
// You probably want this to be true
|
// You probably want this to be true
|
||||||
|
|
|
@ -227,6 +227,9 @@ void si4063_disable_tx()
|
||||||
// If less than len, remaining bytes will need to be used to top up the buffer
|
// If less than len, remaining bytes will need to be used to top up the buffer
|
||||||
uint16_t si4063_start_tx(uint8_t *data, int len)
|
uint16_t si4063_start_tx(uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
|
// Clear fifo underflow interrupt
|
||||||
|
si4063_fifo_underflow();
|
||||||
|
|
||||||
// Clear TX FIFO
|
// Clear TX FIFO
|
||||||
uint8_t fifo_clear_data[] = {1};
|
uint8_t fifo_clear_data[] = {1};
|
||||||
si4063_send_command(SI4063_COMMAND_FIFO_INFO, 1, fifo_clear_data);
|
si4063_send_command(SI4063_COMMAND_FIFO_INFO, 1, fifo_clear_data);
|
||||||
|
@ -336,6 +339,7 @@ static int si4063_get_band(const uint32_t frequency_hz)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also clears status
|
||||||
bool si4063_fifo_underflow()
|
bool si4063_fifo_underflow()
|
||||||
{
|
{
|
||||||
uint8_t data[] = {0xFF, 0xFF, ~0x20}; // Clear underflow status
|
uint8_t data[] = {0xFF, 0xFF, ~0x20}; // Clear underflow status
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __DELAY_H
|
#ifndef __DELAY_H
|
||||||
#define __DELAY_H
|
#define __DELAY_H
|
||||||
|
|
||||||
#include <stm32f10x.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
10
src/radio.c
10
src/radio.c
|
@ -10,7 +10,7 @@
|
||||||
#include "codecs/morse/morse.h"
|
#include "codecs/morse/morse.h"
|
||||||
#include "codecs/bell/bell.h"
|
#include "codecs/bell/bell.h"
|
||||||
#include "codecs/mfsk/mfsk.h"
|
#include "codecs/mfsk/mfsk.h"
|
||||||
#include "codecs/fifo/fifo.h"
|
#include "codecs/raw/raw.h"
|
||||||
#include "codecs/jtencode/jtencode.h"
|
#include "codecs/jtencode/jtencode.h"
|
||||||
#include "drivers/ubxg6010/ubxg6010.h"
|
#include "drivers/ubxg6010/ubxg6010.h"
|
||||||
#include "radio_internal.h"
|
#include "radio_internal.h"
|
||||||
|
@ -304,13 +304,13 @@ radio_transmit_entry radio_transmit_schedule[] = {
|
||||||
.enabled = RADIO_SI4063_TX_CATS,
|
.enabled = RADIO_SI4063_TX_CATS,
|
||||||
.radio_type = RADIO_TYPE_SI4063,
|
.radio_type = RADIO_TYPE_SI4063,
|
||||||
.data_mode = RADIO_DATA_MODE_CATS,
|
.data_mode = RADIO_DATA_MODE_CATS,
|
||||||
.transmit_count = RADIO_SI4063_TX_CATS,
|
.transmit_count = RADIO_SI4063_TX_CATS_COUNT,
|
||||||
.time_sync_seconds = CATS_TIME_SYNC_SECONDS,
|
.time_sync_seconds = CATS_TIME_SYNC_SECONDS,
|
||||||
.time_sync_seconds_offset = CATS_TIME_SYNC_OFFSET_SECONDS,
|
.time_sync_seconds_offset = CATS_TIME_SYNC_OFFSET_SECONDS,
|
||||||
.frequency = RADIO_SI4063_TX_FREQUENCY_CATS,
|
.frequency = RADIO_SI4063_TX_FREQUENCY_CATS,
|
||||||
.tx_power = RADIO_SI4063_TX_POWER,
|
.tx_power = RADIO_SI4063_TX_POWER,
|
||||||
.payload_encoder = &radio_cats_payload_encoder,
|
.payload_encoder = &radio_cats_payload_encoder,
|
||||||
.fsk_encoder_api = &fifo_fsk_encoder_api,
|
.fsk_encoder_api = &raw_fsk_encoder_api,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -639,7 +639,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
|
||||||
case RADIO_DATA_MODE_CATS:
|
case RADIO_DATA_MODE_CATS:
|
||||||
enable_gps_during_transmit = true;
|
enable_gps_during_transmit = true;
|
||||||
|
|
||||||
fifo_encoder_new(&entry->fsk_encoder);
|
raw_encoder_new(&entry->fsk_encoder);
|
||||||
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
||||||
break;
|
break;
|
||||||
case RADIO_DATA_MODE_WSPR:
|
case RADIO_DATA_MODE_WSPR:
|
||||||
|
@ -778,7 +778,7 @@ static bool radio_stop_transmit(radio_transmit_entry *entry)
|
||||||
mfsk_encoder_destroy(&entry->fsk_encoder);
|
mfsk_encoder_destroy(&entry->fsk_encoder);
|
||||||
break;
|
break;
|
||||||
case RADIO_DATA_MODE_CATS:
|
case RADIO_DATA_MODE_CATS:
|
||||||
fifo_encoder_destroy(&entry->fsk_encoder);
|
raw_encoder_destroy(&entry->fsk_encoder);
|
||||||
break;
|
break;
|
||||||
case RADIO_DATA_MODE_WSPR:
|
case RADIO_DATA_MODE_WSPR:
|
||||||
case RADIO_DATA_MODE_FT8:
|
case RADIO_DATA_MODE_FT8:
|
||||||
|
|
|
@ -207,7 +207,7 @@ void radio_handle_fifo_si4063(radio_transmit_entry *entry, radio_module_state *s
|
||||||
len -= written;
|
len -= written;
|
||||||
|
|
||||||
if(si4063_fifo_underflow()) {
|
if(si4063_fifo_underflow()) {
|
||||||
log_info("FIFO underflow - Aborting");
|
log_info("FIFO underflow - Aborting\n");
|
||||||
shared_state->radio_transmission_finished = true;
|
shared_state->radio_transmission_finished = true;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
Ładowanie…
Reference in New Issue