GEX core repository.
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-core/units/digital_in/_din_exti.c

82 lines
2.0 KiB

7 years ago
//
// 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 DI_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 DI_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 = DI_SendTriggerReportToMaster
};
scheduleJob(&j);
}
}