* added DigitalSequence to chain multiple DigitalSignals added PulseReader for hardware assisted digital signal sampling * added send_time option to start a signal at a specific DWT->CYCCNT value * fixed linter errors and undone function renaming * fixed renaming * flagged functions in api_symbols.csv * allow gpio field to stay uninitialized in digital_signal_prepare_arr() * fix test cases to match (expected) implementation * pulse_reader: build as static library Signed-off-by: g3gg0.de <git@g3gg0.de> * fix starting level detection in pulse_reader * added unit test for pulse_reader * change pulse reader test timings to 1, 10 and 100 ms * fine tuned timings for pulse_reader test * pulse_reader_stop now deinits GPIO as recommended by @gornekich * ran format_py * pulse_reader: remove from API, allow to link with faps Signed-off-by: g3gg0.de <git@g3gg0.de> * remove unit test for pulse_reader again * pulse_reader: add call to set GPIO pull direction * make structures private, add C implementation of digital_signal_update_dma() * digital_signal/pulse_reader: allow parameters for free to be NULL * digital_signal: show unoptimized and optimized code for digital_signal_update_dma() next to each other * pulse_reader: further optimize assembly code * digital_signal: reduce code complexity of digital_signal_update_dma() by only reconfiguring DMA2 * digital_signal: remove assembly code, limiting the performance but increasing portability * added recovery if the timer already expired * digital_signal: fix memory leak * digital_signal: keep lock until all DMA transfers have finished * DigitalSequence: fix issues with concatenation of same levels and spurious bit flips * DigitalSignal: use cyclic DMA buffer for sequences * update api_symbols.csv * Update api_symbols.csv for f18 target * Patches from @gornekich to fix linter warnings. * Remove some redundant if checks * Remove some magic numbers and reformat. * Remove forced terminating edge. Signed-off-by: g3gg0.de <git@g3gg0.de> Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: Tiernan Messmer <tiernan.messmer@gmail.com> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#pragma once
 | 
						|
 | 
						|
#include <stdint.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdbool.h>
 | 
						|
 | 
						|
#include <furi_hal_gpio.h>
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
extern "C" {
 | 
						|
#endif
 | 
						|
 | 
						|
#define PULSE_READER_NO_EDGE (0xFFFFFFFFUL)
 | 
						|
#define PULSE_READER_LOST_EDGE (0xFFFFFFFEUL)
 | 
						|
#define F_TIM2 (64000000UL)
 | 
						|
 | 
						|
/**
 | 
						|
 * unit of the edge durations to return
 | 
						|
 */
 | 
						|
typedef enum {
 | 
						|
    PulseReaderUnit64MHz,
 | 
						|
    PulseReaderUnitPicosecond,
 | 
						|
    PulseReaderUnitNanosecond,
 | 
						|
    PulseReaderUnitMicrosecond,
 | 
						|
} PulseReaderUnit;
 | 
						|
 | 
						|
/* using an anonymous type */
 | 
						|
typedef struct PulseReader PulseReader;
 | 
						|
 | 
						|
/** Allocate a PulseReader object
 | 
						|
 *
 | 
						|
 * Allocates memory for a ringbuffer and initalizes the object
 | 
						|
 *
 | 
						|
 * @param[in]  gpio        the GPIO to use. will get configured as input.
 | 
						|
 * @param[in]  size        number of edges to buffer
 | 
						|
 */
 | 
						|
PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size);
 | 
						|
 | 
						|
/** Free a PulseReader object
 | 
						|
 *
 | 
						|
 * Frees all memory of the given object
 | 
						|
 *
 | 
						|
 * @param[in]  signal      previously allocated PulseReader object.
 | 
						|
 */
 | 
						|
void pulse_reader_free(PulseReader* signal);
 | 
						|
 | 
						|
/** Start signal capturing
 | 
						|
 *
 | 
						|
 * Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values.
 | 
						|
 * Ensure that interrupts are always enabled, as the used EXTI line is handled as one.
 | 
						|
 *
 | 
						|
 * @param[in]  signal      previously allocated PulseReader object.
 | 
						|
 */
 | 
						|
void pulse_reader_start(PulseReader* signal);
 | 
						|
 | 
						|
/** Stop signal capturing
 | 
						|
 *
 | 
						|
 * Frees DMA1, TIM2 and DMAMUX_REQ_GEN_0
 | 
						|
 *
 | 
						|
 * @param[in]  signal      previously allocated PulseReader object.
 | 
						|
 */
 | 
						|
void pulse_reader_stop(PulseReader* signal);
 | 
						|
 | 
						|
/** Recevie a sample from ringbuffer
 | 
						|
 *
 | 
						|
 * Waits for the specified time until a new edge gets detected.
 | 
						|
 * If not configured otherwise, the pulse duration will be in picosecond resolution.
 | 
						|
 * If a bittime was configured, the return value will contain the properly rounded
 | 
						|
 * number of bit times measured.
 | 
						|
 *
 | 
						|
 * @param[in]  signal      previously allocated PulseReader object.
 | 
						|
 * @param[in]  timeout_us  time to wait for a signal [µs]
 | 
						|
 *
 | 
						|
 * @returns the scaled value of the pulse duration
 | 
						|
 */
 | 
						|
uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us);
 | 
						|
 | 
						|
/** Get available samples
 | 
						|
 *
 | 
						|
 * Get the number of available samples in the ringbuffer
 | 
						|
 *
 | 
						|
 * @param[in]  signal  previously allocated PulseReader object.
 | 
						|
 *
 | 
						|
 * @returns the number of samples in buffer
 | 
						|
 */
 | 
						|
uint32_t pulse_reader_samples(PulseReader* signal);
 | 
						|
 | 
						|
/** Set timebase
 | 
						|
 *
 | 
						|
 * Set the timebase to be used when returning pulse duration.
 | 
						|
 *
 | 
						|
 * @param[in]  signal  previously allocated PulseReader object.
 | 
						|
 * @param[in]  unit  PulseReaderUnit64MHz or PulseReaderUnitPicosecond
 | 
						|
 */
 | 
						|
void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit);
 | 
						|
 | 
						|
/** Set bit time
 | 
						|
 *
 | 
						|
 * Set the number of timebase units per bit.
 | 
						|
 * When set, the pulse_reader_receive() will return an already rounded
 | 
						|
 * bit count value instead of the raw duration.
 | 
						|
 *
 | 
						|
 * Set to 1 to return duration again.
 | 
						|
 *
 | 
						|
 * @param[in]  signal    previously allocated PulseReader object.
 | 
						|
 * @param[in]  bit_time
 | 
						|
 */
 | 
						|
void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time);
 | 
						|
 | 
						|
/** Set GPIO pull direction
 | 
						|
 *
 | 
						|
 * Some GPIOs need pulldown, others don't. By default the
 | 
						|
 * pull direction is GpioPullNo.
 | 
						|
 *
 | 
						|
 * @param[in]  signal    previously allocated PulseReader object.
 | 
						|
 * @param[in]  pull      GPIO pull direction
 | 
						|
 */
 | 
						|
void pulse_reader_set_pull(PulseReader* signal, GpioPull pull);
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
}
 | 
						|
#endif
 |