working; especially on eeprom-macro stuff
parent
0ab9483b94
commit
b7e03df76b
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue