/** @file
    Pulse slicer functions.

    Binary slicers (PWM/PPM/Manchester/...) using a pulse data structure as input

    Copyright (C) 2015 Tommy Vestermark

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
*/

#ifndef INCLUDE_PULSE_SLICER_H_
#define INCLUDE_PULSE_SLICER_H_

#include "pulse_detect.h"
#include "r_device.h"

/// Demodulate a Pulse Code Modulation signal.
///
/// Demodulate a Pulse Code Modulation (PCM) signal where bit width
/// is fixed and each bit starts with a pulse or not. It may be either
/// Return-to-Zero (RZ) encoding, where pulses are shorter than bit width
/// or Non-Return-to-Zero (NRZ) encoding, where pulses are equal to bit width
/// The presence of a pulse is:
/// - Presence of a pulse equals 1
/// - Absence of a pulse equals 0
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of pulse [us]
/// - long_width:  Nominal width of bit period [us]
/// - gap_limit:   Maximum gap size before new row of bits (optional) [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - tolerance:   Maximum deviation from nominal widths (optional, default 25%) [us]
/// @return number of events processed
int pulse_slicer_pcm(const pulse_data_t *pulses, r_device *device);

/// Demodulate a Pulse Position Modulation signal.
///
/// Demodulate a Pulse Position Modulation (PPM) signal consisting of pulses with variable gap.
/// Pulse width may be fixed or variable.
/// Gap between pulses determine the encoding:
/// - Short gap will add a 0 bit
/// - Long  gap will add a 1 bit
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of '0' [us]
/// - long_width:  Nominal width of '1' [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - gap_limit:   Maximum gap size before new row of bits [us]
/// - tolerance:   Maximum deviation from nominal widths (optional, raw if 0) [us]
/// @return number of events processed
int pulse_slicer_ppm(const pulse_data_t *pulses, r_device *device);

/// Demodulate a Pulse Width Modulation signal.
///
/// Demodulate a Pulse Width Modulation (PWM) signal consisting of short, long, and optional sync pulses.
/// Gap between pulses may be of fixed size or variable (e.g. fixed period)
/// - Short pulse will add a 1 bit
/// - Long pulse will add a 0 bit
/// - Sync pulse (optional) will add a new row to bitbuffer
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of '1' [us]
/// - long_width:  Nominal width of '0' [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - gap_limit:   Maximum gap size before new row of bits [us]
/// - sync_width:  Nominal width of sync pulse (optional) [us]
/// - tolerance:   Maximum deviation from nominal widths (optional, raw if 0) [us]
/// @return number of events processed
int pulse_slicer_pwm(const pulse_data_t *pulses, r_device *device);

/// Demodulate a Manchester encoded signal with a hardcoded zerobit in front.
///
/// Demodulate a Manchester encoded signal where first rising edge is counted as a databit
/// and therefore always will be zero (Most likely a hardcoded Oregon Scientific peculiarity)
///
/// Clock is recovered from the data based on pulse width. When time since last bit is more
/// than 1.5 times the clock half period (short_width) it is declared a data edge where:
/// - Rising edge means bit = 0
/// - Falling edge means bit = 1
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of clock half period [us]
/// - long_width:  Not used
/// - reset_limit: Maximum gap size before End Of Message [us].
/// @return number of events processed
int pulse_slicer_manchester_zerobit(const pulse_data_t *pulses, r_device *device);

/// Demodulate a Differential Manchester Coded signal.
///
/// No level shift within the clock cycle translates to a logic 0
/// One level shift within the clock cycle translates to a logic 1
/// Each clock cycle begins with a level shift
///
///     +---+   +---+   +-------+       +  high
///     |   |   |   |   |       |       |
///     |   |   |   |   |       |       |
///     +   +---+   +---+       +-------+  low
///
///     ^       ^       ^       ^       ^  clock cycle
///     |   1   |   1   |   0   |   0   |  translates as
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Width in samples of '1' [us]
/// - long_width:  Width in samples of '0' [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - tolerance:   Maximum deviation from nominal widths [us]
/// @return number of events processed
int pulse_slicer_dmc(const pulse_data_t *pulses, r_device *device);

/// Demodulate a raw Pulse Interval and Width Modulation signal.
///
/// Each level shift is a new bit.
/// A short interval is a logic 1, a long interval a logic 0
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of a bit [us]
/// - long_width:  Maximum width of a run of bits [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - tolerance:   Maximum deviation from nominal widths [us]
/// @return number of events processed
int pulse_slicer_piwm_raw(const pulse_data_t *pulses, r_device *device);

/// Demodulate a differential Pulse Interval and Width Modulation signal.
///
/// Each level shift is a new bit.
/// A short interval is a logic 1, a long interval a logic 0
///
/// @param pulses The pulse sequence to demodulate
/// @param device Modulation parameters of
/// - short_width: Nominal width of '1' [us]
/// - long_width:  Nominal width of '0' [us]
/// - reset_limit: Maximum gap size before End Of Message [us].
/// - tolerance:   Maximum deviation from nominal widths [us]
/// @return number of events processed
int pulse_slicer_piwm_dc(const pulse_data_t *pulses, r_device *device);

int pulse_slicer_nrzs(const pulse_data_t *pulses, r_device *device);

int pulse_slicer_osv1(const pulse_data_t *pulses, r_device *device);

/// Simulate demodulation using a given signal code string.
///
/// The (optionally "0x" prefixed) hex code is processed into a bitbuffer_t.
/// Each row is optionally prefixed with a length enclosed in braces "{}" or
/// separated with a slash "/" character. Whitespace is ignored.
///
/// @param code The pulse sequence to demodulate in text format
/// @param device Device params are disregarded.
/// @return number of events processed
int pulse_slicer_string(const char *code, r_device *device);

#endif /* INCLUDE_PULSE_SLICER_H_ */
