用在数字信号处理算法计算时窗的向量,矩阵,时间序列数据结构array_mem。
1 头文件
#include "qs_config.h"
#define QS_ARRAY_MEM_LIST_SIZE 40
#define QS_ARRAY_MEM_SIZE 2100 + 10
typedef struct
{
Type _data[QS_ARRAY_MEM_SIZE]; /**< points to the data of the array. */
int16_t id;
int16_t next;
} qs_array_mem_t;
/**
* @brief Instance structure for the array structure.
*/
typedef struct
{
uint16_t N; /**< number of columns of the array. */
qs_array_mem_t *_x; /**< points to the data of the array. */
} qs_array_inst;
typedef struct
{
uint16_t N; /**< number of columns of the array. */
qs_array_mem_t *_x; /**< points to the data of the array. */
qs_array_mem_t *_t;
} qs_dual_array_inst;
/**
* @brief Instance structure for the Q31 matrix structure.
*/
typedef struct
{
uint16_t M; /**< number of rows of the matrix. */
uint16_t N; /**< number of columns of the matrix. */
qs_array_mem_t *_x; /**< points to the data of the matrix. */
} qs_matrix_inst;
typedef struct
{
qs_array_mem_t items[QS_ARRAY_MEM_LIST_SIZE];
int16_t head;
int16_t free;
} qs_array_mem_list_t;
void QS_STDCALL qs_array_mem_init(void);
qs_ret_code_t QS_STDCALL qs_array_mem_alloc(qs_array_inst* p_inst);
qs_ret_code_t QS_STDCALL qs_dual_array_mem_alloc(qs_dual_array_inst* p_inst);
void QS_STDCALL qs_array_mem_free(qs_array_inst* p_inst);
void QS_STDCALL qs_dual_array_mem_free(qs_dual_array_inst* p_inst);
qs_ret_code_t QS_STDCALL qs_matrix_mem_alloc(qs_matrix_inst* p_inst);
void QS_STDCALL qs_matrix_mem_free(qs_matrix_inst* p_inst);
int16_t qs_array_mem_get_free_len(void);
int16_t qs_array_mem_get_used_len(void);
int16_t qs_array_mem_get_max_used_len(void);
2 源文件
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include "qs_log.h"
#include "qs_array_mem.h"
static char TAG[]="array_mem";
static qs_array_mem_list_t m_mem;
static bool m_init = false;
static int16_t max_used_len = 0;
static void qs_array_mem_print(void);
void qs_array_mem_init(void)
{
for (int i = 0; i < QS_ARRAY_MEM_LIST_SIZE - 1; i++) {
m_mem.items[i].next = i + 1;
m_mem.items[i].id = -1;
}
m_mem.items[QS_ARRAY_MEM_LIST_SIZE - 1].next = -1;
m_mem.free = 0;
m_mem.head = -1;
//qs_array_mem_print();
m_init = true;
}
static void qs_array_mem_print(void)
{
QS_LOG_INFO(TAG, "head %d, free %d",m_mem.head, m_mem.free);
for (int i = 0; i < QS_ARRAY_MEM_LIST_SIZE; i++) {
QS_LOG_INFO(TAG, "[%d]%d, next %d",i,m_mem.items[i].id, m_mem.items[i].next);
}
}
int16_t qs_array_mem_get_free_len(void)
{
int16_t len = 0;
int16_t p = m_mem.free;
while (p >= 0) {
p = m_mem.items[p].next;
len ++;
}
return len;
}
int16_t qs_array_mem_get_used_len(void)
{
int16_t len = 0;
int16_t p = m_mem.head;
while (p >= 0) {
p = m_mem.items[p].next;
len ++;
}
return len;
}
int16_t qs_array_mem_get_max_used_len(void)
{
return max_used_len;
}
qs_array_mem_t* array_mem_alloc(void)
{
if(!m_init) {
qs_array_mem_init();
}
int16_t p = m_mem.free;
if (p < 0) {
return NULL;
}
//QS_LOG_INFO("", "p %d free id %d head %d", p, m_mem.items[p].next, m_mem.head);
m_mem.free = m_mem.items[p].next;
m_mem.items[p].next = m_mem.head;
m_mem.head = p;
m_mem.items[p].id = p;
//QS_LOG_INFO("", "p %d head next id %d head %d",p, m_mem.items[p].next, m_mem.head );
return &m_mem.items[p];
}
void array_mem_free(qs_array_mem_t* p_mem)
{
if(!m_init) {
m_init = true;
qs_array_mem_init();
}
int16_t p = m_mem.head;
int16_t prev = -1;
//QS_LOG_INFO("", "item %d %d %d %d", m_mem.items[7].next, m_mem.items[6].next, m_mem.items[5].next, m_mem.items[4].next);
while (p >= 0) {
if (p == p_mem->id) {
int16_t next = m_mem.items[p].next;
(prev >= 0) ? (m_mem.items[prev].next = next) : (m_mem.head = next);
m_mem.items[p].next = m_mem.free;
m_mem.free = p;
p_mem->id = -1;
//QS_LOG_INFO("", "find p %d", p);
break;
} else {
//QS_LOG_INFO("", "search next p %d", m_mem.items[p].next);
prev = p;
p = m_mem.items[p].next;
//
}
}
}
qs_ret_code_t QS_STDCALL qs_array_mem_alloc(qs_array_inst* p_inst)
{
if (NULL == (p_inst->_x = array_mem_alloc())) {
qs_array_mem_print();
return QS_ERROR_NO_MEM;
}
int16_t used_len = qs_array_mem_get_used_len();
if(max_used_len < used_len) {
max_used_len = used_len;
}
return QS_SUCCESS;
}
qs_ret_code_t QS_STDCALL qs_dual_array_mem_alloc(qs_dual_array_inst* p_inst)
{
if (NULL == (p_inst->_x = array_mem_alloc())) {
return QS_ERROR_NO_MEM;
}
if (NULL == (p_inst->_t = array_mem_alloc())) {
array_mem_free(p_inst->_x);
return QS_ERROR_NO_MEM;
}
return QS_SUCCESS;
}
void QS_STDCALL qs_array_mem_free(qs_array_inst* p_inst)
{
array_mem_free(p_inst->_x);
p_inst->N = 0;
}
void QS_STDCALL qs_dual_array_mem_free(qs_dual_array_inst* p_inst)
{
array_mem_free(p_inst->_x);
array_mem_free(p_inst->_t);
p_inst->N = 0;
}
qs_ret_code_t QS_STDCALL qs_matrix_mem_alloc(qs_matrix_inst* p_inst)
{
if (NULL == (p_inst->_x = array_mem_alloc())) {
return QS_ERROR_NO_MEM;
}
return QS_SUCCESS;
}
void QS_STDCALL qs_matrix_mem_free(qs_matrix_inst* p_inst)
{
array_mem_free(p_inst->_x);
p_inst->N = 0;
}
3 应用代码——初始化
qs_array_mem_init();
4 应用代码——5阶8HZ IIR巴特沃夫低通滤波器模块代码
//Response Type: Lowpass
//Design Method: IIR Butterworth
//Filter Order: Specify order 5
//Fs: 200
//Fc: 8
void QS_STDCALL qs_array_filter_8hz_butter_lp(qs_array_inst *p_inst)
{
uint16_t x,y;
uint16_t N = p_inst->N;
QS_ASSERT(N > 1);
qs_array_inst m_a;
QS_ASSERT(QS_SUCCESS == (qs_array_mem_alloc(&m_a)));
Type *_a = m_a._x->_data;
Type *_b = (Type*)p_inst->_x->_data;
Type a[6] = { 1.000000 , -4.1873 , 7.0697 , -6.01, 2.5704, -0.4422 };
Type b[6] = { 0.0000214, 0.000107, 0.000214, 0.000214, 0.000107, 0.0000214};
Type xBuf[8] = { 0,0,0,0,0,0,0,0 };
Type yBuf[8] = { 0,0,0,0,0,0,0,0 };
for (x = 0; x < N; x ++) {
for (y = 5; y > 0; y --) {
yBuf[y] = yBuf[y - 1];
xBuf[y] = xBuf[y - 1];
}
xBuf[0] = _b[x];
yBuf[0] = 0;
for (y = 1; y < 6; y ++)
{
yBuf[0] = yBuf[0] + b[y] * xBuf[y];
yBuf[0] = yBuf[0] - a[y] * yBuf[y];
}
yBuf[0] = yBuf[0] + b[0] * xBuf[0];
_a[x] = yBuf[0];
}
for (x = 0; x < N; x ++) {
_b[x] = _a[x];
}
qs_array_mem_free(&m_a);
}