Rewrite all units and other logic to better use return values and added TRY() helper
This commit is contained in:
+14
-21
@@ -51,7 +51,7 @@ static void DI_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Parse a key-value pair from the INI file */
|
||||
static bool DI_loadIni(Unit *unit, const char *key, const char *value)
|
||||
static error_t DI_loadIni(Unit *unit, const char *key, const char *value)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -67,13 +67,13 @@ static bool DI_loadIni(Unit *unit, const char *key, const char *value)
|
||||
}
|
||||
else if (streq(key, "pull-down")) {
|
||||
priv->pulldown = parse_pinmask(value, &suc);
|
||||
dbg("parsinf ini, pulldown = %X", priv->pulldown);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return E_BAD_KEY;
|
||||
}
|
||||
|
||||
return suc;
|
||||
if (!suc) return E_BAD_VALUE;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Generate INI file section for the unit */
|
||||
@@ -101,11 +101,11 @@ static void DI_writeIni(Unit *unit, IniWriter *iw)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
static bool DI_preInit(Unit *unit)
|
||||
static error_t DI_preInit(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv), &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_OUT_OF_MEM;
|
||||
|
||||
// some defaults
|
||||
priv->port_name = 'A';
|
||||
@@ -113,11 +113,11 @@ static bool DI_preInit(Unit *unit)
|
||||
priv->pulldown = 0x0000;
|
||||
priv->pullup = 0x0000;
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
static bool DI_init(Unit *unit)
|
||||
static error_t DI_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -127,14 +127,10 @@ static bool DI_init(Unit *unit)
|
||||
|
||||
// --- Parse config ---
|
||||
priv->port = port2periph(priv->port_name, &suc);
|
||||
if (!suc) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
return false;
|
||||
}
|
||||
if (!suc) return E_BAD_CONFIG;
|
||||
|
||||
// Claim all needed pins
|
||||
suc = rsc_claim_gpios(unit, priv->port_name, priv->pins);
|
||||
CHECK_SUC();
|
||||
TRY(rsc_claim_gpios(unit, priv->port_name, priv->pins));
|
||||
|
||||
uint16_t mask = 1;
|
||||
for (int i = 0; i < 16; i++, mask <<= 1) {
|
||||
@@ -158,7 +154,7 @@ static bool DI_init(Unit *unit)
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +192,7 @@ enum PinCmd_ {
|
||||
};
|
||||
|
||||
/** Handle a request message */
|
||||
static bool DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
static error_t DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
(void)pp;
|
||||
|
||||
@@ -209,14 +205,11 @@ static bool DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Payloa
|
||||
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));
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
default:
|
||||
com_respond_bad_cmd(frame_id);
|
||||
return false;
|
||||
return E_UNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -48,7 +48,7 @@ static void DO_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Parse a key-value pair from the INI file */
|
||||
static bool DO_loadIni(Unit *unit, const char *key, const char *value)
|
||||
static error_t DO_loadIni(Unit *unit, const char *key, const char *value)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -66,10 +66,11 @@ static bool DO_loadIni(Unit *unit, const char *key, const char *value)
|
||||
priv->open_drain = parse_pinmask(value, &suc);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return E_BAD_KEY;
|
||||
}
|
||||
|
||||
return suc;
|
||||
if (!suc) return E_BAD_VALUE;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Generate INI file section for the unit */
|
||||
@@ -93,11 +94,11 @@ static void DO_writeIni(Unit *unit, IniWriter *iw)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
static bool DO_preInit(Unit *unit)
|
||||
static error_t DO_preInit(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv), &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_OUT_OF_MEM;
|
||||
|
||||
// some defaults
|
||||
priv->port_name = 'A';
|
||||
@@ -105,11 +106,11 @@ static bool DO_preInit(Unit *unit)
|
||||
priv->open_drain = 0x0000;
|
||||
priv->initial = 0x0000;
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
static bool DO_init(Unit *unit)
|
||||
static error_t DO_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -119,14 +120,10 @@ static bool DO_init(Unit *unit)
|
||||
|
||||
// --- Parse config ---
|
||||
priv->port = port2periph(priv->port_name, &suc);
|
||||
if (!suc) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
return false;
|
||||
}
|
||||
if (!suc) return E_BAD_CONFIG;
|
||||
|
||||
// Claim all needed pins
|
||||
suc = rsc_claim_gpios(unit, priv->port_name, priv->pins);
|
||||
CHECK_SUC();
|
||||
TRY(rsc_claim_gpios(unit, priv->port_name, priv->pins));
|
||||
|
||||
uint16_t mask = 1;
|
||||
for (int i = 0; i < 16; i++, mask <<= 1) {
|
||||
@@ -148,7 +145,7 @@ static bool DO_init(Unit *unit)
|
||||
priv->port->ODR &= ~priv->pins;
|
||||
priv->port->ODR |= priv->initial;
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Tear down the unit */
|
||||
@@ -190,10 +187,8 @@ enum PinCmd_ {
|
||||
};
|
||||
|
||||
/** Handle a request message */
|
||||
static bool DO_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
static error_t DO_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
(void)pp;
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
uint16_t packed = pp_u16(pp);
|
||||
@@ -208,29 +203,26 @@ static bool DO_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Payloa
|
||||
set = spread;
|
||||
reset = (~spread) & mask;
|
||||
priv->port->BSRR = set | (reset<<16);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_SET:
|
||||
priv->port->BSRR = spread;
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_CLEAR:
|
||||
priv->port->BSRR = (spread<<16);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_TOGGLE:;
|
||||
spread = (uint16_t) (~priv->port->ODR) & mask;
|
||||
set = spread;
|
||||
reset = (~spread) & mask;
|
||||
priv->port->BSRR = set | (reset<<16);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
default:
|
||||
com_respond_bad_cmd(frame_id);
|
||||
return false;
|
||||
return E_UNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
+58
-110
@@ -55,7 +55,7 @@ static void UI2C_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Parse a key-value pair from the INI file */
|
||||
static bool UI2C_loadIni(Unit *unit, const char *key, const char *value)
|
||||
static error_t UI2C_loadIni(Unit *unit, const char *key, const char *value)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -73,10 +73,11 @@ static bool UI2C_loadIni(Unit *unit, const char *key, const char *value)
|
||||
priv->speed = (uint8_t) avr_atoi(value);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return E_BAD_KEY;
|
||||
}
|
||||
|
||||
return suc;
|
||||
if (!suc) return E_BAD_VALUE;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Generate INI file section for the unit */
|
||||
@@ -100,11 +101,11 @@ static void UI2C_writeIni(Unit *unit, IniWriter *iw)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
static bool UI2C_preInit(Unit *unit)
|
||||
static error_t UI2C_preInit(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv), &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_OUT_OF_MEM;
|
||||
|
||||
// some defaults
|
||||
priv->periph_num = 1;
|
||||
@@ -112,41 +113,36 @@ static bool UI2C_preInit(Unit *unit)
|
||||
priv->anf = true;
|
||||
priv->dnf = 0;
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
static bool UI2C_init(Unit *unit)
|
||||
static error_t UI2C_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
if (!(priv->periph_num >= 1 && priv->periph_num <= 2)) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
dbg("!! Bad I2C periph");
|
||||
return false;
|
||||
dbg("!! Bad I2C periph"); // TODO report
|
||||
return E_BAD_CONFIG;
|
||||
}
|
||||
|
||||
if (!(priv->speed >= 1 && priv->speed <= 3)) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
dbg("!! Bad I2C speed");
|
||||
return false;
|
||||
return E_BAD_CONFIG;
|
||||
}
|
||||
|
||||
if (priv->dnf > 15) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
dbg("!! Bad I2C DNF bw");
|
||||
return false;
|
||||
return E_BAD_CONFIG;
|
||||
}
|
||||
|
||||
// assign and claim the peripheral
|
||||
if (priv->periph_num == 1) {
|
||||
suc = rsc_claim(unit, R_I2C1);
|
||||
CHECK_SUC();
|
||||
TRY(rsc_claim(unit, R_I2C1));
|
||||
priv->periph = I2C1;
|
||||
} else {
|
||||
suc = rsc_claim(unit, R_I2C2);
|
||||
CHECK_SUC();
|
||||
TRY(rsc_claim(unit, R_I2C2));
|
||||
priv->periph = I2C2;
|
||||
}
|
||||
|
||||
@@ -192,15 +188,15 @@ static bool UI2C_init(Unit *unit)
|
||||
// first, we have to claim the pins
|
||||
Resource r_sda = pin2resource(portname, pin_sda, &suc);
|
||||
Resource r_scl = pin2resource(portname, pin_scl, &suc);
|
||||
CHECK_SUC();
|
||||
rsc_claim(unit, r_sda);
|
||||
rsc_claim(unit, r_scl);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_BAD_CONFIG;
|
||||
|
||||
TRY(rsc_claim(unit, r_sda));
|
||||
TRY(rsc_claim(unit, r_scl));
|
||||
|
||||
GPIO_TypeDef *port = port2periph(portname, &suc);
|
||||
uint32_t ll_pin_scl = pin2ll(pin_scl, &suc);
|
||||
uint32_t ll_pin_sda = pin2ll(pin_sda, &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_BAD_CONFIG;
|
||||
|
||||
// configure AF
|
||||
if (pin_scl < 8) LL_GPIO_SetAFPin_0_7(port, ll_pin_scl, af_i2c);
|
||||
@@ -237,7 +233,7 @@ static bool UI2C_init(Unit *unit)
|
||||
LL_I2C_DisableOwnAddress1(priv->periph); // OA not used
|
||||
LL_I2C_SetMode(priv->periph, LL_I2C_MODE_I2C); // not using SMBus
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Tear down the unit */
|
||||
@@ -283,19 +279,19 @@ static void i2c_reset(struct priv *priv)
|
||||
LL_I2C_Enable(priv->periph);
|
||||
}
|
||||
|
||||
static bool i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_state)
|
||||
static error_t i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_state)
|
||||
{
|
||||
uint32_t t_start = HAL_GetTick();
|
||||
while (((priv->periph->ISR & flag)!=0) != stop_state) {
|
||||
if (HAL_GetTick() - t_start > 10) {
|
||||
i2c_reset(priv);
|
||||
return false;
|
||||
return E_HW_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
bool UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount)
|
||||
error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
@@ -304,10 +300,7 @@ bool UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcou
|
||||
uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT;
|
||||
if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly
|
||||
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)) {
|
||||
dbg("BUSY TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0));
|
||||
|
||||
bool first = true;
|
||||
while (bcount > 0) {
|
||||
@@ -320,24 +313,18 @@ bool UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcou
|
||||
bcount -= chunk_remain;
|
||||
|
||||
for (; chunk_remain > 0; chunk_remain--) {
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_TXIS, 1)) {
|
||||
dbg("TXIS TOUT, remain %d", (int)chunk_remain);
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_TXIS, 1));
|
||||
uint8_t byte = *bytes++;
|
||||
LL_I2C_TransmitData8(priv->periph, byte);
|
||||
}
|
||||
}
|
||||
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)) {
|
||||
dbg("STOPF TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1));
|
||||
LL_I2C_ClearFlag_STOP(priv->periph);
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
bool UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount)
|
||||
error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
@@ -346,19 +333,12 @@ bool UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount)
|
||||
uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT;
|
||||
if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly
|
||||
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)) {
|
||||
dbg("BUSY TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0));
|
||||
|
||||
bool first = true;
|
||||
uint32_t n = 0;
|
||||
while (bcount > 0) {
|
||||
if (!first) {
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_TCR, 1)) {
|
||||
dbg("TCR TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_TCR, 1));
|
||||
}
|
||||
|
||||
uint8_t chunk_remain = (uint8_t) ((bcount > 255) ? 255 : bcount); // if more than 255, first chunk is 255
|
||||
@@ -369,116 +349,84 @@ bool UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount)
|
||||
bcount -= chunk_remain;
|
||||
|
||||
for (; chunk_remain > 0; chunk_remain--) {
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_RXNE, 1)) {
|
||||
dbg("RXNE TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_RXNE, 1));
|
||||
|
||||
uint8_t byte = LL_I2C_ReceiveData8(priv->periph);
|
||||
*dest++ = byte;
|
||||
}
|
||||
}
|
||||
|
||||
if (!i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)) {
|
||||
dbg("STOPF TOUT");
|
||||
return false;
|
||||
}
|
||||
TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1));
|
||||
LL_I2C_ClearFlag_STOP(priv->periph);
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
bool UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width)
|
||||
error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width)
|
||||
{
|
||||
if (!UU_I2C_Write(unit, addr, ®num, 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we read the register as if it was a unsigned integer
|
||||
if (!UU_I2C_Read(unit, addr, (uint8_t *) unit_tmp512, width)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
TRY(UU_I2C_Write(unit, addr, ®num, 1));
|
||||
TRY(UU_I2C_Read(unit, addr, dest, width));
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
bool UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width)
|
||||
error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width)
|
||||
{
|
||||
// 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);
|
||||
pb_buf(&pb, bytes, width);
|
||||
|
||||
if (!UU_I2C_Write(unit, addr, (uint8_t *) unit_tmp512, pb_length(&pb))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
TRY(UU_I2C_Write(unit, addr, (uint8_t *) unit_tmp512, pb_length(&pb)));
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Handle a request message */
|
||||
static bool UI2C_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
static error_t UI2C_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
uint16_t addr;
|
||||
uint32_t len;
|
||||
uint8_t regnum;
|
||||
uint32_t size;
|
||||
|
||||
// 10-bit address has the highest bit set to 1 to indicate this
|
||||
|
||||
uint8_t regnum; // register number
|
||||
uint32_t size; // register width
|
||||
// NOTE: 10-bit addresses must have the highest bit set to 1 for indication (0x8000 | addr)
|
||||
|
||||
switch (command) {
|
||||
/** Write byte(s) - addr:u16, byte(s) */
|
||||
case CMD_WRITE:
|
||||
addr = pp_u16(pp);
|
||||
const uint8_t *bb = pp_tail(pp, &len);
|
||||
|
||||
if (!UU_I2C_Write(unit, addr, bb, len)) {
|
||||
com_respond_err(frame_id, "TX FAIL");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
return UU_I2C_Write(unit, addr, bb, len);
|
||||
|
||||
/** Read byte(s) - addr:u16, len:u16 */
|
||||
case CMD_READ:
|
||||
addr = pp_u16(pp);
|
||||
len = pp_u16(pp);
|
||||
|
||||
if (!UU_I2C_Read(unit, addr, (uint8_t *) unit_tmp512, len)) {
|
||||
com_respond_err(frame_id, "RX FAIL");
|
||||
return false;
|
||||
}
|
||||
TRY(UU_I2C_Read(unit, addr, (uint8_t *) unit_tmp512, len));
|
||||
com_respond_buf(frame_id, MSG_SUCCESS, (uint8_t *) unit_tmp512, len);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
/** Read register(s) - addr:u16, reg:u8, size:u16 */
|
||||
case CMD_READ_REG:;
|
||||
addr = pp_u16(pp);
|
||||
regnum = pp_u8(pp); // register number
|
||||
size = pp_u8(pp); // total number of bytes to read (allows use of auto-increment)
|
||||
size = pp_u16(pp); // total number of bytes to read (allows use of auto-increment)
|
||||
|
||||
if (!UU_I2C_ReadReg(unit, addr, regnum, (uint8_t *) unit_tmp512, size)) {
|
||||
com_respond_err(frame_id, "READ REG FAIL");
|
||||
return false;
|
||||
}
|
||||
TRY(UU_I2C_ReadReg(unit, addr, regnum, (uint8_t *) unit_tmp512, size));
|
||||
com_respond_buf(frame_id, MSG_SUCCESS, (uint8_t *) unit_tmp512, size);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
/** Write a register - addr:u16, reg:u8, byte(s) */
|
||||
case CMD_WRITE_REG:
|
||||
addr = pp_u16(pp);
|
||||
regnum = pp_u8(pp); // register number
|
||||
|
||||
const uint8_t *tail = pp_tail(pp, &size);
|
||||
|
||||
if (!UU_I2C_WriteReg(unit, addr, regnum, tail, size)) {
|
||||
com_respond_err(frame_id, "WRITE REG FAIL");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
return UU_I2C_WriteReg(unit, addr, regnum, tail, size);
|
||||
|
||||
default:
|
||||
com_respond_bad_cmd(frame_id);
|
||||
return false;
|
||||
return E_UNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -20,7 +20,7 @@ extern const UnitDriver UNIT_I2C;
|
||||
* @param bcount - byte count
|
||||
* @return success
|
||||
*/
|
||||
bool UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount);
|
||||
error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount);
|
||||
|
||||
/**
|
||||
* Raw read from I2C
|
||||
@@ -31,7 +31,7 @@ bool UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcou
|
||||
* @param bcount - byte count
|
||||
* @return success
|
||||
*/
|
||||
bool UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount);
|
||||
error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount);
|
||||
|
||||
/**
|
||||
* Read one or more registers from a I2C register-based device with auto-increment.
|
||||
@@ -43,7 +43,7 @@ bool UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount);
|
||||
* @param width - register width (or multiple consecutive registers total size)
|
||||
* @return success
|
||||
*/
|
||||
bool UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width);
|
||||
error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width);
|
||||
|
||||
/**
|
||||
* Write a register value
|
||||
@@ -55,7 +55,7 @@ bool UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, ui
|
||||
* @param width - register width (number of bytes)
|
||||
* @return success
|
||||
*/
|
||||
bool UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width);
|
||||
error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width);
|
||||
|
||||
/**
|
||||
* Write a 8-bit register value
|
||||
@@ -66,7 +66,7 @@ bool UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *b
|
||||
* @param value - byte to write to the register
|
||||
* @return success
|
||||
*/
|
||||
static inline bool UU_I2C_WriteReg8(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t value)
|
||||
static inline error_t UU_I2C_WriteReg8(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t value)
|
||||
{
|
||||
return UU_I2C_WriteReg(unit, addr, regnum, &value, 1);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ static void Npx_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Parse a key-value pair from the INI file */
|
||||
static bool Npx_loadIni(Unit *unit, const char *key, const char *value)
|
||||
static error_t Npx_loadIni(Unit *unit, const char *key, const char *value)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -55,10 +55,11 @@ static bool Npx_loadIni(Unit *unit, const char *key, const char *value)
|
||||
priv->pixels = (uint16_t) avr_atoi(value);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return E_BAD_KEY;
|
||||
}
|
||||
|
||||
return suc;
|
||||
if (!suc) return E_BAD_VALUE;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Generate INI file section for the unit */
|
||||
@@ -76,22 +77,22 @@ static void Npx_writeIni(Unit *unit, IniWriter *iw)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
static bool Npx_preInit(Unit *unit)
|
||||
static error_t Npx_preInit(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv), &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_OUT_OF_MEM;
|
||||
|
||||
// some defaults
|
||||
priv->pin_number = 0;
|
||||
priv->port_name = 'A';
|
||||
priv->pixels = 1;
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
static bool Npx_init(Unit *unit)
|
||||
static error_t Npx_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
@@ -100,13 +101,10 @@ static bool Npx_init(Unit *unit)
|
||||
priv->ll_pin = pin2ll(priv->pin_number, &suc);
|
||||
priv->port = port2periph(priv->port_name, &suc);
|
||||
Resource rsc = pin2resource(priv->port_name, priv->pin_number, &suc);
|
||||
if (!suc) {
|
||||
unit->status = E_BAD_CONFIG;
|
||||
return false;
|
||||
}
|
||||
if (!suc) return E_BAD_CONFIG;
|
||||
|
||||
// --- Claim resources ---
|
||||
if (!rsc_claim(unit, rsc)) return false;
|
||||
TRY(rsc_claim(unit, rsc));
|
||||
|
||||
// --- Init hardware ---
|
||||
LL_GPIO_SetPinMode(priv->port, priv->ll_pin, LL_GPIO_MODE_OUTPUT);
|
||||
@@ -117,7 +115,7 @@ static bool Npx_init(Unit *unit)
|
||||
|
||||
ws2812_clear(priv->port, priv->ll_pin, priv->pixels);
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Tear down the unit */
|
||||
@@ -140,6 +138,51 @@ static void Npx_deInit(Unit *unit)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/* Clear the strip */
|
||||
error_t UU_NEOPIXEL_Clear(Unit *unit)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
ws2812_clear(priv->port, priv->ll_pin, priv->pixels);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/* Load packed */
|
||||
error_t UU_NEOPIXEL_Load(Unit *unit, const uint8_t *packed_rgb, uint32_t nbytes)
|
||||
{
|
||||
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);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/* Load U32, LE or BE */
|
||||
static error_t load_u32(Unit *unit, const uint8_t *bytes, uint32_t nbytes, bool bige)
|
||||
{
|
||||
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);
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/* Load U32, LE */
|
||||
inline error_t UU_NEOPIXEL_LoadU32LE(Unit *unit, const uint8_t *bytes, uint32_t nbytes)
|
||||
{
|
||||
return load_u32(unit, bytes, nbytes, false);
|
||||
}
|
||||
|
||||
/* Load U32, BE */
|
||||
inline error_t UU_NEOPIXEL_LoadU32BE(Unit *unit, const uint8_t *bytes, uint32_t nbytes)
|
||||
{
|
||||
return load_u32(unit, bytes, nbytes, true);
|
||||
}
|
||||
|
||||
/* Get the pixel count */
|
||||
inline uint16_t UU_NEOPIXEL_GetCount(Unit *unit)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
return priv->pixels;
|
||||
}
|
||||
|
||||
enum PinCmd_ {
|
||||
CMD_CLEAR = 0,
|
||||
CMD_LOAD = 1,
|
||||
@@ -149,46 +192,39 @@ enum PinCmd_ {
|
||||
};
|
||||
|
||||
/** Handle a request message */
|
||||
static bool Npx_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
static error_t Npx_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
(void)pp;
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
uint32_t len;
|
||||
const uint8_t *bytes;
|
||||
|
||||
switch (command) {
|
||||
/** Clear the entire strip */
|
||||
case CMD_CLEAR:
|
||||
ws2812_clear(priv->port, priv->ll_pin, priv->pixels);
|
||||
break;
|
||||
return UU_NEOPIXEL_Clear(unit);
|
||||
|
||||
case CMD_LOAD:
|
||||
if (pp_length(pp) != priv->pixels*3) goto bad_count;
|
||||
ws2812_load_raw(priv->port, priv->ll_pin, pp->current, priv->pixels);
|
||||
break;
|
||||
/** Load packed RGB colors (length must match the strip size) */
|
||||
case CMD_LOAD:;
|
||||
bytes = pp_tail(pp, &len);
|
||||
return UU_NEOPIXEL_Load(unit, bytes, len);
|
||||
|
||||
/** Load sparse (uint32_t) colors, 0x00RRGGBB, little endian. */
|
||||
case CMD_LOAD_U32_LE:
|
||||
if (pp_length(pp) != priv->pixels*4) goto bad_count;
|
||||
ws2812_load_sparse(priv->port, priv->ll_pin, pp->current, priv->pixels, 0);
|
||||
break;
|
||||
bytes = pp_tail(pp, &len);
|
||||
return UU_NEOPIXEL_LoadU32LE(unit, bytes, len);
|
||||
|
||||
/** Load sparse (uint32_t) colors, 0x00RRGGBB, big endian. */
|
||||
case CMD_LOAD_U32_BE:
|
||||
if (pp_length(pp) != priv->pixels*4) goto bad_count;
|
||||
ws2812_load_sparse(priv->port, priv->ll_pin, pp->current, priv->pixels, 1);
|
||||
break;
|
||||
bytes = pp_tail(pp, &len);
|
||||
return UU_NEOPIXEL_LoadU32BE(unit, bytes, len);
|
||||
|
||||
/** Get the Neopixel strip length */
|
||||
case CMD_GET_LEN:
|
||||
com_respond_u16(frame_id, priv->pixels);
|
||||
break;
|
||||
com_respond_u16(frame_id, UU_NEOPIXEL_GetCount(unit));
|
||||
return E_SUCCESS;
|
||||
|
||||
default:
|
||||
com_respond_bad_cmd(frame_id);
|
||||
return false;
|
||||
return E_UNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
bad_count:
|
||||
com_respond_err(frame_id, "BAD PIXEL COUNT");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -9,4 +9,44 @@
|
||||
|
||||
extern const UnitDriver UNIT_NEOPIXEL;
|
||||
|
||||
/**
|
||||
* Clear the Neopixel strip
|
||||
*
|
||||
* @param unit
|
||||
* @return success
|
||||
*/
|
||||
error_t UU_NEOPIXEL_Clear(Unit *unit);
|
||||
|
||||
/**
|
||||
* Load the strip with packed bytes R,G,B.
|
||||
*
|
||||
* @param unit
|
||||
* @param packed_rgb - bytes to load
|
||||
* @param nbytes - number of bytes, must be count*3
|
||||
* @return success
|
||||
*/
|
||||
error_t UU_NEOPIXEL_Load(Unit *unit, const uint8_t *packed_rgb, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Load the strip with sparse (uint32_t) colors 0x00RRGGBB as little endian bytes
|
||||
* (B, G, R, 0, ...)
|
||||
*
|
||||
* @param unit
|
||||
* @param bytes - bytes to load
|
||||
* @param nbytes - number of bytes, must be count*4
|
||||
* @return success
|
||||
*/
|
||||
error_t UU_NEOPIXEL_LoadU32LE(Unit *unit, const uint8_t *bytes, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* Load the strip with sparse (uint32_t) colors 0x00RRGGBB as big endian bytes
|
||||
* (0, R, G, B, ...)
|
||||
*
|
||||
* @param unit
|
||||
* @param bytes - bytes to load
|
||||
* @param nbytes - number of bytes, must be count*4
|
||||
* @return success
|
||||
*/
|
||||
error_t UU_NEOPIXEL_LoadU32BE(Unit *unit, const uint8_t *bytes, uint32_t nbytes);
|
||||
|
||||
#endif //U_NEOPIXEL_H
|
||||
|
||||
@@ -28,7 +28,7 @@ void ws2812_byte(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t b)
|
||||
}
|
||||
|
||||
/** Set many RGBs from packed stream */
|
||||
void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count)
|
||||
void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, const uint8_t *rgbs, uint32_t count)
|
||||
{
|
||||
vPortEnterCritical();
|
||||
uint8_t b, g, r;
|
||||
@@ -45,7 +45,7 @@ void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_
|
||||
}
|
||||
|
||||
/** Set many RGBs from uint32 stream */
|
||||
void ws2812_load_sparse(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count, bool bigendian)
|
||||
void ws2812_load_sparse(GPIO_TypeDef *port, uint32_t ll_pin, const uint8_t *rgbs, uint32_t count, bool bigendian)
|
||||
{
|
||||
vPortEnterCritical();
|
||||
uint8_t b, g, r;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* @param rgbs - packed R,G,B, R,G,B, ... array
|
||||
* @param count - number of pixels (triplets)
|
||||
*/
|
||||
void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count);
|
||||
void ws2812_load_raw(GPIO_TypeDef *port, uint32_t ll_pin, const uint8_t *rgbs, uint32_t count);
|
||||
|
||||
/**
|
||||
* Load all pixels with BLACK (0,0,0)
|
||||
@@ -30,6 +30,6 @@ void ws2812_clear(GPIO_TypeDef *port, uint32_t ll_pin, uint32_t count);
|
||||
* @param count - number of pixels
|
||||
* @param bigendian - big endian ordering
|
||||
*/
|
||||
void ws2812_load_sparse(GPIO_TypeDef *port, uint32_t ll_pin, uint8_t *rgbs, uint32_t count, bool bigendian);
|
||||
void ws2812_load_sparse(GPIO_TypeDef *port, uint32_t ll_pin, const uint8_t *rgbs, uint32_t count, bool bigendian);
|
||||
|
||||
#endif //WS2812_H
|
||||
|
||||
+13
-25
@@ -32,14 +32,9 @@ static void Tst_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Parse a key-value pair from the INI file */
|
||||
static bool Tst_loadIni(Unit *unit, const char *key, const char *value)
|
||||
static error_t Tst_loadIni(Unit *unit, const char *key, const char *value)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
//
|
||||
|
||||
return suc;
|
||||
return E_BAD_KEY;
|
||||
}
|
||||
|
||||
/** Generate INI file section for the unit */
|
||||
@@ -53,26 +48,26 @@ static void Tst_writeIni(Unit *unit, IniWriter *iw)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
static bool Tst_preInit(Unit *unit)
|
||||
static error_t Tst_preInit(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv), &suc);
|
||||
CHECK_SUC();
|
||||
if (!suc) return E_OUT_OF_MEM;
|
||||
|
||||
//
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
static bool Tst_init(Unit *unit)
|
||||
static error_t Tst_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
//
|
||||
|
||||
return true;
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
/** Tear down the unit */
|
||||
@@ -124,22 +119,18 @@ static void bw_dump(struct bulk_write *bulk, const uint8_t *chunk, uint32_t len)
|
||||
}
|
||||
|
||||
/** Handle a request message */
|
||||
static bool Tst_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
static error_t Tst_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
|
||||
{
|
||||
(void)pp;
|
||||
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
switch (command) {
|
||||
case CMD_PING:
|
||||
com_respond_ok(frame_id);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_ECHO:;
|
||||
uint32_t len;
|
||||
const uint8_t *data = pp_tail(pp, &len);
|
||||
com_respond_buf(frame_id, MSG_SUCCESS, data, len);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_BULKREAD:;
|
||||
BulkRead *br = malloc(sizeof(struct bulk_read));
|
||||
@@ -150,7 +141,7 @@ static bool Tst_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Paylo
|
||||
br->read = br_longtext;
|
||||
|
||||
bulkread_start(comm, br);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
case CMD_BULKWRITE:;
|
||||
BulkWrite *bw = malloc(sizeof(struct bulk_write));
|
||||
@@ -161,14 +152,11 @@ static bool Tst_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Paylo
|
||||
bw->write = bw_dump;
|
||||
|
||||
bulkwrite_start(comm, bw);
|
||||
break;
|
||||
return E_SUCCESS;
|
||||
|
||||
default:
|
||||
com_respond_bad_cmd(frame_id);
|
||||
return false;
|
||||
return E_UNKNOWN_COMMAND;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user