GEX protocol documentation
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gex-docs/UNIT_FCAP.md

193 lines
5.3 KiB

# Frequency / Pulse measurement
- Frequency measurement
- Direct method (counting pulses in a time period)
- Indirect method (measuring a single pulse)
- PWM measurement - Indirect method also reports duty cycle
- Single pulse measurement
- Free-running pulse counter
### Direct vs Indirect method
The direct method works well for a wide range of frequencies, from Hz to tens of MHz. For
6 years ago
very high frequencies, a prescaller can be enabled. This method has a resolution of 1 Hz. It could be increased by extending the measurement time, usually 1 second.
The indirect method has a sub-Hz resolution and is much faster than the direct method for
low frequencies. It can be used for signals up to tens of kHz, while the direct method
can handle 20 MHz or more without issues.
*NOTE:* The accuracy of all measurements is dependent on the system clock speed.
To measure the system clock using an external counter, you can output it on a pin using
the MCO function configured in `SYSTEM.INI`.
### Burst vs Continuous
Both the direct and indirect methods can operate in a free-running or burst mode.
- Burst mode performs one or several measurements (with averaging if using the indirect method).
- Free-running (continuous) mode performs periodic measurements without averaging.
The advantage is that the last measurement is always immediately available for read-out, without having to wait for the emasurement.
## Commands
### STOP (0)
Stops all ongoing measurements.
### INDIRECT_CONT_START (1)
Start a free-running frequency / duty cycle measuring using the indirect method.
### INDIRECT_BURST_START (2)
Start a burst of indirect measurements.
Waits for the next rising edge before starting the measurements.
*Request:*
- u16 - number of pulses to average
*Response:*
- u16 - core speed in MHz
- u16 - number of pulses
- u64 - sum of all periods (in core ticks)
- u16 - sum of all on-times (positive interval of the pulse)
GEX avoids using float here to reduce code size and avoid floating
point errors. To get the period, use `period_sec = periods / (mhz * 10e6 * count)`
Frequency is `freq = 1 / period`.
The average duty cycle is `duty = ontimes / periods`
### DIRECT_CONT_START (3)
Start repeated measurement using the direct method.
*Request:*
- u16 - measurement time (ms)
- 0 = no change
- default 1000, configurable in the unit settings
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
### DIRECT_BURST_START (4)
Start a single direct measurement (pulse counting) over
a given time period. Longer periods can be used for higher precision
using averaging.
*Request:*
- u16 - measurement time (ms), often 1000 (=1s)
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
*Response:*
- u8 - prescaller (1,2,4,8)
- u16 - measurement time (ms)
- u32 - pulse count
Calculate the frequency by `freq = (1000 * count * presc) / time_ms`.
### FREECOUNT_START (5)
Clear and start the free-running pulse counter.
*Request:*
- u8 - prescaller (1,2,4,8)
- 0 = no change
- default 1, configurable in the unit settings
### MEASURE_SINGLE_PULSE (6)
Measure a single pulse on the input. Waits for a rising edge.
*NOTE:* The result may be inaccurate if the input is High when starting the measurement.
*Response:*
- u16 - core speed in MHz
- u32 - pulse length (core ticks)
### FREECOUNT_CLEAR (7)
Clear the free-running counter while retrieving the current value.
Normally no pulses should be missed, but please be aware that this
operation is not atomic and glitches can occur at high frequencies.
*Response:*
- u32 - last counter value
### INDIRECT_CONT_READ (10)
Read the latest result from the continuous indirect method measurement
(measurement of individual pulses).
*Response:*
- u16 - core speed in MHz
- u32 - period (core ticks)
- u32 - on-time (positive interval of the pulse)
Duty cycle is `duty = ontime / period`.
Period `period_sec = period / (mhz * 10e6)`.
Frequency `freq = 1 / period_sec`.
### DIRECT_CONT_READ (11)
Read the latest result from the continuous direct method measurement (pulse counting).
*Response:*
- u8 - prescaller (1,2,4,8)
- u16 - measurement time (ms)
- u32 - pulse count
Frequency is `freq = (1000 * presc * count) / time_ms`.
### FREECOUNT_READ (12)
Read the current value of the free-running pulse counter.
*Response:*
- u32 - counter value
### SET_POLARITY (20)
Set the measured pulse polarity.
*NOTE:* This is normally configured in the unit settings.
Changes done through this method are temporary, not persisted to flash. The same
applies to the other SET_* commands.
*Request:*
- u8 - active level (0,1)
### SET_DIR_PRESC (21)
Set prescaller for the direct mode measurement.
*NOTE:* This does not take effect until the direct measurement is restarted. (TODO: fix?)
*Request:*
- u8 - prescaller (1,2,4,8)
### SET_INPUT_FILTER (22)
Set input filtering (a hardware feature designed to ignore short glitches)
*Request:*
- u8 - digital filtering factor (0-15, 0=off)
### SET_DIR_MSEC (23)
Set direct measurement period.
*NOTE:* This does not take effect until the direct measurement is restarted. (TODO: fix?)
*Request:*
- u16 - period in milliseconds
### RESTORE_DEFAULTS (30)
Stop any measurement and restore all the run-time configurable settings to their default
values (as configured in the unit settings).