Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-m committed Nov 17, 2024
0 parents commit 2e644a5
Show file tree
Hide file tree
Showing 19 changed files with 1,633 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)

project(hsdaoh-rp2350 C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()

add_compile_options(-Wall)

include_directories(
include
)

add_subdirectory(libpicohsdaoh)
add_subdirectory(apps)
28 changes: 28 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
BSD 3-Clause License

Copyright (c) 2024 by Steve Markgraf

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# hsdaoh-rp2350 - High Speed Data Acquisition over HDMI
## Stream up to 75 MByte/s from your Raspberry Pi Pico2 to your PC

Using $5 USB3 HDMI capture sticks based on the MacroSilicon MS2130, this project allows to stream out up to 75 MByte/s of real time data from an RP2350 (with overclocking) to a host computer with USB3.
For more information and the host library, see the [main repository](https://github.com/steve-m/hsdaoh) and the [talk at OsmoDevcon '24](https://media.ccc.de/v/osmodevcon2024-200-low-cost-high-speed-data-acquisition-over-hdmi).

![Raspberry Pi Pico2 with MS2130 stick](https://steve-m.de/projects/hsdaoh/pico2_hsdaoh.jpg)

## Building

Make sure you have the latest version of the [pico-sdk](https://github.com/raspberrypi/pico-sdk) installed together with an appropriate compiler. You should be able to build the [pico-examples](https://github.com/raspberrypi/pico-examples).

To build hsdaoh-rp2350:

git clone https://github.com/steve-m/hsdaoh-rp2350.git
mkdir hsdaoh-rp2350/build
cd hsdaoh-rp2350/build
export PICO_SDK_PATH=/<path-to>/pico-sdk
cmake -DPICO_PLATFORM=rp2350 -DPICO_BOARD=pico2 ../
make -j 8

After the build succeeds you can copy the resulting *.uf2 file of the application you want to run to the board.

Apart from the Pico2 with the [Pico-DVI-Sock](https://github.com/Wren6991/Pico-DVI-Sock), it also should work with the Adafruit Feather RP2350 with HSTX Port, but so far only the Pico2 was tested.

## Example applications

The repository contains a library - libpicohsdaoh - which implements the main functionality. It reads the data from a ringbuffer, and streams it out via the HSTX port.
In addition to that, the apps folder contains a couple of example applications:

### counter

This application uses the PIO to generate a 16-bit counter value which is written to a DMA ringbuffer, which is then streamed out via hsdaoh. The counter can be verified using the hsdaoh_test host application.

### internal_adc

The data from the internal ADC is streamed out via USB. Default configuration is overclocking the ADC to 3.33 MS/s. Using the USB PLL and overvolting beyond VREG_VOLTAGE_MAX, up to 7.9 MS/s can be achieved.

### external_adc

This app contains a PIO program that reads the data from a 12-bit ADC connected to GP0-GP11, outputs the ADC clock on GP22, and packs the 12 bit samples to 16-bit words to achieve maximum throughput.
It is meant to be used with cheap AD9226 ADC boards. The default setting is overclocking the RP2350 to 320 MHz and driving the ADC with a 40 MHz clock. With higher overclocking up to 50.25 MHz ADC clock can be used.
This can be used for sampling the IF of a tuner/downcoverter, as a direct-sampling HF SDR, or for capturing a video signal e.g. with [vhsdecode](https://github.com/oyvindln/vhs-decode).

![Pico2 with AD9226 ADC board](https://steve-m.de/projects/hsdaoh/rp2350_external_adc.jpg)

## Credits

hsdaoh-rp2350 is developed by Steve Markgraf, and is based on the [dvi_out_hstx_encoder](https://github.com/raspberrypi/pico-examples/tree/master/hstx/dvi_out_hstx_encoder) example, and code by Shuichi Takano [implementing the HDMI data island encoding](https://github.com/shuichitakano/pico_lib/blob/master/dvi/data_packet.cpp), required to send HDMI info frames.
3 changes: 3 additions & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_subdirectory(counter)
add_subdirectory(external_adc)
add_subdirectory(internal_adc)
21 changes: 21 additions & 0 deletions apps/counter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
add_executable(counter
counter.c
)

target_compile_options(counter PRIVATE -Wall)

target_link_libraries(counter
pico_stdlib
pico_multicore
pico_util
hardware_pio
hardware_dma
libpicohsdaoh
)
pico_generate_pio_header(counter ${CMAKE_CURRENT_LIST_DIR}/counter.pio)

# enable usb output, disable uart output
pico_enable_stdio_usb(counter 1)

# create map/bin/hex file etc.
pico_add_extra_outputs(counter)
136 changes: 136 additions & 0 deletions apps/counter/counter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* hsdaoh - High Speed Data Acquisition over MS213x USB3 HDMI capture sticks
* Implementation for the Raspberry Pi RP2350 HSTX peripheral
*
* PIO counter value example, counter can be verified with hsdaoh_test
*
* Copyright (c) 2024 by Steve Markgraf <[email protected]>
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors may
* be used to endorse or promote products derived from this software
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#include "pico/stdlib.h"
#include "hardware/clocks.h"
#include "hardware/irq.h"
#include "hardware/sync.h"
#include "hardware/vreg.h"
#include "hardware/dma.h"
#include "hardware/pio.h"

#include "picohsdaoh.h"
#include "counter.pio.h"

#define SYS_CLK 250000

#define DMACH_PIO_PING 0
#define DMACH_PIO_PONG 1

static bool pio_dma_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN];
int ringbuf_head = 0;

void __scratch_y("") pio_dma_irq_handler()
{
uint ch_num = pio_dma_pong ? DMACH_PIO_PONG : DMACH_PIO_PING;
dma_channel_hw_t *ch = &dma_hw->ch[ch_num];
dma_hw->intr = 1u << ch_num;
pio_dma_pong = !pio_dma_pong;

ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES;

ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = RBUF_DATA_LEN;

hsdaoh_update_head(ringbuf_head);
}

void init_pio_input(void)
{
PIO pio = pio0;
uint offset = pio_add_program(pio, &counter_program);
uint sm_data = pio_claim_unused_sm(pio, true);
counter_program_init(pio, sm_data, offset);

dma_channel_config c;
c = dma_channel_get_default_config(DMACH_PIO_PING);
channel_config_set_chain_to(&c, DMACH_PIO_PONG);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm_data, false));
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
channel_config_set_transfer_data_size(&c, DMA_SIZE_16);

dma_channel_configure(
DMACH_PIO_PING,
&c,
&ringbuffer[0 * RBUF_SLICE_LEN],
&pio->rxf[sm_data],
RBUF_DATA_LEN,
false
);
c = dma_channel_get_default_config(DMACH_PIO_PONG);
channel_config_set_chain_to(&c, DMACH_PIO_PING);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm_data, false));
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
channel_config_set_transfer_data_size(&c, DMA_SIZE_16);

dma_channel_configure(
DMACH_PIO_PONG,
&c,
&ringbuffer[1 * RBUF_SLICE_LEN],
&pio->rxf[sm_data],
RBUF_DATA_LEN,
false
);

dma_hw->ints0 |= (1u << DMACH_PIO_PING) | (1u << DMACH_PIO_PONG);
dma_hw->inte0 |= (1u << DMACH_PIO_PING) | (1u << DMACH_PIO_PONG);
irq_set_exclusive_handler(DMA_IRQ_0, pio_dma_irq_handler);
irq_set_enabled(DMA_IRQ_0, true);

dma_channel_start(DMACH_PIO_PING);
}

int main()
{
set_sys_clock_khz(SYS_CLK, true);

/* set HSTX clock to sysclk/2 */
hw_write_masked(
&clocks_hw->clk[clk_hstx].div,
2 << CLOCKS_CLK_HSTX_DIV_INT_LSB,
CLOCKS_CLK_HSTX_DIV_INT_BITS
);

stdio_init_all();

hsdaoh_init(ringbuffer);
hsdaoh_start();
init_pio_input();

while (1)
__wfi();
}
42 changes: 42 additions & 0 deletions apps/counter/counter.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
;
; Copyright (c) 2024 Steve Markgraf <[email protected]>
;
; SPDX-License-Identifier: BSD-3-Clause
;
; Generate 16 bit counter in PIO
;

.pio_version 0
.program counter

public entry_point:

.wrap_target
jmp x-- dummylabel
dummylabel:
mov isr, ~x
push
.wrap

% c-sdk {
static inline void counter_program_init(PIO pio, uint sm, uint offset)
{
pio_sm_config c = counter_program_get_default_config(offset);

sm_config_set_in_shift(
&c,
false, // Shift-to-right = false (i.e. shift to left)
false, // Autopush enabled
1 // Autopush threshold, ignored
);

// disable the TX FIFO to make the RX FIFO deeper.
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);

sm_config_set_clkdiv(&c, 4.f);

// Load our configuration, and start the program from the beginning
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}
20 changes: 20 additions & 0 deletions apps/external_adc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
add_executable(external_adc
external_adc.c
)

target_compile_options(external_adc PRIVATE -Wall)

target_link_libraries(external_adc
pico_stdlib
pico_util
hardware_pio
hardware_dma
libpicohsdaoh
)
pico_generate_pio_header(external_adc ${CMAKE_CURRENT_LIST_DIR}/adc_12bit_input.pio)

# enable usb output, disable uart output
pico_enable_stdio_usb(external_adc 1)

# create map/bin/hex file etc.
pico_add_extra_outputs(external_adc)
Loading

0 comments on commit 2e644a5

Please sign in to comment.