kopia lustrzana https://github.com/eleccoder/raspi-pico-aprs-tnc
Porównaj commity
8 Commity
753d2925a2
...
d6867e1a84
Autor | SHA1 | Data |
---|---|---|
eleccoder | d6867e1a84 | |
eleccoder | 525671c31e | |
eleccoder | 4a97c15181 | |
eleccoder | ad314db081 | |
eleccoder | bb08012dca | |
eleccoder | 7b91b2eba1 | |
eleccoder | 02a22624f1 | |
eleccoder | b437375ee5 |
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
include(cmake/pico_sdk_import.cmake) # File copied from $PICO_SDK_PATH/pico-sdk/external
|
include(cmake/pico_sdk_import.cmake) # File copied from $PICO_SDK_PATH/external
|
||||||
include(cmake/pico_extras_import.cmake) # File copied from $PICO_SDK_PATH/pico-extras/external
|
include(cmake/pico_extras_import.cmake) # File copied from $PICO_SDK_PATH/../pico-extras/external
|
||||||
|
|
||||||
project(raspi-pico-aprs-tnc VERSION 0.1)
|
project(raspi-pico-aprs-tnc VERSION 0.1)
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
pico_sdk_init()
|
pico_sdk_init()
|
||||||
|
|
||||||
|
|
||||||
# (1) Setup of eleccoder's version of Philip Heron's 'ax25beacon' project
|
# Setup of eleccoder's version of Philip Heron's 'ax25beacon' project
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(ax25_aprs_lib
|
FetchContent_Declare(ax25_aprs_lib
|
||||||
|
@ -24,7 +24,7 @@ FetchContent_MakeAvailable(ax25_aprs_lib)
|
||||||
add_library(ax25_aprs_lib::ax25beacon ALIAS ax25beacon)
|
add_library(ax25_aprs_lib::ax25beacon ALIAS ax25beacon)
|
||||||
|
|
||||||
|
|
||||||
# (2) Configure the library build
|
# ##### Configure the build of the 'aprs_pico' library #####
|
||||||
|
|
||||||
set(TARGET_LIB_NAME aprs_pico)
|
set(TARGET_LIB_NAME aprs_pico)
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ target_include_directories(${TARGET_LIB_NAME} PUBLIC
|
||||||
# Enable on demand
|
# Enable on demand
|
||||||
#target_compile_options(${TARGET_LIB_NAME} PRIVATE "-Wundef;-Wall")
|
#target_compile_options(${TARGET_LIB_NAME} PRIVATE "-Wundef;-Wall")
|
||||||
|
|
||||||
# This properly resolves the include dirs of the dependent libraries
|
|
||||||
target_link_libraries(${TARGET_LIB_NAME}
|
target_link_libraries(${TARGET_LIB_NAME}
|
||||||
ax25_aprs_lib::ax25beacon
|
ax25_aprs_lib::ax25beacon
|
||||||
pico_audio_pwm
|
pico_audio_pwm
|
||||||
|
@ -51,7 +50,7 @@ target_link_libraries(${TARGET_LIB_NAME}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# (3) Configure the example application build
|
# ##### Configure the build of the example application #####
|
||||||
|
|
||||||
set(TARGET_EXAMPLE_EXE_NAME aprs_pico_example)
|
set(TARGET_EXAMPLE_EXE_NAME aprs_pico_example)
|
||||||
|
|
||||||
|
@ -63,11 +62,11 @@ target_include_directories(${TARGET_EXAMPLE_EXE_NAME} PRIVATE
|
||||||
include
|
include
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set the console interface
|
# Configure the console interface
|
||||||
pico_enable_stdio_usb(${TARGET_EXAMPLE_EXE_NAME} 1) # USB
|
pico_enable_stdio_usb(${TARGET_EXAMPLE_EXE_NAME} 1) # USB
|
||||||
#pico_enable_stdio_uart(${TARGET_EXAMPLE_EXE_NAME} 1) # UART
|
#pico_enable_stdio_uart(${TARGET_EXAMPLE_EXE_NAME} 1) # UART
|
||||||
|
|
||||||
# create map/bin/hex file etc.
|
# Create map/bin/hex file etc.
|
||||||
pico_add_extra_outputs(${TARGET_EXAMPLE_EXE_NAME})
|
pico_add_extra_outputs(${TARGET_EXAMPLE_EXE_NAME})
|
||||||
|
|
||||||
target_link_libraries(${TARGET_EXAMPLE_EXE_NAME}
|
target_link_libraries(${TARGET_EXAMPLE_EXE_NAME}
|
||||||
|
|
|
@ -54,7 +54,7 @@ cmake --build build
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build
|
cd build
|
||||||
(flash 'aprs_pico_example.uf2' or 'aprs_pico_example.elf' to the Pico board as usual)
|
Flash 'aprs_pico_example[.uf2|.elf|.bin]' to the Pico board as usual
|
||||||
```
|
```
|
||||||
|
|
||||||
The analog AFSK audio signal will be available at the filter's line-out. You can probe it by 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 analog AFSK audio signal will be available at the filter's line-out. You can probe it by 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).
|
||||||
|
|
|
@ -26,14 +26,14 @@ if (NOT PICO_EXTRAS_PATH)
|
||||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
PICO_EXTRAS
|
pico_extras
|
||||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
|
||||||
GIT_TAG master
|
GIT_TAG master
|
||||||
)
|
)
|
||||||
if (NOT PICO_EXTRAS)
|
if (NOT pico_extras)
|
||||||
message("Downloading PICO EXTRAS")
|
message("Downloading Raspberry Pi Pico Extras")
|
||||||
FetchContent_Populate(PICO_EXTRAS)
|
FetchContent_Populate(pico_extras)
|
||||||
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_SOURCE_DIR})
|
set(PICO_EXTRAS_PATH ${pico_extras_SOURCE_DIR})
|
||||||
endif ()
|
endif ()
|
||||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
else ()
|
else ()
|
||||||
|
@ -59,4 +59,4 @@ endif ()
|
||||||
|
|
||||||
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
|
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
|
||||||
|
|
||||||
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)
|
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)
|
||||||
|
|
|
@ -29,11 +29,22 @@ if (NOT PICO_SDK_PATH)
|
||||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
FetchContent_Declare(
|
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||||
pico_sdk
|
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
FetchContent_Declare(
|
||||||
GIT_TAG master
|
pico_sdk
|
||||||
)
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
GIT_SUBMODULES_RECURSE FALSE
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (NOT pico_sdk)
|
if (NOT pico_sdk)
|
||||||
message("Downloading Raspberry Pi Pico SDK")
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
FetchContent_Populate(pico_sdk)
|
FetchContent_Populate(pico_sdk)
|
||||||
|
|
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 90 KiB Po Szerokość: | Wysokość: | Rozmiar: 73 KiB |
Plik binarny nie jest wyświetlany.
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Project 'raspi-pico-aprs-tnc'
|
* Project 'raspi-pico-aprs-tnc'
|
||||||
* Copyright (C) 2021 Thomas Glau, DL3TG
|
* Copyright (C) 2021-2023 Thomas Glau, DL3TG
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -61,11 +61,12 @@ bool aprs_pico_sendAPRS(audio_buffer_pool_t* audio_buffer_pool,
|
||||||
uint16_t volume);
|
uint16_t volume);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Generates a 1 KHz sine wave PWM-signal at GPIO-pin 'GP0'
|
/** \brief Generates a sine wave PWM-signal at GPIO-pin 'GP0'
|
||||||
*
|
*
|
||||||
* \param[in, out] audio_buffer_pool The pool of audio buffers to be used for rendering the sine audio signal
|
* \param[in, out] audio_buffer_pool The pool of audio buffers to be used for rendering the sine audio signal
|
||||||
|
* \param[in] freq_in_hz The frequency of the sine wave to be generated (in Hz)
|
||||||
* \param[in] volume The volume level of the generated signal (0 ... 256)
|
* \param[in] volume The volume level of the generated signal (0 ... 256)
|
||||||
*/
|
*/
|
||||||
void aprs_pico_send1kHz(audio_buffer_pool_t* audio_buffer_pool, uint16_t volume);
|
void aprs_pico_send_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz, uint16_t volume);
|
||||||
|
|
||||||
#endif // APRS_PICO_H
|
#endif // APRS_PICO_H
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Project 'raspi-pico-aprs-tnc'
|
* Project 'raspi-pico-aprs-tnc'
|
||||||
* Copyright (C) 2021 Thomas Glau, DL3TG
|
* Copyright (C) 2021-2023 Thomas Glau, DL3TG
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -108,7 +108,7 @@ static void aprs_pico_initClock(unsigned int sample_freq_in_hz)
|
||||||
* \param[in] pcm_data The PCM audio samples to be rendered
|
* \param[in] pcm_data The PCM audio samples to be rendered
|
||||||
* \param[in] num_samples The number of PCM audio samples to be rendered
|
* \param[in] num_samples The number of PCM audio samples to be rendered
|
||||||
* \param[in] volume The volume level of the generated AFSK signal (0 ... 256)
|
* \param[in] volume The volume level of the generated AFSK signal (0 ... 256)
|
||||||
* \param[in] is_loop_forever If 'true', the rendering of the audio samples will be continuously repeated
|
* \param[in] is_loop_forever If 'true', rendering of the audio samples will be continuously repeated
|
||||||
*/
|
*/
|
||||||
static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool, const int16_t* pcm_data,
|
static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool, const int16_t* pcm_data,
|
||||||
unsigned int num_samples, uint16_t volume, bool is_loop_forever)
|
unsigned int num_samples, uint16_t volume, bool is_loop_forever)
|
||||||
|
@ -116,24 +116,25 @@ static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool,
|
||||||
assert(audio_buffer_pool != NULL);
|
assert(audio_buffer_pool != NULL);
|
||||||
assert(pcm_data != NULL);
|
assert(pcm_data != NULL);
|
||||||
|
|
||||||
unsigned int pos = 0u;
|
unsigned int idx_src = 0u;
|
||||||
bool is_keep_going = true;
|
bool is_keep_going = true;
|
||||||
|
|
||||||
|
// Write the PCM sample data into the audio buffer(s) while applying the 'volume' value
|
||||||
while (is_keep_going)
|
while (is_keep_going)
|
||||||
{
|
{
|
||||||
audio_buffer_t* buffer = take_audio_buffer(audio_buffer_pool, true);
|
audio_buffer_t* audio_buffer = take_audio_buffer(audio_buffer_pool, true);
|
||||||
int16_t* samples = (int16_t*)buffer->buffer->bytes;
|
int16_t* audio_buffer_pcm_data = (int16_t*)audio_buffer->buffer->bytes;
|
||||||
|
|
||||||
for (unsigned int i = 0u; i < buffer->max_sample_count; i++)
|
for (unsigned int idx_dst = 0u; idx_dst < audio_buffer->max_sample_count; idx_dst++)
|
||||||
{
|
{
|
||||||
samples[i] = ((int32_t)volume * (int32_t)pcm_data[pos]) >> 8u;
|
audio_buffer_pcm_data[idx_dst] = ((int32_t)volume * (int32_t)pcm_data[idx_src]) >> 8u;
|
||||||
pos++;
|
idx_src++;
|
||||||
|
|
||||||
if (pos == num_samples)
|
if (idx_src == num_samples)
|
||||||
{
|
{
|
||||||
if (is_loop_forever)
|
if (is_loop_forever)
|
||||||
{
|
{
|
||||||
pos = 0u;
|
idx_src = 0u;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -143,8 +144,8 @@ static void aprs_pico_renderAudioSamples(audio_buffer_pool_t* audio_buffer_pool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->sample_count = buffer->max_sample_count;
|
audio_buffer->sample_count = audio_buffer->max_sample_count;
|
||||||
give_audio_buffer(audio_buffer_pool, buffer);
|
give_audio_buffer(audio_buffer_pool, audio_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,34 +177,36 @@ audio_buffer_pool_t* aprs_pico_init()
|
||||||
|
|
||||||
|
|
||||||
// See the header file for documentation
|
// See the header file for documentation
|
||||||
void aprs_pico_send1kHz(audio_buffer_pool_t* audio_buffer_pool, uint16_t volume)
|
void aprs_pico_send_sine_wave(audio_buffer_pool_t* audio_buffer_pool, unsigned int freq_in_hz, uint16_t volume)
|
||||||
{
|
{
|
||||||
assert(audio_buffer_pool != NULL);
|
assert(audio_buffer_pool != NULL);
|
||||||
|
|
||||||
// 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
|
||||||
unsigned int sample_freq_in_hz = APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ;
|
const unsigned int SAMPLE_FREQ_IN_HZ = APRS_PICO__PICO_EXTRA_AUDIO_PWM_LIB_FIXED_SAMPLE_FREQ_IN_HZ;
|
||||||
|
const unsigned int num_samples_per_period = SAMPLE_FREQ_IN_HZ / freq_in_hz;
|
||||||
|
|
||||||
aprs_pico_initClock(sample_freq_in_hz);
|
typedef int16_t wave_table_value_t;
|
||||||
|
const wave_table_value_t WAVE_TABLE_VALUE_MAX = INT16_MAX;
|
||||||
|
|
||||||
const unsigned int TONE_FREQ_IN_HZ = 1000u;
|
|
||||||
const unsigned int num_samples = sample_freq_in_hz / TONE_FREQ_IN_HZ;
|
|
||||||
|
|
||||||
int16_t* sine_wave_table = malloc(num_samples * sizeof(int16_t));
|
aprs_pico_initClock(SAMPLE_FREQ_IN_HZ);
|
||||||
|
|
||||||
if (!sine_wave_table)
|
wave_table_value_t* sine_period_wave_table = malloc(num_samples_per_period * sizeof(wave_table_value_t));
|
||||||
|
|
||||||
|
if (sine_period_wave_table == NULL)
|
||||||
{
|
{
|
||||||
panic("Out of memory: malloc() failed.\n");
|
panic("Out of memory: malloc() failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0u; i < num_samples; i++)
|
for (unsigned int i = 0u; i < num_samples_per_period; i++)
|
||||||
{
|
{
|
||||||
sine_wave_table[i] = (int16_t)(32767.0f * sinf(2.0f * (float)M_PI * (float)i / (float)num_samples));
|
sine_period_wave_table[i] = (wave_table_value_t)((float)WAVE_TABLE_VALUE_MAX * sinf(2.0f * (float)M_PI * (float)i / (float)num_samples_per_period));
|
||||||
}
|
}
|
||||||
|
|
||||||
aprs_pico_renderAudioSamples(audio_buffer_pool, sine_wave_table, num_samples, volume, true);
|
aprs_pico_renderAudioSamples(audio_buffer_pool, sine_period_wave_table, num_samples_per_period, volume, true);
|
||||||
|
|
||||||
free(sine_wave_table);
|
free(sine_period_wave_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Project 'raspi-pico-aprs-tnc'
|
* Project 'raspi-pico-aprs-tnc'
|
||||||
* Copyright (C) 2021 Thomas Glau, DL3TG
|
* Copyright (C) 2021-2023 Thomas Glau, DL3TG
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,9 +31,10 @@ int main()
|
||||||
|
|
||||||
#if (SINE_WAVE_TEST == 1)
|
#if (SINE_WAVE_TEST == 1)
|
||||||
|
|
||||||
const uint16_t VOLUME = 128u;
|
const unsigned int FREQ_IN_HZ = 1000u;
|
||||||
|
const uint16_t VOLUME = 128u;
|
||||||
|
|
||||||
aprs_pico_send1kHz(audio_buffer_pool, VOLUME);
|
aprs_pico_send_sine_wave(audio_buffer_pool, FREQ_IN_HZ, VOLUME);
|
||||||
|
|
||||||
#else // !SINE_WAVE_TEST
|
#else // !SINE_WAVE_TEST
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue