Created
December 18, 2022 09:13
-
-
Save Sasszem/08f3c470e0b7a078011578757b6063b7 to your computer and use it in GitHub Desktop.
Transmit a 440Hz triangle wave through FM using the libhackrf API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <libhackrf/hackrf.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <pthread.h> | |
#include <unistd.h> | |
#include <complex.h> | |
#include <stdint.h> | |
const double f_mod = 440; | |
const uint64_t sample_rate = 10000000; | |
double triangle() { | |
/* | |
* Generate an f_mod frequency triangle wave in the -1 - 1 region | |
* each call to this function generates a single sample | |
*/ | |
static double state; | |
static uint64_t samples_generated; | |
const uint64_t period_in_samples = sample_rate / f_mod; | |
const double step = 4.0 / period_in_samples; // we need to go from -1 to 1 in half the period | |
if (samples_generated < period_in_samples / 2 ) | |
state += step; | |
else | |
state -= step; | |
// this way we don't need to modulo it | |
if (samples_generated ++ == period_in_samples) | |
samples_generated = 0; | |
return state - 1.0; | |
} | |
volatile double complex phasor = 1.0; | |
int xfered_samples = 0; | |
int samples_to_xfer = 5*sample_rate; | |
volatile int should_stop = 0; | |
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
int transfer_callback(hackrf_transfer *transfer) { | |
int8_t *signed_buffer = (int8_t*)transfer->buffer; | |
for (int i = 0; i<transfer->buffer_length; i+=2) { | |
phasor *= cexp(I*6.28*3000 / sample_rate*triangle()); | |
// any IQ samples can be written here, now I'm doing FM modulation with a triangle wave | |
signed_buffer[i] = 128 * creal(phasor); | |
signed_buffer[i+1] = 128 * cimag(phasor); | |
} | |
transfer->valid_length = transfer->buffer_length; | |
xfered_samples += transfer->buffer_length; | |
if (xfered_samples >= samples_to_xfer) { | |
return 1; | |
} | |
return 0; | |
} | |
void flush_callback(hackrf_transfer *transfer) { | |
pthread_mutex_lock(&mutex); | |
pthread_cond_broadcast(&cond); | |
pthread_mutex_unlock(&mutex); | |
} | |
int main() { | |
hackrf_init(); | |
hackrf_device *device = NULL; | |
hackrf_open(&device); | |
hackrf_set_freq(device, 144500000); | |
hackrf_set_sample_rate(device, 10000000); | |
hackrf_set_amp_enable(device, 1); | |
hackrf_set_txvga_gain(device, 20); | |
// hackrf_set_tx_underrun_limit(device, 100000); | |
hackrf_enable_tx_flush(device, flush_callback, NULL); | |
hackrf_start_tx(device, transfer_callback, NULL); | |
pthread_mutex_lock(&mutex); | |
pthread_cond_wait(&cond, &mutex); | |
hackrf_stop_tx(device); | |
hackrf_close(device); | |
hackrf_exit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment