#include #include #include #include #include #include "utils.h" #include "layer1/tx.h" #include "layer1/rx.h" #define RESULT_CHECK(stmt) { \ result_t res = stmt; \ if(res != OK) { \ fprintf(stderr, "Error %d in %s:%d!", res, __FILE__, __LINE__); \ exit(1); \ } \ } void print_complex_array(const char *varname, float complex const *array, size_t len) { fprintf(stderr, "%s=np.array([%f%+fj", varname, crealf(array[0]), cimagf(array[0])); for(size_t k = 1; k < len; k++) { fprintf(stderr, ", %f%+fj", crealf(array[k]), cimagf(array[k])); } fprintf(stderr, "])\n"); } void cb_rx(rx_evt_t evt, uint8_t *packet_data, size_t packet_len) { switch(evt) { case RX_EVT_CHECKSUM_ERROR: fprintf(stderr, "Received a message of %zu bytes, but decoding failed.\n", packet_len); fprintf(stderr, "=== FAILED PAYLOAD ===\n"); fprintf(stderr, "%s\n", packet_data); fprintf(stderr, "=======================\n"); break; case RX_EVT_PACKET_RECEIVED: fprintf(stderr, "=== DECODED PAYLOAD ===\n"); fprintf(stderr, "%s\n", packet_data); fprintf(stderr, "=======================\n"); break; case RX_EVT_PREAMBLE_FOUND: fprintf(stderr, "Found preamble!\n"); break; } } int main(void) { uint8_t msg_org[] = "Hello Liquid! This is the message to transmit. Hopefully it can be decoded correctly..."; // ** Modulate packet ** layer1_tx_t tx; RESULT_CHECK(layer1_tx_init(&tx)); RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, msg_org, sizeof(msg_org))); RESULT_CHECK(layer1_tx_finalize_burst(&tx)); size_t burst_len = layer1_tx_get_sample_count(&tx); const float complex *whole_burst = layer1_tx_get_sample_data(&tx); dump_array_cf(whole_burst, burst_len, 1.0f, "/tmp/tx.cpx"); // ** Apply channel distortions ** channel_cccf channel = channel_cccf_create(); float snr = 10.0f; channel_cccf_add_awgn(channel, -snr, snr); channel_cccf_add_carrier_offset(channel, 0.20f, 1.00f); channel_cccf_add_shadowing(channel, 1.00f, 0.1f); // channel float complex msg_received[burst_len]; //memcpy(msg_received, whole_burst, sizeof(whole_burst)); // no noise in channel channel_cccf_execute_block(channel, whole_burst, burst_len, msg_received); // scale the entire signal to give the AGC something to do for(size_t i = 0; i < burst_len; i++) { msg_received[i] *= 0.02f; } dump_array_cf(msg_received, burst_len, 1.0f, "/tmp/rx.cpx"); // ** RX starts here ** layer1_rx_t rx; RESULT_CHECK(layer1_rx_init(&rx, cb_rx)); RESULT_CHECK(layer1_rx_process(&rx, msg_received, burst_len)); // cleanup channel_cccf_destroy(channel); layer1_tx_shutdown(&tx); layer1_rx_shutdown(&rx); fprintf(stderr, "Done.\n"); }