Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/instructions/cpp-style.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ Always put the macro name in the closing comment:
#endif /* SOME_OPTION */
```

## Preferences

Prefer a `switch` statement over a long `if`/`else if` chain.

## Doxygen API documentation

Public **declarations** (in `.h`) carry a full Doxygen block; **definitions**
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ OldQtCode/
WorkingDocs
**/imgui.ini

# Extracted FX2 firmware (redistribution rights are not established)
firmware/*
!firmware/.gitkeep

20 changes: 18 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ FetchContent_MakeAvailable(imgui)
find_package(OpenGL REQUIRED)
find_package(SDL2 REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(Threads REQUIRED)
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0)

set(APP_NAME run)
Expand All @@ -32,7 +33,9 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O2")

set(SOURCES_LIST
app/main.cpp
usb/usb_device.cpp
usb/src/usb_device.cpp
usb/src/firmware_loader.cpp
capture/acquisition_loop.cpp
${imgui_SOURCE_DIR}/imgui.cpp
${imgui_SOURCE_DIR}/imgui_draw.cpp
${imgui_SOURCE_DIR}/imgui_tables.cpp
Expand All @@ -42,7 +45,9 @@ set(SOURCES_LIST
)

set(HEADERS_LIST
usb/usb_device.h
usb/inc/usb_device.h
usb/inc/firmware_loader.h
capture/acquisition_loop.h
)

if(CMAKE_BUILD_TYPE MATCHES "Debug")
Expand All @@ -59,8 +64,18 @@ endif()

add_executable(${APP_NAME} ${SOURCES_LIST})

add_custom_command(
TARGET ${APP_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/oscilloscope.bmp
$<TARGET_FILE_DIR:${APP_NAME}>/oscilloscope.bmp
VERBATIM
)

target_include_directories(${APP_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/usb/inc
${imgui_SOURCE_DIR}
${imgui_SOURCE_DIR}/backends
)
Expand All @@ -69,5 +84,6 @@ target_link_libraries(${APP_NAME} PRIVATE
SDL2::SDL2
OpenGL::GL
PkgConfig::LIBUSB
Threads::Threads
)

86 changes: 84 additions & 2 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,90 @@ Records key decisions, structural changes, and completed development stages.
- Added a Linux udev rule for non-root DSO-2250 access through libusb.
- Verified the connect/disconnect lifecycle with a connected Hantek DSO-2250.

## 2026-09-02

### Research - FX2 firmware upload requirement

- Investigated the old code for a host "presence ping" that would explain the
DSO-2250 status LED behavior (red blink on USB link, green blink on host
activity, long red+green during data bursts).
- Found no dedicated ping command: `HantekDSOAThread::run()` in
`OldQtCode/src/hantekdsoathread.cpp` polls `dsoGetCaptureState` in a loop
with a `msleep(timeBase)` delay; the repeated bulk transaction itself is
what the firmware reports as host activity.
- Found that the DSO-2250 uses a Cypress EZ-USB FX2 chip with RAM-resident
firmware. `OldQtCode/dsoextractfw/HantekDSO.rules` uploads
`DSO2250_firmware.hex` and `DSO2250_loader.hex` through `fxload` on every
USB "add" event; `OldQtCode/dsoextractfw/dsoextractfw.c` extracts those hex
files from the official Windows driver (`1.SYS`).
- Until firmware is uploaded, the device stays in a bare bootloader state:
no status LED activity and no working bulk endpoints. This explains the
LED blinking seen on Windows (official driver uploads firmware
automatically) versus no blinking on Linux with the current codebase (no
firmware upload step exists yet, and no `.hex` firmware files are present
in this repository).
- The firmware `.hex` files are not included because the official installer
prohibits unauthorized redistribution; they must be extracted from a
user's copy of the official Windows driver before the USB layer can work
end-to-end.

## 2026-09-04

### Stage 3 - Endpoint read loop complete

- Corrected the extracted DSO-2250 loader and firmware images and verified
their Intel HEX checksums; the files remain excluded from Git because
redistribution rights have not been established.
- Added support for the operational `04b5:2250` identity alongside the
`04b4:2250` bootloader identity.
- Wait for FX2 re-enumeration with bounded polling after firmware upload and
reconnect to the operational device on interface 0, alternate setting 0.
- Extended the supplied udev rule to grant access to both USB identities.
- Added vendor control-transfer helpers and the DSO-2250 initialization
sequence required before endpoint polling.
- Implemented a dedicated acquisition thread that sends the capture-state
request to bulk endpoint `0x02` and reads 512-byte responses from endpoint
`0x86`.
- Added successful-poll, transfer-error, and last-capture-state tracking with
thread-safe counters.
- Made endpoint activity follow the Start/Stop lifecycle instead of beginning
at Connect; Stop, Disconnect, mode changes, application shutdown, and device
loss stop and join the acquisition thread before releasing USB resources.
- Disabled Start until a live device is connected and disabled device rescans
while a connection is active.
- Select Live mode at startup when a supported device is present, otherwise
retain Demo mode.

### Hardware verification

- Verified firmware re-enumeration from `04b4:2250` to `04b5:2250` on a
physical Hantek DSO-2250.
- Verified successful `B3`, `B2`, bulk OUT, and 512-byte bulk IN transfers.
- Confirmed the instrument LED lifecycle: red after Connect, green during
Start/acquisition, red after Stop, and off after Disconnect.

### Firmware extractor repair

- Added a maintained extraction utility under `tools/` for users who possess
the official `Dso2250x861.sys` Windows driver.
- Fixed the historical extractor's unhandled padding byte, which inserted an
extra zero and dropped the final data byte in every Intel HEX record.
- Skip empty 22-byte separator records instead of emitting invalid
`:0000000000` lines.
- Fixed loader range calculation and added validation for record layout, EOF
records, and generated checksums.
- Verified extraction from the official `Dso2250x861.sys` driver end to end;
both generated HEX files match the hardware-tested files byte for byte.

### USB module structure

- Moved USB headers to `usb/inc/` and implementations to `usb/src/` after the
module grew beyond a single source/header pair.
- Updated CMake source lists, include directories, and dependent includes for
the new layout.

### Next USB tasks

- Read endpoint data chunks in a dedicated acquisition path.
- Decode capture-state responses and acquired sample packets.
- Add buffering between USB reads and waveform processing.
- Handle timeouts, I/O errors, disconnects, and recovery states.
- Add automatic recovery for transfer errors and unexpected disconnections.
69 changes: 56 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ is developed independently and has no Qt dependency.

## Status

Current version: `0.2.0`.
Current version: `0.2.2`.

The current iteration provides the first UI shell:
The current iteration provides a working USB connection and endpoint polling
path for the Hantek DSO-2250:

- CMake build configuration for C++14;
- `Debug` and `Release` build targets;
- a Makefile and Bash build script for Linux;
- an SDL2 window with an OpenGL 3 context;
- Dear ImGui integration, a menu, control panel, status line, and display grid;
- a pinned Dear ImGui source dependency (`v1.90.9`) fetched by CMake.
- a pinned Dear ImGui source dependency (`v1.90.9`) fetched by CMake;
- discovery and connection through libusb;
- FX2 firmware upload and operational-device re-enumeration;
- a Start/Stop-controlled acquisition thread that polls the bulk endpoints;
- poll and transfer-error counters in the status line.

The shell provides presentation-only controls for acquisition state, demo mode,
timebase, and the two channel scales. USB acquisition and waveform processing
are planned for later iterations.
The application starts in Live mode when a supported device is present and in
Demo mode otherwise. Connecting prepares the device; endpoint traffic begins
only after pressing Start and stops after pressing Stop.

## Planned Stack

Expand All @@ -44,8 +49,11 @@ Oscilloscope/
├── core/ Shared types and application logic.
├── docs/ Project documentation.
├── render/ Oscilloscope waveform rendering.
├── tools/ Optional firmware extraction utilities.
├── ui/ User interface.
├── usb/ USB device communication.
│ ├── inc/ USB module headers.
│ └── src/ USB module implementations.
├── WorkingDocs/ Technical specification and device documentation.
├── OldQtCode/ Historical Qt4/KDE4 reference implementation.
├── CMakeLists.txt CMake build configuration.
Expand All @@ -63,28 +71,63 @@ The current application requires:
- SDL2 development files;
- OpenGL development files.
- libusb-1.0 development files.
- `fxload` for uploading the RAM-resident FX2 firmware.
- binutils development files for building the optional firmware extractor.

On Debian, Ubuntu, and Linux Mint:

```bash
sudo apt-get update
sudo apt-get install build-essential cmake make pkg-config libsdl2-dev libgl1-mesa-dev libusb-1.0-0-dev
sudo apt-get install build-essential cmake make pkg-config libsdl2-dev \
libgl1-mesa-dev libusb-1.0-0-dev fxload binutils-dev
```

Dear ImGui is downloaded automatically by CMake during configuration.

### Hantek DSO-2250 USB Access

Linux requires a udev rule for a regular desktop user to open the Hantek device
through libusb. Install the supplied rule, reload udev rules, then reconnect the
oscilloscope:
through libusb. The rule covers both the `04b4:2250` bootloader identity and the
`04b5:2250` operational identity. Install the supplied rule, reload udev rules,
then reconnect the oscilloscope:

```bash
sudo cp usb/80-hantek-dso-2250.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
```

### Hantek DSO-2250 Firmware

The official installer states that unauthorized reproduction or distribution
of the program, or any portion of it, is prohibited. Because separate firmware
redistribution rights have not been established, the extracted firmware is not
stored in this repository. Supply the files at these default paths:

```text
firmware/DSO2250_loader.hex
firmware/DSO2250_firmware.hex
```

Set `OSCILLOSCOPE_FIRMWARE_DIR` to use another directory. On Connect, the
application uploads the firmware to a `04b4:2250` device with `fxload`, waits
for it to re-enumerate as `04b5:2250`, and then opens the operational device.

The repository provides a repaired extractor for users who have the official
32-bit Windows driver. Locate `Dso2250x861.sys` in the extracted driver package,
then run:

```bash
mkdir -p firmware Output
cc -std=c11 -Wall -Wextra -Wpedantic tools/dsoextractfw.c \
-o Output/dsoextractfw -lbfd
./Output/dsoextractfw /path/to/Dso2250x861.sys firmware
```

The utility validates record sizes, Intel HEX record types, and EOF records,
and calculates checksums while writing `DSO2250_firmware.hex` and
`DSO2250_loader.hex`.

## Build

### Makefile
Expand Down Expand Up @@ -171,10 +214,10 @@ CI can update only the version metadata by passing `--skip-build`.

## Next Steps

1. Add a demo waveform to the display grid.
2. Implement a two-channel model, timebase, and basic controls.
3. Add libusb support and a safe acquisition thread.
4. Handle device disconnection and fallback to demo mode.
1. Decode capture-state responses and acquired sample packets.
2. Add buffering between USB acquisition and waveform processing.
3. Render live and demo waveforms on the display grid.
4. Implement the two-channel model, timebase, and instrument controls.

The full goals, constraints, and architecture are documented in
`WorkingDocs/TECHNICAL_SPECIFICATION.md`.
Expand Down
Loading
Loading