element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
RoadTests & Reviews
  • Products
  • More
RoadTests & Reviews
Review Blogs Giga Oscilloscope
  • Blogs
  • RoadTest Forum
  • Documents
  • RoadTests
  • Reviews
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join RoadTests & Reviews to participate - click to join for free!
  • Share
  • More
  • Cancel
  • Author Author: dougw
  • Date Created: 2 Dec 2025 9:13 PM Date Created
  • Views 58 views
  • Likes 7 likes
  • Comments 1 comment
Related
Recommended
  • Arduino Giga Oscilloscope Demo
  • dougw

Giga Oscilloscope

dougw
dougw
2 Dec 2025

Intro

The last demo I want to show in this road test is an oscilloscope application. The Arduino Giga with its display has the infrastructure to implement an oscilloscope function so I wanted to include a quick demo of this in action.. This demo simply captures samples from the ADC and displays them on screen.

This program uses the touch screen to control the time scale, the amplitude and the trigger.

image

GIGA Scope Video

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Giga Scope Sketch

/*
  Giga Display Oscilloscope
  by Doug Wong 2025
  - Continuous plotting of ADC (A0) on 800x480 Landscape.
  - Scanline refresh (Erase old pixel -> Draw new pixel).
  - Touch Controls:
    1. Bottom (0-700px, H=50): Sets Delay (0-100us)
    2. Right (W=50, H=480): Sets Gain (0.1x - 1.0x)
    3. Leftt (W=50, H=480): Sets Trigger (0 - 480)
    Touch the screen to update signal trace - stop touching to freeze the trace
*/

#include "Arduino_GigaDisplay_GFX.h"
#include "Arduino_H7_Video.h"
#include "Arduino_GigaDisplayTouch.h"

GigaDisplay_GFX display;

// --- Configuration ---
#define SCREEN_WIDTH  800
#define SCREEN_HEIGHT 480
#define ADC_PIN       A0

// UI Dimensions
#define BOTTOM_TOUCH_WIDTH 700
#define BOTTOM_TOUCH_HEIGHT 50
#define RIGHT_TOUCH_WIDTH  50
#define RIGHT_TOUCH_HEIGHT 480

// Colors
#define COLOR_BG    0x0000 // Black
#define COLOR_TRACE 0x07E0 // Green
#define COLOR_TEXT  0xFFFF // White
#define COLOR_UI    0x3333 // Dark Grey (for UI guides)

// --- Objects ---
Arduino_H7_Video Display(800, 480, GigaDisplayShield);
Arduino_GigaDisplayTouch Touch;

// --- Global Variables ---
uint16_t signalBuffer[SCREEN_WIDTH]; // Stores Y-coordinates of the previous scan
int currentX = 0;
int rawADC;
int tADC;
int lastADC;

// Oscilloscope Settings
unsigned long sampleDelayMicros = 0; // 0 to 130 microseconds
float gain = 0.1;                    // 0.1 to 1.0
int gaini;
int trigger = 200;

// Helper to track previous touch state to avoid flickering UI updates
int lastTouchZoneDelay = -1;
int lastTouchZoneGain = -1;
uint8_t contacts;
GDTpoint_t points[5];

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
  // Initialize Serial (Optional for debug)
  Serial.begin(115200);

  // Initialize Display
  Display.begin();
  display.begin();
  display.setRotation(1);
  display.fillScreen(COLOR_BG);

  // Initialize Touch
  Touch.begin();

  // Configure ADC
  analogReadResolution(12); // 0-4095
  pinMode(ADC_PIN, INPUT);

  // Initialize Buffer (Center screen initially)
  for (int i = 0; i < SCREEN_WIDTH; i++) {
    signalBuffer[i] = SCREEN_HEIGHT / 2;
  }
  
  // Draw UI Guidelines (Optional: Visual indicators for touch areas)
  gaini = gain * 10;
//  drawInterfaceGuides();
  updateStatsOnScreen();
}

void loop() {
  // 1. Handle Touch Input (Check strictly before sampling to adjust params)
  handleTouch();

//  tADC = analogRead(ADC_PIN);
//  if (tADC > lastADC && tADC > trigger) {
 for (int X = 0; X < SCREEN_WIDTH; X++) {

  // Perform Trace Update

  // 2. Capture New Sample
  rawADC = analogRead(ADC_PIN);

  // 3. Erase the pixel from the previous scan at this X position
  display.drawPixel(X, signalBuffer[X], COLOR_BG);

  // 4. Calculate Logic
  int newY = SCREEN_HEIGHT - round(rawADC * gain);
  
  // 5. Draw New Pixel
  display.drawPixel(X, newY, COLOR_TRACE);

  // 6. Update Buffer
  signalBuffer[X] = newY;

  // 7. Apply Sample Delay
  if (sampleDelayMicros > 0) {
    delayMicroseconds(sampleDelayMicros);
  }
 }
//}
//  lastADC = tADC;
//  display.fillRect(0, 20, 2, 2, COLOR_BG);     //need to isplay something for the drawPixel activity to be displayed
}

