@@ -239,98 +239,57 @@ bool setEntityValue(page_iterator_t &entity, uint16_t offset, byte value)
239239 }
240240}
241241
242- // ========================= Static page size computation & checking ===================
243-
244- // Since pages are a logical contiguous block, we can automatically compute the
245- // logical start address of every item: the first one starts at zero, following
246- // items must start at the end of the previous.
247- #define ENTITY_START_VAR entityStartAddress
248- // Compute the start address of the next entity. We need this to be a constexpr
249- // so we can static assert on it later. So we cannot increment an exiting var.
250- #define UPDATE_ENTITY_START (entitySize ) ENTITY_START_VAR = ENTITY_START_VAR + (entitySize);
251- //
252- #define ITEM_INDEX_VAR itemIndex
253- #define UPDATE_ITEM_INDEX () ++ITEM_INDEX_VAR;
254-
255- // ========================= Logical page end processing ===================
242+ // ========================= Offset to entity support ===================
256243
257- // The members of all page_iterator_t instances are compile time constants and
258- // thus all page_iterator_t instances *could* be compile time constants.
259- //
260- // If we declare them inline as part of return statements, gcc recognises they
261- // are constants (even without constexpr). Constants need to be stored somewhere:
262- // gcc places them in the .data section, which is placed in SRAM :-(.
263- //
264- // So we would end up using several hundred bytes of SRAM.
265- //
266- // Instead we use this (and other) intermediate factory function(s) - it provides a barrier that
267- // forces GCC to construct the page_iterator_t instance at runtime.
268- static inline page_iterator_t create_end_iterator (uint8_t pageNum, uint8_t index, uint16_t start)
244+ void nextEntity (page_iterator_t &entity, uint16_t nextBlockSize)
269245{
270- return page_iterator_t ( End,
271- entity_page_location_t (pageNum, index),
272- entity_page_address_t (start, 0U ));
246+ ++entity.location .index ;
247+ entity.address = entity.address .next (nextBlockSize);
273248}
274249
275- // Signal the end of a page
276- #define END_OF_PAGE (pageNum ) return create_end_iterator((pageNum), ITEM_INDEX_VAR, ENTITY_START_VAR);
277-
278250// ========================= Table processing ===================
279251
280- static inline page_iterator_t create_table_iterator (void *pTable, table_type_t key, uint8_t pageNum, uint8_t index, uint16_t start, uint16_t size)
252+ template <class table_t >
253+ static void checkIsInTable (page_iterator_t &result, table_t *pTable, uint16_t offset)
281254{
282- return page_iterator_t ( pTable, key,
283- entity_page_location_t (pageNum, index),
284- entity_page_address_t (start, size));
255+ if (result.type ==End)
256+ {
257+ nextEntity (result, get_table_axisy_end (pTable));
258+ if (result.address .isOffsetInEntity (offset))
259+ {
260+ result.setTable (pTable, pTable->type_key );
261+ }
262+ }
285263}
286264
287- // If the offset is in range, create a Table entity_t
288- #define CHECK_TABLE (pageNum, offset, pTable ) \
289- if (offset < ENTITY_START_VAR+get_table_axisy_end(pTable)) \
290- { \
291- return create_table_iterator (pTable, (pTable)->type_key , \
292- (pageNum), ITEM_INDEX_VAR, \
293- ENTITY_START_VAR, get_table_axisy_end ((pTable))); \
294- } \
295- UPDATE_ENTITY_START (get_table_axisy_end(pTable)) \
296- UPDATE_ITEM_INDEX()
297-
298265// ========================= Raw memory block processing ===================
299266
300- static inline page_iterator_t create_raw_iterator( void *pBuffer, uint8_t pageNum, uint8_t index, uint16_t start , uint16_t size )
267+ static void checkIsInRaw ( page_iterator_t &result, void *pEntity, uint16_t entitySize , uint16_t offset )
301268{
302- return page_iterator_t ( pBuffer,
303- entity_page_location_t (pageNum, index),
304- entity_page_address_t (start, size));
269+ if (result.type ==End)
270+ {
271+ nextEntity (result, entitySize);
272+ if (result.address .isOffsetInEntity (offset))
273+ {
274+ result.setRaw (pEntity);
275+ }
276+ }
305277}
306278
307- // If the offset is in range, create a Raw entity_t
308- #define CHECK_RAW (pageNum, offset, pDataBlock, blockSize ) \
309- if (offset < ENTITY_START_VAR+blockSize) \
310- { \
311- return create_raw_iterator ((pDataBlock), (pageNum), ITEM_INDEX_VAR, ENTITY_START_VAR, (blockSize));\
312- } \
313- UPDATE_ENTITY_START (blockSize) \
314- UPDATE_ITEM_INDEX()
315-
316279// ========================= Empty entity processing ===================
317280
318- static inline page_iterator_t create_empty_iterator( uint8_t pageNum, uint8_t index, uint16_t start , uint16_t size )
281+ static void checkIsInEmpty ( page_iterator_t &result, uint16_t entitySize , uint16_t offset )
319282{
320- return page_iterator_t ( NoEntity,
321- entity_page_location_t (pageNum, index),
322- entity_page_address_t (start, size));
283+ if (result.type ==End)
284+ {
285+ nextEntity (result, entitySize);
286+ if (result.address .isOffsetInEntity (offset))
287+ {
288+ result.setNoEntity ();
289+ }
290+ }
323291}
324292
325- // If the offset is in range, create a "no entity"
326- #define CHECK_NOENTITY (pageNum, offset, blockSize ) \
327- if (offset < ENTITY_START_VAR+blockSize) \
328- { \
329- return create_empty_iterator ((pageNum), ITEM_INDEX_VAR, ENTITY_START_VAR, (blockSize));\
330- } \
331- UPDATE_ENTITY_START (blockSize) \
332- UPDATE_ITEM_INDEX()
333-
334293// ===============================================================================
335294
336295// Does the heavy lifting of mapping page+offset to an entity
@@ -339,123 +298,130 @@ static inline page_iterator_t create_empty_iterator(uint8_t pageNum, uint8_t ind
339298// That uses flash memory, which is scarce. And it was too slow.
340299static page_iterator_t map_page_offset_to_entity (uint8_t pageNumber, uint16_t offset)
341300{
342- // The start address of the 1st entity in any page.
343- uint16_t ENTITY_START_VAR = 0U ;
344- uint8_t ITEM_INDEX_VAR = 0U ;
301+ // This is mutated by the checkIsIn* functions to return the entity that matches the offset
302+ page_iterator_t result ( End, // Signal that no entity has been found yet
303+ entity_page_location_t (pageNumber, (uint8_t )-1 /* Deliberate, so we can increment index AND address as one operation */ ),
304+ entity_page_address_t (0U , 0U ));
345305
346306 switch (pageNumber)
347307 {
348308 case veMapPage:
349309 // LCOV_EXCL_BR_START
350310 // The first entity on the page has a missing branch not covered
351- // No idea why, so exclude froom branch coverage for the moment
352- CHECK_TABLE (veMapPage, offset, &fuelTable)
311+ // No idea why, so exclude from branch coverage for the moment
312+ checkIsInTable (result, &fuelTable, offset);
353313 // LCOV_EXCL_BR_STOP
354314 break ;
355315
356316 case ignMapPage: // Ignition settings page (Page 2)
357317 // LCOV_EXCL_BR_START
358- CHECK_TABLE (ignMapPage, offset, &ignitionTable)
318+ checkIsInTable (result, &ignitionTable, offset);
359319 // LCOV_EXCL_BR_STOP
360320 break ;
361321
362322 case afrMapPage: // Air/Fuel ratio target settings page
363323 // LCOV_EXCL_BR_START
364- CHECK_TABLE (afrMapPage, offset, &afrTable)
324+ checkIsInTable (result, &afrTable, offset);
365325 // LCOV_EXCL_BR_STOP
366326 break ;
367327
368328 case boostvvtPage: // Boost, VVT and staging maps (all 8x8)
369329 // LCOV_EXCL_BR_START
370- CHECK_TABLE (boostvvtPage, offset, &boostTable)
330+ checkIsInTable (result, &boostTable, offset);
371331 // LCOV_EXCL_BR_STOP
372- CHECK_TABLE (boostvvtPage, offset, &vvtTable)
373- CHECK_TABLE (boostvvtPage, offset, &stagingTable)
332+ checkIsInTable (result, &vvtTable, offset);
333+ checkIsInTable (result, &stagingTable, offset);
374334 break ;
375335
376336 case seqFuelPage:
377337 // LCOV_EXCL_BR_START
378- CHECK_TABLE (seqFuelPage, offset, &trim1Table)
338+ checkIsInTable (result, &trim1Table, offset);
379339 // LCOV_EXCL_BR_STOP
380- CHECK_TABLE (seqFuelPage, offset, &trim2Table)
381- CHECK_TABLE (seqFuelPage, offset, &trim3Table)
382- CHECK_TABLE (seqFuelPage, offset, &trim4Table)
383- CHECK_TABLE (seqFuelPage, offset, &trim5Table)
384- CHECK_TABLE (seqFuelPage, offset, &trim6Table)
385- CHECK_TABLE (seqFuelPage, offset, &trim7Table)
386- CHECK_TABLE (seqFuelPage, offset, &trim8Table)
340+ checkIsInTable (result, &trim2Table, offset);
341+ checkIsInTable (result, &trim3Table, offset);
342+ checkIsInTable (result, &trim4Table, offset);
343+ checkIsInTable (result, &trim5Table, offset);
344+ checkIsInTable (result, &trim6Table, offset);
345+ checkIsInTable (result, &trim7Table, offset);
346+ checkIsInTable (result, &trim8Table, offset);
387347 break ;
388348
389349 case fuelMap2Page:
390350 // LCOV_EXCL_BR_START
391- CHECK_TABLE (fuelMap2Page, offset, &fuelTable2)
351+ checkIsInTable (result, &fuelTable2, offset);
392352 // LCOV_EXCL_BR_STOP
393353 break ;
394354
395355 case wmiMapPage:
396356 // LCOV_EXCL_BR_START
397- CHECK_TABLE (wmiMapPage, offset, &wmiTable)
357+ checkIsInTable (result, &wmiTable, offset);
398358 // LCOV_EXCL_BR_STOP
399- CHECK_TABLE (wmiMapPage, offset, &vvt2Table)
400- CHECK_TABLE (wmiMapPage, offset, &dwellTable)
401- CHECK_NOENTITY (wmiMapPage, offset, 8U )
359+ checkIsInTable (result, &vvt2Table, offset);
360+ checkIsInTable (result, &dwellTable, offset);
361+ checkIsInEmpty (result, 8U , offset);
402362 break ;
403363
404364 case ignMap2Page:
405365 // LCOV_EXCL_BR_START
406- CHECK_TABLE (ignMap2Page, offset, &ignitionTable2)
366+ checkIsInTable (result, &ignitionTable2, offset);
407367 // LCOV_EXCL_BR_STOP
408368 break ;
409369
410370 case veSetPage:
411371 // LCOV_EXCL_BR_START
412- CHECK_RAW (veSetPage, offset, &configPage2, sizeof (configPage2))
372+ checkIsInRaw (result, &configPage2, sizeof (configPage2), offset);
413373 // LCOV_EXCL_BR_STOP
414374 break ;
415375
416376 case ignSetPage:
417377 // LCOV_EXCL_BR_START
418- CHECK_RAW (ignSetPage, offset, &configPage4, sizeof (configPage4))
378+ checkIsInRaw (result, &configPage4, sizeof (configPage4), offset);
419379 // LCOV_EXCL_BR_STOP
420380 break ;
421381
422382 case afrSetPage:
423383 // LCOV_EXCL_BR_START
424- CHECK_RAW (afrSetPage, offset, &configPage6, sizeof (configPage6))
384+ checkIsInRaw (result, &configPage6, sizeof (configPage6), offset);
425385 // LCOV_EXCL_BR_STOP
426386 break ;
427387
428388 case canbusPage:
429389 // LCOV_EXCL_BR_START
430- CHECK_RAW (canbusPage, offset, &configPage9, sizeof (configPage9))
390+ checkIsInRaw (result, &configPage9, sizeof (configPage9), offset);
431391 // LCOV_EXCL_BR_STOP
432392 break ;
433393
434394 case warmupPage:
435395 // LCOV_EXCL_BR_START
436- CHECK_RAW (warmupPage, offset, &configPage10, sizeof (configPage10))
396+ checkIsInRaw (result, &configPage10, sizeof (configPage10), offset);
437397 // LCOV_EXCL_BR_STOP
438398 break ;
439399
440400 case progOutsPage:
441401 // LCOV_EXCL_BR_START
442- CHECK_RAW (progOutsPage, offset, &configPage13, sizeof (configPage13))
402+ checkIsInRaw (result, &configPage13, sizeof (configPage13), offset);
443403 // LCOV_EXCL_BR_STOP
444404 break ;
445405
446406 case boostvvtPage2: // Boost, VVT and staging maps (all 8x8)
447407 // LCOV_EXCL_BR_START
448- CHECK_TABLE (boostvvtPage2, offset, &boostTableLookupDuty)
408+ checkIsInTable (result, &boostTableLookupDuty, offset);
449409 // LCOV_EXCL_BR_STOP
450- CHECK_RAW (boostvvtPage2, offset, &configPage15, sizeof (configPage15))
410+ checkIsInRaw (result, &configPage15, sizeof (configPage15), offset);
451411 break ;
452412
453413 default :
454414 // Nothing to do
455415 break ;
456416 }
457417
458- END_OF_PAGE (pageNumber)
418+ // Nothing matched, so we are at the end of the known entities for the page.
419+ if (result.type ==End)
420+ {
421+ nextEntity (result, 0U );
422+ }
423+
424+ return result;
459425}
460426
461427
@@ -469,7 +435,7 @@ uint8_t getPageCount(void)
469435uint16_t getPageSize (byte pageNum)
470436{
471437 page_iterator_t entity = map_page_offset_to_entity (pageNum, UINT16_MAX);
472- return entity.address .start + entity.address .size ;;
438+ return entity.address .start + entity.address .size ;
473439}
474440
475441static inline uint16_t pageOffsetToEntityOffset (const page_iterator_t &entity, uint16_t pageOffset)
0 commit comments