re-added linked lists :D; and minor aesthetic changes

partial-rewrite
Ben Blazak 2013-05-09 02:02:48 -07:00
parent 65ecf576d3
commit 49f3d4bdd5
13 changed files with 343 additions and 19 deletions

View File

@ -134,6 +134,15 @@
(http://mathforum.org/library/drmath/view/52343.html)
`(-1)%5` in python returns `4` (just like it should)
* [Is it safe to free `void *`?]
(http://stackoverflow.com/a/2182522/2360353)
Yes. The memory manager keeps track of the size of allocations - and the
pointer you pass to `free()` is cast to `void *` before deallocation anyway.
* [Why do we need C Unions?]
(http://stackoverflow.com/questions/252552/why-do-we-need-c-unions)
Some good examples of what Unions are good for.
### C++ Stuff
* [Google C++ Style Guide]

View File

@ -34,7 +34,7 @@ void kb__layout__exec_key(bool pressed, uint8_t row, uint8_t column) {
void (*function)(void);
uint8_t layer;
for(uint8_t i = 0; i < layer_stack__size()+1+1; i++) { // i = offset+1
for (uint8_t i=0; i < layer_stack__size()+1+1; i++) { // i = offset+1
if (i == 0)
if (!pressed)
layer = pressed_layer[row][column];

View File

@ -73,17 +73,17 @@ bool kb__led__read(uint8_t led) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void kb__led__all_on(void) {
for(uint8_t i=1; i<=3; i++)
for (uint8_t i=1; i<=3; i++)
kb__led__on(i);
}
void kb__led__all_off(void) {
for(uint8_t i=1; i<=3; i++)
for (uint8_t i=1; i<=3; i++)
kb__led__off(i);
}
void kb__led__all_set(float n) {
for(uint8_t i=1; i<=3; i++)
for (uint8_t i=1; i<=3; i++)
kb__led__set(i, n);
}

View File

@ -46,6 +46,9 @@ include $(CURDIR)/options.mk
CURDIR := $(ROOTDIR)/lib/layout/layer-stack
include $(CURDIR)/options.mk
# -------
CURDIR := $(ROOTDIR)/lib/data-types/list
include $(CURDIR)/options.mk
# -------
CURDIR := $(firstword $(CURDIRS))
CURDIRS := $(wordlist 2,$(words $(CURDIRS)),$(CURDIRS))

View File

@ -0,0 +1,167 @@
/* ----------------------------------------------------------------------------
* Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (see "doc/licenses/MIT.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
/** description
* An interface to a simple linked-list that can be used to implement lists,
* queues, stacks, and things
*
* Prefix: `list__`
*
*
* Implementation notes:
*
* - All functions that accept an `index` should set `index %= list->length`
* before using it. This will make all passed indices valid. It will also
* provide a convenient way to reference the last element of a list, by
* passing `-1` as the index (as in Python).
*/
#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__DATA_TYPES__LIST__H
#define ERGODOX_FIRMWARE__FIRMWARE__LIB__DATA_TYPES__LIST__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include <stdint.h>
// ----------------------------------------------------------------------------
typedef struct list__node_t {
struct list__node_t * next;
} list__node_t;
typedef struct list__list_t {
list__node_t * head;
list__node_t * tail;
uint8_t length;
} list__list_t;
// ----------------------------------------------------------------------------
list__list_t * list__new (void);
void * list__insert ( list__list_t * list,
int8_t index,
uint8_t size );
void * list__peek (list__list_t * list, int8_t index);
void * list__pop__no_free (list__list_t * list, int8_t index);
void list__free (list__list_t * list);
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__FIRMWARE__LIB__DATA_TYPES__LIST__H
// ============================================================================
// === documentation ==========================================================
// ============================================================================
// ----------------------------------------------------------------------------
// typedefs -------------------------------------------------------------------
// ----------------------------------------------------------------------------
// === list__node_t ===
/** typedefs/list__node_t/description
* The type of a "node", for the purposes of this library
*
* Full node types should be defined in the using '.c' or '.h' file, with
* something like
*
* typedef struct {
* list__node_t _private;
* uint8_t data;
* } node_t;
*
* The functions that return pointers to nodes will return `void *` pointers,
* so functions in the using '.c' file also need to cast these return values to
* the appropriate type before use.
*/
// === list__list_t ===
/** typedefs/list__list_t/description
* Simple struct to define and keep track of our list
*/
// ----------------------------------------------------------------------------
// functions ------------------------------------------------------------------
// ----------------------------------------------------------------------------
// === list__new() ===
/** functions/list__new/description
* Allocate a new (empty) list
*
* Returns:
* - success: A pointer to the new list
* - failure: `NULL`
*/
// === list__insert() ===
/** functions/list__insert/description
* Insert `node` at position `index % list->length`
*
* Arguments:
* - `list`: A pointer to the list to be operated on
* - `index`: An `int8_t` indicating the position the new node will occupy
* - `size`: The size of the full node type (as in `sizeof(node_t)`) defined in
* the using '.c' or '.h' file, so we know how much memory to allocate
*
* Returns:
* - success: A `void *` pointer to the new node
* - failure: `NULL`
*
* Warning:
* - For any given list, the `size` passed to this function should always be
* the same.
*
* Caution:
* - Initialization of the data to be stored in the node is the calling
* function's responsibility.
*/
// === list__peek() ===
/** functions/list__peek/description
* Return a pointer to the node at position `index % list->length`
*
* Arguments:
* - `list`: A pointer to the list to be operated on
* - `index`: An `int8_t` indicating the position of the node to peek at
*
* Returns:
* - success: A `void *` pointer to the node at position `index % list->length`
* - failure: `NULL`
*/
// === list__pop__no_free() ===
/** functions/list__pop__no_free/description
* Return a pointer to the node at position `index % list->length`, and remove
* the node from the list
*
* Warning:
* - Does not free the node's memory - this is the calling function's
* responsibility. If you want to pop the node and free its memory without
* looking at it, call `free( list__pop__no_free( node ) )`.
*
* Arguments:
* - `list`: A pointer to the list to be operated on
* - `index`: An `int8_t` indicating the position of the node to pop
*
* Returns:
* - success: A `void *` pointer to the node at position `index % list->length`
* - failure: `NULL`
*/
// === list__free() ===
/** functions/list__free/description
* Free all node pointers in `list`, then free `list`
*
* Arguments:
* - `list`: A pointer to the list to be operated on
*/

View File

@ -0,0 +1,129 @@
/* ----------------------------------------------------------------------------
* Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (see "doc/licenses/MIT.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
/** description
* Implements the list type in "../list.h"
*/
#include <stddef.h>
#include <stdlib.h>
#include "../list.h"
// ----------------------------------------------------------------------------
list__list_t * list__new(void) {
list__list_t * list = malloc( sizeof(list__list_t) );
if (!list) return NULL;
list->head = NULL;
list->tail = NULL;
list->length = 0;
return list;
}
void * list__insert(list__list_t * list, int8_t index, uint8_t size) {
list__node_t * node = malloc(size);
if (!node) return NULL;
list->length++;
if (list->length == 1) {
// insert as only node (no others exist yet)
list->head = node;
list->tail = node;
node->next = NULL;
} else {
index %= list->length;
if (index == 0) {
// insert as first node
node->next = list->head;
list->head = node;
} else if (index == list->length-1) {
// insert as last node
list->tail->next = node;
list->tail = node;
node->next = NULL;
} else {
// insert as other node
list__node_t * previous = list->head;
for (uint8_t i=1; i<index; i++)
previous = previous->next;
node->next = previous->next;
previous->next = node;
}
}
return node;
}
void * list__peek(list__list_t * list, int8_t index) {
// if no nodes exist
if (list->length == 0)
return NULL;
index %= list->length;
// if last node
if (index == list->length-1)
return list->tail;
// else
list__node_t * node = list->head;
for (uint8_t i=0; i<index; i++)
node = node->next;
return node;
}
void * list__pop__no_free(list__list_t * list, int8_t index) {
// if no nodes exist
if (list->length == 0)
return NULL;
index %= list->length;
list__node_t * node;
if (index == 0) {
// pop first node
node = list->head;
list->head = node->next;
} else {
// find the `index-1`th node
list__node_t * previous = list->head;
for (uint8_t i=1; i<index; i++)
previous = previous->next;
// if last node
if (index == list->length-1)
list->tail = previous;
// pop the node at `index`
node = previous->next;
previous->next = node->next;
}
list->length--;
return node;
}
void list__free(list__list_t * list) {
list__node_t * node;
while (list->head) {
node = list->head;
list->head = list->head->next;
free(node);
}
free(list);
}

View File

@ -0,0 +1,15 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2013 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (see "doc/licenses/MIT.md")
# Project located at <https://github.com/benblazak/ergodox-firmware>
# -----------------------------------------------------------------------------
## description
# list options
#
# This file is meant to be included by the using '.../options.mk'
#
SRC += $(wildcard $(CURDIR)/*.c)

View File

@ -14,8 +14,8 @@
*/
#ifndef ERGODOX_FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H
#define ERGODOX_FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H
#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H
#define ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@ -25,5 +25,5 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H
#endif // ERGODOX_FIRMWARE__FIRMWARE__LIB__LAYOUT__EEPROM_MACRO__H

View File

@ -14,10 +14,13 @@
*
* Prefixes: `keys__`, [none]
*
* Usage: `#define` `KEYS__DEFAULT` and `KEYS__SHIFTED` before `#include`ing.
*
* TODO: add media and mouse keys (after i figure out which OSs are supposed to
* support which keys)
* Usage:
* - `#define` `KEYS__DEFAULT` and `KEYS__SHIFTED` before `#include`ing.
* - These macros should probably do what their names imply (i.e. define a
* "default" or "shifted" key, respectively, whatever that means to the
* implementing layout), but in a practical sense they can be used however
* one wants. They're simply a really convenient way to generate almost
* the same bit of code for a lot of (key_name, key_code) pairs.
*/

View File

@ -132,7 +132,7 @@ static uint8_t _shift_elements(uint8_t offset, bool up) {
uint8_t increment = (up) ? -1 : 1 ;
uint8_t end = (up) ? _filled-1-offset : _filled-1 ;
for(uint8_t i=start; i!=(end+increment); i+=increment) {
for (uint8_t i=start; i!=(end+increment); i+=increment) {
_stack[i-increment].id = _stack[i].id;
_stack[i-increment].number = _stack[i].number;
}
@ -197,7 +197,7 @@ uint8_t layer_stack__pop_id(uint8_t layer_id) {
}
uint8_t layer_stack__find_id(uint8_t layer_id) {
for(uint8_t i=0; i<_filled; i++)
for (uint8_t i=0; i<_filled; i++)
if (_stack[i].id == layer_id)
return _filled-1-i; // offset
return -1; // failure: return an invalid offset

View File

@ -7,8 +7,6 @@
/** description
* Implements the timer functions defined in "../timer.h" for the ATMega32U4
*
* Prefix: `timer__`
*
* See the accompanying '.md' file for documentation.
*/

View File

@ -59,7 +59,7 @@ uint8_t usb__kb__send_report (void);
*/
// === usb__is_configured ===
/** variables/usb__is_configured/description
/** functions/usb__is_configured/description
* Check whether this device has been configured by the host
*
* Returns:

View File

@ -82,7 +82,7 @@ int main(void) {
time_scan_started // on the first iteration, scan immediately
= timer__get_milliseconds() - OPT__DEBOUNCE_TIME;
for(;;) {
for (;;) {
temp = is_pressed;
is_pressed = was_pressed;
was_pressed = temp;
@ -96,8 +96,8 @@ int main(void) {
kb__update_matrix(*is_pressed);
// "execute" keys that have changed state
for(row=0; row<OPT__KB__ROWS; row++) {
for(col=0; col<OPT__KB__COLUMNS; col++) {
for (row=0; row<OPT__KB__ROWS; row++) {
for (col=0; col<OPT__KB__COLUMNS; col++) {
key_is_pressed = (*is_pressed)[row][col];
key_was_pressed = (*was_pressed)[row][col];