lib/eeprom-macro : debating implementation
parent
0c23c45627
commit
56cbc8cb1b
|
@ -170,6 +170,10 @@
|
|||
`uint8_t`s when operating on things then, when possible, and to just not
|
||||
bitshift `char`s.
|
||||
|
||||
* [GCC docs : Variable Attributes]
|
||||
(http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html)
|
||||
How to byte align variables in GCC (among other things...)
|
||||
|
||||
### C++ Stuff
|
||||
|
||||
* [Google C++ Style Guide]
|
||||
|
|
|
@ -13,29 +13,25 @@
|
|||
* implementation.
|
||||
*
|
||||
*
|
||||
* TODO: might need a "get_size_total()" and "get_size_free()" later, for
|
||||
* information display purposes
|
||||
* Usage notes:
|
||||
*
|
||||
* - These function will play back keystrokes, not actions. This means that
|
||||
* new macro definitions may affect old ones. It also means that different
|
||||
* keyboard states may lead to different actions being performed for the same
|
||||
* macro (if, say, the layer the macro is on is mostly transparent, and there
|
||||
* is a different layer underneath it on a subsequent press than there was
|
||||
* during definition).
|
||||
*
|
||||
* TODO: rewrite the following
|
||||
* notes:
|
||||
* - Even though `eeprom_macro__index_t` has distinct fields, there is nothing
|
||||
* that says the calling function(s) must maintain those semantic meanings.
|
||||
* I imagine that under most circumstances one would want to, but as long as
|
||||
* the '.c' file implementing this interface agrees (or at least works) with
|
||||
* whatever the calling functions are doing, things should be fine.
|
||||
*
|
||||
* - these functions will play back keystrokes, not functions or (layer, row,
|
||||
* column) tuples, or anything like that. this means that if you press a key
|
||||
* that has a macro assigned to it while defining a new macro, the former
|
||||
* macro will be activated each time the new macro is run (unless it is
|
||||
* deleted). this means that if you intend to use these functions to move
|
||||
* letter keys around, you should probably have a layer somewhere with all
|
||||
* the letters on it, and define the macros on your home layer to press keys
|
||||
* on that other layer. otherwise, assigning a macro to a letter key will
|
||||
* make that letter unreachable until the macro is removed.
|
||||
*
|
||||
* - or (instead of the above) `...exec_key()` could handle macro assignment
|
||||
* differently, and trigger macro replay based on something besides what i'm
|
||||
* currently thinking of for the ergodox. that is, "layers" here need not
|
||||
* correspond to "layers" elsewhere in the firmware, except for the purposes
|
||||
* of convenience, and possibly sanity (both of which are typically overruled
|
||||
* by memory constraints...).
|
||||
* - Particularly, if there were a layout implementation that ignored
|
||||
* layers, but wanted to manually map different key combinations to
|
||||
* different macros for a given key, this could be done by repurposing
|
||||
* the `layer` field to mean "key combination id" (or some such thing).
|
||||
*/
|
||||
|
||||
|
||||
|
@ -80,7 +76,8 @@ void eeprom_macro__clear_all (void);
|
|||
/** types/eeprom_macro__index_t/description
|
||||
* A convenient way to specify a position in the layer matrix
|
||||
*
|
||||
* Used here to uniquely identify macros, and to group them for optimizations.
|
||||
* Used here as a UID (Unique IDentifier) for macros, and to group them for
|
||||
* optimizations.
|
||||
*
|
||||
* Notes:
|
||||
* - This format artificially limits the number of layers, rows, and columns
|
||||
|
@ -144,7 +141,7 @@ void eeprom_macro__clear_all (void);
|
|||
*
|
||||
* Arguments:
|
||||
* - `skip`: The number of keystrokes at the end of our recording to ignore
|
||||
* - `index`: The unique ID of this macro
|
||||
* - `index`: The UID of this macro
|
||||
*
|
||||
* Returns:
|
||||
* - success: `0`
|
||||
|
@ -157,10 +154,10 @@ void eeprom_macro__clear_all (void);
|
|||
|
||||
// === eeprom_macro__play ===
|
||||
/** functions/eeprom_macro__play/description
|
||||
* Play back recorded keystrokes for the macro with unique ID `index`
|
||||
* Play back recorded keystrokes for the macro with UID `index`
|
||||
*
|
||||
* Arguments:
|
||||
* - `index`: The unique ID of the macro to play
|
||||
* - `index`: The UID of the macro to play
|
||||
*
|
||||
* Returns:
|
||||
* - `0`: Macro successfully played
|
||||
|
@ -175,10 +172,10 @@ void eeprom_macro__clear_all (void);
|
|||
|
||||
// === eeprom_macro__clear ===
|
||||
/** functions/eeprom_macro__clear/description
|
||||
* Clear the macro with unique ID `index`
|
||||
* Clear the macro with UID `index`
|
||||
*
|
||||
* Arguments:
|
||||
* - `index`: The unique ID of the macro to clear
|
||||
* - `index`: The UID of the macro to clear
|
||||
*/
|
||||
|
||||
// === eeprom_macro__clear_all ===
|
||||
|
|
|
@ -8,13 +8,18 @@
|
|||
* Implements the eeprom-macro functionality defined in "../eeprom-macro.h" for
|
||||
* the ATMega32U4
|
||||
*
|
||||
*
|
||||
* Implementation notes:
|
||||
*
|
||||
* - "block"s are 4 bytes long, aligned on the 4 byte boundary
|
||||
* - blocks are pointed to by `uint8_t`s
|
||||
*
|
||||
* - Blocks are pointed to by `uint8_t`s
|
||||
* - the EEPROM contains 1024 bytes = 256 blocks
|
||||
* (i.e. 2^10 bytes, 2^8 blocks)
|
||||
* - the beginning of a block is pointed to by
|
||||
* `eeprom_address = block_address<<2`
|
||||
* `eeprom_address = block_address << 2`
|
||||
*
|
||||
* - A "UID" (Unique ID) in this file is a `eeprom_macro__index_t`
|
||||
*/
|
||||
|
||||
|
||||
|
@ -36,11 +41,14 @@
|
|||
* Size (in blocks): 1
|
||||
*
|
||||
* Format:
|
||||
* - byte 0: the version of this layout
|
||||
* - `0x00`, `0xFF` => uninitialized
|
||||
* - byte 1: the number of rows in the table
|
||||
* - byte 2: the number of columns in the table
|
||||
* - byte 3: the first free block not yet used by `MACROS`
|
||||
*
|
||||
* struct {
|
||||
* uint8_t version; // the version of this layout
|
||||
* // `0x00`,`0xFF` => uninitialized
|
||||
* uint8_t rows; // the number of rows in the table
|
||||
* uint8_t columns; // the number of columns in the table
|
||||
* uint8_t free; // the first free block not yet used for macros
|
||||
* };
|
||||
*
|
||||
* Notes:
|
||||
* - The number of rows and columns is significant to the offsets of some of
|
||||
|
@ -57,7 +65,7 @@
|
|||
*
|
||||
* Notes:
|
||||
* - Each entry is a block pointer to the first macro with the corresponding
|
||||
* `row` and `column` in its unique ID
|
||||
* `row` and `column` in its UID
|
||||
*
|
||||
* Format:
|
||||
* - A `[ROWS][COLUMNS]` table, where the `[row][column]` entry can be accessed
|
||||
|
@ -72,17 +80,23 @@
|
|||
* Size (in blocks): `END - MACROS + 1` (since `END` is included)
|
||||
*
|
||||
* Format: macro header:
|
||||
* - byte 0: a block pointer to the next macro with the same `row` and `column`
|
||||
* in its unique ID
|
||||
* - `0x00` => this macro is the last in the linked list for this `row`,
|
||||
* `column` pair
|
||||
* - `0xFF` => this macro has been deleted
|
||||
* - byte 1: the run length of the macro, in number of key actions
|
||||
* - byte 2..3: the unique ID of this macro (its `index`)
|
||||
*
|
||||
* Format: key action
|
||||
* - The same as the format of `eeprom_macro__index_t` (which is the format of
|
||||
* the unique IDs), except that `layer` will be ignored
|
||||
* struct {
|
||||
* uint8_t next; // a block pointer to the next macro with the same
|
||||
* // `row` and `column` in its UID
|
||||
* // `0x00` => this macro is the last in the linked
|
||||
* // list for this `row`, `column` pair
|
||||
* // `0xFF` => this macro has been deleted
|
||||
* uint8_t length; // the run length of the macro, in number of
|
||||
* // key actions
|
||||
* eeprom_macro__index_t index; // the UID of this macro
|
||||
* };
|
||||
*
|
||||
* Format: key action:
|
||||
*
|
||||
* struct {
|
||||
* eeprom_macro__index_t index; // `layer` will be ignored
|
||||
* };
|
||||
*/
|
||||
#define MACROS (TABLE + ((ROWS * COLUMNS + 0b11) >> 2))
|
||||
|
||||
|
@ -94,5 +108,46 @@
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// sanity check
|
||||
#if MACROS+10 >= END
|
||||
#error "Insufficient EEPROM allocated to \".../firmware/lib/eeprom-macro\""
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: if we do it this way, this belongs in the options file
|
||||
#define OPT__EEPROM_MACRO__SIZE 1024
|
||||
|
||||
#define VERSION 1
|
||||
|
||||
struct {
|
||||
uint8_t version; // the version of this layout
|
||||
// `0x00`,`0xFF` => uninitialized
|
||||
uint8_t rows; // the number of rows in the table
|
||||
uint8_t columns; // the number of columns in the table
|
||||
uint8_t free; // the first free block not yet used for macros
|
||||
} header EEMEM;
|
||||
|
||||
uint8_t table[OPT__KB__ROWS][OPT__KB__COLUMNS] EEMEM;
|
||||
|
||||
uint8_t macros[ OPT__EEPROM_MACRO__SIZE-sizeof(header)-sizeof(table) ] EEMEM;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void f(void) {
|
||||
uint8_t version1 = eeprom_read_byte( (HEADER<<2) + 0 );
|
||||
uint8_t version2 = eeprom_read_byte( &header.version );
|
||||
|
||||
uint8_t ptr1 = eeprom_read_byte( TABLE + 5*COLUMNS + 3 );
|
||||
uint8_t ptr2 = eeprom_read_byte( &table[5][3] );
|
||||
|
||||
|
||||
// to suppress warnings about unused variables...
|
||||
uint8_t version3 = version1+version2;
|
||||
version3++;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: functions
|
||||
|
||||
|
|
Loading…
Reference in New Issue