├── README.md └── hackrf_beep.c /README.md: -------------------------------------------------------------------------------- 1 | # hackrf_beep 2 | Simple demo of using libhackrf to transmit a two-tone beep. 3 | -------------------------------------------------------------------------------- /hackrf_beep.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************************************************************************************/ 2 | /* Purpose: Simple demo of using libhackrf to transmit a two-tone beep. */ 3 | /* Author: Copyright (c) 2015, W.B.Hill ( M1BKF) All rights reserved. */ 4 | /* License: Derived from hackrf_transfer, any parts written by my released into the public domain. */ 5 | /****************************************************************************************************************************************************/ 6 | 7 | /* 8 | * This transmits at the transmit frequency, tf, +800KHz (the HamRadio APRS frequency here.) 9 | * At a sample rate of 8M samples/s, for 800KHz there are 10 samples per carrier wave. 10 | * The Mark and Space frequcies are 1200Hz and 2200Hz respectively, so 6666 and 3636 samples per wave. 11 | * Assuming that the signal switches between mark and space at arbitraty times, the carrier 12 | * will be at one of 10 possible phase angles, the carrier offset, co. The modulating signals 13 | * similarly at offsets of mo and so. To prevent "chirps" in the signal at the frequence of 14 | * transition from mark to space, there should be no discontinuity in either the modulating or 15 | * the carrier waves. So the mark and space waveforms are pre-calculated for all possible phase 16 | * angles (for speed), and changover starts from the corresponding entry, for smooth transition. 17 | */ 18 | 19 | // gcc -std=c11 -o hackrf_beep hackrf_beep.c -lhackrf 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | // Transmit frequency. 33 | const uint64_t tf = 144000000L ; 34 | // Sample rate. 35 | const uint32_t sr = 8000000 ; 36 | // Transmitter IF gain. 37 | const unsigned int gain = 47 ; 38 | // Depth of modulation. 39 | const double dm = 4.0 / 3.0 ; 40 | // Precalc, its used a bit. 41 | const double tau = 2.0 * M_PI ; 42 | 43 | 44 | // Lookup tables, mark and space, one wave long at 8M samples/s 45 | int8_t mi[6666][10] ; 46 | int8_t mq[6666][10] ; 47 | int8_t si[3636][10] ; 48 | int8_t sq[3636][10] ; 49 | 50 | // Playback phase offsets for carrier, mark and space. 51 | int co, mo, so ; 52 | 53 | // Sample number. 54 | long sn ; 55 | 56 | // Mark or space? 57 | bool ms ; 58 | 59 | // Handle for the HackRF 60 | static hackrf_device* device = NULL ; 61 | 62 | // Time to give up? 63 | volatile bool do_exit = false ; 64 | 65 | 66 | // Dump more data to the HackRF. 67 | int 68 | tx_callback ( hackrf_transfer* transfer ) 69 | { 70 | // How much to do? 71 | size_t count = transfer->valid_length ; 72 | // Copy it over. 73 | int i = 0 ; 74 | // Mark or space? 75 | if ( ms ) 76 | { 77 | while ( i < count ) 78 | { 79 | ( transfer->buffer ) [i++] = mi[mo][co] ; 80 | ( transfer->buffer ) [i++] = mq[mo][co] ; 81 | co++ ; co %= 10 ; 82 | mo++ ; mo %= 6666 ; 83 | } 84 | so = 3636 * mo / 6666 ; 85 | } 86 | else 87 | { 88 | while ( i < count ) 89 | { 90 | ( transfer->buffer ) [i++] = si[so][co] ; 91 | ( transfer->buffer ) [i++] = sq[so][co] ; 92 | co++ ; co %= 10 ; 93 | so++ ; so %= 3636 ; 94 | } 95 | mo = 6666 * so / 3636 ; 96 | } 97 | sn += count ; 98 | // Every second, change. 99 | if ( sn >= sr ) 100 | { 101 | ms = !ms ; 102 | sn -= sr ; 103 | } 104 | return 0 ; 105 | } 106 | 107 | 108 | // Deal with interruptions. 109 | void 110 | sigint_callback_handler ( int signum ) 111 | { 112 | fprintf ( stderr, "Caught signal %d\n", signum ) ; 113 | do_exit = true ; 114 | } 115 | 116 | 117 | int 118 | main ( int argc, char** argv ) 119 | { 120 | /* 121 | * Setup. 122 | */ 123 | // How did it do? 124 | int result ; 125 | // Signal and carrier angle. 126 | double sa, ca ; 127 | // Sample offsets. 128 | co = 0 ; mo = 0 ; so = 0 ; 129 | // Sample number. 130 | sn = 0L ; 131 | // Mark or space? 132 | ms = false ; 133 | // Catch signals that we want to handle gracefully. 134 | signal ( SIGINT, &sigint_callback_handler ) ; 135 | signal ( SIGILL, &sigint_callback_handler ) ; 136 | signal ( SIGFPE, &sigint_callback_handler ) ; 137 | signal ( SIGSEGV, &sigint_callback_handler ) ; 138 | signal ( SIGTERM, &sigint_callback_handler ) ; 139 | signal ( SIGABRT, &sigint_callback_handler ) ; 140 | // This takes a bit. 141 | fprintf ( stderr, "Precalculating lookup tables...\n" ) ; 142 | /* 143 | * Precalc waveforms. 144 | */ 145 | // Lookup for 1200Hz. 146 | for ( int s = 0 ; s < 6666; s++ ) 147 | { 148 | sa = s * tau / 6666.0 ; 149 | for ( int c = 0; c < 10; c++ ) 150 | { 151 | ca = c * tau / 10.0 ; 152 | mi[s][c] = ( int8_t ) ( 127.0 * sin ( ca - dm * cos ( sa ) ) ) ; 153 | mq[s][c] = ( int8_t ) ( 127.0 * cos ( ca - dm * cos ( sa ) ) ) ; 154 | } 155 | } 156 | // Lookup for 2200Hz. 157 | for ( int s = 0 ; s < 3636; s++ ) 158 | { 159 | sa = s * tau / 3636.0 ; 160 | for ( int c = 0; c < 10; c++ ) 161 | { 162 | ca = c * tau / 10.0 ; 163 | si[s][c] = ( int8_t ) ( 127.0 * sin ( ca - dm * cos ( sa ) ) ) ; 164 | sq[s][c] = ( int8_t ) ( 127.0 * cos ( ca - dm * cos ( sa ) ) ) ; 165 | } 166 | } 167 | /* 168 | * Setup the HackRF for transmitting at full power, 8M samples/s, 144MHz 169 | */ 170 | // Ok. 171 | fprintf ( stderr, "Setting up the HackRF...\n" ) ; 172 | // Initialize the HackRF. 173 | result = hackrf_init() ; 174 | if ( result != HACKRF_SUCCESS ) 175 | { 176 | fprintf ( stderr, "hackrf_init() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 177 | return EXIT_FAILURE ; 178 | } 179 | // Open the HackRF. 180 | result = hackrf_open ( &device ) ; 181 | if ( result != HACKRF_SUCCESS ) 182 | { 183 | fprintf ( stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 184 | return EXIT_FAILURE ; 185 | } 186 | // Set the sample rate. 187 | result = hackrf_set_sample_rate_manual ( device, sr, 1 ) ; 188 | if ( result != HACKRF_SUCCESS ) 189 | { 190 | fprintf ( stderr, "hackrf_sample_rate_set() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 191 | return EXIT_FAILURE ; 192 | } 193 | // Set the filter bandwith to default. 194 | result = hackrf_set_baseband_filter_bandwidth ( device, hackrf_compute_baseband_filter_bw_round_down_lt ( sr ) ) ; 195 | if ( result != HACKRF_SUCCESS ) 196 | { 197 | fprintf ( stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 198 | return EXIT_FAILURE ; 199 | } 200 | // Set the gain. 201 | result = hackrf_set_txvga_gain ( device, gain ) ; 202 | result |= hackrf_start_tx ( device, tx_callback, NULL ) ; 203 | if ( result != HACKRF_SUCCESS ) 204 | { 205 | fprintf ( stderr, "hackrf_start_tx() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 206 | return EXIT_FAILURE ; 207 | } 208 | // Set the transmit frequency. 209 | result = hackrf_set_freq ( device, tf ) ; 210 | if ( result != HACKRF_SUCCESS ) 211 | { 212 | fprintf ( stderr, "hackrf_set_freq() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 213 | return EXIT_FAILURE ; 214 | } 215 | // Turn on the amp. 216 | result = hackrf_set_amp_enable ( device, ( uint8_t ) 1 ) ; 217 | if ( result != HACKRF_SUCCESS ) 218 | { 219 | fprintf ( stderr, "hackrf_set_amp_enable() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 220 | return EXIT_FAILURE ; 221 | } 222 | /* 223 | * Transmitting. 224 | */ 225 | // Ready? 226 | fprintf ( stderr, "Transmitting, stop with Ctrl-C\n" ) ; 227 | // Spin until done or killed. 228 | while ( ( hackrf_is_streaming ( device ) == HACKRF_TRUE ) && ( do_exit == false ) ) sleep ( 1 ) ; 229 | /* 230 | * Clean up and shut down. 231 | */ 232 | // What happened? 233 | result = hackrf_is_streaming ( device ) ; 234 | if ( do_exit ) 235 | { 236 | printf ( "\nUser cancel, exiting...\n" ) ; 237 | } 238 | else 239 | { 240 | fprintf ( stderr, "\nExiting... hackrf_is_streaming() result: %s (%d)\n", hackrf_error_name ( result ), result ) ; 241 | } 242 | // Shut down the HackRF. 243 | if ( device != NULL ) 244 | { 245 | result = hackrf_stop_tx ( device ) ; 246 | if ( result != HACKRF_SUCCESS ) 247 | { 248 | fprintf ( stderr, "hackrf_stop_tx() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 249 | } 250 | result = hackrf_close ( device ) ; 251 | if ( result != HACKRF_SUCCESS ) 252 | { 253 | fprintf ( stderr, "hackrf_close() failed: %s (%d)\n", hackrf_error_name ( result ), result ) ; 254 | } 255 | hackrf_exit() ; 256 | } 257 | // That's all, folks!!! 258 | return EXIT_SUCCESS ; 259 | } 260 | --------------------------------------------------------------------------------