diff --git a/include/canmap.h b/include/canmap.h index b075b72..b9fbb7f 100644 --- a/include/canmap.h +++ b/include/canmap.h @@ -65,6 +65,7 @@ class CanMap: CanCallback void HandleRx(uint32_t canId, uint32_t data[2], uint8_t dlc) override; void Clear(); void SendAll(); + bool SendByIndex(uint8_t ididx); int AddSend(Param::PARAM_NUM param, uint32_t canId, uint8_t offsetBits, int8_t length, float gain); int AddRecv(Param::PARAM_NUM param, uint32_t canId, uint8_t offsetBits, int8_t length, float gain); int AddSend(Param::PARAM_NUM param, uint32_t canId, uint8_t offsetBits, int8_t length, float gain, int8_t offset); @@ -96,6 +97,7 @@ class CanMap: CanCallback CANIDMAP canRecvMap[MAX_MESSAGES]; CANPOS canPosMap[MAX_ITEMS + 1]; //Last item is a "tail" + bool Send(CANIDMAP *map); void ClearMap(CANIDMAP *canMap); int Add(CANIDMAP *canMap, Param::PARAM_NUM param, uint32_t canId, uint8_t offsetBits, int8_t length, float gain, int8_t offset); uint32_t SaveToFlash(uint32_t baseAddress, uint32_t* data, int len); diff --git a/src/canmap.cpp b/src/canmap.cpp index 18b4606..a384c79 100644 --- a/src/canmap.cpp +++ b/src/canmap.cpp @@ -181,70 +181,17 @@ void CanMap::SendAll() { forEachCanMap(curMap, canSendMap) { - uint32_t data[2] = { 0 }; //Had an issue with uint64_t, otherwise would have used that - uint8_t maxBit = 0; - - forEachPosMap(curPos, curMap) - { - if (isSaving) return; //Only send mapped messages when not currently saving to flash - - float val = Param::GetFloat((Param::PARAM_NUM)curPos->mapParam); - - val *= curPos->gain; - val += curPos->offset; - // convert to a signed integer value before storing in an unsigned to - // avoid sign-extension problems when we start shifting and masking - uint32_t ival = (int32_t)val; - uint8_t numBits = ABS(curPos->numBits); - ival &= (1UL << numBits) - 1; - - if (curPos->numBits < 0) // big-endian - { - //Swap byte order - const uint8_t* bptr = (uint8_t*)&ival; - ival = (bptr[0] << 24) | (bptr[1] << 16) | (bptr[2] << 8) | bptr[3]; - - if (curPos->offsetBits < 32) //all data in first word - { - data[0] |= ival >> (31 - curPos->offsetBits); - } - else if ((curPos->offsetBits + curPos->numBits) >= 31) //all data in second word - { - data[1] |= ival >> (63 - curPos->offsetBits); - } - else //data spans across both words - { - data[0] |= ival << (curPos->offsetBits - 31); - data[1] |= ival >> (63 - curPos->offsetBits); - } - maxBit = MAX(maxBit, curPos->offsetBits); - } - else // little-endian - { - if (curPos->offsetBits > 31) - { - // data entirely in the second word - data[1] |= ival << (curPos->offsetBits - 32); - } - else if ((curPos->offsetBits + curPos->numBits) <= 32) - { - // data entirely in the first word - data[0] |= ival << curPos->offsetBits; - } - else - { - // data spans both words - data[0] |= ival << curPos->offsetBits; - data[1] |= ival >> (32 - curPos->offsetBits); - } - maxBit = MAX(maxBit, curPos->offsetBits + curPos->numBits); - } - } + if (!Send(curMap)) + return; + } +} - uint8_t numBytes = (maxBit + 7) / 8; +bool CanMap::SendByIndex(uint8_t ididx) +{ + if (ididx >= MAX_MESSAGES || canSendMap[ididx].first == MAX_ITEMS) + return false; - canHardware->Send(curMap->canId, data, numBytes); - } + return Send(&canSendMap[ididx]); } /** \brief Add periodic CAN message @@ -529,6 +476,74 @@ void CanMap::IterateCanMap(void (*callback)(Param::PARAM_NUM, uint32_t, uint8_t, /****************** Private methods and ISRs ********************/ +bool CanMap::Send(CANIDMAP *map) +{ + uint32_t data[2] = { 0 }; //Had an issue with uint64_t, otherwise would have used that + uint8_t maxBit = 0; + + forEachPosMap(curPos, map) + { + if (isSaving) return false; //Only send mapped messages when not currently saving to flash + + float val = Param::GetFloat((Param::PARAM_NUM)curPos->mapParam); + + val *= curPos->gain; + val += curPos->offset; + // convert to a signed integer value before storing in an unsigned to + // avoid sign-extension problems when we start shifting and masking + uint32_t ival = (int32_t)val; + uint8_t numBits = ABS(curPos->numBits); + ival &= (1UL << numBits) - 1; + + if (curPos->numBits < 0) // big-endian + { + //Swap byte order + const uint8_t* bptr = (uint8_t*)&ival; + ival = (bptr[0] << 24) | (bptr[1] << 16) | (bptr[2] << 8) | bptr[3]; + + if (curPos->offsetBits < 32) //all data in first word + { + data[0] |= ival >> (31 - curPos->offsetBits); + } + else if ((curPos->offsetBits + curPos->numBits) >= 31) //all data in second word + { + data[1] |= ival >> (63 - curPos->offsetBits); + } + else //data spans across both words + { + data[0] |= ival << (curPos->offsetBits - 31); + data[1] |= ival >> (63 - curPos->offsetBits); + } + maxBit = MAX(maxBit, curPos->offsetBits); + } + else // little-endian + { + if (curPos->offsetBits > 31) + { + // data entirely in the second word + data[1] |= ival << (curPos->offsetBits - 32); + } + else if ((curPos->offsetBits + curPos->numBits) <= 32) + { + // data entirely in the first word + data[0] |= ival << curPos->offsetBits; + } + else + { + // data spans both words + data[0] |= ival << curPos->offsetBits; + data[1] |= ival >> (32 - curPos->offsetBits); + } + maxBit = MAX(maxBit, curPos->offsetBits + curPos->numBits); + } + } + + uint8_t numBytes = (maxBit + 7) / 8; + + canHardware->Send(map->canId, data, numBytes); + return true; +} + void CanMap::ClearMap(CANIDMAP *canMap) { for (int i = 0; i < MAX_MESSAGES; i++) diff --git a/test/test_canmap.cpp b/test/test_canmap.cpp index 183b429..e27b2ea 100644 --- a/test/test_canmap.cpp +++ b/test/test_canmap.cpp @@ -611,6 +611,22 @@ static void remove_at_max_messages_is_safe() ASSERT(canId == 0x300); } +static void send_map_by_index_sends_only_selected_message() +{ + canMap->AddSend(Param::ocurlim, 0x101, 0, 8, 1.0, 0); + canMap->AddSend(Param::amp, 0x102, 0, 8, 1.0, 0); + Param::SetFloat(Param::ocurlim, 0x11); + Param::SetFloat(Param::amp, 0x22); + + ASSERT(canMap->SendByIndex(1)); + ASSERT(canStub->m_canId == 0x102); + ASSERT(canStub->m_data[0] == 0x22); + ASSERT(canStub->m_len == 1); + + ASSERT(!canMap->SendByIndex(2)); + ASSERT(!canMap->SendByIndex(MAX_MESSAGES)); +} + static void create_and_delete_complex_map_once() { canMap->AddSend(Param::amp, 257, 24, 8, -1.00, 0); @@ -1204,4 +1220,5 @@ REGISTER_TEST( create_and_delete_complex_map_once, get_map_at_max_messages_returns_null, remove_at_max_messages_is_safe, + send_map_by_index_sends_only_selected_message, RECEIVE_TESTS);