void handleTouch() {

  // Read touch points
  contacts = Touch.getTouchPoints(points);

  if (contacts > 0) {
    int ty = SCREEN_HEIGHT - points[0].x;
    int tx = points[0].y;

    // --- Check Bottom Area (Delay Control) ---
    // Area: x[0-700], y[430-480] (Bottom 50px)
    if (tx > 50 && tx < BOTTOM_TOUCH_WIDTH && ty > (SCREEN_HEIGHT - BOTTOM_TOUCH_HEIGHT)) {
      // 14 Zones, 50px wide each. 
      int zone = (tx - 50) / 50; 
      if (zone > 12) zone = 12;

      // Map zone 0-13 to 0-56 microseconds (step of 4)
      sampleDelayMicros = zone * 10;
    }

    // --- Check Right Area (Gain Control) ---
    // Area: x[750-800], y[0-480]
    else if (tx >= (SCREEN_WIDTH - RIGHT_TOUCH_WIDTH)) {
      // 12 Zones, 40px high each.
      int zone = (SCREEN_HEIGHT - ty) / 40;
      if (zone > 11) zone = 11;

      // Map zone 0-11 to Gain 0.1 - 1.0
      // We have 12 steps to cover range 0.9. 
      // Step size approx 0.081. 
      // Simple linear mapping: 0.1 + (zone / 11.0) * 0.9
      gain = 0.1 + ((float)zone / 11.0) * 0.9;
    }

        // --- Check Leftt Area (Trigger Control) ---
    // Area: x[0-50], y[0-480]
    else if (tx < (50)) {

      trigger = SCREEN_HEIGHT - points[0].x;
    }
      updateStatsOnScreen();
  }
}

// Draws visual markers so you know where to touch
void drawInterfaceGuides() {
    // Divider for Bottom Area
    display.drawLine(0, SCREEN_HEIGHT - BOTTOM_TOUCH_HEIGHT, BOTTOM_TOUCH_WIDTH, SCREEN_HEIGHT - BOTTOM_TOUCH_HEIGHT, COLOR_UI);
    // Ticks for Bottom Area
    for(int i=0; i<=14; i++) {
        display.drawLine(i*50, SCREEN_HEIGHT - BOTTOM_TOUCH_HEIGHT, i*50, SCREEN_HEIGHT, COLOR_UI);
    }

    // Divider for Right Area
    display.drawLine(SCREEN_WIDTH - RIGHT_TOUCH_WIDTH, 0, SCREEN_WIDTH - RIGHT_TOUCH_WIDTH, SCREEN_HEIGHT, COLOR_UI);
    // Ticks for Right Area
    for(int i=0; i<=12; i++) {
        display.drawLine(SCREEN_WIDTH - RIGHT_TOUCH_WIDTH, i*40, SCREEN_WIDTH, i*40, COLOR_UI);
    }
}

// Displays current settings in top left corner
void updateStatsOnScreen() {
    // Simple text overlay to show current settings
    // We draw a black box first to erase old text
    display.fillRect(0, 0, 300, 20, COLOR_BG); 
    
    display.setCursor(0, 0);
    display.setTextSize(2);
    display.setTextColor(COLOR_UI);
    
    display.print("Delay: ");
    display.print(sampleDelayMicros);
    display.print("us | Gain: ");
    gaini = (1.1 - gain) * 10;
    display.print(gaini);
}

The scope function is very screen-centric. Since the display is 800x480, every trace has exactly 800 samples, which are also stored in a buffer so that the pixel at each of the 800 positions may be erased before being replaced by a new sample. This way, the whole screen does not need to be redrawn, just the pixel that is changing.

The ADC is being run with 12 bit resolution (4096 counts full scale), which is almost 10 times more that the 480 pixel LCD can display,  480 counts of a possible 4096 times 3.3 volts (the ADC max) gives  0.387 Volts at 1 ADC count per pixel. This means we want a maximum gain to correspond to 0.387 Volts providing 480 counts. At the minimum gain we want 4096 counts to correspond to 480 pixels. The touch slider on the right of the screen is actually set up to go from a gain of 0.1 to a gain of 1 times the ADC reading, but this is displayed as a gain of 1 to 10, just to keep the display simple.

The time scale is also based on Giga performance. The loop to capture an ADC sample, delete the old sample and display the new one has a minimum period. This period can be extended from 0 microseconds to 120 microseconds using the invisible slider at the bottom of the screen. I tried graticule marks on the screen, but got rid of them because the aesthetic cost outweighed the marginal benefit.

The trigger slider is on the left. It simply picks which vertical pixel will be used as the trace trigger.

Discussion

I liked that the Giga and its display are fast enough to make a low frequency scope function, although my implementation leaves  a lot to be desired. I learned a few things about how hard it would be to make a siick scope, which is always good, and I am happy that this sketch at least provides some proof that a scope function is possible.

In looking at the video, I probably should have chosen a white scope trace instead of green - it would have been s bit brighter. It looks great to the human eye - just the camera had a hard time showing the trace.

Links:

Unboxing and display demo

Touch Screen and USB memory demo

GIGA display of an Arducam video camera

GIGA VU Meter and Spectrum Analyzer

GIGA WAV Player

GIGA HID Touch Keyboard

GIGA MQTT Client

Giga Paint

Giga Scope

Final Giga Road Test Blog

Giga R1 Road Test page

  • Sign in to reply
  • DAB
    DAB 15 hours ago

    Well done Douglas.

    Back in 1983 I programmed an early attempt at a digital oscilloscope to analyze radar patterns using a Z80.

    For the time we did quite well.

    The GIGA implementation is very good compared to what we achieved.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube