Program Listing for File special.h

Return to documentation for file (include/libcaer/events/special.h)

#ifndef LIBCAER_EVENTS_SPECIAL_H_
#define LIBCAER_EVENTS_SPECIAL_H_

#include "common.h"

#ifdef __cplusplus
extern "C" {
#endif

#define SPECIAL_TYPE_SHIFT 1
#define SPECIAL_TYPE_MASK  0x0000007F
#define SPECIAL_DATA_SHIFT 8
#define SPECIAL_DATA_MASK  0x00FFFFFF

enum caer_special_event_types {
    TIMESTAMP_WRAP              = 0,
    TIMESTAMP_RESET             = 1,
    EXTERNAL_INPUT_RISING_EDGE  = 2,
    EXTERNAL_INPUT_FALLING_EDGE = 3,
    EXTERNAL_INPUT_PULSE        = 4,
    DVS_ROW_ONLY = 5,
    EXTERNAL_INPUT1_RISING_EDGE     = 6,
    EXTERNAL_INPUT1_FALLING_EDGE    = 7,
    EXTERNAL_INPUT1_PULSE           = 8,
    EXTERNAL_INPUT2_RISING_EDGE     = 9,
    EXTERNAL_INPUT2_FALLING_EDGE    = 10,
    EXTERNAL_INPUT2_PULSE           = 11,
    EXTERNAL_GENERATOR_RISING_EDGE  = 12,
    EXTERNAL_GENERATOR_FALLING_EDGE = 13,
    APS_FRAME_START                 = 14,
    APS_FRAME_END                   = 15,
    APS_EXPOSURE_START              = 16,
    APS_EXPOSURE_END                = 17,
    EVENT_READOUT_START             = 18,
};

PACKED_STRUCT(struct caer_special_event {
    uint32_t data;
    int32_t timestamp;
});

typedef struct caer_special_event *caerSpecialEvent;
typedef const struct caer_special_event *caerSpecialEventConst;

PACKED_STRUCT(struct caer_special_event_packet {
    struct caer_event_packet_header packetHeader;
    struct caer_special_event events[];
});

typedef struct caer_special_event_packet *caerSpecialEventPacket;
typedef const struct caer_special_event_packet *caerSpecialEventPacketConst;

static inline caerSpecialEventPacket caerSpecialEventPacketAllocate(
    int32_t eventCapacity, int16_t eventSource, int32_t tsOverflow) {
    return ((caerSpecialEventPacket) caerEventPacketAllocate(eventCapacity, eventSource, tsOverflow, SPECIAL_EVENT,
        sizeof(struct caer_special_event), offsetof(struct caer_special_event, timestamp)));
}

static inline caerSpecialEventPacket caerSpecialEventPacketFromPacketHeader(caerEventPacketHeader header) {
    if (caerEventPacketHeaderGetEventType(header) != SPECIAL_EVENT) {
        return (NULL);
    }

    return ((caerSpecialEventPacket) header);
}

static inline caerSpecialEventPacketConst caerSpecialEventPacketFromPacketHeaderConst(
    caerEventPacketHeaderConst header) {
    if (caerEventPacketHeaderGetEventType(header) != SPECIAL_EVENT) {
        return (NULL);
    }

    return ((caerSpecialEventPacketConst) header);
}

static inline caerSpecialEvent caerSpecialEventPacketGetEvent(caerSpecialEventPacket packet, int32_t n) {
    // Check that we're not out of bounds.
    if (n < 0 || n >= caerEventPacketHeaderGetEventCapacity(&packet->packetHeader)) {
        caerLogEHO(CAER_LOG_CRITICAL, "Special Event",
            "Called caerSpecialEventPacketGetEvent() with invalid event offset %" PRIi32
            ", while maximum allowed value is %" PRIi32 ".",
            n, caerEventPacketHeaderGetEventCapacity(&packet->packetHeader) - 1);
        return (NULL);
    }

    // Return a pointer to the specified event.
    return (packet->events + n);
}

static inline caerSpecialEventConst caerSpecialEventPacketGetEventConst(caerSpecialEventPacketConst packet, int32_t n) {
    // Check that we're not out of bounds.
    if (n < 0 || n >= caerEventPacketHeaderGetEventCapacity(&packet->packetHeader)) {
        caerLogEHO(CAER_LOG_CRITICAL, "Special Event",
            "Called caerSpecialEventPacketGetEventConst() with invalid event offset %" PRIi32
            ", while maximum allowed value is %" PRIi32 ".",
            n, caerEventPacketHeaderGetEventCapacity(&packet->packetHeader) - 1);
        return (NULL);
    }

    // Return a pointer to the specified event.
    return (packet->events + n);
}

static inline int32_t caerSpecialEventGetTimestamp(caerSpecialEventConst event) {
    return (I32T(le32toh(U32T(event->timestamp))));
}

static inline int64_t caerSpecialEventGetTimestamp64(caerSpecialEventConst event, caerSpecialEventPacketConst packet) {
    return (I64T((U64T(caerEventPacketHeaderGetEventTSOverflow(&packet->packetHeader)) << TS_OVERFLOW_SHIFT)
                 | U64T(caerSpecialEventGetTimestamp(event))));
}

static inline void caerSpecialEventSetTimestamp(caerSpecialEvent event, int32_t timestamp) {
    if (timestamp < 0) {
        // Negative means using the 31st bit!
        caerLogEHO(CAER_LOG_CRITICAL, "Special Event", "Called caerSpecialEventSetTimestamp() with negative value!");
        return;
    }

    event->timestamp = I32T(htole32(U32T(timestamp)));
}

static inline bool caerSpecialEventIsValid(caerSpecialEventConst event) {
    return (GET_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK));
}

