working; especially on eeprom-macro stuff

partial-rewrite
Ben Blazak 2013-06-04 01:42:11 -07:00
parent 0ab9483b94
commit b7e03df76b
4 changed files with 101 additions and 111 deletions

View File

@ -65,6 +65,10 @@ void kb__layout__exec_key(bool pressed, uint8_t row, uint8_t column) {
(*function)();
// TODO: *always* tick keypresses
// TODO: instead of this, set a flag for the type of key pressed,
// and any functions that execute can check it, and conditionally
// reschedule themselves to run later, if they so desire
if (_flags.tick_keypresses)
timer___tick_keypresses();

View File

@ -87,6 +87,12 @@
#define OPT__USB__PRODUCT_ID 0x6028 // ErgoDox Ergonomic Keyboard
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#define OPT__EEPROM_MACRO__EEPROM_SIZE 1024
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__FIRMWARE__KEYBOARD__ERGODOX__OPTIONS__H

View File

@ -15,7 +15,7 @@
*
* Usage notes:
*
* - These function will play back keystrokes, not actions. This means that
* - These functions 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
@ -23,12 +23,13 @@
* during definition).
*
* - 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.
* that says the calling function(s) must maintain the semantic meanings of
* those fields. I imagine that under most circumstances one would want to,
* but as long as the '.c' file implementing this interface agree (or at
* least work) with whatever the calling functions are doing, things should
* be fine.
*
* - Particularly, if there were a layout implementation that ignored
* - For example, 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).
@ -41,6 +42,11 @@
// ----------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
// ----------------------------------------------------------------------------
typedef struct {
bool pressed : 1;
uint8_t layer : 5;

View File

@ -8,77 +8,103 @@
* 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
* - 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`
*
* - A "UID" (Unique ID) in this file is a `eeprom_macro__index_t`
* Terms (for the purposes of this file):
* - A "UID" (Unique IDentifier) is an `eeprom_macro__index_t`
*/
#include <stdint.h>
#include <avr/eeprom.h>
#include "../eeprom-macro.h"
// ----------------------------------------------------------------------------
// for convenience
#define ROWS OPT__KB__ROWS
#define COLUMNS OPT__KB__COLUMNS
// TODO: consider moving this, and all similar things in other files, into the
// '.h' files instead (and *always* including the '.h' files in implementing
// '.c' files)
#ifndef OPT__EEPROM_MACRO__EEPROM_SIZE
#error "OPT__EEPROM_MACRO__EEPROM_SIZE not defined"
#endif
/** macros/OPT__EEPROM_MACRO__EEPROM_SIZE/description
* The total size (in bytes) of the EEPROM memory to be allocated by this file
*
* Notes:
* - The ATMega32U4 has 1024 bytes of internal EEPROM total
*/
// ----------------------------------------------------------------------------
/** macros/HEADER/description
* The beginning of the `HEADER` section (the lowest block of the EEPROM that
* we're allowed to use)
*
* Size (in blocks): 1
*
* Format:
*
* 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
* the sections, and so is important to keep track of here, along with the
* version number.
/** macros/VERSION/description
* The version number of this EEPROM layout
*/
#define HEADER 0x00
#define VERSION 1
/** macros/TABLE/description
* The beginning of the `TABLE` section
// ----------------------------------------------------------------------------
/** types/eeprom/description
* The layout of this library's data in the EEPROM
*
* Size (in blocks): `ceil( (ROWS * COLUMNS) / 4 )`
* - This is conveniently calculated by taking `(ROWS * COLUMNS + 0b11) >> 2`
* Struct members:
* - `header`: For keeping track of layout metadata
* - `version`: The version of this layout
* - `0x00`, `0xFF` => uninitialized
* - `free`: The first free element in `macros.data`
*
* Notes:
* - Each entry is a block pointer to the first macro with the corresponding
* `row` and `column` in its UID
* - `table`: To help in quickly finding macros based on UID
* - `rows`: The number of rows this table has
* - `columns`: The number of columns this table has
* - `data`: Each entry contains the index of the beginning of the first
* macro with the corresponding row and column in its UID
*
* Format:
* - A `[ROWS][COLUMNS]` table, where the `[row][column]` entry can be accessed
* by taking the `[ (row * COLUMNS) + column ]` entry (as is normal with
* arrays in C).
* - `macros`: A block of memory for storing macros
* - `size`: `sizeof(struct macros) >> 2`;
* - `data`: TODO
*/
#define TABLE (HEADER + 1)
struct eeprom {
struct header {
uint8_t version;
uint8_t free;
} header;
/** macros/TABLE/description
* The beginning of the `MACROS` section
*
* Size (in blocks): `END - MACROS + 1` (since `END` is included)
*
struct table {
uint8_t rows;
uint8_t columns;
uint8_t data[OPT__KB__ROWS][OPT__KB__COLUMNS];
} table;
struct macros {
uint8_t size;
uint32_t data[ ( OPT__EEPROM_MACRO__EEPROM_SIZE
- sizeof(struct header)
- sizeof(struct table) ) >> 2 ];
} macros;
};
/** types/macro_header/description
* TODO
*/
struct macro_header {
uint8_t next;
uint8_t length;
eeprom_macro__index_t index;
};
/** types/macro_action/description
* TODO
*/
struct macro_action {
bool pressed : 1;
uint8_t row : 7;
uint8_t column : 7;
};
// ----------------------------------------------------------------------------
// TODO: functions
/*
* Format: macro header:
*
* struct {
@ -98,56 +124,4 @@
* eeprom_macro__index_t index; // `layer` will be ignored
* };
*/
#define MACROS (TABLE + ((ROWS * COLUMNS + 0b11) >> 2))
/** macros/END/description
* The end of the `MACROS` section (the highest block of the EEPROM that we're
* allowed to use)
*/
#define END 0xFF
// ----------------------------------------------------------------------------
// 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