BlueAndi / vscp-framework

Very Simple Control Protocol (VSCP) Level 1 Framework
Other
12 stars 8 forks source link

Dynamic DM #20

Closed troky closed 4 years ago

troky commented 5 years ago

I have node with highly configurabile outputs at runtime and I would like to dynamically add/remove DM rows. Currenly it is not possible because VSCP_CONFIG_DM_ROWS is hardcoded. What would be proper way to do it? Is it sane request at all?

BlueAndi commented 5 years ago

VSCP_CONFIG_DM_ROWS contains the max. number of DM rows, your node can have. Each row can be enabled/disabled separately, which is the way to go, depended on your configuraton at runtime.

troky commented 5 years ago

Yes, I am aware of that. Thing is that I have some hardcoded DM rows in flash, some of them are in EEPROM and some of them are created/deleted in runtime (RAM) and looking for way to seamlessly merge them. I'll do magic in vscp_ps_access_read8()

BlueAndi commented 5 years ago

Or in this case you change the vscp_dm_readDecisionMatrix() with a little bit less magic. But of course the merge effort for any updated vscp-framework.

How many rows you have in flash, EEPROM and RAM? You split them over all three, because you run out of RAM or EEPROM? And are you using the standard DM or the extended version?

troky commented 5 years ago

Well, I have several problems regarding DM. Let me give you bigger picture... I have 16 outputs. Each output has config byte, zone byte and subzone byte defined. Config describes hardware (relay output, OC, TTL, etc... enabled/disabled). Each output turns on and off based on received event with matched zone/subzone. Each output can react on more than one event -> 0-n DM rows for one output. To achieve that I need to use extendedDM with N rows. Yes, I can limit N to some acceptable maximum, lets say 2 per output that gives me 32 rows that is total of 512 bytes (using extDM). Also, I have some (8) hardcoded DM rows that are not configurabile - additional 128 bytes.

I have problem with EEPROM space. FLASH and RAM are not problem. Using EEPROM emulation in FLASH is big waste of space because for each byte one uint32 is stored in EEPROM... and in current implementation I am limited to 200-300 bytes.

I asked for dynamic DM because almost all DM rows can be dynamicaly generated based on output's zone/subzone and event class/type so I can serve part od DM from RAM.

... and there is another thing that bugs me alot: DM reading inefficiency. There are so many unnecessary CPU cycles used to read DM byte by byte. Imagine that I have large enough (I2C)EEPROM with 512 bytes of DM... For every received VSCP event I have to read up to 512 bytes from EEPROM byte by byte.

My current idea (without any change to vscp framework) is to store complete DM in one FLASH block (2kB) and read/serve it from RAM, and implement special register/trigger to save it back in FLASH completely.

Making vscp_dm_readDecisionMatrix() and vscp_dm_readDecisionMatrixExt() portable would solve many problems.

BlueAndi commented 5 years ago

Well, I see your challenge. Making vscp_dm_readDecisionMatrix() and vscp_dm_readDecisionMatrixExt() portable would be not enough, as it will raise other problems with current features. I will think about how this could be done with respect to other features.

A DM row caching can be done inside the low level access routine, but I guess you already did that. With the address and the size in the PS, its possible.

BlueAndi commented 5 years ago

In the first step I could add additional functions for multi-byte persistent storage read/write access, which can be implemented by the user.

/**
 * Read several bytes from the persistent memory.
 *
 * @param[in]   addr    Address in persistent memory
 * @param[in]   buffer  Buffer where to read the data in
 * @param[in]   size    Buffer size in bytes
 */
extern void vscp_ps_access_readMultiple(uint16_t addr, uint8_t* const buffer, uint8_t size);

/**
 * Write several bytes to the persistent memory.
 *
 * @param[in]   addr    Address in persistent memory
 * @param[in]   buffer  Buffer with data to write
 * @param[in]   size    Buffer size in bytes
 */
extern void vscp_ps_access_writeMultiple(uint16_t addr, const uint8_t* const buffer, uint8_t size);

During normal operation, the DM will use them (indirect through the layers) for reading a DM row (+ ext.) and for restoring factory settings (write access).

What I would like to introduce additional is that the DM first reads only the flags to determine whether a row is enabled or not. In case its enabled, it will read the whole row.

Any access via virtual register map will still use single byte access.

troky commented 5 years ago

I've decided to keep/cache complete DM in RAM and keep copy in FLASH. Anything that will help this idea and/or reduce reading DM byte by byte from PS would be nice.

BlueAndi commented 5 years ago

I updated the framework, please check.

troky commented 5 years ago

Looking good so far.

I (probably) fixed problem with hardcoded VSCP_CONFIG_DM_ROWS :)

`

define VSCP_CONFIG_DM_ROWS vscp_ps_access_getDMRowCount()

`