添加一些关于midi播放的项目
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Anders Kalør
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,4 @@
|
||||
Ring-Buffer
|
||||
===========
|
||||
|
||||
A simple ring buffer (circular buffer) designed for embedded systems.
|
||||
@@ -0,0 +1,10 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -g -O2 -std=c99
|
||||
|
||||
all: simple
|
||||
|
||||
simple: ../ringbuffer.c simple.c
|
||||
$(CC) $(CFLAGS) -o simple simple.c ../ringbuffer.c
|
||||
|
||||
clean:
|
||||
rm -f simple
|
||||
@@ -0,0 +1,86 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "../ringbuffer.h"
|
||||
|
||||
int main(void) {
|
||||
int i, cnt;
|
||||
char buf;
|
||||
char buf_arr[50];
|
||||
|
||||
/* Create and initialize ring buffer */
|
||||
ring_buffer_t ring_buffer;
|
||||
ring_buffer_init(&ring_buffer);
|
||||
|
||||
/* Add elements to buffer; one at a time */
|
||||
for(i = 0; i < 100; i++) {
|
||||
ring_buffer_queue(&ring_buffer, i);
|
||||
}
|
||||
|
||||
/* Verify size */
|
||||
assert(ring_buffer_num_items(&ring_buffer) == 100);
|
||||
|
||||
/* Peek third element */
|
||||
cnt = ring_buffer_peek(&ring_buffer, &buf, 3);
|
||||
/* Assert byte returned */
|
||||
assert(cnt == 1);
|
||||
/* Assert contents */
|
||||
assert(buf == 3);
|
||||
|
||||
/* Dequeue all elements */
|
||||
for(cnt = 0; ring_buffer_dequeue(&ring_buffer, &buf) > 0; cnt++) {
|
||||
/* Do something with buf... */
|
||||
assert(buf == cnt);
|
||||
printf("Read: %d\n", buf);
|
||||
}
|
||||
printf("\n===============\n");
|
||||
|
||||
/* Add array */
|
||||
ring_buffer_queue_arr(&ring_buffer, "Hello, Ring Buffer!", 20);
|
||||
|
||||
/* Is buffer empty? */
|
||||
assert(!ring_buffer_is_empty(&ring_buffer));
|
||||
|
||||
/* Dequeue all elements */
|
||||
while(ring_buffer_dequeue(&ring_buffer, &buf) > 0) {
|
||||
/* Print contents */
|
||||
printf("Read: %c\n", buf);
|
||||
}
|
||||
|
||||
/* Add new array */
|
||||
ring_buffer_queue_arr(&ring_buffer, "Hello again, Ring Buffer!", 26);
|
||||
|
||||
/* Dequeue array in two parts */
|
||||
printf("Read:\n");
|
||||
cnt = ring_buffer_dequeue_arr(&ring_buffer, buf_arr, 13);
|
||||
printf("%d\n", cnt);
|
||||
assert(cnt == 13);
|
||||
/* Add \0 termination before printing */
|
||||
buf_arr[13] = '\0';
|
||||
printf("%s\n", buf_arr);
|
||||
/* Dequeue remaining */
|
||||
cnt = ring_buffer_dequeue_arr(&ring_buffer, buf_arr, 13);
|
||||
assert(cnt == 13);
|
||||
printf("%s", buf_arr);
|
||||
|
||||
|
||||
printf("\n===============\n");
|
||||
|
||||
/* Overfill buffer */
|
||||
for(i = 0; i < 1000; i++) {
|
||||
ring_buffer_queue(&ring_buffer, (i % 127));
|
||||
}
|
||||
|
||||
/* Is buffer full? */
|
||||
if(ring_buffer_is_full(&ring_buffer)) {
|
||||
cnt = ring_buffer_num_items(&ring_buffer);
|
||||
printf("Buffer is full and contains %d bytes\n", cnt);
|
||||
}
|
||||
|
||||
/* Dequeue all elements */
|
||||
while(ring_buffer_dequeue(&ring_buffer, &buf) > 0) {
|
||||
/* Print contents */
|
||||
printf("Read: 0x%02x\n", buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "ringbuffer.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implementation of ring buffer functions.
|
||||
*/
|
||||
|
||||
void ring_buffer_init(ring_buffer_t *buffer) {
|
||||
buffer->tail_index = 0;
|
||||
buffer->head_index = 0;
|
||||
}
|
||||
|
||||
void ring_buffer_queue(ring_buffer_t *buffer, uint8_t data) {
|
||||
/* Is buffer full? */
|
||||
if(ring_buffer_is_full(buffer)) {
|
||||
/* Is going to overwrite the oldest byte */
|
||||
/* Increase tail index */
|
||||
buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK);
|
||||
}
|
||||
|
||||
/* Place data in buffer */
|
||||
buffer->buffer[buffer->head_index] = data;
|
||||
buffer->head_index = ((buffer->head_index + 1) & RING_BUFFER_MASK);
|
||||
}
|
||||
|
||||
void ring_buffer_queue_arr(ring_buffer_t *buffer, const uint8_t *data, ring_buffer_size_t size) {
|
||||
/* Add bytes; one by one */
|
||||
ring_buffer_size_t i;
|
||||
for(i = 0; i < size; i++) {
|
||||
ring_buffer_queue(buffer, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ring_buffer_size_t ring_buffer_dequeue(ring_buffer_t *buffer, uint8_t *data) {
|
||||
if(ring_buffer_is_empty(buffer)) {
|
||||
/* No items */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = buffer->buffer[buffer->tail_index];
|
||||
buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, uint8_t *data, ring_buffer_size_t len) {
|
||||
if(ring_buffer_is_empty(buffer)) {
|
||||
/* No items */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data_ptr = data;
|
||||
ring_buffer_size_t cnt = 0;
|
||||
while((cnt < len) && ring_buffer_dequeue(buffer, data_ptr)) {
|
||||
cnt++;
|
||||
data_ptr++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
ring_buffer_size_t ring_buffer_peek(ring_buffer_t *buffer, uint8_t *data, ring_buffer_size_t index) {
|
||||
if(index >= ring_buffer_num_items(buffer)) {
|
||||
/* No items at index */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add index to pointer */
|
||||
ring_buffer_size_t data_index = ((buffer->tail_index + index) & RING_BUFFER_MASK);
|
||||
*data = buffer->buffer[data_index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern inline ring_buffer_size_t ring_buffer_is_empty(ring_buffer_t *buffer);
|
||||
extern inline ring_buffer_size_t ring_buffer_is_full(ring_buffer_t *buffer);
|
||||
extern inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer);
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Prototypes and structures for the ring buffer module.
|
||||
*/
|
||||
|
||||
#ifndef RINGBUFFER_H
|
||||
#define RINGBUFFER_H
|
||||
|
||||
/**
|
||||
* The size of a ring buffer.
|
||||
* Due to the design only <tt> RING_BUFFER_SIZE-1 </tt> items
|
||||
* can be contained in the buffer.
|
||||
* The buffer size must be a power of two.
|
||||
*/
|
||||
#define RING_BUFFER_SIZE 512
|
||||
|
||||
#if (RING_BUFFER_SIZE & (RING_BUFFER_SIZE - 1)) != 0
|
||||
#error "RING_BUFFER_SIZE must be a power of two"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The type which is used to hold the size
|
||||
* and the indicies of the buffer.
|
||||
* Must be able to fit \c RING_BUFFER_SIZE .
|
||||
*/
|
||||
typedef uint32_t ring_buffer_size_t;
|
||||
|
||||
/**
|
||||
* Used as a modulo operator
|
||||
* as <tt> a % b = (a & (b 鈭� 1)) </tt>
|
||||
* where \c a is a positive index in the buffer and
|
||||
* \c b is the (power of two) size of the buffer.
|
||||
*/
|
||||
#define RING_BUFFER_MASK (RING_BUFFER_SIZE-1)
|
||||
|
||||
/**
|
||||
* Simplifies the use of <tt>struct ring_buffer_t</tt>.
|
||||
*/
|
||||
typedef struct ring_buffer_t ring_buffer_t;
|
||||
|
||||
/**
|
||||
* Structure which holds a ring buffer.
|
||||
* The buffer contains a buffer array
|
||||
* as well as metadata for the ring buffer.
|
||||
*/
|
||||
struct ring_buffer_t {
|
||||
/** Buffer memory. */
|
||||
char buffer[RING_BUFFER_SIZE];
|
||||
/** Index of tail. */
|
||||
ring_buffer_size_t tail_index;
|
||||
/** Index of head. */
|
||||
ring_buffer_size_t head_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the ring buffer pointed to by <em>buffer</em>.
|
||||
* This function can also be used to empty/reset the buffer.
|
||||
* @param buffer The ring buffer to initialize.
|
||||
*/
|
||||
void ring_buffer_init(ring_buffer_t *buffer);
|
||||
|
||||
/**
|
||||
* Adds a byte to a ring buffer.
|
||||
* @param buffer The buffer in which the data should be placed.
|
||||
* @param data The byte to place.
|
||||
*/
|
||||
void ring_buffer_queue(ring_buffer_t *buffer, uint8_t data);
|
||||
|
||||
/**
|
||||
* Adds an array of bytes to a ring buffer.
|
||||
* @param buffer The buffer in which the data should be placed.
|
||||
* @param data A pointer to the array of bytes to place in the queue.
|
||||
* @param size The size of the array.
|
||||
*/
|
||||
void ring_buffer_queue_arr(ring_buffer_t *buffer, const uint8_t *data, ring_buffer_size_t size);
|
||||
|
||||
/**
|
||||
* Returns the oldest byte in a ring buffer.
|
||||
* @param buffer The buffer from which the data should be returned.
|
||||
* @param data A pointer to the location at which the data should be placed.
|
||||
* @return 1 if data was returned; 0 otherwise.
|
||||
*/
|
||||
ring_buffer_size_t ring_buffer_dequeue(ring_buffer_t *buffer, uint8_t *data);
|
||||
|
||||
/**
|
||||
* Returns the <em>len</em> oldest bytes in a ring buffer.
|
||||
* @param buffer The buffer from which the data should be returned.
|
||||
* @param data A pointer to the array at which the data should be placed.
|
||||
* @param len The maximum number of bytes to return.
|
||||
* @return The number of bytes returned.
|
||||
*/
|
||||
ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, uint8_t *data, ring_buffer_size_t len);
|
||||
/**
|
||||
* Peeks a ring buffer, i.e. returns an element without removing it.
|
||||
* @param buffer The buffer from which the data should be returned.
|
||||
* @param data A pointer to the location at which the data should be placed.
|
||||
* @param index The index to peek.
|
||||
* @return 1 if data was returned; 0 otherwise.
|
||||
*/
|
||||
ring_buffer_size_t ring_buffer_peek(ring_buffer_t *buffer, uint8_t *data, ring_buffer_size_t index);
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a ring buffer is empty.
|
||||
* @param buffer The buffer for which it should be returned whether it is empty.
|
||||
* @return 1 if empty; 0 otherwise.
|
||||
*/
|
||||
inline ring_buffer_size_t ring_buffer_is_empty(ring_buffer_t *buffer) {
|
||||
return (buffer->head_index == buffer->tail_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a ring buffer is full.
|
||||
* @param buffer The buffer for which it should be returned whether it is full.
|
||||
* @return 1 if full; 0 otherwise.
|
||||
*/
|
||||
inline ring_buffer_size_t ring_buffer_is_full(ring_buffer_t *buffer) {
|
||||
return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK) == RING_BUFFER_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of items in a ring buffer.
|
||||
* @param buffer The buffer for which the number of items should be returned.
|
||||
* @return The number of items in the ring buffer.
|
||||
*/
|
||||
inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer) {
|
||||
return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK);
|
||||
}
|
||||
|
||||
#endif /* RINGBUFFER_H */
|
||||
Reference in New Issue
Block a user