pulse generation for digital out

This commit is contained in:
2018-03-08 00:49:21 +01:00
parent 274f2be6e0
commit 590d550a09
11 changed files with 181 additions and 23 deletions
+103 -3
View File
@@ -7,8 +7,20 @@
#include "unit_dout.h"
#define DOUT_INTERNAL
#include "_dout_internal.h"
static void clear_pulse_by_mask(struct priv *priv, uint16_t spread)
{
assert_param(priv);
for (int i = 0; i < 16; i++) {
if (spread & (1 << i)) {
priv->msec_pulse_cnt[i] = 0;
}
}
}
error_t UU_DOut_Write(Unit *unit, uint16_t packed)
{
CHECK_TYPE(unit, &UNIT_DOUT);
@@ -16,6 +28,7 @@ error_t UU_DOut_Write(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
uint16_t set = spread;
uint16_t reset = ((~spread) & mask);
@@ -30,6 +43,7 @@ error_t UU_DOut_Set(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
priv->port->BSRR = spread;
return E_SUCCESS;
@@ -42,8 +56,9 @@ error_t UU_DOut_Clear(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
priv->port->BSRR = (spread<<16);
priv->port->BSRR = (spread << 16);
return E_SUCCESS;
}
@@ -54,11 +69,12 @@ error_t UU_DOut_Toggle(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
uint16_t flipped = (uint16_t) (~priv->port->ODR) & mask;
uint16_t set = flipped & spread;
uint16_t reset = ((~flipped) & mask) & spread;
priv->port->BSRR = set | (reset<<16);
priv->port->BSRR = set | (reset << 16);
return E_SUCCESS;
}
@@ -68,6 +84,90 @@ error_t UU_DOut_GetPinCount(Unit *unit, uint8_t *count)
struct priv *priv = unit->data;
uint32_t packed = pinmask_pack(0xFFFF, priv->pins);
*count = (uint8_t)(32 - __CLZ(packed));
*count = (uint8_t) (32 - __CLZ(packed));
return E_SUCCESS;
}
error_t UU_DOut_Pulse(Unit *unit, uint16_t packed, bool polarity, bool is_usec, uint16_t count)
{
CHECK_TYPE(unit, &UNIT_DOUT);
struct priv *priv = unit->data;
assert_param(priv);
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
vPortEnterCritical();
if (is_usec) {
// we're gonna do this right here as a delay loop.
if (count >= 1000) {
// too long, fall back to msec
count /= 1000;
is_usec = false;
}
else {
const uint32_t bsrr1 = spread << (polarity ? 0 : 16);
const uint32_t bsrr0 = spread << (polarity ? 16 : 0);
const uint32_t start = PTIM_MicroDelayAlign();
priv->port->BSRR = bsrr1;
PTIM_MicroDelayAligned(count, start);
priv->port->BSRR = bsrr0;
}
}
if (!is_usec) {
// Load the counters
for (int i = 0; i < 16; i++) {
if (spread & (1 << i)) {
priv->msec_pulse_cnt[i] = (uint16_t) (count + 1);
}
}
if (polarity) {
priv->msec_pulse_scheduled_1 |= spread;
} else {
priv->msec_pulse_scheduled_0 |= spread;
}
unit->_tick_cnt = 0;
unit->tick_interval = 1;
}
vPortExitCritical();
return E_SUCCESS;
}
void DOut_Tick(Unit *unit)
{
struct priv *priv = unit->data;
uint16_t odr = (uint16_t) priv->port->ODR;
int live_cnt = 0;
for (int i = 0; i < 16; i++) {
if (priv->msec_pulse_scheduled_1 & (1<<i)) {
odr |= (1<<i);
} else if (priv->msec_pulse_scheduled_0 & (1<<i)) {
odr &= ~(1<<i);
}
if (priv->msec_pulse_cnt[i] > 0) {
live_cnt++;
priv->msec_pulse_cnt[i]--;
if (priv->msec_pulse_cnt[i] == 0) {
odr ^= 1 << i;
}
}
}
priv->port->ODR = odr;
priv->msec_pulse_scheduled_1 = 0;
priv->msec_pulse_scheduled_0 = 0;
if (live_cnt == 0) {
unit->_tick_cnt = 0;
unit->tick_interval = 0;
}
}
+5
View File
@@ -19,6 +19,9 @@ struct priv {
uint16_t open_drain; // open drain pins
GPIO_TypeDef *port;
uint16_t msec_pulse_cnt[16];
uint16_t msec_pulse_scheduled_1;
uint16_t msec_pulse_scheduled_0;
};
/** Allocate data structure and set defaults */
@@ -46,4 +49,6 @@ error_t DOut_init(Unit *unit);
/** Tear down the unit */
void DOut_deInit(Unit *unit);
void DOut_Tick(Unit *unit);
#endif //GEX_F072_DOUT_INTERNAL_H
+10 -2
View File
@@ -9,10 +9,11 @@
#include "_dout_internal.h"
enum PinCmd_ {
CMD_TEST = 0,
CMD_QUERY = 0,
CMD_SET = 1,
CMD_CLEAR = 2,
CMD_TOGGLE = 3,
CMD_PULSE = 4,
};
/** Handle a request message */
@@ -21,7 +22,7 @@ static error_t DOut_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
uint16_t packed = pp_u16(pp);
switch (command) {
case CMD_TEST:
case CMD_QUERY:
return UU_DOut_Write(unit, packed);
case CMD_SET:
@@ -33,6 +34,12 @@ static error_t DOut_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
case CMD_TOGGLE:
return UU_DOut_Toggle(unit, packed);
case CMD_PULSE:;
bool polarity = pp_bool(pp);
bool is_usec = pp_bool(pp);
uint16_t count = pp_u16(pp);
return UU_DOut_Pulse(unit, packed, polarity, is_usec, count);
default:
return E_UNKNOWN_COMMAND;
}
@@ -55,4 +62,5 @@ const UnitDriver UNIT_DOUT = {
.deInit = DOut_deInit,
// Function
.handleRequest = DOut_handleRequest,
.updateTick = DOut_Tick,
};
+12
View File
@@ -56,4 +56,16 @@ error_t UU_DOut_Toggle(Unit *unit, uint16_t packed);
*/
error_t UU_DOut_GetPinCount(Unit *unit, uint8_t *count);
/**
* Send a pulse
*
* @param unit
* @param packed - pins to pulse
* @param polarity - pulse active level
* @param is_usec - use usec precision (for < 1 ms)
* @param count - number of units (msec or usec)
* @return success
*/
error_t UU_DOut_Pulse(Unit *unit, uint16_t packed, bool polarity, bool is_usec, uint16_t count);
#endif //U_DOUT_H