static inline void caerSpecialEventValidate(caerSpecialEvent event, caerSpecialEventPacket packet) {
    if (!caerSpecialEventIsValid(event)) {
        SET_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK, 1);

        // Also increase number of events and valid events.
        // Only call this on (still) invalid events!
        caerEventPacketHeaderSetEventNumber(
            &packet->packetHeader, caerEventPacketHeaderGetEventNumber(&packet->packetHeader) + 1);
        caerEventPacketHeaderSetEventValid(
            &packet->packetHeader, caerEventPacketHeaderGetEventValid(&packet->packetHeader) + 1);
    }
    else {
        caerLogEHO(CAER_LOG_CRITICAL, "Special Event", "Called caerSpecialEventValidate() on already valid event.");
    }
}

static inline void caerSpecialEventInvalidate(caerSpecialEvent event, caerSpecialEventPacket packet) {
    if (caerSpecialEventIsValid(event)) {
        CLEAR_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK);

        // Also decrease number of valid events. Number of total events doesn't change.
        // Only call this on valid events!
        caerEventPacketHeaderSetEventValid(
            &packet->packetHeader, caerEventPacketHeaderGetEventValid(&packet->packetHeader) - 1);
    }
    else {
        caerLogEHO(CAER_LOG_CRITICAL, "Special Event", "Called caerSpecialEventInvalidate() on already invalid event.");
    }
}

static inline uint8_t caerSpecialEventGetType(caerSpecialEventConst event) {
    return U8T(GET_NUMBITS32(event->data, SPECIAL_TYPE_SHIFT, SPECIAL_TYPE_MASK));
}

static inline void caerSpecialEventSetType(caerSpecialEvent event, uint8_t type) {
    CLEAR_NUMBITS32(event->data, SPECIAL_TYPE_SHIFT, SPECIAL_TYPE_MASK);
    SET_NUMBITS32(event->data, SPECIAL_TYPE_SHIFT, SPECIAL_TYPE_MASK, type);
}

static inline uint32_t caerSpecialEventGetData(caerSpecialEventConst event) {
    return U32T(GET_NUMBITS32(event->data, SPECIAL_DATA_SHIFT, SPECIAL_DATA_MASK));
}

static inline void caerSpecialEventSetData(caerSpecialEvent event, uint32_t data) {
    CLEAR_NUMBITS32(event->data, SPECIAL_DATA_SHIFT, SPECIAL_DATA_MASK);
    SET_NUMBITS32(event->data, SPECIAL_DATA_SHIFT, SPECIAL_DATA_MASK, data);
}

