Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
4f0a064
Updated gitignore for Maven/Java Projects
Mac-Coleman Nov 20, 2024
b068f22
First test of Java building with Maven
Mac-Coleman Nov 20, 2024
27580c1
Added commons-lang3 as a java dependency
Mac-Coleman Nov 20, 2024
0df91cb
Added Constants.java
Mac-Coleman Nov 20, 2024
ddd5d9c
Added prepare and teardown methods to java base class
Mac-Coleman Nov 20, 2024
d5ba3e0
Added a random java task
Mac-Coleman Nov 20, 2024
15fa27c
First working version of a java task
Mac-Coleman Nov 20, 2024
40876f1
Fixed name of task!
Mac-Coleman Nov 20, 2024
837a209
Added --no-upload flag
Mac-Coleman Nov 20, 2024
89b4595
Changed RainbowWaveJava to more accurately reflect the Python Rainbow…
Mac-Coleman Nov 20, 2024
ba9a671
Added py4j to setup.py
Mac-Coleman Nov 20, 2024
1a7e017
Added short bash script for compiling the java project
Mac-Coleman Nov 21, 2024
3be48d4
Added a basic setup script to move py4j to the maven repository!
Mac-Coleman Nov 21, 2024
2039cc8
Added new error messages for setup failure
Mac-Coleman Nov 21, 2024
c6d73dd
Added command to start java server
Mac-Coleman Nov 22, 2024
4e235b2
Automatically start and wait for gateway server, add --disable-java flag
Mac-Coleman Nov 22, 2024
682d0e5
Added maven to install script
Mac-Coleman Nov 22, 2024
cf5452c
Added setup and compile steps to install.sh
Mac-Coleman Nov 22, 2024
d789674
Merge branch 'main' into java
itsactuallyluna9 Nov 22, 2024
764b03c
fix screen manager in run_gif
itsactuallyluna9 Nov 22, 2024
732149f
Translated compile_java_project.sh to python
Mac-Coleman Nov 22, 2024
e82ff11
Translated start_java_server.sh to python
Mac-Coleman Nov 22, 2024
f01ba4b
Translated setup_java_project.sh to python
Mac-Coleman Nov 23, 2024
61af229
Make python main program run python java server, change simulator tas…
Mac-Coleman Nov 23, 2024
b52c661
Change install and start scripts to use python scripts for managing j…
Mac-Coleman Nov 23, 2024
1d7b124
Delete java-related shell scripts (replaced with Python)
Mac-Coleman Nov 23, 2024
825eb29
Changed error message to reflect new python script
Mac-Coleman Nov 23, 2024
d078f40
Used Py4J "Launch Gateway" method instead of custom subprocess.Popen …
Mac-Coleman Nov 25, 2024
72ccaf0
Remove tools/start_java_server.py
Mac-Coleman Nov 25, 2024
16224ca
fix paths
itsactuallyluna9 Dec 1, 2024
77b6dcf
Merge branch 'java' of https://github.com/CornellCollegeComputingClub…
Mac-Coleman Dec 2, 2024
97645ea
Revert "Merge branch 'java' of https://github.com/CornellCollegeCompu…
Mac-Coleman Dec 2, 2024
b386e44
Reapply fix paths
Mac-Coleman Dec 2, 2024
7cd5578
Returned Status from Java
Mac-Coleman Dec 2, 2024
f25171f
add really horrible memory stress test
itsactuallyluna9 Dec 2, 2024
97d2b8f
Bump Py4J version, update Java setup + compilation scripts
Mac-Coleman Feb 12, 2025
ec68b5e
Switch to BufferedImage + Add Lissajous task
Mac-Coleman Feb 12, 2025
77fa6fb
Added rainbow colors to Lissajous to demonstrate Java BufferedImage uses
Mac-Coleman Feb 12, 2025
b9c32f2
Fixed operating system compatibility in build scripts
Mac-Coleman Feb 13, 2025
b72296e
Fixed classpath to add commons-lang3 to py4j server
Mac-Coleman Feb 13, 2025
4da33c4
Fixed usage of JavaTaskBase's getLcdText method in python JavaTask class
Mac-Coleman Feb 13, 2025
31c2a76
Fixed JavaTaskBase getLcdText default implementation to match Python …
Mac-Coleman Feb 14, 2025
89bd6d4
Added task for testing panel synchronization
Mac-Coleman Feb 17, 2025
07ec244
Forgot to return true
Mac-Coleman Feb 17, 2025
64f71d9
Attempt to remove Neopixel class
Mac-Coleman Feb 18, 2025
d3fc55f
Forgot to save file :(
Mac-Coleman Feb 18, 2025
d5d7908
Fix types before turning to Color
Mac-Coleman Feb 18, 2025
58aec8d
Fix: slices are only for position
Mac-Coleman Feb 18, 2025
3f018af
fixed lambda definition
Mac-Coleman Feb 18, 2025
e31af7e
Deleted Neopixel class
Mac-Coleman Feb 18, 2025
3be9023
Added sleep implementation to MatrixScreen to match SimulatorScreen
Mac-Coleman Feb 18, 2025
3fdb291
Disable TimingTest
Mac-Coleman Feb 18, 2025
5a15d20
Disable JVMStressTest. I still need to implement ignored tasks in Java
Mac-Coleman Feb 18, 2025
02a85eb
Artificial Horizon Task
Mac-Coleman Feb 19, 2025
edb4277
Fix colors in java task
Mac-Coleman Feb 19, 2025
45c240d
Add option to specify starting task for faster testing
Mac-Coleman Feb 19, 2025
717bff8
Attempt gamma correction for sign
Mac-Coleman Feb 19, 2025
1ca74cb
Limit brightness during gamma correction
Mac-Coleman Feb 19, 2025
2b2c9a5
Make 16 colors in Rainbow Wave instead of twelve
Mac-Coleman Feb 19, 2025
73e5a4f
Fix broken condition in init_screen
Mac-Coleman Feb 19, 2025
0ac43a7
New Double Pendulum task to test basic Verlet integration physics
Mac-Coleman Feb 28, 2025
a3f880f
Fixed bug causing screen to not be updated before override with --sta…
Mac-Coleman Feb 28, 2025
3569402
Changing tasks that use complex numbers to use the python complex type
Mac-Coleman Sep 1, 2025
e8773f6
Fixed teardown methods for Java Tasks
Mac-Coleman Sep 3, 2025
e406025
Added linear motion constraint for Verlet Particles
Mac-Coleman Sep 3, 2025
8c36152
Added new "Cornell Gears" task
Mac-Coleman Sep 3, 2025
3508c7b
Finally updated the --gif option to use canonical names instead of cl…
Mac-Coleman Feb 10, 2026
e4942ec
Update main sign image
Mac-Coleman Feb 10, 2026
820ce2e
Updated README to have more thorough information about Java tasks
Mac-Coleman Feb 10, 2026
5721413
Updated documentation to explain why to choose Python or Java
Mac-Coleman Feb 10, 2026
2d22fc8
Updated to use canonical names where possible
Mac-Coleman Feb 10, 2026
09b885f
Updated matrix to use perf_counter_ns instead of arrow to reduce jitter
Mac-Coleman Feb 11, 2026
9db28e8
Forgot to use same units for delay
Mac-Coleman Feb 11, 2026
25762f2
Hitch-finding test
Mac-Coleman Feb 13, 2026
2f90532
Revert "Hitch-finding test"
Mac-Coleman Feb 13, 2026
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
48 changes: 48 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,51 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/


# Maven Projects ----------------------------------------------------------------------------------
# https://github.com/github/gitignore/blob/main/Maven.gitignore
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar

# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

# Java Projects -----------------------------------------------------------------------------------
# https://github.com/github/gitignore/blob/main/Java.gitignore
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
63 changes: 37 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# C4 Sign
funny sign go brrrrrrrr

![An image of the C4 Sign, displaying the C4 Logo](./docs/images/demo.jpg)
![An image of the C4 Sign, displaying the C4 Logo](./docs/images/demo.png)

The C4 Sign is an LED sign that students can write programs for to display at our events on campus!
Programs can be written in either Java or Python.
It features a 32x32 color LED display for graphics and a 16x2 character LCD screen for text.

If you are interested in writing a display program for it, please make a fork of this repository.
Expand All @@ -12,33 +13,23 @@ Get in touch with us if you have any questions or want advice for how to write y
The LED Sign channel of our discord server is a great place to get advice both from club executives and from other students.
Feel free to make whatever you like for the sign, this is a chance to use your programming skills to channel your creativity and self-expression!

# Installation and Setup
## Tutorial

Check [the tutorial](./docs/tutorial.md) to learn how you can begin writing your own sign programs.

# Program Examples
You can see simulated outputs of the display programs [here](./docs/screen_tasks.md).
If you want to see how each task works, the programs can be found in `/c4_sign/screen_tasks`.
## Program Examples
You can watch each display program [here](./docs/screen_tasks.md).
If you want to see how each task works, the programs can be found in `/c4_sign/screen_tasks` and `/c4_sign/java_c4sign/src/main/java/com/cornellcollegecomputingclub/c4sign_tasks`.

## Documentation
Our documentation is currently incomplete, but much of the screen's workings can be found in the `/docs/` directory.
See the [documentation home page](./docs/index.md).

## Simulator

The simulator is a simple program that simulates the sign. It's not perfect, but it's good enough for testing.
The simulator is a simple program that simulates the sign.
It allows you to write programs for the sign without physical access!

```bash
python3 -m pip install -e '.[simulator]'
python3 -m c4_sign --simulator
```

You can test the simulator at any time you like by running with the following command:
```bash
python3 -m c4_sign --simulator
```
This will open a new browser window where you can interact with the sign simulator. Currently, it looks like this:
![The simulator displaying the "pong" task](./docs/images/simulator.png)

It shows you a visualization of the 32 by 32 pixel matrix, and the attached 16x2 character LCD screen.
Expand All @@ -47,16 +38,7 @@ You can use the dropdown menu at the bottom to choose a task to run, then press
You can use the simulator to test out your program without needing to be near the sign all the time!
Whenever you make changes to your program, visualizing them is as simple as running the above command and selecting it in the simulator

## Real Sign

[To be written]

```bash
python3 -m pip install -e '.[physical]'
python3 -m c4_sign
```

# Wishlist
## Wishlist
The following is a list of programs that could be neat to have on our sign!
If you are unsure what to make, you can use the list below as inspiration.

Expand All @@ -71,6 +53,35 @@ If you are unsure what to make, you can use the list below as inspiration.

If you want to make something, but are struggling with ideas, feel free to reach out to us or ask in our Discord.

# Installation

In order to make a program that runs on the sign, you will have to locally install the sign software and simulator so that you can test your program.

Here's how you can install the C4 Sign software:

1. Make sure you have Python and Git installed. Python 3.9 or above should be good. *If you want to write your program with Java, which is recommended for graphics-intense tasks, make sure to also install Maven.*
2. Sign into Github and make a fork of this repository.
3. Navigate to the folder where you would like to download the software, and clone your fork of our git repository!
`git clone https://github.com/{Your username here}/c4-sign`
4. Enter the `c4-sign` repository by typing `cd c4-sign`.
5. **Optional:** If you want to, you can create a virtual environment for this project. If you don't know what a virtual environment is, you can skip this step. If you want to make one, run `python3 -m venv ./venv` and then activate the virtual environment in whichever way you typically do that with your operating system.
6. Run `python3 -m pip install -e '.[simulator]'`. This will install the simulator software on your computer.

Congrats! You can now run the simulator in **python-only** mode. To do so, run:
`python3 -m c4_sign --simulator --disable-java` and a new web browser window will appear with the simulator! It may take a while for that to happen as it will download certain resources first.

If you want to work with Java, there are a few more steps.

7. Run `python3 tools/setup_java_project.py`. This will make sure the necessary Java and Python dependencies are available.
8. Run `python3 tools/compile_java_project.py`. This will compile the Java project correctly for the sign software to use it. **You must run this command every time you want to test changes to a Java file.**

Nice! Now you can run the simulator in **python and java mode**. To do so, run:
`python3 -m c4_sign --simulator`. The Java and the Python tasks should now be available!

Problems?

Please email us or ask for help in the `#led-sign` channel of our discord server!

## Updates

Updates happen either:
Expand Down
2 changes: 2 additions & 0 deletions bin/start_sign.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ git pull
# sudo python3 -m pip install -e .
# this takes a while to run. TODO: FIX.

/home/c4/c4-sign/venv/bin/python3 tools/compile_java_project.py

sudo /home/c4/c4-sign/venv/bin/python3 -m c4_sign

exit 0
62 changes: 54 additions & 8 deletions c4_sign/ScreenManager.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
import importlib
from datetime import timedelta
import random
import subprocess
import os
import sys
from typing import Union
from pathlib import Path
from time import sleep

from loguru import logger

from c4_sign.base_task import OptimScreenTask, ScreenTask
from py4j.java_gateway import JavaGateway
from py4j.protocol import Py4JError

from c4_sign.base_task import OptimScreenTask, ScreenTask, JavaTask
from c4_sign.lib.canvas import Canvas
from c4_sign.loading_manager import LoadingManager


class ScreenManager:
def __init__(self, make_histograms):
def __init__(self, make_histograms, enable_java):
self.tasks = []
self.current_task = None
self.index = 0
self.make_histograms = make_histograms
self.java_enabled = enable_java

@property
def current_tasks(self) -> list[ScreenTask]:
Expand All @@ -31,7 +40,7 @@ def update_tasks(self, loading_manager: Union[None, LoadingManager] = None):
if (
isinstance(obj, type)
and issubclass(obj, ScreenTask)
and obj not in (ScreenTask, OptimScreenTask)
and obj not in (ScreenTask, OptimScreenTask, JavaTask)
and obj.ignore is False
):
logger.debug("Adding screen task: {}", obj.__name__)
Expand All @@ -45,6 +54,43 @@ def update_tasks(self, loading_manager: Union[None, LoadingManager] = None):
instance.set_make_histogram(self.make_histograms)
self.tasks.append(instance)
logger.debug("Screen Task {} added!", obj.__name__)


if self.java_enabled:
# start java server!

script_path = os.path.abspath(os.path.dirname(__file__))

classpath_delimiter = ";" if os.name == "nt" else ":"

# TODO: Think about extracting this somewhere that makes more sense.
c4_jar = str(Path(script_path) / "java_c4sign" / "target" / "java_c4sign-1.0-SNAPSHOT.jar")
lang3_jar = str(Path.home() / ".m2" / "repository" / "org" / "apache" / "commons" / "commons-lang3" / "3.17.0" / "commons-lang3-3.17.0.jar")
math3_jar = str(Path.home() / ".m2" / "repository" / "org" / "apache" / "commons" / "commons-math3" / "3.6.1" / "commons-math3-3.6.1.jar")

gateway = JavaGateway.launch_gateway(classpath=classpath_delimiter.join([c4_jar, lang3_jar, math3_jar]), die_on_exit=True)

java_task_controller = gateway.jvm.com.cornellcollegecomputingclub.java_c4sign.JavaTaskController()

tasks = java_task_controller.getActiveTasks()

logger.info("Connection to Py4J Gateway Server established!")

logger.debug("Java tasks discovered!")
for task in tasks:
if loading_manager:
with loading_manager(task.getTitle()):
instance = JavaTask(task)
instance.set_make_histogram(self.make_histograms)
self.tasks.append(instance)
else:
instance = JavaTask(task)
instance.set_make_histogram(self.make_histograms)
self.tasks.append(instance)
logger.debug("Screen Task {} added!", task.getTitle())
else:
logger.warning("Java tasks are disabled! This is fine on the simulator, but make sure they're enabled in the physical display!")

# now, shuffle the tasks with an arbitrary seed (so that it's the same between simulator and real)
rand = random.Random(0xd883ff)
rand.shuffle(self.tasks)
Expand All @@ -54,14 +100,14 @@ def override_current_task(self, task: Union[str, ScreenTask]):
# if task is a string, find the task by name
if isinstance(task, str):
for t in self.tasks:
if t.__class__.__name__ == task:
if t.canonical_name == task:
task = t
break
else:
# task not found!
logger.warning(f"Task {task} not found!")
return
logger.info("Overriding current task with {}", task.__class__.__name__)
logger.info("Overriding current task with {}", task.canonical_name)
if self.current_task:
self.current_task.teardown(True)
self.current_task = task
Expand All @@ -75,7 +121,7 @@ def draw(self, canvas: Canvas, delta_time: timedelta):
logger.debug("Looping back to the start!")
self.index = 0
self.current_task = self.current_tasks[self.index]
logger.debug("Trying to start task: {}", self.current_task.__class__.__name__)
logger.debug("Trying to start task: {}", self.current_task.canonical_name)
if not self.current_task.prepare():
# uh... we don't want to do anything!
# so let's just skip this task!
Expand All @@ -85,9 +131,9 @@ def draw(self, canvas: Canvas, delta_time: timedelta):
if self.index >= len(self.current_tasks):
self.index = 0
return self.draw(canvas, delta_time)
logger.debug("Task {} ready!", self.current_task.__class__.__name__)
logger.debug("Task {} ready!", self.current_task.canonical_name)
if self.current_task.draw(canvas, delta_time):
logger.debug("Task {} finished!", self.current_task.__class__.__name__)
logger.debug("Task {} finished!", self.current_task.canonical_name)
self.current_task = None
self.index += 1
return True
Expand Down
Loading