Detailed Specifications¶
Host Tools¶
Unlike some previous years, the host tools this year are created by the organizers and read-only. The host tools create a basic input/output format for communications between your devices and the host computer. More information on the host tools is available here.
Design Package¶
The Generate Secrets and Generate Subscription scripts and the Encoder must be
implemented as a pip-installable Python package named ectf25_design
.
Generate Secrets¶
Generate Secrets is a function that should be importable using:
from ectf25_design.gen_secrets import gen_secrets
The function takes a list of channels that will be valid in the system and returns any secrets that will be passed to future steps. Channel 0 is always assumed to be valid and will not be passed in the list.
The full required interface is as follows:
def gen_secrets(channels: list[int]) -> bytes:
pass
Generate Subscription¶
Generate Subscription is a function that should be importable using:
from ectf25_design.gen_subscription import gen_subscription
The function takes the secrets generated by Generate Secrets and the Decoder ID, the start and end timestamps, and the channel number the subscription will be valid for.
The full required interface is as follows:
def gen_subscription(
secrets: bytes, device_id: int, start: int, end: int, channel: int
) -> bytes:
pass
Encoder¶
The Encoder is a class that should be importable using:
from ectf25_design.encoder import Encoder
The class is initialized with the raw value of the secrets file generated by
Generate Secrets. The class must also implement the encode
function, which
accpets the channel the frame will be sent on, the raw frame, and the timestamp
and must return the encoded frame data as a bytes object.
The full required interface is as follows:
class Encoder:
def __init__(self, secrets: bytes):
pass
def encode(self, channel: int, frame: bytes, timestamp: int) -> bytes:
pass
You may change the package however you would like so long as that interface is implemented.
Decoder Firmware¶
There are three required functional elements to the Decoder firmware. These elements directly relate to the host tools:
List Subscribed Channels
Update Subscribed Channels
Decode TV Frame Data
All functional requirements must align with the Timing Requirements
Decoder Interface¶
All communications between the Decoder and the Host Computer will
take place over UART at a baud rate of 115200
. Said communications must
adhere to the protocol specified by the host tools and documented here. The
host_messaging
library included in the example design provides an easy
interface to send messages to the host tools.
The message structure is made of 4 components:
Name |
Size |
Description |
---|---|---|
MAGIC |
1 byte |
Message start byte, ‘%’ |
OPCODE |
1 byte |
Indicates the type of message |
LENGTH |
2 bytes |
Length of the message body |
BODY |
Variable Length |
Actual message contents |
The length may be 0 in which case the message body will be empty. The first3 components (MAGIC, OPCODE, and LENGTH) are considered the message headerand are distinct from the rest of the message (BODY). All integer values (except in design-specific fields) are in little endian. The host tools accept five types of messages:
Type |
Opcode |
Use |
---|---|---|
Decode |
|
Decode frame command/response |
Subscribe |
|
Subscription update command/response |
List |
|
List subscribed channels command/response |
Ack |
|
Acknowledge the receipt of data |
Error |
|
Notify of an error/failure. Exits Host Tool |
Debug |
|
Provide debug information (ignored by testing framework) |
For example, a subscribe
command with a size of 0x20 bytes will have a header that looks like:
‘%S\x20\x00
’.
Except for debug messages, the Host Computer will initiate all communication with the Decoder. An exchange of a message will start with the sender sending the 4 header bytes. The receiver will send an ACK indicating it is ready for more data. The sender will then send the content of the body 256 bytes at a time. After every 256 bytes, the receiver will send an ACK indicating it is ready for more data. The final chunk of data, regardless of whether it is 256 bytes long or less than that must also be ACKed.
The exception to this process is debug messages. When a Decoder sends a debug message, the host will not ACK any portion of it.
When processing a command on the Decoder fails, the Decoder must respond with an error message type. The contents of the error do not matter. When processing a command on the Decoder succeeds, the Decoder must respond with a message type that is the same as the command (see below for contents).
List Channels¶
The list channels functionality must return ALL channels that the Decoder has a valid subscription for. The body of the response will contain a list of channels and the start and end timestamps that define the active lifetime of the subscription.
Host Command¶
The List command will have an empty body.
Decoder Response¶
Name |
Size |
Description |
---|---|---|
Num channels |
32 bits |
Number of valid subscriptions |
Subscriptions |
Variable len |
An array of |
Name |
Size |
Description |
---|---|---|
Channel ID |
32 bits |
ID of the subscribed channel |
Start |
64 bits |
Start timestamp of subscription |
End |
64 bits |
End timestamp of subscription |
Update Subscription¶
The update subscription functionality must handle updating the current subscription for a given channel.
Host Command¶
Name |
Size |
Description |
---|---|---|
Subscription data |
Variable len |
Design-specific subscription data |
Decoder Response¶
The subscribe response will have an empty body
Decode Frame¶
The decode frame function must handle the decoding for a provided TV frame. If the frame is from a channel the Decoder has a valid and active subscription for or is sent on the emergency broadcast channel (channel 0), it must decode the frame.
Host Command¶
Name |
Size |
Description |
---|---|---|
Encoded frame data |
Variable len |
Design-specific frame data |
Decoder Response¶
Name |
Size |
Description |
---|---|---|
Decoded frame |
Variable len |
The decoded frame must match the length and content of the frame passed to the Encoder |
Example¶
Suppose the host wants to issue the list
command. It will first send the command header. Per the
spec, it will use an opcode of L
and a size of 0x0. This makes the header ‘%L\x00\x00
’.
After sending the header, the host will wait for an ACK (’%A\x00\x00
’) from the Decoder. If the
command had a non-zero size, the host would send the body now and wait for an ACK, but that’s not
the case here. Instead, the host will now wait for a response message from the Decoder.
Processing the list
command succeeds on the Decoder, so it will respond with the same message
type as the command. Let’s suppose the Decoder is subscribed to two channels: channel 1 starting at
time 128 and ending at time 255 and channel 4 starting at time 0x4141 and ending at time 0x4242.
Thus, the the total message size is 44 and the Decoder will send the header ‘%L\x2c\x00
’. The
host will respond with an ACK. Then the Decoder will send the command body:
char *msg = ""
"\x02\x00\x00\x00" // Number of channels (2)
"\x01\x00\x00\x00" // 1st channel ID (1)
"\x80\x00\x00\x00\x00\x00\x00\x00" // Start timestamp (128)
"\xff\x00\x00\x00\x00\x00\x00\x00" // End timestamp (255)
"\x04\x00\x00\x00" // 1st channel ID (4)
"\x41\x41\x00\x00\x00\x00\x00\x00" // Start timestamp (0x4141)
"\x42\x42\x00\x00\x00\x00\x00\x00"; // End timestamp (0x4242)
After sending the response contents, the Decoder will wait for an ACK before attempting to receive the next command.
Detailed Requirements¶
The following constraints must be met:
Operation |
Maximum Time for Completion |
---|---|
Device Wake |
1 second |
List Channels |
500 milliseconds |
Update Subscription |
500 milliseconds |
Operation |
Minimum Throughput |
---|---|
Encoder |
1,000 64B frames per second |
Decoder |
10 64B frames per second |
Component |
Size |
---|---|
Channel ID |
Max 4 bytes |
Timestamp |
Max 8 bytes |
Decoded frame |
Max 64 bytes |
Channel Type |
Required |
---|---|
Standard channels |
8 channels |
Emergency channels |
1 channel (always channel 0) |
Allowed Programming Languages¶
To build the firmware your design, your team may choose to implement your design in any compatible language. To align with good development practices, you must not use a language that was specifically chosen to be difficult to understand.
The pre-approved programming languages are: C, C++, and Rust. If you wish to use a different language, please reach out to the organizers first.
Be aware that if your team decides to use a language which incorporates a panic handler, your design must still adhere to the Timing Requirements and should not enter an infinite loop in response to any normal input.
The Reference Design was created in C, and as such if your team decides to use another programming language, the Dockerfile must be updated to allow for the organizers and teams to be able to build and utilize your design.