#define CAER_SPECIAL_ITERATOR_ALL_START(SPECIAL_PACKET)                                                     \
    for (int32_t caerSpecialIteratorCounter = 0;                                                            \
         caerSpecialIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader); \
         caerSpecialIteratorCounter++) {                                                                    \
        caerSpecialEvent caerSpecialIteratorElement                                                         \
            = caerSpecialEventPacketGetEvent(SPECIAL_PACKET, caerSpecialIteratorCounter);

#define CAER_SPECIAL_CONST_ITERATOR_ALL_START(SPECIAL_PACKET)                                               \
    for (int32_t caerSpecialIteratorCounter = 0;                                                            \
         caerSpecialIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader); \
         caerSpecialIteratorCounter++) {                                                                    \
        caerSpecialEventConst caerSpecialIteratorElement                                                    \
            = caerSpecialEventPacketGetEventConst(SPECIAL_PACKET, caerSpecialIteratorCounter);

#define CAER_SPECIAL_ITERATOR_ALL_END }

#define CAER_SPECIAL_ITERATOR_VALID_START(SPECIAL_PACKET)                                                   \
    for (int32_t caerSpecialIteratorCounter = 0;                                                            \
         caerSpecialIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader); \
         caerSpecialIteratorCounter++) {                                                                    \
        caerSpecialEvent caerSpecialIteratorElement                                                         \
            = caerSpecialEventPacketGetEvent(SPECIAL_PACKET, caerSpecialIteratorCounter);                   \
        if (!caerSpecialEventIsValid(caerSpecialIteratorElement)) {                                         \
            continue;                                                                                       \
        } // Skip invalid special events.

#define CAER_SPECIAL_CONST_ITERATOR_VALID_START(SPECIAL_PACKET)                                             \
    for (int32_t caerSpecialIteratorCounter = 0;                                                            \
         caerSpecialIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader); \
         caerSpecialIteratorCounter++) {                                                                    \
        caerSpecialEventConst caerSpecialIteratorElement                                                    \
            = caerSpecialEventPacketGetEventConst(SPECIAL_PACKET, caerSpecialIteratorCounter);              \
        if (!caerSpecialEventIsValid(caerSpecialIteratorElement)) {                                         \
            continue;                                                                                       \
        } // Skip invalid special events.

#define CAER_SPECIAL_ITERATOR_VALID_END }

#define CAER_SPECIAL_REVERSE_ITERATOR_ALL_START(SPECIAL_PACKET)                      \
    for (int32_t caerSpecialIteratorCounter                                          \
         = caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader) - 1; \
         caerSpecialIteratorCounter >= 0; caerSpecialIteratorCounter--) {            \
        caerSpecialEvent caerSpecialIteratorElement                                  \
            = caerSpecialEventPacketGetEvent(SPECIAL_PACKET, caerSpecialIteratorCounter);
#define CAER_SPECIAL_CONST_REVERSE_ITERATOR_ALL_START(SPECIAL_PACKET)                \
    for (int32_t caerSpecialIteratorCounter                                          \
         = caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader) - 1; \
         caerSpecialIteratorCounter >= 0; caerSpecialIteratorCounter--) {            \
        caerSpecialEventConst caerSpecialIteratorElement                             \
            = caerSpecialEventPacketGetEventConst(SPECIAL_PACKET, caerSpecialIteratorCounter);

#define CAER_SPECIAL_REVERSE_ITERATOR_ALL_END }

#define CAER_SPECIAL_REVERSE_ITERATOR_VALID_START(SPECIAL_PACKET)                         \
    for (int32_t caerSpecialIteratorCounter                                               \
         = caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader) - 1;      \
         caerSpecialIteratorCounter >= 0; caerSpecialIteratorCounter--) {                 \
        caerSpecialEvent caerSpecialIteratorElement                                       \
            = caerSpecialEventPacketGetEvent(SPECIAL_PACKET, caerSpecialIteratorCounter); \
        if (!caerSpecialEventIsValid(caerSpecialIteratorElement)) {                       \
            continue;                                                                     \
        } // Skip invalid special events.

#define CAER_SPECIAL_CONST_REVERSE_ITERATOR_VALID_START(SPECIAL_PACKET)                        \
    for (int32_t caerSpecialIteratorCounter                                                    \
         = caerEventPacketHeaderGetEventNumber(&(SPECIAL_PACKET)->packetHeader) - 1;           \
         caerSpecialIteratorCounter >= 0; caerSpecialIteratorCounter--) {                      \
        caerSpecialEventConst caerSpecialIteratorElement                                       \
            = caerSpecialEventPacketGetEventConst(SPECIAL_PACKET, caerSpecialIteratorCounter); \
        if (!caerSpecialEventIsValid(caerSpecialIteratorElement)) {                            \
            continue;                                                                          \
        } // Skip invalid special events.

#define CAER_SPECIAL_REVERSE_ITERATOR_VALID_END }

static inline caerSpecialEvent caerSpecialEventPacketFindEventByType(caerSpecialEventPacket packet, uint8_t type) {
    CAER_SPECIAL_ITERATOR_ALL_START(packet)
    if (caerSpecialEventGetType(caerSpecialIteratorElement) == type) {
        // Found it, return it.
        return (caerSpecialIteratorElement);
    }
    CAER_SPECIAL_ITERATOR_ALL_END

    // Found nothing, return nothing.
    return (NULL);
}

static inline caerSpecialEventConst caerSpecialEventPacketFindEventByTypeConst(
    caerSpecialEventPacketConst packet, uint8_t type) {
    CAER_SPECIAL_CONST_ITERATOR_ALL_START(packet)
    if (caerSpecialEventGetType(caerSpecialIteratorElement) == type) {
        // Found it, return it.
        return (caerSpecialIteratorElement);
    }
    CAER_SPECIAL_ITERATOR_ALL_END

    // Found nothing, return nothing.
    return (NULL);
}

static inline caerSpecialEvent caerSpecialEventPacketFindValidEventByType(caerSpecialEventPacket packet, uint8_t type) {
    CAER_SPECIAL_ITERATOR_VALID_START(packet)
    if (caerSpecialEventGetType(caerSpecialIteratorElement) == type) {
        // Found it, return it.
        return (caerSpecialIteratorElement);
    }
    CAER_SPECIAL_ITERATOR_VALID_END

    // Found nothing, return nothing.
    return (NULL);
}

static inline caerSpecialEventConst caerSpecialEventPacketFindValidEventByTypeConst(
    caerSpecialEventPacketConst packet, uint8_t type) {
    CAER_SPECIAL_CONST_ITERATOR_VALID_START(packet)
    if (caerSpecialEventGetType(caerSpecialIteratorElement) == type) {
        // Found it, return it.
        return (caerSpecialIteratorElement);
    }
    CAER_SPECIAL_ITERATOR_VALID_END

    // Found nothing, return nothing.
    return (NULL);
}

#ifdef __cplusplus
}
#endif

#endif /* LIBCAER_EVENTS_SPECIAL_H_ */