From 7622cf0aafaae5474149b52bb220000d6504937a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 15 Feb 2018 00:40:21 +0100 Subject: [PATCH] added optimized spread/pack utils + "high-speed" variants of DOut UU --- platform/hw_utils.c | 21 ++++++++--- platform/hw_utils.h | 14 ++++++-- units/digital_out/_dout_api.c | 68 +++++++++++++++++++++++------------ units/digital_out/unit_dout.h | 11 ++++++ 4 files changed, 85 insertions(+), 29 deletions(-) diff --git a/platform/hw_utils.c b/platform/hw_utils.c index 876b280..7619775 100644 --- a/platform/hw_utils.c +++ b/platform/hw_utils.c @@ -240,34 +240,45 @@ char * pinmask2str_up(uint32_t pins, char *buffer) return buffer; } -/** Spread packed port pins using a mask */ -uint32_t pinmask_spread(uint32_t packed, uint32_t mask) +/** spread a packed pinfield using a mask */ +uint32_t pinmask_spread_32(uint32_t packed, uint32_t mask) { uint32_t result = 0; uint32_t poke = 1; + if(packed == 0) return 0; + for (int i = 0; i<32; i++) { - if (mask & (1<>= 1; + // if (mask == 0) break; } + return result; } /** Pack spread port pins using a mask */ -uint32_t pinmask_pack(uint32_t spread, uint32_t mask) +uint32_t pinmask_pack_32(uint32_t spread, uint32_t mask) { uint32_t result = 0; uint32_t poke = 1; for (int i = 0; i<32; i++) { - if (mask & (1<>= 1; + // if (mask == 0) break; } return result; } diff --git a/platform/hw_utils.h b/platform/hw_utils.h index 8577cff..cbe0673 100644 --- a/platform/hw_utils.h +++ b/platform/hw_utils.h @@ -98,7 +98,12 @@ char * pinmask2str_up(uint32_t pins, char *buffer); * @param mask - positions of the bits (eg. 0x8803) * @return - bits spread to their positions (always counting from right) */ -uint32_t pinmask_spread(uint32_t packed, uint32_t mask); +uint32_t pinmask_spread_32(uint32_t packed, uint32_t mask); + +static inline uint16_t pinmask_spread(uint16_t packed, uint16_t mask) +{ + return (uint16_t) pinmask_spread_32(packed, mask); +} /** * Pack spread port pins using a mask @@ -107,7 +112,12 @@ uint32_t pinmask_spread(uint32_t packed, uint32_t mask); * @param mask - mask of the bits we want to pack (eg. 0x8803) * @return - packed bits, right aligned (eg. 0b1110) */ -uint32_t pinmask_pack(uint32_t spread, uint32_t mask); +uint32_t pinmask_pack_32(uint32_t spread, uint32_t mask); + +static inline uint16_t pinmask_pack(uint32_t spread, uint32_t mask) +{ + return (uint16_t) pinmask_pack_32(spread, mask); +} /** * Convert spread port pin number to a packed index using a mask diff --git a/units/digital_out/_dout_api.c b/units/digital_out/_dout_api.c index a7557a3..66b8857 100644 --- a/units/digital_out/_dout_api.c +++ b/units/digital_out/_dout_api.c @@ -9,56 +9,80 @@ #define DOUT_INTERNAL #include "_dout_internal.h" -error_t UU_DOut_Write(Unit *unit, uint16_t packed) +error_t UU_DOut_Spread(Unit *unit, uint16_t packed, uint16_t *spread_out) { CHECK_TYPE(unit, &UNIT_DOUT); + *spread_out = UU_DOut_Spread_HS(unit, packed); + return E_SUCCESS; +} +uint16_t UU_DOut_Spread_HS(Unit *unit, uint16_t packed) +{ struct priv *priv = unit->data; uint16_t mask = priv->pins; - uint16_t spread = pinmask_spread(packed, mask); + return pinmask_spread(packed, mask); +} +void UU_DOut_Write_HS(Unit *unit, uint16_t spread) +{ + struct priv *priv = unit->data; + uint16_t mask = priv->pins; uint16_t set = spread; uint16_t reset = ((~spread) & mask); priv->port->BSRR = set | (reset << 16); - return E_SUCCESS; } -error_t UU_DOut_Set(Unit *unit, uint16_t packed) +void UU_DOut_Set_HS(Unit *unit, uint16_t spread) { - CHECK_TYPE(unit, &UNIT_DOUT); - struct priv *priv = unit->data; - uint16_t mask = priv->pins; - uint16_t spread = pinmask_spread(packed, mask); - priv->port->BSRR = spread; - return E_SUCCESS; } -error_t UU_DOut_Clear(Unit *unit, uint16_t packed) +void UU_DOut_Clear_HS(Unit *unit, uint16_t spread) { - CHECK_TYPE(unit, &UNIT_DOUT); - struct priv *priv = unit->data; - uint16_t mask = priv->pins; - uint16_t spread = pinmask_spread(packed, mask); - priv->port->BSRR = (spread<<16); - return E_SUCCESS; } -error_t UU_DOut_Toggle(Unit *unit, uint16_t packed) +void UU_DOut_Toggle_HS(Unit *unit, uint16_t spread) { - CHECK_TYPE(unit, &UNIT_DOUT); - struct priv *priv = unit->data; uint16_t mask = priv->pins; - uint16_t spread = pinmask_spread(packed, mask); - 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); +} + +error_t UU_DOut_Write(Unit *unit, uint16_t packed) +{ + CHECK_TYPE(unit, &UNIT_DOUT); + const uint16_t spread = UU_DOut_Spread_HS(unit, packed); + UU_DOut_Write_HS(unit, spread); + return E_SUCCESS; +} + +error_t UU_DOut_Set(Unit *unit, uint16_t packed) +{ + CHECK_TYPE(unit, &UNIT_DOUT); + const uint16_t spread = UU_DOut_Spread_HS(unit, packed); + UU_DOut_Set_HS(unit, spread); + return E_SUCCESS; +} + +error_t UU_DOut_Clear(Unit *unit, uint16_t packed) +{ + CHECK_TYPE(unit, &UNIT_DOUT); + const uint16_t spread = UU_DOut_Spread_HS(unit, packed); + UU_DOut_Clear_HS(unit, spread); + return E_SUCCESS; +} + +error_t UU_DOut_Toggle(Unit *unit, uint16_t packed) +{ + CHECK_TYPE(unit, &UNIT_DOUT); + const uint16_t spread = UU_DOut_Spread_HS(unit, packed); + UU_DOut_Toggle_HS(unit, spread); return E_SUCCESS; } diff --git a/units/digital_out/unit_dout.h b/units/digital_out/unit_dout.h index b14d1c7..0e6787d 100644 --- a/units/digital_out/unit_dout.h +++ b/units/digital_out/unit_dout.h @@ -56,4 +56,15 @@ error_t UU_DOut_Toggle(Unit *unit, uint16_t packed); */ error_t UU_DOut_GetPinCount(Unit *unit, uint8_t *count); +// --- high-speed variants, without type checking and spreading --- + +/** Spread a packed word */ +error_t UU_DOut_Spread(Unit *unit, uint16_t packed, uint16_t *spread_out); + +uint16_t UU_DOut_Spread_HS(Unit *unit, uint16_t packed); +void UU_DOut_Write_HS(Unit *unit, uint16_t spread); +void UU_DOut_Set_HS(Unit *unit, uint16_t spread); +void UU_DOut_Clear_HS(Unit *unit, uint16_t spread); +void UU_DOut_Toggle_HS(Unit *unit, uint16_t spread); + #endif //U_DOUT_H