|
|
|
//
|
|
|
|
// Created by MightyPork on 2018/02/03.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "platform.h"
|
|
|
|
#include "unit_base.h"
|
|
|
|
|
|
|
|
#define DIN_INTERNAL
|
|
|
|
|
|
|
|
#include "_din_internal.h"
|
|
|
|
#include "_din_exti.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a trigger event to master (called on the message queue thread).
|
|
|
|
*
|
|
|
|
* unit - unit
|
|
|
|
* timestamp - timestamp
|
|
|
|
* data1 - packed, triggering pin
|
|
|
|
* data2 - snapshot
|
|
|
|
*/
|
|
|
|
static void DIn_SendTriggerReportToMaster(Job *job)
|
|
|
|
{
|
|
|
|
PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL);
|
|
|
|
pb_u16(&pb, (uint16_t) job->data1); // packed, 1 on the triggering pin
|
|
|
|
pb_u16(&pb, (uint16_t) job->data2); // packed, snapshot
|
|
|
|
assert_param(pb.ok);
|
|
|
|
|
|
|
|
EventReport event = {
|
|
|
|
.unit = job->unit,
|
|
|
|
.timestamp = job->timestamp,
|
|
|
|
.data = pb.start,
|
|
|
|
.length = (uint16_t) pb_length(&pb),
|
|
|
|
};
|
|
|
|
|
|
|
|
EventReport_Send(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* EXTI callback for pin change interrupts
|
|
|
|
*
|
|
|
|
* @param arg - the unit is passed here
|
|
|
|
*/
|
|
|
|
void DIn_handleExti(void *arg)
|
|
|
|
{
|
|
|
|
const uint64_t ts = PTIM_GetMicrotime();
|
|
|
|
|
|
|
|
Unit *unit = arg;
|
|
|
|
struct priv *priv = unit->data;
|
|
|
|
const uint16_t snapshot = (uint16_t) priv->port->IDR;
|
|
|
|
|
|
|
|
uint16_t trigger_map = 0;
|
|
|
|
|
|
|
|
uint16_t mask = 1;
|
|
|
|
const uint16_t armed_pins = priv->arm_single | priv->arm_auto;
|
|
|
|
for (int i = 0; i < 16; i++, mask <<= 1) {
|
|
|
|
if (!LL_EXTI_ReadFlag_0_31(LL_EXTI_LINES[i])) continue;
|
|
|
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINES[i]);
|
|
|
|
|
|
|
|
// Armed and ready
|
|
|
|
if ((armed_pins & mask) && (priv->holdoff_countdowns[i] == 0)) {
|
|
|
|
// Mark as captured
|
|
|
|
trigger_map |= (1 << i);
|
|
|
|
// Start hold-off (no-op if zero hold-off)
|
|
|
|
priv->holdoff_countdowns[i] = priv->trig_holdoff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disarm all possibly used single triggers
|
|
|
|
priv->arm_single &= ~trigger_map;
|
|
|
|
|
|
|
|
if (trigger_map != 0) {
|
|
|
|
Job j = {
|
|
|
|
.unit = unit,
|
|
|
|
.timestamp = ts,
|
|
|
|
.data1 = pinmask_pack(trigger_map, priv->pins),
|
|
|
|
.data2 = pinmask_pack(snapshot, priv->pins),
|
|
|
|
.cb = DIn_SendTriggerReportToMaster
|
|
|
|
};
|
|
|
|
scheduleJob(&j);
|
|
|
|
}
|
|
|
|
}
|