ESP32-based project to make a display for speedcubing timers.
We seek to create an alternative to commercially available displays which is cheaper, lighter,open-source, repairable, and sustainable.
Take a look at the open issues on the repository to see how you can contribute. Open an issue for a request or suggestion. You can also send an email for contato@abracm.org.br for enquries, contributions, feedback, etc.
The language of the project is English to make it more accesible worldwide.
Please stick to the following best practices when contributing to this project:
Currently, the code is functional, but the documentation needs work, which makes it hard for communities to build their own version. The work plan is on the short medium term is:
TODO add video demo
From Libs.zip, extrac Libs folder and copy it's contents to your Arduino/Libraries directory.
Software Installation guide:
TODO
Draft preview of the project (using the acrylic covers)
Schematics for the ESP32 C3 mini are as follows:
Schematics for the ESP32 S2 are also available at doc/schematics_esp32_s2.jpg
Two alternatives for encasing the hardware:
Materials/type | Details |
---|---|
|
cutout for CNC available on doc/acrylic-cover.skp , see doc/prototype_demo.skp for demo on how to build |
3D printed case | draft design available on doc/draft_case.stl (WIP) |
For power, you could use:
For the display stand, you could use the 3D-printed stand available on doc/stand.stl
.
Current estimates for the cost of the materials for a display are of around USD ~20 (buying supplies off China e.g. Aliexpress).
We are specially greatful to Fabio Seiji Massui 2013MASS01 for kicking off this project and inspiring us to pursue the goal of developing an open-source and cheap alternative to commercial displays.
Other contributors include:
The Speedstacks timers send a digital audio signal thorugh the data port (example). This is a guide how on to interpret the signal.
The timer sends the signal with a fixed rate of 1200 bits per second (check if this is correct and consistent across all timer generations). It sends a packet that are 90 or 100 bytes long to convey a single time to be displayed.
The bitstream user a standard idle value (0 or 1) to inform when a byte or a packet ended. The idle value varies across timer generations (see section below on timer generations).
Each byte is proceeded by a non-idle value, to show that the byte has begun, and followed by an idle value, to show that it has ended.
example of a Gen 3 timer bitstream- the idle value is 1
example of a Gen 4 timer bitstream- the idle value is 0
Each packet is separated by an unspecificed number of idle values (check if we can tell an exact amount and if it is consistent across timers). Therefore, to check if a packet has ended, you just need to check if you can read ten or more equal values in a row, as that couldn't happen if a byte was being transmitted.
A time to be displayed is sent as a packet that can be 9 or 10 bytes long. The lenght of the packet is determined by the timer generation (see section below on timer generations).
Because of the non-idle value and idle value that go before and after each byte, the bytes take 10 bits to be transmitted, and the packet lenghts are therefore 90 or 100 bits.
Here is an example of a full packet extracted from a Gen 3 timer that will use to break down what each byte means. TODO
Notice that this packet it 10 bytes long and uses 1 as its idle value.
These are what each byte consists of:
The first byte is an ASCII code for one of the following letters, which represent the state the timer is in:
These are the bytes that convey the time information. Byte 7 may or may not be a part of this depending on the timer generation (see section below on timer generations).
Here is the breakdown on byte-by-byte:
The byte represents the ASCII code for the digit, which is the digit + 48
This byte is a checksum of the previous bytes (2-6 or 2-7), to ensure the reading is correct.
It it the sum of the values (not the ASCII codes) of all digits + 64.
These bytes are the ASCII codes for \n (newline) and \r (carriage return). Is this just useless?
After reading the 10 bits necessary for a byte (non-idle value + byte + idle value), you must first discard the 1st and the last bits of the byte.
Then, you must place the bits in reverse order. E.g. (11001001 becomes 10010011)
Finally, the bits must be inverted to arrive at the final byte (10010011 becomes 01101100). do timers with a 0 idle value also need to be inverted?
WIP
can we easily support other non-speedstacks timers? testing needed