mirror of
https://github.com/osiweb/unified_retro_keyboard.git
synced 2024-10-03 23:54:44 +00:00
e13c9d6888
Was only testing for handle less than next_handle, but not checking for negative handle values. Fixed to use buffer_handle_valid() to test for a valid handle.
206 lines
5.6 KiB
C
206 lines
5.6 KiB
C
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
|
|
//
|
|
// Unified Keyboard Project
|
|
// ASDF keyboard firmware
|
|
//
|
|
// asdf_buffer.c
|
|
//
|
|
// This is a circular buffer module that can be used by any part of the code
|
|
// that requires buffering. Buffering provides an interface between the
|
|
// generation of keycodes and the hardware-level keycode transmission, which may
|
|
// occur at different rates.
|
|
//
|
|
// Copyright 2019 David Fenyes
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it under
|
|
// the terms of the GNU General Public License as published by the Free Software
|
|
// Foundation, either version 3 of the License, or (at your option) any later
|
|
// version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
// details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include "asdf.h"
|
|
#include "asdf_buffer.h"
|
|
|
|
// Implementation Notes:
|
|
//
|
|
// 1) Note that this implementation does not support dynamic allocation and
|
|
// freeing of buffers. Each buffer is allocated at startup and is stable forever
|
|
// afterwards.
|
|
//
|
|
// 2) Buffer handles are indices into an array of buffer-tracking structures.
|
|
// Using indices rather than pointers incurs a small performance penalty for the
|
|
// extra level of indirection, but affords the advantage of testing the buffer
|
|
// handle for validity.
|
|
|
|
|
|
// Define the low-level details for each buffer.
|
|
typedef struct {
|
|
asdf_keycode_t *buf;
|
|
int16_t size;
|
|
uint8_t head;
|
|
uint8_t tail;
|
|
uint8_t count;
|
|
} asdf_buffer_t;
|
|
|
|
// This is the pool of codes available for buffering. This pool is divided among
|
|
// the allocated buffers.
|
|
static asdf_keycode_t buffer_pool[ASDF_BUFFER_POOL_SIZE];
|
|
|
|
// This array stores the buffering details for each allocated buffer. The number
|
|
// of available buffers is defined in the header file.
|
|
static asdf_buffer_t buffers[ASDF_BUFFER_NUM_HANDLES];
|
|
|
|
// Index of the beginning of unallocated part of the buffer pool.
|
|
static int16_t buffer_pool_next_available;
|
|
|
|
// Index of the next available buffer handle
|
|
static asdf_buffer_handle_t next_handle;
|
|
|
|
|
|
// PROCEDURE: asdf_buffer_init
|
|
// INPUTS: none
|
|
// OUTPUTS: none
|
|
//
|
|
// DESCRIPTION: Initialize the buffer pool and handles
|
|
//
|
|
// SIDE EFFECTS: See description
|
|
//
|
|
// NOTES:
|
|
//
|
|
// SCOPE: public
|
|
//
|
|
// COMPLEXITY: 1
|
|
//
|
|
void asdf_buffer_init(void)
|
|
{
|
|
buffer_pool_next_available = 0;
|
|
next_handle = 0;
|
|
}
|
|
|
|
// PROCEDURE: buffer_handle_valid
|
|
// INPUTS: (uint8_t) handle - handle to be checked
|
|
// OUTPUTS: returns TRUE if the handle is a valid allocated handle.
|
|
//
|
|
// DESCRIPTION: Returns TRUE if the handle is one that has been allocated.
|
|
//
|
|
// SIDE EFFECTS: none
|
|
//
|
|
// NOTES:
|
|
//
|
|
// SCOPE: private
|
|
//
|
|
// COMPLEXITY: 1
|
|
//
|
|
uint8_t buffer_handle_valid(asdf_buffer_handle_t handle)
|
|
{
|
|
return ((handle >= 0) && (handle < next_handle));
|
|
}
|
|
|
|
// PROCEDURE: asdf_buffer_new
|
|
// INPUTS: (uint16_t) size: size of the buffer to allocate.
|
|
//
|
|
// OUTPUTS: returns a uint8_t handle to identify the buffer allocated from the
|
|
// pool.
|
|
//
|
|
// DESCRIPTION: Receives a request to allocate a fixed-size buffer from the
|
|
// pool. If there is enough room in the buffer pool, and if a buffer handle is
|
|
// available, then allocate space from the pool, initialize the next available
|
|
// buffer struct, and return the handle.
|
|
//
|
|
// SIDE EFFECTS: see above
|
|
//
|
|
// SCOPE: public
|
|
//
|
|
// COMPLEXITY: 3
|
|
//
|
|
asdf_buffer_handle_t asdf_buffer_new(int16_t size)
|
|
{
|
|
asdf_buffer_handle_t handle = ASDF_BUFFER_INVALID;
|
|
|
|
if (next_handle < ASDF_BUFFER_NUM_HANDLES) {
|
|
if (size <= (ASDF_BUFFER_POOL_SIZE - buffer_pool_next_available)) {
|
|
handle = next_handle++;
|
|
|
|
buffers[handle].size = size;
|
|
buffers[handle].buf = &buffer_pool[buffer_pool_next_available];
|
|
buffers[handle].head = 0;
|
|
buffers[handle].tail = 0;
|
|
buffers[handle].count = 0;
|
|
|
|
buffer_pool_next_available += size;
|
|
}
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
|
|
// PROCEDURE: asdf_buffer_put
|
|
//
|
|
// INPUTS:(asdf_buffer_t) buffer_handle: pointer to the buffer struct.
|
|
// (asdf_keycode_t) code: code to be added to the queue.
|
|
//
|
|
// OUTPUTS: None
|
|
//
|
|
// DESCRIPTION: Add the keycode to the head of the output buffer. If the buffer
|
|
// is full, quietly drop the keycode.
|
|
//
|
|
// SIDE EFFECTS: See DESCRIPTION
|
|
//
|
|
// NOTES:
|
|
//
|
|
// COMPLEXITY: 3
|
|
//
|
|
// SCOPE: public
|
|
//
|
|
void asdf_buffer_put(asdf_buffer_handle_t handle, asdf_keycode_t code)
|
|
{
|
|
if (buffer_handle_valid(handle)) {
|
|
if (buffers[handle].count < buffers[handle].size) {
|
|
buffers[handle].buf[buffers[handle].head] = code;
|
|
buffers[handle].head = (buffers[handle].head + 1) % buffers[handle].size;
|
|
buffers[handle].count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// PROCEDURE: asdf_buffer_get
|
|
//
|
|
// INPUTS: None
|
|
//
|
|
// OUTPUTS: returns next code in the buffer.
|
|
//
|
|
// DESCRIPTION: Gets the next queued code in the output buffer and return the
|
|
// value.
|
|
//
|
|
// SIDE EFFECTS: Removes a code from the queue.
|
|
//
|
|
// NOTES: If the buffer is empty, the code ASDF_INVALID_CODE is returned.
|
|
//
|
|
// COMPLEXITY: 2
|
|
//
|
|
// SCOPE: Public
|
|
//
|
|
asdf_keycode_t asdf_buffer_get(asdf_buffer_handle_t handle)
|
|
{
|
|
asdf_keycode_t code = ASDF_INVALID_CODE;
|
|
if (buffer_handle_valid(handle) && buffers[handle].count) {
|
|
code = buffers[handle].buf[buffers[handle].tail];
|
|
buffers[handle].tail = (buffers[handle].tail + 1) % buffers[handle].size;
|
|
buffers[handle].count--;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
//-------|---------|---------+---------+---------+---------+---------+---------+
|
|
// Above line is 80 columns, and should display completely in the editor.
|