(working: eeprom-macro)

partial-rewrite
Ben Blazak 2014-05-26 20:29:08 -07:00
parent 0fd92b5840
commit b099061e6a
1 changed files with 109 additions and 36 deletions

View File

@ -655,11 +655,72 @@ out:
return 2; // write failed; data lost return 2; // write failed; data lost
} }
// ----------------------------------------------------------------------------
// helper functions -----------------------------------------------------------
/** functions/write_key_action_for_new_macro/description
* Write the given key-action to the next empty space in the macros block of
* the EEPROM
*
* Arguments:
* - `k`: A pointer to the key-action to write
*
* Returns:
* - success: `0`
* - failure: [other]
*
* Assumptions:
* - A macro is currently in progress (i.e. `new_end_macro` is not `0`).
*
* Notes:
* - We make sure to leave 1 empty byte for the end macro.
* - We update the value of `new_end_macro` (either to indicate the bytes that
* were written, or to cancel the current macro if writing failed).
*/
static inline uint8_t write_key_action_for_new_macro(key_action_t * k) {
uint8_t ret; // for function return values
ret = write_key_action(new_end_macro, k, EEMEM_MACROS_END-1);
if (! ret) {
if ( compress() ) goto out; // compress failed (macro cancelled)
ret = write_key_action(new_end_macro, k, EEMEM_MACROS_END-1);
if (! ret) goto out; // write failed again, or not enough room
}
new_end_macro += ret;
return 0;
out:
new_end_macro = 0;
return 1;
}
/**
* Deletes the macro remapping the given key-action, if it exists
*
* Arguments:
* - `k`: A pointer to the key-action to delete
*
* Returns:
* - success: `0`
* - failure: [other]
*/
static inline uint8_t delete_macro_if_exists(key_action_t * k) {
void * k_location = find_key_action(k);
if (k_location)
if ( eeprom__write(k_location, TYPE_DELETED) )
return 1; // write failed
return 0; // success
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// public functions ----------------------------------------------------------- // public functions -----------------------------------------------------------
// TODO: go over all these, and make sure they conform to the header // TODO: go over all these, and make sure they conform to the header
// documentation // documentation (and that they work properly)
/** functions/eeprom_macro__init/description /** functions/eeprom_macro__init/description
* Implementation notes: * Implementation notes:
@ -695,10 +756,10 @@ uint8_t eeprom_macro__init(void) {
/** functions/eeprom_macro__record_init/description /** functions/eeprom_macro__record_init/description
* Implementation notes: * Implementation notes:
* - At minimum, for a normal macro, we will need a `type` byte, `length` byte, * - At minimum, for a normal macro, we will need a `type` byte, a `length`
* key-action 0 (the action to remap), key-action 1 (a press), and key-action * byte, and 3 key-actions (the key-action to remap, 1 press, and 1 release).
* 2 (a release). Key-actions take a minimum of 1 byte, so our minimum macro * Key-actions take a minimum of 1 byte, so our minimum macro will be 5
* will be 5 bytes. * bytes.
*/ */
uint8_t eeprom_macro__record_init( bool pressed, uint8_t eeprom_macro__record_init( bool pressed,
uint8_t layer, uint8_t layer,
@ -711,11 +772,6 @@ uint8_t eeprom_macro__record_init( bool pressed,
if ( end_macro + 5 > EEMEM_MACROS_END ) if ( end_macro + 5 > EEMEM_MACROS_END )
return 1; // not enough room 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 = { key_action_t k = {
.pressed = pressed, .pressed = pressed,
.layer = layer, .layer = layer,
@ -723,18 +779,11 @@ uint8_t eeprom_macro__record_init( bool pressed,
.column = column, .column = column,
}; };
if ( delete_macro_if_exists(&k) ) return 1; // failure
new_end_macro = end_macro + 2; new_end_macro = end_macro + 2;
// TODO: return write_key_action_for_new_macro(&k);
// - 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;
} }
uint8_t eeprom_macro__record_action( bool pressed, uint8_t eeprom_macro__record_action( bool pressed,
@ -745,8 +794,6 @@ uint8_t eeprom_macro__record_action( bool pressed,
if (! new_end_macro) if (! new_end_macro)
return 1; // no macro in progress return 1; // no macro in progress
uint8_t ret; // for function return values
key_action_t k = { key_action_t k = {
.pressed = pressed, .pressed = pressed,
.layer = layer, .layer = layer,
@ -754,21 +801,33 @@ uint8_t eeprom_macro__record_action( bool pressed,
.column = column, .column = column,
}; };
// TODO: // TODO: if length is too long, finalize this macro, and start a
// - call compress() if the write fails, to see if that helps // continuation one
// - if compress() succeeds, but the write still fails, we should cancel //
// the current macro (if compress() fails, the current macro will be // - key-actions are at most 4 bytes long, so we make sure there are at
// canceled anyway) // least 4 bytes left in the allowable length of this macro; not worth it
ret = write_key_action(new_end_macro, &k, EEMEM_MACROS_END-1); // to calculate the encoded length of the key-action to be written
if (! ret) return 1; // write failed, or not enough room if ( new_end_macro - end_macro > UINT8_MAX - 4 ) {
end_macro += ret; if ( eeprom_macro__record_finalize() ) return 1; // failure
return 0; // TODO: we can't just call ...init(). we probably need a file-local
// variable too, to keep track of whether the new macro is
// `TYPE_VALID_MACRO` or `TYPE_CONTINUED`.
}
return write_key_action_for_new_macro(&k);
} }
uint8_t eeprom_macro__record_finalize(void) { uint8_t eeprom_macro__record_finalize(void) {
// TODO if ( eeprom__write( new_end_macro, TYPE_END ) ) goto out;
if ( eeprom__write( end_macro+1, new_end_macro - end_macro ) ) goto out;
if ( eeprom__write( end_macro, TYPE_VALID_MACRO ) ) goto out;
return 0; return 0;
out:
new_end_macro = 0;
return 1;
} }
uint8_t eeprom_macro__record_cancel(void) { uint8_t eeprom_macro__record_cancel(void) {
@ -788,16 +847,30 @@ bool eeprom_macro__exists( bool pressed,
uint8_t layer, uint8_t layer,
uint8_t row, uint8_t row,
uint8_t column ) { uint8_t column ) {
// TODO
return false; key_action_t k = {
.pressed = pressed,
.layer = layer,
.row = row,
.column = column,
};
return find_key_action(&k);
} }
uint8_t eeprom_macro__clear( bool pressed, uint8_t eeprom_macro__clear( bool pressed,
uint8_t layer, uint8_t layer,
uint8_t row, uint8_t row,
uint8_t column ) { uint8_t column ) {
// TODO
return 0; key_action_t k = {
.pressed = pressed,
.layer = layer,
.row = row,
.column = column,
};
return delete_macro_if_exists(&k);
} }
/** functions/eeprom_macro__clear_all/description /** functions/eeprom_macro__clear_all/description