# Custom 7- segment display

**URL:** https://discourse.processing.org/t/custom-7-segment-display/49045
**Category:** Processing for Android
**Created:** [July 24, 2026, 7:56pm UTC](https://discourse.processing.org/t/custom-7-segment-display/49045 "2026-07-24T19:56:31Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [July 24, 2026, 7:56pm UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/1 "2026-07-24T19:56:31Z")

</div>

```auto

import processing.sound.*; 

AudioIn mic;
Waveform waveform;
int numSamples = 1024; 
float sampleRate = 44100; 
float smoothedFreq = 0; 

boolean[][] segments = {
  {true, true, true, true, true, true, false}, 
  {false, true, true, false, false, false, false}, 
  {true, true, false, true, true, false, true }, 
  {true, true, true, true, false, false, true }, 
  {false, true, true, false, false, true, true }, 
  {true, false, true, true, false, true, true }, 
  {true, false, true, true, true, true, true }, 
  {true, true, true, false, false, false, false}, 
  {true, true, true, true, true, true, true }, 
  {true, true, true, true, false, true, true }  
};

void setup() {
  size(displayWidth, displayHeight);
  frameRate(30); 
  
  mic = new AudioIn(this, 0);
  mic.start();
  
  waveform = new Waveform(this, numSamples);
  waveform.input(mic);
}

void draw() {
  background(10, 20, 10); 
  
  waveform.analyze();
  
  float totalPeriodsSamples = 0;
  int crossingCount = 0;
  float lastCrossingTime = -1;
  float maxPeak = 0;
  
  for (int i = 1; i < numSamples; i++) {
    float prev = waveform.data[i - 1];
    float curr = waveform.data[i];
    
    if (abs(curr) > maxPeak) maxPeak = abs(curr);
    
    if ((prev >= 0 && curr < 0) || (prev < 0 && curr >= 0)) {
      float fraction = abs(prev) / (abs(prev) + abs(curr));
      float exactCrossingTime = (i - 1) + fraction;
      
      if (lastCrossingTime != -1) {
        totalPeriodsSamples += (exactCrossingTime - lastCrossingTime);
        crossingCount++;
      }
      lastCrossingTime = exactCrossingTime;
    }
  }
  
  float frequencyHz = 0;
  if (crossingCount > 0 && totalPeriodsSamples > 0) {
    float avgHalfPeriod = totalPeriodsSamples / crossingCount;
    frequencyHz = sampleRate / (2.0 * avgHalfPeriod);
  }
  
  if (frequencyHz > 20000) frequencyHz = 20000;
  if (maxPeak < 0.015 || crossingCount < 2) frequencyHz = 0;
  
  smoothedFreq = lerp(smoothedFreq, frequencyHz, 0.25);
  
  float boxW = width * 0.85;
  float boxH = height * 0.35;
  float boxX = (width - boxW) / 2;
  float boxY = (height - boxH) / 2;
  
  stroke(0, 120, 30);
  strokeWeight(5);
  fill(5, 15, 5);
  rect(boxX, boxY, boxW, boxH, 15);
  
  noStroke();
  if ((frameCount / 6) % 2 == 0 && maxPeak > 0.015) {
    fill(0, 255, 50); 
  } else {
    fill(5, 40, 10);  
  }
  ellipse(boxX + 40, boxY + 40, 15, 15);
  fill(0, 200, 40);
  textSize(24);
  text("GATE", boxX + 65, boxY + 48);
  
  float w = boxW * 0.11;    
  float h = w * 1.8; 
  float spacing = w * 0.22;  
  float totalDigitsW = (w * 5) + (spacing * 4);
  float startX = boxX + (boxW - totalDigitsW) / 2;
  float digitsY = boxY + (boxH - h) / 2 + 10;
  
  int displayVal = int(smoothedFreq);
  int d5 = (displayVal / 10000) % 10; 
  int d4 = (displayVal / 1000) % 10;  
  int d3 = (displayVal / 100) % 10;   
  int d2 = (displayVal / 10) % 10;    
  int d1 = displayVal % 10;           
  
  drawSevenSegment(startX, digitsY, w, h, d5);
  drawSevenSegment(startX + (w + spacing), digitsY, w, h, d4);
  
  drawDecimalDot(startX + (w + spacing) * 2 - (spacing / 2), digitsY + h, w);
  
  drawSevenSegment(startX + (w + spacing) * 2, digitsY, w, h, d3);
  drawSevenSegment(startX + (w + spacing) * 3, digitsY, w, h, d2);
  drawSevenSegment(startX + (w + spacing) * 4, digitsY, w, h, d1);
  
  fill(0, 255, 50);
  textSize(35);
  text("kHz", boxX + boxW - 80, boxY + boxH - 35);
  
  fill(0, 100, 25);
  textSize(22);
  text("SIGNAL LEVEL", boxX + 40, boxY + boxH - 35);
  
  float barMaxW = boxW * 0.45;
  float barW = map(maxPeak, 0, 0.5, 0, barMaxW);
  barW = constrain(barW, 0, barMaxW);
  
  stroke(0, 60, 15);
  strokeWeight(2);
  noFill();
  rect(boxX + 220, boxY + boxH - 52, barMaxW, 18, 3);
  
  noStroke();
  fill(0, 255, 50);
  rect(boxX + 222, boxY + boxH - 50, barW, 14, 2);
}

void drawSevenSegment(float x, float y, float w, float h, int num) {
  float t = w * 0.16; 
  float g = 1.5;      
  
  color onColor = color(0, 255, 50);  
  color offColor = color(5, 30, 10); 
  
  noStroke();
  pushMatrix();
  translate(x, y);
  shearX(radians(-7)); 
  
  fill(segments[num][0] ? onColor : offColor);
  beginShape(); vertex(t + g, 0); vertex(w - t - g, 0); vertex(w - (t/2) - g, t/2); vertex(w - t - g, t); vertex(t + g, t); vertex((t/2) + g, t/2); endShape(CLOSE);
  
  fill(segments[num][1] ? onColor : offColor);
  beginShape(); vertex(w, t + g); vertex(w, (h/2) - (t/2) - g); vertex(w - (t/2), (h/2) - g); vertex(w - t, (h/2) - (t/2) - g); vertex(w - t, t + g); vertex(w - (t/2), (t/2) + g); endShape(CLOSE);
  
  fill(segments[num][2] ? onColor : offColor);
  beginShape(); vertex(w, (h/2) + (t/2) + g); vertex(w, h - t - g); vertex(w - (t/2), h - (t/2) - g); vertex(w - t, h - t - g); vertex(w - t, (h/2) + (t/2) + g); vertex(w - (t/2), (h/2) + g); endShape(CLOSE);
  
  fill(segments[num][3] ? onColor : offColor);
  beginShape(); vertex(t + g, h - t); vertex(w - t - g, h - t); vertex(w - (t/2) - g, h - (t/2)); vertex(w - t - g, h); vertex(t + g, h); vertex((t/2) + g, h - (t/2)); endShape(CLOSE);
  
  fill(segments[num][4] ? onColor : offColor);
  beginShape(); vertex(t, (h/2) + (t/2) + g); vertex(t, h - t - g); vertex(t/2, h - (t/2) - g); vertex(0, h - t - g); vertex(0, (h/2) + (t/2) + g); vertex(t/2, (h/2) + g); endShape(CLOSE);
  
  fill(segments[num][5] ? onColor : offColor);
  beginShape(); vertex(t, t + g); vertex(t, (h/2) - (t/2) - g); vertex(t/2, (h/2) - g); vertex(0, (h/2) - (t/2) - g); vertex(0, t + g); vertex(t/2, (t/2) + g); endShape(CLOSE);
  
  fill(segments[num][6] ? onColor : offColor);
  beginShape(); vertex(t + g, (h/2) - (t/2)); vertex(w - t - g, (h/2) - (t/2)); vertex(w - (t/2) - g, h/2); vertex(w - t - g, (h/2) + (t/2)); vertex(t + g, (h/2) + (t/2)); vertex((t/2) + g, h/2); endShape(CLOSE);
  
  popMatrix();
}

void drawDecimalDot(float x, float y, float w) {
  float dotSize = w * 0.15;
  fill(0, 255, 50); 
  noStroke();
  rect(x, y - dotSize, dotSize, dotSize, 1);
}

```

 ![Screenshot_2026-07-24-22-43-12-040](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/3/9/3934bf6c54fe35340d667f9dae7d57affc69f9aa.jpeg)

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [July 25, 2026, 12:52am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/2 "2026-07-25T00:52:18Z")

</div>

I am unable to run the demo in Android mode with Processing 4.5.6 on MacOS (M4 Tahoe 26.5) and get this error message:

```processing
Build folder: /var/folders/x2/hwxvmv9s6t16_tkw9tgmbp040000gn/T/android737348970227068550sketch
Exception in thread "Thread-54" java.lang.NullPointerException: Cannot read the array length because "list" is null
	at processing.app.Library.wrapFiles(Library.java:429)
	at processing.app.Library.getApplicationExports(Library.java:439)
	at processing.mode.android.AndroidBuild.copyImportedLibs(AndroidBuild.java:839)
	at processing.mode.android.AndroidBuild.createAppModule(AndroidBuild.java:481)
	at processing.mode.android.AndroidBuild.createProject(AndroidBuild.java:262)
	at processing.mode.android.AndroidBuild.build(AndroidBuild.java:223)
	at processing.mode.android.AndroidMode.handleRunDevice(AndroidMode.java:294)
	at processing.mode.android.AndroidEditor$17.run(AndroidEditor.java:421)

```

I get the same error message if I run the following reference code in Android mode:

```processing
import processing.sound.*;

void setup() {
  Sound.list();
}

```

I am using a Samsung A8 tablet. There is no microphone connected to it. What type of device are you running the code on and does it have a microphone attached to it (or use an internal microphone)?

**Addendum:**

Runs without error in Java mode. Numbers change if I add a microphone.

 ![sevenSeg](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/0/f/0f8f984e51576322943dd55f0412fc06f2944d71.png)

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [July 25, 2026, 2:10am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/3 "2026-07-25T02:10:17Z")

</div>

Cool beans!

Android phone:

 ![Screenshot_20260724-220300.sketch_260724b](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/9/a/9a1ba8a0f5b525659efe5a2e1a87f55fbaf86e63.png)

_[A440 (pitch standard) - Wikipedia](https://en.wikipedia.org/wiki/A440_(pitch_standard))_

I got it to work with:

- Processing 4.5.6 and Processing 4.3.4 for W10
- Android Mode 4.6.1
- Sound Library 2.3.1
- Applying necessary permissions for microphone.

> **\*\*\* Update \*\*\*\***
>
> There is a [sound-android.zip](https://github.com/processing/processing-sound/releases/download/v2.4.0/sound-android.zip) that is available in the assets here:
> 
> [https://github.com/processing/processing-sound/releases#release-v2.4.0](https://github.com/processing/processing-sound/releases#release-v2.4.0)
> 
> See comment here:  
> [Implement audio file decoding support on Android using MediaCodec · Issue #86 · processing/processing-sound · GitHub](https://github.com/processing/processing-sound/issues/86#issuecomment-5086403049)
> 
> I recommend keeping a separate sketchbook folder for Android sketches.

`:)`

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [July 25, 2026, 2:55am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/4 "2026-07-25T02:55:13Z")

</div>

My tablet android 8 the sketch works without errors on APDE 5.1

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [July 25, 2026, 2:56am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/5 "2026-07-25T02:56:21Z")

</div>

@glv As always you are creative

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [July 25, 2026, 5:15am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/6 "2026-07-25T05:15:54Z")

</div>

I finally got it to run in Windows 11. Error messages from Processing 4.5.6 were helpful. I was referred to Examples/Libraries/Sound/IO/AudioInputAndroid. Based on these suggestions I added an initialize function and microphone permissions as shown below:

**Modified source code:**

```processing
import processing.sound.*; 

AudioIn mic;
Waveform waveform;

AudioIn input;
Amplitude loudness;

int numSamples = 1024; 
float sampleRate = 44100; 
float smoothedFreq = 0; 

boolean[][] segments = {
  {true, true, true, true, true, true, false}, 
  {false, true, true, false, false, false, false}, 
  {true, true, false, true, true, false, true }, 
  {true, true, true, true, false, false, true }, 
  {false, true, true, false, false, true, true }, 
  {true, false, true, true, false, true, true }, 
  {true, false, true, true, true, true, true }, 
  {true, true, true, false, false, false, false}, 
  {true, true, true, true, true, true, true }, 
  {true, true, true, true, false, true, true }  
};

void setup() {
  size(displayWidth, displayHeight);
  frameRate(30); 
    if (hasPermission("android.permission.RECORD_AUDIO")) {
    initialize(true);
  } else {
    requestPermission("android.permission.RECORD_AUDIO", "initialize");
  }
 // input = new AudioIn(this, 0);
 // input.start();
  
  waveform = new Waveform(this, numSamples);
  waveform.input(input);
}

void initialize(boolean granted) {
  if (!granted) {
    return;
  }

  // Create an Audio input and grab the 1st channel
  input = new AudioIn(this, 0);

  // Begin capturing the audio input
  input.start();
  // start() activates audio capture so that you can use it as
  // the input to live sound analysis, but it does NOT cause the
  // captured audio to be played back to you. if you also want the
  // microphone input to be played back to you, call
  // input.play();
  // instead (be careful with your speaker volume, you might produce
  // painful audio feedback. best to first try it out wearing headphones!)

  // Create a new Amplitude analyzer
  loudness = new Amplitude(this);

  // Patch the input to the volume analyzer
  loudness.input(input);
}

void draw() {
  background(10, 20, 10); 
  
  waveform.analyze();
  
  float totalPeriodsSamples = 0;
  int crossingCount = 0;
  float lastCrossingTime = -1;
  float maxPeak = 0;
  
  for (int i = 1; i < numSamples; i++) {
    float prev = waveform.data[i - 1];
    float curr = waveform.data[i];
    
    if (abs(curr) > maxPeak) maxPeak = abs(curr);
    
    if ((prev >= 0 && curr < 0) || (prev < 0 && curr >= 0)) {
      float fraction = abs(prev) / (abs(prev) + abs(curr));
      float exactCrossingTime = (i - 1) + fraction;
      
      if (lastCrossingTime != -1) {
        totalPeriodsSamples += (exactCrossingTime - lastCrossingTime);
        crossingCount++;
      }
      lastCrossingTime = exactCrossingTime;
    }
  }
  
  float frequencyHz = 0;
  if (crossingCount > 0 && totalPeriodsSamples > 0) {
    float avgHalfPeriod = totalPeriodsSamples / crossingCount;
    frequencyHz = sampleRate / (2.0 * avgHalfPeriod);
  }
  
  if (frequencyHz > 20000) frequencyHz = 20000;
  if (maxPeak < 0.015 || crossingCount < 2) frequencyHz = 0;
  
  smoothedFreq = lerp(smoothedFreq, frequencyHz, 0.25);
  
  float boxW = width * 0.85;
  float boxH = height * 0.35;
  float boxX = (width - boxW) / 2;
  float boxY = (height - boxH) / 2;
  
  stroke(0, 120, 30);
  strokeWeight(5);
  fill(5, 15, 5);
  rect(boxX, boxY, boxW, boxH, 15);
  
  noStroke();
  if ((frameCount / 6) % 2 == 0 && maxPeak > 0.015) {
    fill(0, 255, 50); 
  } else {
    fill(5, 40, 10);  
  }
  ellipse(boxX + 40, boxY + 40, 15, 15);
  fill(0, 200, 40);
  textSize(24);
  text("GATE", boxX + 65, boxY + 48);
  
  float w = boxW * 0.11;    
  float h = w * 1.8; 
  float spacing = w * 0.22;  
  float totalDigitsW = (w * 5) + (spacing * 4);
  float startX = boxX + (boxW - totalDigitsW) / 2;
  float digitsY = boxY + (boxH - h) / 2 + 10;
  
  int displayVal = int(smoothedFreq);
  int d5 = (displayVal / 10000) % 10; 
  int d4 = (displayVal / 1000) % 10;  
  int d3 = (displayVal / 100) % 10;   
  int d2 = (displayVal / 10) % 10;    
  int d1 = displayVal % 10;           
  
  drawSevenSegment(startX, digitsY, w, h, d5);
  drawSevenSegment(startX + (w + spacing), digitsY, w, h, d4);
  
  drawDecimalDot(startX + (w + spacing) * 2 - (spacing / 2), digitsY + h, w);
  
  drawSevenSegment(startX + (w + spacing) * 2, digitsY, w, h, d3);
  drawSevenSegment(startX + (w + spacing) * 3, digitsY, w, h, d2);
  drawSevenSegment(startX + (w + spacing) * 4, digitsY, w, h, d1);
  
  fill(0, 255, 50);
  textSize(35);
  text("kHz", boxX + boxW - 80, boxY + boxH - 35);
  
  fill(0, 100, 25);
  textSize(22);
  text("SIGNAL LEVEL", boxX + 40, boxY + boxH - 35);
  
  float barMaxW = boxW * 0.45;
  float barW = map(maxPeak, 0, 0.5, 0, barMaxW);
  barW = constrain(barW, 0, barMaxW);
  
  stroke(0, 60, 15);
  strokeWeight(2);
  noFill();
  rect(boxX + 220, boxY + boxH - 52, barMaxW, 18, 3);
  
  noStroke();
  fill(0, 255, 50);
  rect(boxX + 222, boxY + boxH - 50, barW, 14, 2);
}

void drawSevenSegment(float x, float y, float w, float h, int num) {
  float t = w * 0.16; 
  float g = 1.5;      
  
  color onColor = color(0, 255, 50);  
  color offColor = color(5, 30, 10); 
  
  noStroke();
  pushMatrix();
  translate(x, y);
  shearX(radians(-7)); 
  
  fill(segments[num][0] ? onColor : offColor);
  beginShape(); vertex(t + g, 0); vertex(w - t - g, 0); vertex(w - (t/2) - g, t/2); vertex(w - t - g, t); vertex(t + g, t); vertex((t/2) + g, t/2); endShape(CLOSE);
  
  fill(segments[num][1] ? onColor : offColor);
  beginShape(); vertex(w, t + g); vertex(w, (h/2) - (t/2) - g); vertex(w - (t/2), (h/2) - g); vertex(w - t, (h/2) - (t/2) - g); vertex(w - t, t + g); vertex(w - (t/2), (t/2) + g); endShape(CLOSE);
  
  fill(segments[num][2] ? onColor : offColor);
  beginShape(); vertex(w, (h/2) + (t/2) + g); vertex(w, h - t - g); vertex(w - (t/2), h - (t/2) - g); vertex(w - t, h - t - g); vertex(w - t, (h/2) + (t/2) + g); vertex(w - (t/2), (h/2) + g); endShape(CLOSE);
  
  fill(segments[num][3] ? onColor : offColor);
  beginShape(); vertex(t + g, h - t); vertex(w - t - g, h - t); vertex(w - (t/2) - g, h - (t/2)); vertex(w - t - g, h); vertex(t + g, h); vertex((t/2) + g, h - (t/2)); endShape(CLOSE);
  
  fill(segments[num][4] ? onColor : offColor);
  beginShape(); vertex(t, (h/2) + (t/2) + g); vertex(t, h - t - g); vertex(t/2, h - (t/2) - g); vertex(0, h - t - g); vertex(0, (h/2) + (t/2) + g); vertex(t/2, (h/2) + g); endShape(CLOSE);
  
  fill(segments[num][5] ? onColor : offColor);
  beginShape(); vertex(t, t + g); vertex(t, (h/2) - (t/2) - g); vertex(t/2, (h/2) - g); vertex(0, (h/2) - (t/2) - g); vertex(0, t + g); vertex(t/2, (t/2) + g); endShape(CLOSE);
  
  fill(segments[num][6] ? onColor : offColor);
  beginShape(); vertex(t + g, (h/2) - (t/2)); vertex(w - t - g, (h/2) - (t/2)); vertex(w - (t/2) - g, h/2); vertex(w - t - g, (h/2) + (t/2)); vertex(t + g, (h/2) + (t/2)); vertex((t/2) + g, h/2); endShape(CLOSE);
  
  popMatrix();
}

void drawDecimalDot(float x, float y, float w) {
  float dotSize = w * 0.15;
  fill(0, 255, 50); 
  noStroke();
  rect(x, y - dotSize, dotSize, dotSize, 1);
}  

```

**Sketch permissions added:**

```processing
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"/>
    <uses-permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>

```

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [July 25, 2026, 5:33am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/7 "2026-07-25T05:33:00Z")

</div>

Excellent work. The idea is not about reading the frequency; the idea is to design a 7-segment display without using special files, font libraries, or character libraries.

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [July 25, 2026, 8:15am UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/8 "2026-07-25T08:15:11Z")

</div>

This is really neat. 🥳

I tried it on 4.5.2 and it didn’t initially work because it didn’t like `size()` inside the `setup` method so I changed it to

```auto
void settings(){
    size(displayWidth, displayHeight);
}

void setup() {

  frameRate(30); 

```

and it worked a treat 👌😀👍

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [July 25, 2026, 1:32pm UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/9 "2026-07-25T13:32:23Z")

</div>

Just curious; what operating system are you using (and if Apple which chip)?

---

<div class="post-metadata">

### Author: ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)
#### Post date: [July 25, 2026, 2:46pm UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/10 "2026-07-25T14:46:45Z")

</div>

> [@jafal](#):
>
> the idea is to design a 7-segment display without using special files, font libraries, or character libraries.

If you’re just interested in the display and not frequencies, something like this seems to work ok (even on a M4 mac):

```processing
boolean[][] segments = {
  {true, true, true, true, true, true, false},
  {false, true, true, false, false, false, false},
  {true, true, false, true, true, false, true },
  {true, true, true, true, false, false, true },
  {false, true, true, false, false, true, true },
  {true, false, true, true, false, true, true },
  {true, false, true, true, true, true, true },
  {true, true, true, false, false, false, false},
  {true, true, true, true, true, true, true },
  {true, true, true, true, false, true, true }
};

void settings() {
  fullScreen();
}

void setup() {
  frameRate(10);
}

void draw() {
  background(10, 20, 10);

  float boxW = width * 0.85;
  float boxH = height * 0.35;
  float boxX = (width - boxW) / 2;
  float boxY = (height - boxH) / 2;

  stroke(0, 120, 30);
  strokeWeight(5);
  fill(5, 15, 5);
  rect(boxX, boxY, boxW, boxH, 15);

  noStroke();

  ellipse(boxX + 40, boxY + 40, 15, 15);
  fill(0, 200, 40);

  float w = boxW * 0.11;
  float h = w * 1.8;
  float spacing = w * 0.22;
  float totalDigitsW = (w * 5) + (spacing * 4);
  float startX = boxX + (boxW - totalDigitsW) / 2;
  float digitsY = boxY + (boxH - h) / 2 + 10;

  int displayVal = int(random(99000));
  int d5 = (displayVal / 10000) % 10;
  int d4 = (displayVal / 1000) % 10;
  int d3 = (displayVal / 100) % 10;
  int d2 = (displayVal / 10) % 10;
  int d1 = displayVal % 10;

  drawSevenSegment(startX, digitsY, w, h, d5);
  drawSevenSegment(startX + (w + spacing), digitsY, w, h, d4);

  drawDecimalDot(startX + (w + spacing) * 2 - (spacing / 2), digitsY + h, w);

  drawSevenSegment(startX + (w + spacing) * 2, digitsY, w, h, d3);
  drawSevenSegment(startX + (w + spacing) * 3, digitsY, w, h, d2);
  drawSevenSegment(startX + (w + spacing) * 4, digitsY, w, h, d1);

  stroke(0, 60, 15);
  strokeWeight(2);
  noFill();

  noStroke();
  fill(0, 255, 50);
}

void drawSevenSegment(float x, float y, float w, float h, int num) {
  float t = w * 0.16;
  float g = 1.5;

  color onColor = color(0, 255, 50);
  color offColor = color(5, 30, 10);

  noStroke();
  pushMatrix();
  translate(x, y);
  shearX(radians(-7));

  fill(segments[num][0] ? onColor : offColor);
  beginShape();
  vertex(t + g, 0);
  vertex(w - t - g, 0);
  vertex(w - (t/2) - g, t/2);
  vertex(w - t - g, t);
  vertex(t + g, t);
  vertex((t/2) + g, t/2);
  endShape(CLOSE);

  fill(segments[num][1] ? onColor : offColor);
  beginShape();
  vertex(w, t + g);
  vertex(w, (h/2) - (t/2) - g);
  vertex(w - (t/2), (h/2) - g);
  vertex(w - t, (h/2) - (t/2) - g);
  vertex(w - t, t + g);
  vertex(w - (t/2), (t/2) + g);
  endShape(CLOSE);

  fill(segments[num][2] ? onColor : offColor);
  beginShape();
  vertex(w, (h/2) + (t/2) + g);
  vertex(w, h - t - g);
  vertex(w - (t/2), h - (t/2) - g);
  vertex(w - t, h - t - g);
  vertex(w - t, (h/2) + (t/2) + g);
  vertex(w - (t/2), (h/2) + g);
  endShape(CLOSE);

  fill(segments[num][3] ? onColor : offColor);
  beginShape();
  vertex(t + g, h - t);
  vertex(w - t - g, h - t);
  vertex(w - (t/2) - g, h - (t/2));
  vertex(w - t - g, h);
  vertex(t + g, h);
  vertex((t/2) + g, h - (t/2));
  endShape(CLOSE);

  fill(segments[num][4] ? onColor : offColor);
  beginShape();
  vertex(t, (h/2) + (t/2) + g);
  vertex(t, h - t - g);
  vertex(t/2, h - (t/2) - g);
  vertex(0, h - t - g);
  vertex(0, (h/2) + (t/2) + g);
  vertex(t/2, (h/2) + g);
  endShape(CLOSE);

  fill(segments[num][5] ? onColor : offColor);
  beginShape();
  vertex(t, t + g);
  vertex(t, (h/2) - (t/2) - g);
  vertex(t/2, (h/2) - g);
  vertex(0, (h/2) - (t/2) - g);
  vertex(0, t + g);
  vertex(t/2, (t/2) + g);
  endShape(CLOSE);

  fill(segments[num][6] ? onColor : offColor);
  beginShape();
  vertex(t + g, (h/2) - (t/2));
  vertex(w - t - g, (h/2) - (t/2));
  vertex(w - (t/2) - g, h/2);
  vertex(w - t - g, (h/2) + (t/2));
  vertex(t + g, (h/2) + (t/2));
  vertex((t/2) + g, h/2);
  endShape(CLOSE);

  popMatrix();
}

void drawDecimalDot(float x, float y, float w) {
  float dotSize = w * 0.15;
  fill(0, 255, 50);
  noStroke();
  rect(x, y - dotSize, dotSize, dotSize, 1);
}

```

It’s really impressive in java mode.

---

<div class="post-metadata">

### Author: ![jafal](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jafal/32/19112_2.png) [@jafal](https://discourse.processing.org/u/jafal)
#### Post date: [July 25, 2026, 11:02pm UTC](https://discourse.processing.org/t/custom-7-segment-display/49045/11 "2026-07-25T23:02:21Z")

</div>

I’m Using an 8-year-old Android 8.1 tablet with microcontrollers like Arduino or ESP is a great way to build many cheap projects without using an expensive Raspberry Pi or similar boards.

 ![tablet](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/9/d/9d365bf6d6484c15cf3757e39efc999b7b780ead.jpeg)

Edit : I’m often use APDE .
