added unit type checks to UU_ functions
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
#include "utils/payload_builder.h"
|
||||
#include "utils/payload_parser.h"
|
||||
|
||||
#define CHECK_TYPE(_unit, _driver) do { \
|
||||
if ((_unit->driver) != (_driver)) \
|
||||
return E_BAD_UNIT_TYPE; \
|
||||
} while (0)
|
||||
|
||||
extern char unit_tmp512[512]; // temporary static buffer - not expected to be accessed asynchronously
|
||||
// TODO add mutex?
|
||||
|
||||
|
||||
@@ -187,6 +187,14 @@ static void DI_deInit(Unit *unit)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
error_t UU_DI_Read(Unit *unit, uint16_t *packed)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_DIN);
|
||||
struct priv *priv = unit->data;
|
||||
*packed = port_pack((uint16_t) priv->port->IDR, priv->pins);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
enum PinCmd_ {
|
||||
CMD_READ = 0,
|
||||
};
|
||||
@@ -194,14 +202,12 @@ enum PinCmd_ {
|
||||
/** Handle a request message */
|
||||
static error_t DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
(void)pp;
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
uint16_t packed = port_pack((uint16_t) priv->port->IDR, priv->pins);
|
||||
uint16_t packed = 0;
|
||||
|
||||
switch (command) {
|
||||
case CMD_READ:;
|
||||
TRY(UU_DI_Read(unit, &packed));
|
||||
|
||||
PayloadBuilder pb = pb_start((uint8_t*)unit_tmp512, 64, NULL);
|
||||
pb_u16(&pb, packed);
|
||||
com_respond_buf(frame_id, MSG_SUCCESS, (uint8_t *) unit_tmp512, pb_length(&pb));
|
||||
|
||||
@@ -179,6 +179,60 @@ static void DO_deInit(Unit *unit)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
error_t UU_DO_Write(Unit *unit, uint16_t packed)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_DOUT);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
uint16_t mask = priv->pins;
|
||||
uint16_t spread = port_spread(packed, mask);
|
||||
|
||||
uint16_t set = spread;
|
||||
uint16_t reset = ((~spread) & mask);
|
||||
priv->port->BSRR = set | (reset << 16);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
error_t UU_DO_Set(Unit *unit, uint16_t packed)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_DOUT);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
uint16_t mask = priv->pins;
|
||||
uint16_t spread = port_spread(packed, mask);
|
||||
|
||||
priv->port->BSRR = spread;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
error_t UU_DO_Clear(Unit *unit, uint16_t packed)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_DOUT);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
uint16_t mask = priv->pins;
|
||||
uint16_t spread = port_spread(packed, mask);
|
||||
|
||||
priv->port->BSRR = (spread<<16);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
error_t UU_DO_Toggle(Unit *unit, uint16_t packed)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_DOUT);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
uint16_t mask = priv->pins;
|
||||
uint16_t spread = port_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);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
enum PinCmd_ {
|
||||
CMD_WRITE = 0,
|
||||
CMD_SET = 1,
|
||||
@@ -193,32 +247,18 @@ static error_t DO_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Pay
|
||||
|
||||
uint16_t packed = pp_u16(pp);
|
||||
|
||||
uint16_t mask = priv->pins;
|
||||
uint16_t spread = port_spread(packed, mask);
|
||||
|
||||
uint16_t set, reset;
|
||||
|
||||
switch (command) {
|
||||
case CMD_WRITE:;
|
||||
set = spread;
|
||||
reset = (~spread) & mask;
|
||||
priv->port->BSRR = set | (reset<<16);
|
||||
return E_SUCCESS;
|
||||
case CMD_WRITE:
|
||||
return UU_DO_Write(unit, packed);
|
||||
|
||||
case CMD_SET:
|
||||
priv->port->BSRR = spread;
|
||||
return E_SUCCESS;
|
||||
return UU_DO_Set(unit, packed);
|
||||
|
||||
case CMD_CLEAR:
|
||||
priv->port->BSRR = (spread<<16);
|
||||
return E_SUCCESS;
|
||||
return UU_DO_Clear(unit, packed);
|
||||
|
||||
case CMD_TOGGLE:;
|
||||
spread = (uint16_t) (~priv->port->ODR) & mask;
|
||||
set = spread;
|
||||
reset = (~spread) & mask;
|
||||
priv->port->BSRR = set | (reset<<16);
|
||||
return E_SUCCESS;
|
||||
case CMD_TOGGLE:
|
||||
return UU_DO_Toggle(unit, packed);
|
||||
|
||||
default:
|
||||
return E_UNKNOWN_COMMAND;
|
||||
|
||||
@@ -293,6 +293,8 @@ static error_t i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_s
|
||||
|
||||
error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_I2C);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10);
|
||||
@@ -326,6 +328,8 @@ error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t b
|
||||
|
||||
error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_I2C);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10);
|
||||
@@ -370,6 +374,8 @@ error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest,
|
||||
|
||||
error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_I2C);
|
||||
|
||||
// we have to insert the address first - needs a buffer (XXX realistically the buffer needs 1-4 bytes + addr)
|
||||
PayloadBuilder pb = pb_start((uint8_t*)unit_tmp512, 512, NULL);
|
||||
pb_u8(&pb, regnum);
|
||||
|
||||
@@ -141,6 +141,8 @@ static void Npx_deInit(Unit *unit)
|
||||
/* Clear the strip */
|
||||
error_t UU_NEOPIXEL_Clear(Unit *unit)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_NEOPIXEL);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
ws2812_clear(priv->port, priv->ll_pin, priv->pixels);
|
||||
return E_SUCCESS;
|
||||
@@ -149,6 +151,8 @@ error_t UU_NEOPIXEL_Clear(Unit *unit)
|
||||
/* Load packed */
|
||||
error_t UU_NEOPIXEL_Load(Unit *unit, const uint8_t *packed_rgb, uint32_t nbytes)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_NEOPIXEL);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
if (nbytes != 3*priv->pixels) return E_BAD_COUNT;
|
||||
ws2812_load_raw(priv->port, priv->ll_pin, packed_rgb, priv->pixels);
|
||||
@@ -158,6 +162,8 @@ error_t UU_NEOPIXEL_Load(Unit *unit, const uint8_t *packed_rgb, uint32_t nbytes)
|
||||
/* Load U32, LE or BE */
|
||||
static error_t load_u32(Unit *unit, const uint8_t *bytes, uint32_t nbytes, bool bige)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_NEOPIXEL);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
if (nbytes != 4*priv->pixels) return E_BAD_COUNT;
|
||||
ws2812_load_sparse(priv->port, priv->ll_pin, bytes, priv->pixels, bige);
|
||||
@@ -177,10 +183,13 @@ inline error_t UU_NEOPIXEL_LoadU32BE(Unit *unit, const uint8_t *bytes, uint32_t
|
||||
}
|
||||
|
||||
/* Get the pixel count */
|
||||
inline uint16_t UU_NEOPIXEL_GetCount(Unit *unit)
|
||||
error_t UU_NEOPIXEL_GetCount(Unit *unit, uint16_t *count)
|
||||
{
|
||||
CHECK_TYPE(unit, &UNIT_NEOPIXEL);
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
return priv->pixels;
|
||||
*count = priv->pixels;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
enum PinCmd_ {
|
||||
@@ -218,8 +227,10 @@ static error_t Npx_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Pa
|
||||
return UU_NEOPIXEL_LoadU32BE(unit, bytes, len);
|
||||
|
||||
/** Get the Neopixel strip length */
|
||||
case CMD_GET_LEN:
|
||||
com_respond_u16(frame_id, UU_NEOPIXEL_GetCount(unit));
|
||||
case CMD_GET_LEN:;
|
||||
uint16_t count;
|
||||
TRY(UU_NEOPIXEL_GetCount(unit, &count));
|
||||
com_respond_u16(frame_id, count);
|
||||
return E_SUCCESS;
|
||||
|
||||
default:
|
||||
|
||||
@@ -49,4 +49,13 @@ error_t UU_NEOPIXEL_LoadU32LE(Unit *unit, const uint8_t *bytes, uint32_t nbytes)
|
||||
*/
|
||||
error_t UU_NEOPIXEL_LoadU32BE(Unit *unit, const uint8_t *bytes, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Get number of pixels on the strip
|
||||
*
|
||||
* @param unit
|
||||
* @param count - destination for the count value
|
||||
* @return success
|
||||
*/
|
||||
error_t UU_NEOPIXEL_GetCount(Unit *unit, uint16_t *count);
|
||||
|
||||
#endif //U_NEOPIXEL_H
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
X(NO_SUCH_UNIT, NULL) \
|
||||
X(OVERRUN, NULL) /* used in bulk transfer */ \
|
||||
X(PROTOCOL_BREACH, NULL) /* eating with the wrong spoon */ \
|
||||
X(BAD_UNIT_TYPE, NULL) \
|
||||
\
|
||||
/* VFS user errors (those are meant to be shown to user) */ \
|
||||
X(ERROR_DURING_TRANSFER, "Error during transfer") \
|
||||
|
||||
Reference in New Issue
Block a user