[sdiy] Rotary Switch -> illuminated PB w/ multicolor LED?
brianw at audiobanshee.com
Mon Feb 21 21:41:27 CET 2022
There are many ways to program Flash or EEPROM bits at a time without an erase operation before every write.
The example given is somewhat unique, because there is only one value. A '1' bit means erased and unused, while a '0' bit means programmed. Thus, it's necessary to look at multiple bits to determine the value. Since there are an even number of bits in every byte, your read algorithm can skip every '0x00' byte because it's all zeroes. A '0x00' byte does not change the value since there are an even number of inversions. There are only 9 possible patterns for a byte, so that would be a quick algorithm. Basically, search for the first non-zero byte and then interpret the 9 possible patterns to see whether the value is 'Off' or 'On'. This is the only technique that requires scanning multiple bit fields to arrive at a final value.
It's possible to use multiple bits per field when writing so that you have more than one possible value, and also so you don't have to consider more than one bit field to determine the value. The only catch is that you need to reserve the 'All Ones' pattern to mean erased, NULL, or unwritten. If you don't reserve the 'All Ones' pattern as NULL, then there's no way to distinguish between writing that particular value versus making no change relative to any of the other values.
For example, if you consume two bits per field written, then you have three possible values (10 01 00) besides 'erased' (11). Three bits give seven values (110 101 100 011 010 001 000) besides 'erased' (111). I'm considering NULL, 'unwritten' and 'erased' to mean the same thing.
If your rotary switch has more than three positions, you'll need to consume more than two bits per write. Then, when reading the value from non-volatile memory at startup, just scan for the last field that is not all ones. You can either scan from the beginning until you read a field that's all ones, and then use the preceding value; or you can scan from the end of NV memory and use the field field that is not all ones.
If your bit field(s) are not an even multiple of 8-bit bytes, you can decide whether to waste bits to force byte alignment, or be sparing of bits and have a more complicated read algorithm. It's actually not too difficult to write a function that will read whole bytes from NV memory and produce bit fields of any size (but be sure to test thoroughly) and this is an algorithm commonly used for compressed data streams.
Using this approach, it's possible to save a fairly large "current state" of your device and still not have to erase the NV memory between every write. As long as the total state requires fewer bits than an entire NV memory page, you can Write multiple times per Erase. In fact, a large structure only needs one field within it to have the 'All Ones' pattern reserved - other fields can use the 'All Ones' pattern after checking the special field.
You need to decide whether to use a single page or multiple pages in the NV memory address range, and then carefully manage the Erase operation to occur only when necessary. Using a single page might be tricky because you risk losing all the settings between Erase (old) and Write (new). A minimum of two pages allows writing to one until it's full, and then when it's time to Erase a page there's always the other page to fall back to in case the new settings are lost (due to premature power loss).
On Feb 21, 2022, at 09:37, grant musictechnologiesgroup.com <grant at musictechnologiesgroup.com> wrote:
> Sorry, I forgot about your previous response, and now I'm trying to wrap
> my head around it. For this one bit, are you just counting the number of
> 1's in the byte (even/odd) to determine on or off?
>> I program a byte at a time. I start at the first byte with all ones = off,
>> so 0x01111111 = on, 0x00111111 = off, etc. Then when the byte gets
>> to zero I move to the next byte and set that to 0x0111111. And so on
>> through the page.
>> Only once the whole page is full of zeros do I erase it.
> If my guess is correct, then the final value for the byte (0000 0000) is
> off and that matches nicely with the initial value (1111 1111) which is
> also off.
> I have to extend that to a larger variable, but I wanted to understand
> your concept.
> ------ Original Message ------
> From: Mike Bryant
> Sent: 2/16/2022 2:01:10 PM
>> You need to just do writes to bytes in sequence. So an all 0's (if it's a clear to 1 memory) represents a null location so move onto the next byte for the real data. Only once you run out of bytes do you need to do a page erase.
>> -----Original Message-----
>> From: grant musictechnologiesgroup.com
>> Sent: 16 February 2022 21:43
>> Well in this application I'm only concerned with a few bits total, but I wonder one thing about wear leveling: since changing a single byte means erasing a whole page (bank/block whatever you want to call it), don't you need to implement multiple pages (banks/blocks) to see a benefit?
>> Or, where is the weakness? Writing or erasing?
More information about the Synth-diy