kopia lustrzana https://github.com/eleccoder/raspi-pico-aprs-tnc
Split into lib + example application
rodzic
190667f82b
commit
906e390786
|
@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
pico_sdk_init()
|
pico_sdk_init()
|
||||||
|
|
||||||
|
|
||||||
# Setup of eleccoder's 'ax25-aprs-lib'
|
# (1) Setup of eleccoder's 'ax25-aprs-lib'
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(ax25_aprs_lib
|
FetchContent_Declare(ax25_aprs_lib
|
||||||
|
@ -24,30 +24,56 @@ FetchContent_MakeAvailable(ax25_aprs_lib)
|
||||||
add_library(ax25_aprs_lib::ax25beacon ALIAS ax25beacon)
|
add_library(ax25_aprs_lib::ax25beacon ALIAS ax25beacon)
|
||||||
|
|
||||||
|
|
||||||
# Setup of the application
|
# (2) Configure the library build
|
||||||
|
|
||||||
set(EXE_NAME aprs_pico)
|
set(TARGET_LIB_NAME aprs_pico)
|
||||||
|
|
||||||
add_executable(${EXE_NAME}
|
add_library(${TARGET_LIB_NAME}
|
||||||
src/aprs_pico.c
|
src/aprs_pico.c)
|
||||||
|
|
||||||
|
set_target_properties(${TARGET_LIB_NAME}
|
||||||
|
PROPERTIES
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${EXE_NAME} PRIVATE
|
target_include_directories(${TARGET_LIB_NAME} PUBLIC
|
||||||
include
|
include
|
||||||
)
|
)
|
||||||
|
|
||||||
#target_compile_options(${EXE_NAME} PRIVATE "-Wall")
|
# Enable on demand
|
||||||
|
#target_compile_options(${TARGET_LIB_NAME} PRIVATE "-Wundef;-Wall")
|
||||||
|
|
||||||
# Set the console interface
|
# This properly resolves the include dirs of the dependent libraries
|
||||||
pico_enable_stdio_usb(aprs_pico 1) # USB
|
target_link_libraries(${TARGET_LIB_NAME}
|
||||||
# pico_enable_stdio_uart(aprs_pico 1) # UART
|
|
||||||
|
|
||||||
# create map/bin/hex file etc.
|
|
||||||
pico_add_extra_outputs(${EXE_NAME})
|
|
||||||
|
|
||||||
target_link_libraries(${EXE_NAME}
|
|
||||||
pico_stdlib
|
|
||||||
pico_audio_pwm
|
|
||||||
ax25_aprs_lib::ax25beacon
|
ax25_aprs_lib::ax25beacon
|
||||||
|
pico_audio_pwm
|
||||||
|
pico_stdlib
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# (3) Configure the example application build
|
||||||
|
|
||||||
|
set(TARGET_EXAMPLE_EXE_NAME aprs_pico_example)
|
||||||
|
|
||||||
|
add_executable(${TARGET_EXAMPLE_EXE_NAME}
|
||||||
|
src/aprs_pico_example.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${TARGET_EXAMPLE_EXE_NAME} PRIVATE
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the console interface
|
||||||
|
pico_enable_stdio_usb(${TARGET_EXAMPLE_EXE_NAME} 1) # USB
|
||||||
|
#pico_enable_stdio_uart(${TARGET_EXAMPLE_EXE_NAME} 1) # UART
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(${TARGET_EXAMPLE_EXE_NAME})
|
||||||
|
|
||||||
|
target_link_libraries(${TARGET_EXAMPLE_EXE_NAME}
|
||||||
|
${TARGET_LIB_NAME}
|
||||||
|
ax25_aprs_lib::ax25beacon
|
||||||
|
pico_audio_pwm
|
||||||
|
pico_stdlib
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
23
README.md
23
README.md
|
@ -6,21 +6,25 @@ An analog line-out audio signal will be produced at GPIO-pin 'GP0'. You can obse
|
||||||
Basically, this is the data/signal flow:
|
Basically, this is the data/signal flow:
|
||||||
|
|
||||||
```
|
```
|
||||||
APRS (text msg + geo-coordinates + meta-data) -> AX.25 -> PCM -> PWM -> Low-Pass filtering -> AFSK signal
|
APRS (text msg + geo-coordinates + meta-data) -> AX.25 -> PCM -> PWM -> Band-Pass filtering -> AFSK audio signal
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Both a static library `libaprs_pico.a` and an example application will be generated by the build.
|
||||||
|
|
||||||
## Preliminaries
|
## Preliminaries
|
||||||
|
|
||||||
Your host platform is assumed to be LINUX.
|
Your host platform is assumed to be LINUX.
|
||||||
If you have already installed the Pico-SDK, set the `PICO_SDK_PATH` environment variable accordingly to avoid installing the SDK twice.
|
If you have already installed the Pico-SDK, set the `PICO_SDK_PATH` environment variable accordingly to avoid installing the SDK twice.
|
||||||
|
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
|
|
||||||
We just need a simple band-pass filter to extract the AFSK-signal from the PWM signal:
|
We just need a simple band-pass filter to extract the AFSK-signal from the PWM signal:
|
||||||
|
|
||||||
![band-pass filter](https://github.com/eleccoder/raspi-pico-aprs-tnc/blob/main/doc/schematic/band_pass_filter.png)
|
![band-pass filter](https://github.com/eleccoder/raspi-pico-aprs-tnc/blob/main/doc/schematic/band_pass_filter.png)
|
||||||
|
|
||||||
## Build the application
|
|
||||||
|
## Build the library and the example application
|
||||||
|
|
||||||
```
|
```
|
||||||
(cd into the cloned dir)
|
(cd into the cloned dir)
|
||||||
|
@ -28,28 +32,27 @@ cmake -S . -B build
|
||||||
cmake --build build
|
cmake --build build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run the application
|
`build/lib/libaprs_pico.a` and `build/aprs_pico_example.xxx` will be created.
|
||||||
|
|
||||||
|
## Run the example application
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build
|
cd build
|
||||||
(flash 'aprs_pico.uf2' or 'aprs_pico.elf' to the Pico board as usual)
|
(flash 'aprs_pico_example.uf2' or 'aprs_pico_example.elf' to the Pico board as usual)
|
||||||
```
|
```
|
||||||
|
|
||||||
The GPIO-pin 'GP0' is the line-out for the analog AFSK-signal. You can observe it by using a scope, listen to it by using an audio amp, or connect it to any RF transceiver to send it on the air (ham radio license required).
|
The GPIO-pin 'GP0' is the line-out for the analog AFSK-signal. You can observe it by using a scope, listen to it by using an audio amp, or connect it to any RF transceiver to send it on the air (ham radio license required).
|
||||||
|
|
||||||
![AFSK scope screenshot](https://github.com/eleccoder/raspi-pico-aprs-tnc/blob/main/doc/img/afsk_scope.png "Scope screenshot of an AFSK output signal")
|
![AFSK scope screenshot](https://github.com/eleccoder/raspi-pico-aprs-tnc/blob/main/doc/img/afsk_scope.png "Scope screenshot of an AFSK output signal")
|
||||||
|
|
||||||
## Modify the application
|
|
||||||
|
|
||||||
To send an APRS message of your choice, you have to modify the *main()* function in `src/aprs_pico.c`.
|
|
||||||
|
|
||||||
## TODO (Aug 2021)
|
## TODO (Aug 2021)
|
||||||
|
|
||||||
- [x] Thorough evaluation
|
- [x] Thorough evaluation, in general
|
||||||
- [x] Send the APRS message on the console (USB or UART) rather than hard-coding
|
- [x] Send the APRS message on the console (USB or UART) rather than hard-coding
|
||||||
- [x] Code documentation
|
|
||||||
- [x] Show how to connect to a Baofeng HT
|
- [x] Show how to connect to a Baofeng HT
|
||||||
- [x] PTT control for HTs
|
- [x] PTT control for RF tranceivers
|
||||||
|
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Project 'raspi-pico-aprs-tnc'
|
||||||
|
* Copyright (C) 2021 Thomas Glau, DL3TG
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APRS_PICO_H
|
||||||
|
#define APRS_PICO_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// WARNING: ATTOW, the pico audio PWM lib worked only @ 22050 Hz sampling frequency and 48 MHz system clock
|
||||||
|
// This is documented here: https://github.com/raspberrypi/pico-extras
|
||||||
|
#define APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ (22050)
|
||||||
|
|
||||||
|
|
||||||
|
void sendAPRS(const char* call_sign_src,
|
||||||
|
const char* call_sign_dst,
|
||||||
|
const char* aprs_path_1,
|
||||||
|
const char* aprs_path_2,
|
||||||
|
const char* aprs_message,
|
||||||
|
const double latitude_in_deg,
|
||||||
|
const double longitude_in_deg,
|
||||||
|
const double altitude_in_m,
|
||||||
|
const uint8_t volume,
|
||||||
|
const bool is_loop);
|
||||||
|
|
||||||
|
|
||||||
|
void send1kHz(unsigned int sample_freq_in_hz, uint8_t volume);
|
||||||
|
|
||||||
|
#endif // APRS_PICO_H
|
105
src/aprs_pico.c
105
src/aprs_pico.c
|
@ -16,7 +16,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <aprs_pico.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
@ -26,21 +27,16 @@
|
||||||
#include <ax25beacon.h>
|
#include <ax25beacon.h>
|
||||||
|
|
||||||
|
|
||||||
// WARNING: ATTOW, the pico audio PWM lib worked only @ 22050 Hz sampling frequency and 48 MHz system clock
|
|
||||||
// This is documented here: https://github.com/raspberrypi/pico-extras
|
|
||||||
#define PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ (22050)
|
|
||||||
#define SINE_WAVE_TEST (0) // For test & debug
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct AudioCallBackUserData
|
typedef struct AudioCallBackUserData
|
||||||
{
|
{
|
||||||
uint aprs_sample_freq_in_hz;
|
unsigned int aprs_sample_freq_in_hz;
|
||||||
bool is_loop;
|
bool is_loop;
|
||||||
uint8_t volume;
|
uint8_t volume;
|
||||||
|
|
||||||
} AudioCallBackUserData_t;
|
} AudioCallBackUserData_t;
|
||||||
|
|
||||||
|
|
||||||
audio_buffer_pool_t* init_audio(uint sample_freq_in_hz, uint16_t audio_buffer_format)
|
static audio_buffer_pool_t* init_audio(unsigned int sample_freq_in_hz, uint16_t audio_buffer_format)
|
||||||
{
|
{
|
||||||
const int NUM_AUDIO_BUFFERS = 3;
|
const int NUM_AUDIO_BUFFERS = 3;
|
||||||
const int SAMPLES_PER_BUFFER = 256;
|
const int SAMPLES_PER_BUFFER = 256;
|
||||||
|
@ -68,12 +64,12 @@ audio_buffer_pool_t* init_audio(uint sample_freq_in_hz, uint16_t audio_buffer_fo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void init(uint sample_freq_in_hz)
|
static void init(unsigned int sample_freq_in_hz)
|
||||||
{
|
{
|
||||||
// WARNING: ATTOW, the pico audio PWM lib worked only @ 22050 Hz sampling frequency and 48 MHz system clock
|
// WARNING: ATTOW, the pico audio PWM lib worked only @ 22050 Hz sampling frequency and 48 MHz system clock
|
||||||
// This is documented here: https://github.com/raspberrypi/pico-extras
|
// This is documented here: https://github.com/raspberrypi/pico-extras
|
||||||
|
|
||||||
if (sample_freq_in_hz == PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ)
|
if (sample_freq_in_hz == APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ)
|
||||||
{
|
{
|
||||||
// This is the safe case, see the comment above
|
// This is the safe case, see the comment above
|
||||||
set_sys_clock_48mhz();
|
set_sys_clock_48mhz();
|
||||||
|
@ -83,7 +79,7 @@ static void init(uint sample_freq_in_hz)
|
||||||
// Compensate a non-'PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ' sampling frequency
|
// Compensate a non-'PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ' sampling frequency
|
||||||
// by a adapting the system clock accordingly
|
// by a adapting the system clock accordingly
|
||||||
|
|
||||||
float sys_clock_in_mhz = 48.0f * (float)sample_freq_in_hz / (float)PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ;
|
float sys_clock_in_mhz = 48.0f * (float)sample_freq_in_hz / (float)APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ;
|
||||||
|
|
||||||
// Round to full Mhz to increase the chance that 'set_sys_clock_khz()' can exactly realize this frequency
|
// Round to full Mhz to increase the chance that 'set_sys_clock_khz()' can exactly realize this frequency
|
||||||
sys_clock_in_mhz = round(sys_clock_in_mhz);
|
sys_clock_in_mhz = round(sys_clock_in_mhz);
|
||||||
|
@ -96,9 +92,9 @@ static void init(uint sample_freq_in_hz)
|
||||||
|
|
||||||
|
|
||||||
static void fill_audio_buffer(audio_buffer_pool_t* audio_pool, const int16_t* pcm_data,
|
static void fill_audio_buffer(audio_buffer_pool_t* audio_pool, const int16_t* pcm_data,
|
||||||
uint num_samples, uint8_t volume, bool is_loop_forever)
|
unsigned int num_samples, uint8_t volume, bool is_loop_forever)
|
||||||
{
|
{
|
||||||
uint pos = 0u;
|
unsigned int pos = 0u;
|
||||||
bool is_keep_going = true;
|
bool is_keep_going = true;
|
||||||
|
|
||||||
while (is_keep_going)
|
while (is_keep_going)
|
||||||
|
@ -106,7 +102,7 @@ static void fill_audio_buffer(audio_buffer_pool_t* audio_pool, const int16_t* pc
|
||||||
audio_buffer_t* buffer = take_audio_buffer(audio_pool, true);
|
audio_buffer_t* buffer = take_audio_buffer(audio_pool, true);
|
||||||
int16_t* samples = (int16_t*)buffer->buffer->bytes;
|
int16_t* samples = (int16_t*)buffer->buffer->bytes;
|
||||||
|
|
||||||
for (uint i = 0u; i < buffer->max_sample_count; i++)
|
for (unsigned int i = 0u; i < buffer->max_sample_count; i++)
|
||||||
{
|
{
|
||||||
samples[i] = (volume * pcm_data[pos]) >> 8u;
|
samples[i] = (volume * pcm_data[pos]) >> 8u;
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -131,13 +127,23 @@ static void fill_audio_buffer(audio_buffer_pool_t* audio_pool, const int16_t* pc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void sendAPRS_audioCallback(void* callback_user_data, int16_t* pcm_data, size_t num_samples)
|
||||||
|
{
|
||||||
|
const AudioCallBackUserData_t user_data = *((const AudioCallBackUserData_t*)callback_user_data);
|
||||||
|
|
||||||
|
audio_buffer_pool_t* audio_pool = init_audio(user_data.aprs_sample_freq_in_hz, AUDIO_BUFFER_FORMAT_PCM_S16);
|
||||||
|
|
||||||
|
fill_audio_buffer(audio_pool, pcm_data, num_samples, user_data.volume, user_data.is_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Test tone: 1 kHz sine wave
|
// Test tone: 1 kHz sine wave
|
||||||
static void send1kHz(uint sample_freq_in_hz, uint8_t volume)
|
void send1kHz( unsigned int sample_freq_in_hz, uint8_t volume)
|
||||||
{
|
{
|
||||||
init(sample_freq_in_hz);
|
init(sample_freq_in_hz);
|
||||||
|
|
||||||
const uint tone_freq_in_hz = 1000u;
|
const unsigned int TONE_FREQ_IN_HZ = 1000u;
|
||||||
const uint num_samples = sample_freq_in_hz / tone_freq_in_hz;
|
const unsigned int num_samples = sample_freq_in_hz / TONE_FREQ_IN_HZ;
|
||||||
|
|
||||||
int16_t* sine_wave_table = malloc(num_samples * sizeof(int16_t));
|
int16_t* sine_wave_table = malloc(num_samples * sizeof(int16_t));
|
||||||
|
|
||||||
|
@ -146,7 +152,7 @@ static void send1kHz(uint sample_freq_in_hz, uint8_t volume)
|
||||||
panic("Out of memory: malloc() failed.\n");
|
panic("Out of memory: malloc() failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i = 0u; i < num_samples; i++)
|
for (unsigned int i = 0u; i < num_samples; i++)
|
||||||
{
|
{
|
||||||
sine_wave_table[i] = (int16_t)(32767.0f * sinf(2.0f * (float)M_PI * (float)i / (float)num_samples));
|
sine_wave_table[i] = (int16_t)(32767.0f * sinf(2.0f * (float)M_PI * (float)i / (float)num_samples));
|
||||||
}
|
}
|
||||||
|
@ -159,26 +165,16 @@ static void send1kHz(uint sample_freq_in_hz, uint8_t volume)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void sendAPRS_audioCallback(void* callback_user_data, int16_t* pcm_data, size_t num_samples)
|
void sendAPRS(const char* call_sign_src,
|
||||||
{
|
const char* call_sign_dst,
|
||||||
const AudioCallBackUserData_t user_data = *((const AudioCallBackUserData_t*)callback_user_data);
|
const char* aprs_path_1,
|
||||||
|
const char* aprs_path_2,
|
||||||
audio_buffer_pool_t* audio_pool = init_audio(user_data.aprs_sample_freq_in_hz, AUDIO_BUFFER_FORMAT_PCM_S16);
|
const char* aprs_message,
|
||||||
|
const double latitude_in_deg,
|
||||||
fill_audio_buffer(audio_pool, pcm_data, num_samples, user_data.volume, user_data.is_loop);
|
const double longitude_in_deg,
|
||||||
}
|
const double altitude_in_m,
|
||||||
|
const uint8_t volume,
|
||||||
|
const bool is_loop)
|
||||||
static void sendAPRS(const char* call_sign_src,
|
|
||||||
const char* call_sign_dst,
|
|
||||||
const char* aprs_path_1,
|
|
||||||
const char* aprs_path_2,
|
|
||||||
const char* aprs_message,
|
|
||||||
const double latitude_in_deg,
|
|
||||||
const double longitude_in_deg,
|
|
||||||
const double altitude_in_m,
|
|
||||||
const uint8_t volume,
|
|
||||||
const bool is_loop)
|
|
||||||
{
|
{
|
||||||
static AudioCallBackUserData_t callback_user_data;
|
static AudioCallBackUserData_t callback_user_data;
|
||||||
|
|
||||||
|
@ -200,30 +196,3 @@ static void sendAPRS(const char* call_sign_src,
|
||||||
aprs_message,
|
aprs_message,
|
||||||
'/', 'O');
|
'/', 'O');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
#if (SINE_WAVE_TEST == 1)
|
|
||||||
|
|
||||||
const uint8_t VOLUME = 128u;
|
|
||||||
send1kHz(PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ, VOLUME);
|
|
||||||
|
|
||||||
#else // !SINE_WAVE_TEST
|
|
||||||
|
|
||||||
// Send an APRS test message
|
|
||||||
sendAPRS("SRC", // Src call sign
|
|
||||||
"DST", // Dst call sign
|
|
||||||
"PATH1",
|
|
||||||
"PATH2",
|
|
||||||
"Test message",
|
|
||||||
10.0, // Lat in deg
|
|
||||||
20.0, // Long in deg
|
|
||||||
100.0, // Alt in m
|
|
||||||
128u, // Volume (0 ... 255)
|
|
||||||
false); // Loop forever
|
|
||||||
|
|
||||||
#endif // SINE_WAVE_TEST, !SINE_WAVE_TEST
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Project 'raspi-pico-aprs-tnc'
|
||||||
|
* Copyright (C) 2021 Thomas Glau, DL3TG
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <aprs_pico.h>
|
||||||
|
|
||||||
|
#define SINE_WAVE_TEST (0) // For test & debug
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#if (SINE_WAVE_TEST == 1)
|
||||||
|
|
||||||
|
const uint8_t VOLUME = 128u;
|
||||||
|
send1kHz(APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ, VOLUME);
|
||||||
|
|
||||||
|
#else // !SINE_WAVE_TEST
|
||||||
|
|
||||||
|
// Send an APRS test message
|
||||||
|
sendAPRS("SRC", // Src call sign
|
||||||
|
"DST", // Dst call sign
|
||||||
|
"PATH1",
|
||||||
|
"PATH2",
|
||||||
|
"Test message",
|
||||||
|
10.0, // Lat in deg
|
||||||
|
20.0, // Long in deg
|
||||||
|
100.0, // Alt in m
|
||||||
|
128u, // Volume (0 ... 255)
|
||||||
|
false); // Loop forever
|
||||||
|
|
||||||
|
#endif // SINE_WAVE_TEST, !SINE_WAVE_TEST
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Ładowanie…
Reference in New Issue