(working: eeprom-macro)

there are a few warnings during compile, but only about functions not
being used.  it's okay: they'll be used soon enough.
partial-rewrite
Ben Blazak 2014-05-26 15:54:13 -07:00
parent 49e8f32a60
commit 0fd92b5840
2 changed files with 135 additions and 55 deletions

View File

@ -25,19 +25,19 @@
* - A "key" is a pair of actions, one for when the key is pressed and another
* for when it is released. We specify keys by their `layer`, `row`, and
* `column`.
* - A "key action" is a single action. We specify key actions by their
* - A "key-action" is a single action. We specify key-actions by their
* `pressed` value (whether the action corresponds to a press (`true`) or
* release (`false`)) and the key they belong to.
* - A "macro" is a collection of data that lives in persistent memory, and
* specifies possibly many actions to perform in the place of a single,
* usually different, action. For the purposes of this library, macros live
* in the EEPROM, and contain a key action who's original behavior we wish
* to mask, and a list of key actions that should be sequentially performed
* in the EEPROM, and contain a key-action who's original behavior we wish
* to mask, and a list of key-actions that should be sequentially performed
* instead.
* - A "keystroke" is a full press then release of a key. Keystrokes may
* overlap each other.
* - To "remap" a key action is to assign a macro to it (masking, not
* replacing, what the key action originally did).
* - To "remap" a key-action is to assign a macro to it (masking, not
* replacing, what the key-action originally did).
* - The "EEPROM" is an "Electronically Erasable Programmable Read Only
* Memory". It is where this library stores persistent data.
* - "EEMEM" is "EEprom MEMory" (i.e. another way of referring to the memory of
@ -67,12 +67,12 @@
* one might wish to do when, for example, quickly swapping the positions of
* two letter keys.
* - With sufficient trickiness, we could probably do away with having `layer`
* in the key actions that make up the body of macros (most of this
* in the key-actions that make up the body of macros (most of this
* trickiness being in the logic for how users record macros and assign them
* to key actions). I could imagine there being situations where this turned
* to key-actions). I could imagine there being situations where this turned
* out to be useful... but I feel like much more often it would just be a bit
* confusing. It would also be inconsistent a little, having two different
* representations of a key action. And it wouldn't actually save us that
* representations of a key-action. And it wouldn't actually save us that
* much EEPROM.
*/
@ -99,6 +99,7 @@ uint8_t eeprom_macro__init (void);
uint8_t eeprom_macro__record_init ( ARGS );
uint8_t eeprom_macro__record_action ( ARGS );
uint8_t eeprom_macro__record_finalize (void);
uint8_t eeprom_macro__record_cancel (void);
uint8_t eeprom_macro__play ( ARGS );
bool eeprom_macro__exists ( ARGS );
uint8_t eeprom_macro__clear ( ARGS );
@ -158,12 +159,12 @@ uint8_t eeprom_macro__clear_all (void);
* Prepare to record a new macro
*
* Arguments:
* - (group) The key action to remap
* - `pressed`: Whether the key action is a press (`true`) or a release
* - (group) The key-action to remap
* - `pressed`: Whether the key-action is a press (`true`) or a release
* (`false`)
* - `layer`: The layer of the key action
* - `row`: The row of the key action
* - `column`: The column of the key action
* - `layer`: The layer of the key-action
* - `row`: The row of the key-action
* - `column`: The column of the key-action
*
* Returns:
* - success: `0`
@ -174,50 +175,75 @@ uint8_t eeprom_macro__clear_all (void);
* recorded when this function is called (i.e. this function has been called
* once already, and `...finalize()` has not been called yet), the old macro
* should be thrown away, and this new one prepared for.
* - If a macro remapping the given key-action already exists, it should be
* deleted.
*/
// === eeprom_macro__record_action() ===
/** functions/eeprom_macro__record_action/description
* Record the next key action of the current macro
* Record the next key-action of the current macro
*
* Arguments:
* - (group) The key action to record
* - `pressed`: Whether the key action is a press (`true`) or a release
* - (group) The key-action to record
* - `pressed`: Whether the key-action is a press (`true`) or a release
* (`false`)
* - `layer`: The layer of the key action
* - `row`: The row of the key action
* - `column`: The column of the key action
* - `layer`: The layer of the key-action
* - `row`: The row of the key-action
* - `column`: The column of the key-action
*
* Returns:
* - success: `0`
* - failure: [other] (not enough memory left to record)
*
* Notes:
* - If this function fails, the current key-action may be canceled (thrown
* away).
*/
// === eeprom_macro__record_finalize() ===
/** functions/eeprom_macro__record_finalize/description
* Finalize the recording of the current macro
*
* Returns
* Returns:
* - success: `0`
* - failure: [other]
*
* Notes:
* - Before this function is called, the macro (even though parts of it may be
* written) should not be readable, or referenced anywhere in the EEPROM.
*
* Notes:
* - If this function fails, the current key-action may be canceled (thrown
* away).
*/
// === eeprom_macro__record_cancel() ===
/** functions/eeprom_macro__record_cancel/description
* Cancel the recording of the current macro
*
* Returns:
* - success: `0`
* - failure: [other]
*
* Notes:
* - Depending on the implementation, this function may not be necessary due to
* the behavior of `eeprom_macro__record_init()` and
* `eeprom_macro__record_finalize()`. In that case this function should
* simply do nothing.
*/
// === eeprom_macro__play() ===
/** functions/eeprom_macro__play/description
* Play back recorded key actions for the macro assigned to the specified key
* Play back recorded key-actions for the macro assigned to the specified key
* action
*
* Arguments:
* - (group) The key action to search for
* - `pressed`: Whether the key action is a press (`true`) or a release
* - (group) The key-action to search for
* - `pressed`: Whether the key-action is a press (`true`) or a release
* (`false`)
* - `layer`: The layer of the key action
* - `row`: The row of the key action
* - `column`: The column of the key action
* - `layer`: The layer of the key-action
* - `row`: The row of the key-action
* - `column`: The column of the key-action
*
* Returns:
* - success: `0` (macro successfully played)
@ -226,15 +252,15 @@ uint8_t eeprom_macro__clear_all (void);
// === eeprom_macro__exists() ===
/** functions/eeprom_macro__exists/description
* Predicate indicating whether the specified key action has been remapped
* Predicate indicating whether the specified key-action has been remapped
*
* Arguments:
* - (group) The key action to search for
* - `pressed`: Whether the key action is a press (`true`) or a release
* - (group) The key-action to search for
* - `pressed`: Whether the key-action is a press (`true`) or a release
* (`false`)
* - `layer`: The layer of the key action
* - `row`: The row of the key action
* - `column`: The column of the key action
* - `layer`: The layer of the key-action
* - `row`: The row of the key-action
* - `column`: The column of the key-action
*
* Returns:
* - `true`: if a macro remapping the given key-action exists
@ -243,15 +269,15 @@ uint8_t eeprom_macro__clear_all (void);
// === eeprom_macro__clear() ===
/** functions/eeprom_macro__clear/description
* Clear (delete) the macro assigned to the given key action
* Clear (delete) the macro assigned to the given key-action
*
* Arguments:
* - (group) The key action to un-remap
* - `pressed`: Whether the key action is a press (`true`) or a release
* - (group) The key-action to un-remap
* - `pressed`: Whether the key-action is a press (`true`) or a release
* (`false`)
* - `layer`: The layer of the key action
* - `row`: The row of the key action
* - `column`: The column of the key action
* - `layer`: The layer of the key-action
* - `row`: The row of the key-action
* - `column`: The column of the key-action
*
* Returns:
* - success: `0`
@ -265,7 +291,7 @@ uint8_t eeprom_macro__clear_all (void);
* Notes:
* - For the purposes of this function, "clearing" the EEPROM means to put it
* in such a state that none of the functions declared here will be able to
* find a macro for any key action. This does not necessarily imply that the
* find a macro for any key-action. This does not necessarily imply that the
* EEPROM is in a fully known state.
*
* Returns:

View File

@ -350,6 +350,7 @@ static uint8_t read_key_action(void * from, key_action_t * k) {
* Arguments:
* - `to`: A pointer to the location in EEPROM at which to begin writing
* - `k`: A pointer to the key-action to write
* - `limit`: A pointer to the last address to which we are allowed to write
*
* Returns:
* - success: The number of bytes written
@ -375,7 +376,7 @@ static uint8_t read_key_action(void * from, key_action_t * k) {
* It's probably worthwhile to note that I was looking at the assembly
* (though not closely) and function size with optimizations turned on.
*/
static uint8_t write_key_action(void * to, key_action_t * k) {
static uint8_t write_key_action(void * to, key_action_t * k, void * limit) {
// ignore the bits we don't need to write
// - if the leading two bits of all three variables are `0b00`, we don't
// need to write a key-action byte containing that pair of bits
@ -411,8 +412,8 @@ static uint8_t write_key_action(void * to, key_action_t * k) {
| ( k->row & 0xC0 ) >> 4
| ( k->column & 0xC0 ) >> 6 ;
if ( to > EEMEM_START || EEMEM_END < to ) return 0; // out of bounds
if ( eeprom__write(to++, byte) ) return 0; // write failed
if ( to > limit ) return 0; // out of bounds
if ( eeprom__write(to++, byte) ) return 0; // write failed
byte = 1 << 6;
@ -442,7 +443,7 @@ static uint8_t write_key_action(void * to, key_action_t * k) {
* of the layout of macros in EEMEM.
*
* Implementation notes:
* - It would be more efficient to convert the given key action into the same
* - It would be more efficient to convert the given key-action into the same
* binary representation as used in the EEPROM, once, and then compare that
* directly with the encoded key-action bytes read; but I don't think it'll
* have enough of an impact on performance to justify rewriting the
@ -657,6 +658,9 @@ out:
// ----------------------------------------------------------------------------
// public functions -----------------------------------------------------------
// TODO: go over all these, and make sure they conform to the header
// documentation
/** functions/eeprom_macro__init/description
* Implementation notes:
* - The initialization of static EEPROM values that this function is supposed
@ -689,23 +693,47 @@ uint8_t eeprom_macro__init(void) {
return 0; // success
}
/** functions/eeprom_macro__record_init/description
* Implementation notes:
* - At minimum, for a normal macro, we will need a `type` byte, `length` byte,
* key-action 0 (the action to remap), key-action 1 (a press), and key-action
* 2 (a release). Key-actions take a minimum of 1 byte, so our minimum macro
* will be 5 bytes.
*/
uint8_t eeprom_macro__record_init( bool pressed,
uint8_t layer,
uint8_t row,
uint8_t column ) {
// TODO: check for out of bounds / failed write
// new_end_macro = end_macro + 2;
//
// key_action_t k = {
// .pressed = pressed,
// .layer = layer,
// .row = row,
// .column = column,
// };
// end_macro += write_key_action( new_end_macro, &k ));
if (new_end_macro)
eeprom_macro__record_cancel();
if ( end_macro + 5 > EEMEM_MACROS_END )
return 1; // not enough room
// TODO:
// - if a macro remapping the given key-action already exists, delete it.
uint8_t ret; // for function return values
key_action_t k = {
.pressed = pressed,
.layer = layer,
.row = row,
.column = column,
};
new_end_macro = end_macro + 2;
// TODO:
// - call compress() if the write fails, to see if that helps
// - if compress() succeeds, but the write still fails, we should cancel
// the current macro (if compress() fails, the current macro will be
// canceled anyway)
ret = write_key_action(new_end_macro, &k, EEMEM_MACROS_END-1);
if (! ret) return 1; // write failed, or not enough room
end_macro += ret;
// TODO
return 0;
}
@ -713,7 +741,28 @@ uint8_t eeprom_macro__record_action( bool pressed,
uint8_t layer,
uint8_t row,
uint8_t column ) {
// TODO
if (! new_end_macro)
return 1; // no macro in progress
uint8_t ret; // for function return values
key_action_t k = {
.pressed = pressed,
.layer = layer,
.row = row,
.column = column,
};
// TODO:
// - call compress() if the write fails, to see if that helps
// - if compress() succeeds, but the write still fails, we should cancel
// the current macro (if compress() fails, the current macro will be
// canceled anyway)
ret = write_key_action(new_end_macro, &k, EEMEM_MACROS_END-1);
if (! ret) return 1; // write failed, or not enough room
end_macro += ret;
return 0;
}
@ -722,6 +771,11 @@ uint8_t eeprom_macro__record_finalize(void) {
return 0;
}
uint8_t eeprom_macro__record_cancel(void) {
new_end_macro = 0;
return 0;
}
uint8_t eeprom_macro__play( bool pressed,
uint8_t layer,
uint8_t row,