(still working)

partial-rewrite
Ben Blazak 2013-08-05 09:16:54 -07:00
parent fbbd4570d4
commit 242d04c9f1
1 changed files with 53 additions and 72 deletions

View File

@ -21,19 +21,27 @@
* erased without warning.
*
*
* Implementation notes:
* Implementation warnings:
*
* - One cannot trust the binary layout of bit-fields. Bit-fields are great,
* but the order of the fields (among other things) is implementation
* defined, and [can change]
* (http://avr.2057.n7.nabble.com/Bit-field-packing-order-changed-between-avrgcc-implementations-td19193.html),
* even between different versions of the same compiler.
* even between different versions of the same compiler. The risk is
* probably low, so I use them here anyway, but it's something to be aware
* of.
*
*
* Implementation notes:
*
* - The default state (the "erased" state) of this EEPROM is all `1`s, which
* makes setting a byte to `0xFF` easier and faster in hardware than zeroing
* it. This is reflected in some of our choices for default values, and
* such.
*
* - In avr-gcc, multi-byte data types are allocated with the least significant
* bit occupying the lowest address.
*
* - For a long time, I was going to try to make this library robust in the
* event of power loss, but in the end I decided not to. This feature is
* meant to be used for *temporary* macros - permanent macros really should
@ -77,12 +85,45 @@
// ----------------------------------------------------------------------------
/** types/header/description
* To describe the data that follows (most likely a sequence of `action`s,
* making this the beginning of a macro)
*
* Struct members:
* - type:
* - `0x00`: deleted macro (only `length` is valid)
* - `0x01`: valid macro
* - ... : (not yet assigned)
* - `0xFF`: macro does not exist
* - `length`: the number of `action`s that follow
* - `uid`: a Unique IDentifier for the macro
*/
typedef struct {
uint8_t type;
uint8_t length;
eeprom_macro__uid_t uid;
} header;
/** types/action/description
* To describe the "press" or "release" of a key when recording or playing back
* a macro
*
* Notes:
* - Only the `pressed`, `row`, and `column` fields are relevant, since these
* are what will be passed to `kb__layout__exec_key()` when playing back the
* macro. `layer` will be ignored. We reuse the `...uid_t` type for
* convenience and consistency.
*/
typedef eeprom_macro__uid_t action;
// ----------------------------------------------------------------------------
/** variables/eeprom/description
* The layout of this library's data in the EEPROM
*
* Struct members:
* - `meta`: For keeping track of layout metadata
* - `version`: The version of this layout (`[10]` for fault tolerance and
* - `version`: The version of this layout (`[8]` for fault tolerance and
* write balancing)
* - `table`: To help in quickly returning if the UID we're searching for does
* not exist
@ -100,75 +141,12 @@
* - `macros`: To hold a block of memory for storing macros
* - `length`: The number of elements in `macros.data` (which is *not* the
* same as the number of macros it can contain)
* - `data`: A collection of "macro"s, where
* - a "macro" is a "header" followed by zero or more "action"s
* - a "header" is
* - 4 bytes, aligned on an index boundary
* - `data`: A collection of "macro"s, where a "macro" is a `header`
* followed by zero or more `action`s
*
* LSB - lowest address
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------|
* | type |
* '---------------------------------------'
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------|
* | run length |
* '---------------------------------------'
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------| UID ...
* | pressed | layer | row ... |
* '---------------------------------------'
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------| ... UID
* | ... row | column |
* '---------------------------------------'
* MSB - highest address
*
* - type:
* - `0x00`: deleted macro (run length is valid)
* - `0x01`: valid macro
* - ... : (not yet assigned)
* - `0xFF`: macro does not exist
* - run length: the number of "actions" that follow
* - UID: an `eeprom_macro__uid_t`, laid out in EEPROM memory as
* shown
*
* - an "action" is
* - 2 bytes, aligned on an index or half index boundary
*
* LSB - lowest address
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------| UID ...
* | pressed | layer | row ... |
* '---------------------------------------'
* .---------------------------------------.
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
* |---------------------------------------| ... UID
* | ... row | column |
* '---------------------------------------'
* MSB - highest address
*
* - UID: an `eeprom_macro__uid_t`, laid out in EEMEM as shown
* - Only "pressed", "row", and "column" are relevant, since
* these are what will be passed to `kb__layout__exec_key()`
* when playing back the macro. "layer" will be ignored.
*
* Notes:
*
* - We depict bytes as little endian (which is the opposite of the way they're
* normally portrayed) to be consistent with the byte-order, which we define
* to be little endian to be consistent with the way that avr-gcc allocates
* datatypes larger than 1 byte (see [this discussion]
* (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=337747)
* on <http://www.avrfreaks.net/>).
* Keep in mind that shifting "right" (with `>>`) still shifts towards the
* 0th bit.
*
* - The struct must be `packed` and `aligned(1)`, or we risk allocating more
* than `OPT__EEPROM_MACRO__EEPROM_SIZE` bytes. This should be the default
* when compiling with `avr-gcc`, but it's important to emphasize that we
@ -188,7 +166,7 @@
*/
struct eeprom {
struct meta {
uint8_t version[10];
uint8_t version[8];
} meta;
struct table {
@ -200,9 +178,10 @@ struct eeprom {
struct macros {
uint8_t length;
uint32_t data[ ( OPT__EEPROM_MACRO__EEPROM_SIZE
- 1 // for `length`
- sizeof(struct meta)
- sizeof(struct table) ) / 4 ];
- 1 // for `length`
- sizeof(struct meta)
- sizeof(struct table) )
/ sizeof(uint32_t) ];
} macros;
} __attribute__((packed, aligned(1))) eeprom EEMEM;
@ -241,6 +220,8 @@ uint8_t eeprom_macro__record_finalize(eeprom_macro__uid_t index) {
uint8_t eeprom_macro__exists(eeprom_macro__uid_t index) {
// TODO
return 0;
}
uint8_t eeprom_macro__play(eeprom_macro__uid_t index) {