Skip to content

Commit

Permalink
[NF] Support for 7-segment display (#9)
Browse files Browse the repository at this point in the history
Added basic support for 7-segment display.
The colon delimiter is not yet properly handled, but digits and dots should work.
  • Loading branch information
matgla authored Dec 8, 2024
1 parent 45698b9 commit 756a132
Show file tree
Hide file tree
Showing 34 changed files with 705 additions and 103 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pico-examples
robot_output.xml
report.html
mono_crash*
.DS_Store
.DS_Store
venv
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,19 @@ inside renode console:
```
and open localhost:8080 in your web browser.

Current visualization is ugly, but it works!
Layouts are defined by user and can be saved in JSON file with `save` button inside `layout` section.

Loading is supported from website or with `visualizationLoadLayout @path_to_file` command.

Elements on PCB can be marked as board elements with `visualizationSetBoardElement <name>` command.
But they are not rendered yet. This is planned feature.

Example GUI may look like shown below:
![gui](./images/gui_example.png)

## Known bugs
There is a bug that sometimes 7-segment display is not rendered correctly.
Zooming or refreshing browser seems to fix the problem as a workaround.

# Multi Node simulation.
Many RP2040 simulators may interwork together. I am using that possibility in full MSPC simulation. To interwork between them GPIOConnector may be used, please check existing usage (`simulation` directory):
Expand Down
5 changes: 4 additions & 1 deletion cores/initialize_peripherals.resc
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@ include $ORIGIN/../emulation/peripherals/watchdog/rp2040_watchdog.cs
include $ORIGIN/../emulation/peripherals/i2c/rp2040_i2c.cs

include $ORIGIN/../emulation/externals/pcf8523.cs
include $ORIGIN/../emulation/externals/segment_display.cs
EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.Miscellaneous.SegmentDisplay"

include $ORIGIN/../emulation/peripherals/psm/rp2040_psm.cs

include $ORIGIN/../emulation/peripherals/psm/rp2040_psm.cs
98 changes: 98 additions & 0 deletions emulation/externals/segment_display.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using Antmicro.Renode.Core;
using Antmicro.Renode.Logging;

namespace Antmicro.Renode.Peripherals.Miscellaneous
{
public class SegmentDisplay : IPeripheral, IGPIOReceiver
{
public SegmentDisplay(int segments = 7, int cells = 1, int colon = 0)
{
sync = new object();
NumberOfSegments = segments;
NumberOfCells = cells;
Colon = colon;
this.segments = new bool[NumberOfSegments];
this.cells = new bool[NumberOfCells];
Reset();
}

public void Reset()
{
for (int c = 0; c < NumberOfCells; ++c)
{
this.cells[c] = false;
}

for (int s = 0; s < NumberOfSegments; ++s)
{
this.segments[s] = false;
}
}

public void OnGPIO(int number, bool value)
{
if (number >= NumberOfSegments + NumberOfCells)
{
return;
}

// if cells change
if (number < NumberOfCells)
{
SetCell(number, value);
}
else
{
SetSegment(number - NumberOfCells, value);
}
}

public event Action<SegmentDisplay, bool[], bool[]> StateChanged;

public void SetSegment(int number, bool state)
{
lock (sync)
{
if (segments[number] != state)
{
segments[number] = state;
StateChanged?.Invoke(this, cells, segments);
this.Log(LogLevel.Noisy, "Segment[{0}] state changed to: {1}", number, state);
}
}
}

public void SetCell(int number, bool state)
{
lock (sync)
{
if (cells[number] != state)
{
cells[number] = state;
StateChanged?.Invoke(this, cells, segments);
this.Log(LogLevel.Noisy, "Cell[{0}] state changed to: {1}", number, state);
}
}
}

public bool[] Segments
{
get => segments;
}

public bool[] Cells
{
get => cells;
}


public readonly int NumberOfSegments;
public readonly int NumberOfCells;
public readonly int Colon;

private readonly object sync;
private bool[] segments;
private bool[] cells;
}
}
Empty file.
Binary file added images/gui_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added visualization/assets/7segment.afdesign
Binary file not shown.
29 changes: 29 additions & 0 deletions visualization/assets/7segment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added visualization/assets/7segment_separator.afdesign
Binary file not shown.
13 changes: 13 additions & 0 deletions visualization/assets/7segment_separator.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 44 additions & 4 deletions visualization/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
import sys

sys.path.append(script_dir)
visualizationPath = None
os.chdir(script_dir)

from Antmicro.Renode.Peripherals.Miscellaneous import LED
from Antmicro.Renode.Peripherals.Miscellaneous import Button

import Antmicro.Renode.Peripherals.Miscellaneous

from Antmicro.Renode.Core import MachineStateChangedEventArgs

from threading import Thread
Expand All @@ -42,6 +44,13 @@
layout = None


def convert_to_array(o):
arr = []
for e in o:
arr.append(e)
return arr


def led_state_change(led, state):
sendMessage({
"msg": "state_change",
Expand All @@ -51,6 +60,16 @@ def led_state_change(led, state):
})


def segment_display_state_changed(display, cells, segments):
sendMessage({
"msg": "state_change",
"peripheral_type": "segment_display",
"name": machine.GetLocalName(display),
"cells": convert_to_array(cells),
"segments": convert_to_array(segments),
})


def process_message(msg):
if msg["type"] == "action":
if msg["target"] == "button":
Expand All @@ -62,7 +81,6 @@ def process_message(msg):

def mc_setVisualizationPath(path):
print("Visualization will be served from: " + path)
visualizationPath = path
os.chdir(path)


Expand All @@ -86,12 +104,18 @@ def mc_stopVisualization():


def machine_state_changed(machine, state):
print("state: ", state)
if state.CurrentState == MachineStateChangedEventArgs.State.Disposed:
print("Dispose visualization")
mc_stopVisualization()


def machine_find_peripheral_type(machine, name):
for peri in machine.GetRegisteredPeripherals():
if name in str(peri.Type):
return peri.Type
return None


def mc_startVisualization(port):
global process
global machine
Expand Down Expand Up @@ -129,10 +153,24 @@ def mc_startVisualization(port):
"msg": "register",
"peripheral_type": "button",
"name": machine.GetLocalName(button),
"state": led.State,
})
buttons[machine.GetLocalName(button)] = button

SegmentDisplay = machine_find_peripheral_type(
machine, "Miscellaneous.SegmentDisplay"
)
segmentDisplays = machine.GetPeripheralsOfType[SegmentDisplay]()
for display in segmentDisplays:
sendMessage({
"msg": "register",
"peripheral_type": "segment_display",
"name": machine.GetLocalName(display),
"segments": convert_to_array(display.Segments),
"cells": convert_to_array(display.Cells),
"colon": display.Colon,
})
display.StateChanged += segment_display_state_changed

if layout is not None:
sendMessage({"msg": "load_layout", "file": layout})

Expand All @@ -153,10 +191,12 @@ def mc_visualizationLoadLayout(file):

sendMessage({"msg": "load_layout", "file": layout})


def mc_visualizationSetBoardElement(name):
print("Setting board element: " + name)
sendMessage({"msg": "set_board_element", "name": name})


def sendMessage(message):
global process
if process.poll() is None:
Expand Down
14 changes: 8 additions & 6 deletions visualization/visualization/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
{
"files": {
"main.css": "/static/css/main.7bab5a1f.css",
"main.js": "/static/js/main.75be53a9.js",
"main.css": "/static/css/main.25333aef.css",
"main.js": "/static/js/main.233f68a9.js",
"static/media/Raspberry_Pi_Pico_top.png": "/static/media/Raspberry_Pi_Pico_top.e33f028f5df6fa7a8812.png",
"static/media/breadboard.svg": "/static/media/breadboard.0b169a51ffbe1f7f8bd530e8f6cb7ed8.svg",
"static/media/7segment.svg": "/static/media/7segment.4e0006b1fe808cef9373e141218a4d64.svg",
"static/media/button.svg": "/static/media/button.477b4b211bc442f2c7af47352b66f76c.svg",
"static/media/led.svg": "/static/media/led.4768c0df04932f68cd84bba91e9f7349.svg",
"static/media/7segment_separator.svg": "/static/media/7segment_separator.4e74319228a46dc74746ad8d50353228.svg",
"index.html": "/index.html",
"main.7bab5a1f.css.map": "/static/css/main.7bab5a1f.css.map",
"main.75be53a9.js.map": "/static/js/main.75be53a9.js.map"
"main.25333aef.css.map": "/static/css/main.25333aef.css.map",
"main.233f68a9.js.map": "/static/js/main.233f68a9.js.map"
},
"entrypoints": [
"static/css/main.7bab5a1f.css",
"static/js/main.75be53a9.js"
"static/css/main.25333aef.css",
"static/js/main.233f68a9.js"
]
}
2 changes: 1 addition & 1 deletion visualization/visualization/build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.75be53a9.js"></script><link href="/static/css/main.7bab5a1f.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.233f68a9.js"></script><link href="/static/css/main.25333aef.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

This file was deleted.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 756a132

Please sign in to comment.