Skip to main content

Signal Control

Under development

Signal Control is under active development and not yet available. The content below describes the previous design and is kept for reference. The design is still being validated, so the final API, the examples, and whether this feature lands in this form are not yet confirmed. Updated documentation will follow here once it is ready.

HC-SR04 ultrasonic sensor

DigitalSignal​

The DigitalSignal is used to handle digital signals! Unlike the other features on this page, DigitalSignal is accurate because it is hardware-backed and runs in a non-blocking manner.

Being hardware backed, this feature only runs on two specific pins: EPDomino24.Gpio.Pin.PH10 (Timer5) and EPDomino24.Gpio.Pin.PA5 (Timer2)

tip

Timers are also used with other features, such as PWM. Once a Timer is reserved for DigitalSignal, it is no longer available for other features.

There are two uses for DigitalSignal, reading a signal (capture) and sending a signal (generate). The capture feature also support capturing a stream of durations (signal analyzer) or a pulse counter.

Generate​

Using the Generate function allows the user to create a very accurate signal generator.

Generate(uint[] data, uint offset, int count)

data is the length of each pulse in ticks

There is a limitation to the data being used: The data array length is limited to 64K elements. Also, adding individual elements together in the array can also not exceed 0xFFFFFFFF in total.

Default Timing

Generate(uint[] data, uint offset, int count, uint multiplier, Edge edge)

Allowed multiplier values range from 5 to 318,000 (318us).

The signal generator start with a signal at edge level. It then toggles the signal every x time. The time is fetched from the array given, one by one. Note that by sending an even count of pulses, the signal will terminate with a !edge level as shown below.

Signal Example

Starting a second write will cause the signal to first go low, which may not be desired, as it causes an extra pulse on the next Generate. This pulse has a variable width. Making sure that the data Length is always an odd number will assure that the signal will terminate at a low-level.

Signal Example

Calling Generate will return immediately (non-blocking) allowing the system to do other tasks while the signal is being generated in the background. When the signal is generated completely, an event is fired. To aid in signal handling, the event provides the final resting level of the signal.

OnGenerateFinished => OnGenerateFinished;

dsig.OnGenerateFinished += (a, b, c) => {
if (b == GpioPinValue.High)
Console.WriteLine("Write done, end state high");
else
Console.WriteLine("Write done, end state low");
};

Capture​

The Capture feature returns an array of timestamps of individual durations. The returned values are in nanoseconds.

tip

Digital Signal is limited to the timer max value, which comes to be about 17.89 seconds. The waitForEdge helps by only starting the timer when there is an active pulse.

var digitalSignal = new DigitalSignalController(EPDomino24.Gpio.Pin.PA5);

bool waitForEdge = false;// Start capturing as soon as Capture is called

// Subscribe event when done capturing
digitalSignal.CaptureFinished += DigitalSignal_OnCaptureFinished;

// Subscribe error
digitalSignal.ErrorReceived += (a,b) => {
Console.WriteLine("Error detected: " + error.ToString());
};

// start capture 100 samples, timeout is 15seconds
digitalSignal.Capture(100, EPDomino24.Gpio.Edge.Rising | EPDomino24.Gpio.Edge.Falling, waitForEdge, TimeSpan.FromSeconds(15));

// Wait for finish capture
// do other work
Thread.Sleep(Timeout.Infinite);

// The event
private static void Digital_OnCaptureFinished(DigitalSignal sender, double[] buffer, uint count, uint initialState, bool aborted) {
if (count == 0) {
Console.WriteLine("no data was captured!");
return;
}
for (int i = 0; i < count; i++) {
Console.WriteLine("Sample [" + i +"]: "+ buffer[i]+" ns");
}
}
note

The first captured pulse will likely have an inaccurate (shorter) value due to system prep-time.

ReadPulse​

ReadPulse can be used to measure frequency and other analyses that require measuring time duration for specific pulse count.

var digitalSignal = new DigitalSignalController(EPDomino24.Gpio.Pin.PH10);

bool waitForEdge = true;// wait for first pulse before starting the measurement

// Subscribe event when done reading
digitalSignal.OnReadPulseFinished += DigitalSignal_ReadPulseFinished;

// Subscribe error
digitalSignal.ErrorReceived += (a,b) => {
Console.WriteLine("Error detected: " + error.ToString());
};

// Start reading 1000 pulses
digitalSignal.ReadPulse(1000, EPDomino24.Gpio.Edge.Rising, waitForEdge);

// do other work...
Thread.Sleep(Timeout.Infinite);

// the event
void Digital_OnReadPulseFinished(DigitalSignal sender, TimeSpan duration, uint count, uint pinValue, bool aborted) {
var ticks = duration.Ticks;
var microsecond = ((double)duration.Ticks) / 10;
var millisecond = ((double)duration.Ticks) / 10000;
var freq = (count / microsecond) * 1000000;

Console.WriteLine("GpioPinValue = " + ((pinValue == 1) ? "High" : "Low"));
Console.WriteLine("PulseCount = " + count);
Console.WriteLine("Duration ticks = " + ticks);
Console.WriteLine("Duration microsecond = " + microsecond);
Console.WriteLine("Duration millisecond = " + millisecond);
Console.WriteLine("freq = " + freq / 1000.0 + " KHz");
}

Abort​

An event is fired when any DigitalSignal operation is completed. In some cases, it may be desired to terminate the operation early, using Abort. When aborted, an event is still triggered, which will contain whatever data/pulses was collected from the trigger to the time Abort was called.

var digitalSignal = new DigitalSignal(EPDomino24.Gpio.Pin.PH10);

var waitForEdge = false;

digitalSignal.OnReadPulseFinished += Digital_OnReadPulseFinished

while (true) {
if (digitalSignal.CanReadPulse) {
digitalSignal.ReadPulse(1000, EPDomino24.Gpio.Edge.Rising, waitForEdge);
Thread.Sleep(1000);
digitalSignal.Abort();
Console.WriteLine("Aborted");
}
}

void Digital_OnReadPulseFinished(DigitalSignal sender, TimeSpan duration, uint count, uint pinValue, bool aborted) {
if (count > 0) {
var microsecond = ((double)duration.Ticks) / 10;
var freq = (count / microsecond) * 1000000;
Console.WriteLine("freq = " + freq / 1000.0 + " KHz");
}
else {
Console.WriteLine("No clock found.");
}
}
tip

In the sample code above you can use PWM to provide the pulse needed to verify the code. Keep in mind that both PWM and DigitalSignal share resources, so a different Timer controller must be used.