forked from PAWPAW-Mirror/lib_xua
Merge commit 'a695e58524b1615a8bfd487bed1e555b2cbea362' into 6V3_DEV
This commit is contained in:
14
module_queue/module_build_info
Normal file
14
module_queue/module_build_info
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# You can set flags specifically for your module by using the MODULE_XCC_FLAGS
|
||||||
|
# variable. So the following
|
||||||
|
#
|
||||||
|
# MODULE_XCC_FLAGS = $(XCC_FLAGS) -O3
|
||||||
|
#
|
||||||
|
# specifies that everything in the modules should have the application
|
||||||
|
# build flags with -O3 appended (so the files will build at
|
||||||
|
# optimization level -O3).
|
||||||
|
#
|
||||||
|
# You can also set MODULE_XCC_C_FLAGS, MODULE_XCC_XC_FLAGS etc..
|
||||||
|
|
||||||
|
MODULE_XCC_XC_FLAGS = $(XCC_XC_FLAGS)
|
||||||
|
|
||||||
|
DEPENDENT_MODULES = module_xassert
|
||||||
1
module_queue/module_description
Normal file
1
module_queue/module_description
Normal file
@@ -0,0 +1 @@
|
|||||||
|
One line module description.
|
||||||
54
module_queue/src/queue.h
Normal file
54
module_queue/src/queue.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef QUEUE_H_
|
||||||
|
#define QUEUE_H_
|
||||||
|
|
||||||
|
#include <xassert.h>
|
||||||
|
|
||||||
|
typedef struct queue_t {
|
||||||
|
/// Read index.
|
||||||
|
unsigned rdptr;
|
||||||
|
/// Write index.
|
||||||
|
unsigned wrptr;
|
||||||
|
unsigned size;
|
||||||
|
unsigned mask;
|
||||||
|
} queue_t;
|
||||||
|
|
||||||
|
inline int is_power_of_2(unsigned x) {
|
||||||
|
return x != 0 && (x & (x - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void queue_init(queue_t &q, unsigned size) {
|
||||||
|
assert(is_power_of_2(size));
|
||||||
|
q.rdptr = 0;
|
||||||
|
q.wrptr = 0;
|
||||||
|
q.size = size;
|
||||||
|
q.mask = size - 1; // Assumes power of two.
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int queue_is_empty(const queue_t &q) {
|
||||||
|
return q.wrptr == q.rdptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int queue_is_full(const queue_t &q) {
|
||||||
|
return q.wrptr - q.rdptr == q.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void queue_push_word(queue_t &q, unsigned array[], unsigned data)
|
||||||
|
{
|
||||||
|
assert(!queue_is_full(q));
|
||||||
|
array[q.wrptr++ & q.mask] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned queue_pop_word(queue_t &q, unsigned array[]) {
|
||||||
|
assert(!queue_is_empty(q));
|
||||||
|
return array[q.rdptr++ & q.mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned queue_items(const queue_t &q) {
|
||||||
|
return q.wrptr - q.rdptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned queue_space(const queue_t &q) {
|
||||||
|
return q.size - queue_items(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* QUEUE_H_ */
|
||||||
11
module_queue/src/queue.xc
Normal file
11
module_queue/src/queue.xc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
// Force external definitions of inline functions.
|
||||||
|
extern inline int is_power_of_2(unsigned x);
|
||||||
|
extern inline void queue_init(queue_t &q, unsigned size);
|
||||||
|
extern inline int queue_is_empty(const queue_t &q);
|
||||||
|
extern inline int queue_is_full(const queue_t &q);
|
||||||
|
extern inline void queue_push_word(queue_t &q, unsigned array[], unsigned data);
|
||||||
|
extern inline unsigned queue_pop_word(queue_t &q, unsigned array[]);
|
||||||
|
extern inline unsigned queue_space(const queue_t &q);
|
||||||
|
extern inline unsigned queue_items(const queue_t &q);
|
||||||
@@ -5,47 +5,81 @@
|
|||||||
|
|
||||||
#include <xs1_user.h>
|
#include <xs1_user.h>
|
||||||
|
|
||||||
|
.text
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// void GetLockResource()
|
// void GetLockResource()
|
||||||
.globl GetLockResource.nstackwords
|
|
||||||
.linkset GetLockResource.nstackwords, 0
|
|
||||||
.globl GetLockResource
|
.globl GetLockResource
|
||||||
.text
|
.type GetLockResource, @function
|
||||||
|
.cc_top GetLockResource.function
|
||||||
|
.align 2
|
||||||
GetLockResource:
|
GetLockResource:
|
||||||
getr r0, XS1_RES_TYPE_LOCK
|
getr r0, XS1_RES_TYPE_LOCK
|
||||||
retsp 0
|
retsp 0
|
||||||
|
.size GetLockResource, .-GetLockResource
|
||||||
|
.cc_bottom GetLockResource.function
|
||||||
|
.globl GetLockResource.nstackwords
|
||||||
|
.globl GetLockResource.maxcores
|
||||||
|
.globl GetLockResource.maxchanends
|
||||||
|
.globl GetLockResource.maxtimers
|
||||||
|
.set GetLockResource.nstackwords, 0
|
||||||
|
.set GetLockResource.maxcores, 1
|
||||||
|
.set GetLockResource.maxchanends, 0
|
||||||
|
.set GetLockResource.maxtimers, 0
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// void ClaimLock(lock l)
|
// void ClaimLock(lock l)
|
||||||
.globl ClaimLock.nstackwords
|
|
||||||
.linkset ClaimLock.nstackwords, 0
|
|
||||||
.globl ClaimLock
|
.globl ClaimLock
|
||||||
.text
|
.type ClaimLock, @function
|
||||||
|
.cc_top ClaimLock.function
|
||||||
|
.align 2
|
||||||
ClaimLock:
|
ClaimLock:
|
||||||
in r0, res[r0]
|
in r0, res[r0]
|
||||||
retsp 0
|
retsp 0
|
||||||
|
.size ClaimLock, .-ClaimLock
|
||||||
|
.cc_bottom ClaimLock.function
|
||||||
|
.globl ClaimLock.nstackwords
|
||||||
|
.globl ClaimLock.maxcores
|
||||||
|
.globl ClaimLock.maxchanends
|
||||||
|
.globl ClaimLock.maxtimers
|
||||||
|
.set ClaimLock.nstackwords, 0
|
||||||
|
.set ClaimLock.maxcores, 1
|
||||||
|
.set ClaimLock.maxchanends, 0
|
||||||
|
.set ClaimLock.maxtimers, 0
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// void FreeLock(lock l)
|
// void FreeLock(lock l)
|
||||||
.globl FreeLock.nstackwords
|
|
||||||
.linkset FreeLock.nstackwords, 0
|
|
||||||
.globl FreeLock
|
.globl FreeLock
|
||||||
.text
|
.cc_top FreeLock.function
|
||||||
|
.align 2
|
||||||
FreeLock:
|
FreeLock:
|
||||||
out res[r0], r0
|
out res[r0], r0
|
||||||
retsp 0
|
retsp 0
|
||||||
|
.size FreeLock, .-FreeLock
|
||||||
|
.cc_bottom FreeLock.function
|
||||||
|
.globl FreeLock.nstackwords
|
||||||
|
.globl FreeLock.maxcores
|
||||||
|
.globl FreeLock.maxchanends
|
||||||
|
.globl FreeLock.maxtimers
|
||||||
|
.set FreeLock.nstackwords, 0
|
||||||
|
.set FreeLock.maxcores, 1
|
||||||
|
.set FreeLock.maxchanends, 0
|
||||||
|
.set FreeLock.maxtimers, 0
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// void FreeLockResource(lock l)
|
// void FreeLockResource(lock l)
|
||||||
.globl FreeLockResource.nstackwords
|
|
||||||
.linkset FreeLockResource.nstackwords, 0
|
|
||||||
.globl FreeLockResource
|
.globl FreeLockResource
|
||||||
.text
|
.cc_top FreeLockResource.function
|
||||||
|
.align 2
|
||||||
FreeLockResource:
|
FreeLockResource:
|
||||||
freer res[r0]
|
freer res[r0]
|
||||||
retsp 0
|
retsp 0
|
||||||
|
.size FreeLockResource, .-FreeLockResource
|
||||||
|
.cc_bottom FreeLockResource.function
|
||||||
|
.globl FreeLockResource.nstackwords
|
||||||
|
.globl FreeLockResource.maxcores
|
||||||
|
.globl FreeLockResource.maxchanends
|
||||||
|
.globl FreeLockResource.maxtimers
|
||||||
|
.set FreeLockResource.nstackwords, 0
|
||||||
|
.set FreeLockResource.maxcores, 1
|
||||||
|
.set FreeLockResource.maxchanends, 0
|
||||||
|
.set FreeLockResource.maxtimers, 0
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
.cc_top doMix##i.function,doMix##i; \
|
.cc_top doMix##i.function,doMix##i; \
|
||||||
.align 4 ;\
|
.align 4 ;\
|
||||||
.globl doMix##i ;\
|
.globl doMix##i ;\
|
||||||
|
.type doMix##i, @function ;\
|
||||||
.globl doMix##i##.nstackwords ;\
|
.globl doMix##i##.nstackwords ;\
|
||||||
.globl doMix##i##.maxthreads ; \
|
.globl doMix##i##.maxthreads ; \
|
||||||
.globl doMix##i##.maxtimers ; \
|
.globl doMix##i##.maxtimers ; \
|
||||||
@@ -42,6 +43,7 @@ doMix##i##: ;\
|
|||||||
retsp 0x0;\
|
retsp 0x0;\
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
|
.size doMix##i, .-doMix##i; \
|
||||||
.cc_bottom doMix##i##.function;
|
.cc_bottom doMix##i##.function;
|
||||||
|
|
||||||
#define N MIX_INPUTS
|
#define N MIX_INPUTS
|
||||||
@@ -124,9 +126,10 @@ DOMIX_BOT(7)
|
|||||||
#undef BODY
|
#undef BODY
|
||||||
#define N MAX_MIX_COUNT
|
#define N MAX_MIX_COUNT
|
||||||
.cc_top setPtr.function,setPtr;
|
.cc_top setPtr.function,setPtr;
|
||||||
.align 4 ;
|
.align 4 ;
|
||||||
.globl setPtr.nstackwords;
|
|
||||||
.globl setPtr;
|
.globl setPtr;
|
||||||
|
.type setPtr, @function
|
||||||
|
.globl setPtr.nstackwords;
|
||||||
.globl setPtr.maxthreads;
|
.globl setPtr.maxthreads;
|
||||||
.globl setPtr.maxtimers;
|
.globl setPtr.maxtimers;
|
||||||
.globl setPtr.maxchanends;
|
.globl setPtr.maxchanends;
|
||||||
@@ -151,14 +154,20 @@ setPtr_go:
|
|||||||
add r1, r1, r2;
|
add r1, r1, r2;
|
||||||
st8 r1, r11[r0];
|
st8 r1, r11[r0];
|
||||||
retsp 0;
|
retsp 0;
|
||||||
|
.size setPtr, .-setPtr
|
||||||
.cc_bottom setPtr.function
|
.cc_bottom setPtr.function
|
||||||
|
|
||||||
.section .cp.const4, "acM", @progbits, 4
|
.section .cp.const4, "acM", @progbits, 4
|
||||||
.LC0:
|
.cc_top .LC0.data
|
||||||
.align 4
|
.align 4
|
||||||
|
.LC0:
|
||||||
.int 0x7fffff00
|
.int 0x7fffff00
|
||||||
|
.cc_bottom .LC0.data
|
||||||
|
.cc_top .LC1.data
|
||||||
|
.align 4
|
||||||
.LC1:
|
.LC1:
|
||||||
.int 0x80000000
|
.int 0x80000000
|
||||||
|
.cc_bottom .LC1.data
|
||||||
|
|
||||||
#undef N
|
#undef N
|
||||||
#undef BODY
|
#undef BODY
|
||||||
|
|||||||
@@ -1,59 +1,63 @@
|
|||||||
|
|
||||||
#include "xs1_kernel.h"
|
#include "xs1_kernel.h"
|
||||||
#include "xs1_user.h"
|
#include "xs1_user.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.global write_sswitch_reg_blind, "f{si}(ui,ui,ui)"
|
.global write_sswitch_reg_blind, "f{si}(ui,ui,ui)"
|
||||||
.global write_sswitch_reg_blind.nstackwords
|
.type write_sswitch_reg_blind, @function
|
||||||
.linkset write_sswitch_reg_blind.nstackwords, 0
|
|
||||||
//.type read_sswitch_reg, @function
|
|
||||||
// r0 - coreid
|
// r0 - coreid
|
||||||
// r1 - reg
|
// r1 - reg
|
||||||
// r2 - data
|
// r2 - data
|
||||||
.cc_top write_sswitch_reg_blind.function, write_sswitch_reg_blind
|
.cc_top write_sswitch_reg_blind.function, write_sswitch_reg_blind
|
||||||
.align 2
|
.align 2
|
||||||
write_sswitch_reg_blind:
|
write_sswitch_reg_blind:
|
||||||
// Check range of coreid
|
// Check range of coreid
|
||||||
shr r3, r0, XS1_CHAN_ID_PROCESSOR_SIZE + XS1_CHAN_ID_NODE_SIZE
|
shr r3, r0, XS1_CHAN_ID_PROCESSOR_SIZE + XS1_CHAN_ID_NODE_SIZE
|
||||||
bt r3, write_switch_reg_fail
|
bt r3, write_switch_reg_fail
|
||||||
|
|
||||||
// Check range of reg
|
// Check range of reg
|
||||||
shr r3, r1, 16
|
shr r3, r1, 16
|
||||||
bt r3, write_switch_reg_fail
|
bt r3, write_switch_reg_fail
|
||||||
|
|
||||||
// Allocate channel end
|
// Allocate channel end
|
||||||
getr r3, XS1_RES_TYPE_CHANEND
|
getr r3, XS1_RES_TYPE_CHANEND
|
||||||
|
|
||||||
// Set destination
|
// Set destination
|
||||||
ldc r11, XS1_RES_TYPE_CONFIG | (XS1_CT_SSCTRL << XS1_CHAN_ID_CHANNUM_SHIFT)
|
ldc r11, XS1_RES_TYPE_CONFIG | (XS1_CT_SSCTRL << XS1_CHAN_ID_CHANNUM_SHIFT)
|
||||||
|
|
||||||
// r0 - l
|
// r0 - l
|
||||||
// r1 - reg
|
// r1 - reg
|
||||||
// r2 - data
|
// r2 - data
|
||||||
// r3 - chanend
|
// r3 - chanend
|
||||||
// r11 - low half of dest
|
// r11 - low half of dest
|
||||||
write_switch_reg:
|
write_switch_reg:
|
||||||
shl r0, r0, XS1_CHAN_ID_PROCESSOR_SHIFT
|
shl r0, r0, XS1_CHAN_ID_PROCESSOR_SHIFT
|
||||||
or r0, r0, r11
|
or r0, r0, r11
|
||||||
setd res[r3], r0
|
setd res[r3], r0
|
||||||
|
|
||||||
// Send packet
|
// Send packet
|
||||||
ldc r11, XS1_CT_WRITEC // Too big for outct immediate
|
ldc r11, XS1_CT_WRITEC // Too big for outct immediate
|
||||||
outct res[r3], r11
|
outct res[r3], r11
|
||||||
mkmsk r0, 32
|
mkmsk r0, 32
|
||||||
shl r0, r0, 8
|
shl r0, r0, 8
|
||||||
shr r11, r1, 8
|
shr r11, r1, 8
|
||||||
or r0, r0, r11
|
or r0, r0, r11
|
||||||
out res[r3], r0 // (0xffffff00) | (reg >> 8)
|
out res[r3], r0 // (0xffffff00) | (reg >> 8)
|
||||||
outt res[r3], r1 // reg & 0xff
|
outt res[r3], r1 // reg & 0xff
|
||||||
out res[r3], r2
|
out res[r3], r2
|
||||||
outct res[r3], XS1_CT_END
|
outct res[r3], XS1_CT_END
|
||||||
|
|
||||||
// Receive response
|
// Receive response
|
||||||
freer res[r3]
|
freer res[r3]
|
||||||
retsp 0
|
retsp 0
|
||||||
write_switch_reg_fail:
|
write_switch_reg_fail:
|
||||||
ldc r0, 0
|
ldc r0, 0
|
||||||
retsp 0
|
retsp 0
|
||||||
.cc_bottom write_sswitch_reg_blind.function
|
.size write_sswitch_reg_blind, .-write_sswitch_reg_blind
|
||||||
|
.cc_bottom write_sswitch_reg_blind.function
|
||||||
|
.global write_sswitch_reg_blind.nstackwords
|
||||||
|
.global write_sswitch_reg_blind.maxchanends
|
||||||
|
.global write_sswitch_reg_blind.maxtimers
|
||||||
|
.global write_sswitch_reg_blind.maxcores
|
||||||
|
.set write_sswitch_reg_blind.nstackwords, 0
|
||||||
|
.set write_sswitch_reg_blind.maxchanends, 1
|
||||||
|
.set write_sswitch_reg_blind.maxtimers, 0
|
||||||
|
.set write_sswitch_reg_blind.maxcores, 0
|
||||||
|
|||||||
@@ -9,3 +9,4 @@
|
|||||||
#
|
#
|
||||||
# You can also set MODULE_XCC_C_FLAGS, MODULE_XCC_XC_FLAGS etc..
|
# You can also set MODULE_XCC_C_FLAGS, MODULE_XCC_XC_FLAGS etc..
|
||||||
|
|
||||||
|
DEPENDENT_MODULES = module_queue
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
// Queue implementation
|
|
||||||
// Offers no protection against adding when full or dequeueing when empty.
|
|
||||||
// Uses read and write counts for pointers to distinguish full and empty cases.
|
|
||||||
// Works from c and xc
|
|
||||||
// Must allocate the memory outside of this and pass it in to init_queue so can statically allocate
|
|
||||||
// Must work for different element sizes
|
|
||||||
|
|
||||||
// This presumes that the xc compiler will not re-use the mem passed to init_queue
|
|
||||||
void init_queue(queue *q, unsigned char arr[], int size, int element_size) {
|
|
||||||
q->rdptr = 0;
|
|
||||||
q->wrptr = 0;
|
|
||||||
q->data = (uintptr_t)arr;
|
|
||||||
q->size = size; // in items, presume that size is power of two
|
|
||||||
q->element_size = element_size; // The size of each element in bytes
|
|
||||||
q->mask = size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern inline void enqueue(queue *q, unsigned value) {
|
|
||||||
switch (q->element_size) {
|
|
||||||
case 4:
|
|
||||||
((unsigned *)q->data)[q->wrptr & q->mask] = value;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
((unsigned char *)q->data)[q->wrptr & q->mask] = (unsigned char)value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
q->wrptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern inline unsigned dequeue(queue *q) {
|
|
||||||
unsigned retval;
|
|
||||||
switch (q->element_size) {
|
|
||||||
case 4:
|
|
||||||
retval = ((unsigned *)q->data)[q->rdptr & q->mask];
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
retval = ((unsigned char *)q->data)[q->rdptr & q->mask];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
q->rdptr++;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern inline int isempty(queue *q) {
|
|
||||||
return (q->rdptr == q->wrptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern inline int isfull(queue *q) {
|
|
||||||
return ((q->wrptr - q->rdptr) == q->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern inline int items(queue *q) {
|
|
||||||
int items = q->wrptr - q->rdptr;
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// How to calculate size? Could make it a function call or leave it as a variable within the struct
|
|
||||||
extern inline int space(queue *q) {
|
|
||||||
return q->size - items(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump(queue *q) {
|
|
||||||
for (int i = q->rdptr; i != q->wrptr; i++) {
|
|
||||||
switch (q->element_size) {
|
|
||||||
case 4:
|
|
||||||
printf("a[%d] = %d\n", i & q->mask, ((unsigned *)q->data)[i & q->mask]);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
printf("a[%d] = %d\n", i & q->mask, ((unsigned char *)q->data)[i & q->mask]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#ifndef QUEUE_H
|
|
||||||
#define QUEUE_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <xccompat.h>
|
|
||||||
|
|
||||||
typedef struct queue {
|
|
||||||
uintptr_t data;
|
|
||||||
int rdptr; // Using absolute indices which count reads and writes so this needs to be considered when accessing.
|
|
||||||
int wrptr;
|
|
||||||
int size;
|
|
||||||
int element_size;
|
|
||||||
int mask;
|
|
||||||
} queue;
|
|
||||||
|
|
||||||
void init_queue(REFERENCE_PARAM(queue, q), unsigned char arr[], int size, int element_size);
|
|
||||||
void enqueue(REFERENCE_PARAM(queue, q), unsigned value);
|
|
||||||
unsigned dequeue(REFERENCE_PARAM(queue, q));
|
|
||||||
int isempty(REFERENCE_PARAM(queue, q));
|
|
||||||
int isfull(REFERENCE_PARAM(queue, q));
|
|
||||||
int items(REFERENCE_PARAM(queue, q));
|
|
||||||
int space(REFERENCE_PARAM(queue, q));
|
|
||||||
void dump(REFERENCE_PARAM(queue, q));
|
|
||||||
|
|
||||||
#endif // QUEUE_H
|
|
||||||
@@ -49,6 +49,8 @@ extern unsigned polltime;
|
|||||||
timer iAPTimer;
|
timer iAPTimer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
||||||
clock ?clk_midi,
|
clock ?clk_midi,
|
||||||
chanend ?c_midi,
|
chanend ?c_midi,
|
||||||
@@ -71,23 +73,23 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
timer t2;
|
timer t2;
|
||||||
|
|
||||||
// One place buffer for data going out to host
|
// One place buffer for data going out to host
|
||||||
queue midi_to_host_fifo;
|
queue_t midi_to_host_fifo;
|
||||||
unsigned char midi_to_host_fifo_arr[4]; // Used for 32bit USB MIDI events
|
unsigned midi_to_host_fifo_arr[1]; // Used for 32bit USB MIDI events
|
||||||
|
|
||||||
unsigned outputting_symbol, outputted_symbol;
|
unsigned outputting_symbol, outputted_symbol;
|
||||||
|
|
||||||
struct midi_in_parse_state mips;
|
struct midi_in_parse_state mips;
|
||||||
|
|
||||||
// the symbol fifo (to go out of uart)
|
// the symbol fifo (to go out of uart)
|
||||||
queue symbol_fifo;
|
queue_t symbol_fifo;
|
||||||
unsigned char symbol_fifo_arr[USB_MIDI_DEVICE_OUT_FIFO_SIZE * 4]; // Used for 32bit USB MIDI events
|
unsigned symbol_fifo_arr[USB_MIDI_DEVICE_OUT_FIFO_SIZE]; // Used for 32bit USB MIDI events
|
||||||
|
|
||||||
unsigned rxPT, txPT;
|
unsigned rxPT, txPT;
|
||||||
int midi_from_host_overflow = 0;
|
int midi_from_host_overflow = 0;
|
||||||
|
|
||||||
//configure_clock_rate(clk_midi, 100, 1);
|
//configure_clock_rate(clk_midi, 100, 1);
|
||||||
init_queue(symbol_fifo, symbol_fifo_arr, USB_MIDI_DEVICE_OUT_FIFO_SIZE, 4);
|
queue_init(symbol_fifo, ARRAY_SIZE(symbol_fifo_arr));
|
||||||
init_queue(midi_to_host_fifo, midi_to_host_fifo_arr, 1, 4);
|
queue_init(midi_to_host_fifo, ARRAY_SIZE(midi_to_host_fifo_arr));
|
||||||
|
|
||||||
configure_out_port(p_midi_out, clk_midi, 1<<MIDI_SHIFT_TX);
|
configure_out_port(p_midi_out, clk_midi, 1<<MIDI_SHIFT_TX);
|
||||||
configure_in_port(p_midi_in, clk_midi);
|
configure_in_port(p_midi_in, clk_midi);
|
||||||
@@ -174,7 +176,7 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
{valid, event} = midi_in_parse(mips, cable_number, rxByte);
|
{valid, event} = midi_in_parse(mips, cable_number, rxByte);
|
||||||
if (valid && isempty(midi_to_host_fifo))
|
if (valid && queue_is_empty(midi_to_host_fifo))
|
||||||
{
|
{
|
||||||
|
|
||||||
event = byterev(event);
|
event = byterev(event);
|
||||||
@@ -189,7 +191,7 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enqueue(midi_to_host_fifo, event);
|
queue_push_word(midi_to_host_fifo, midi_to_host_fifo_arr, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (valid)
|
else if (valid)
|
||||||
@@ -215,10 +217,10 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
// When it has just finished sending a symbol
|
// When it has just finished sending a symbol
|
||||||
|
|
||||||
// Take from FIFO
|
// Take from FIFO
|
||||||
outputting_symbol = dequeue(symbol_fifo);
|
outputting_symbol = queue_pop_word(symbol_fifo, symbol_fifo_arr);
|
||||||
symbol = makeSymbol(outputting_symbol);
|
symbol = makeSymbol(outputting_symbol);
|
||||||
|
|
||||||
if (space(symbol_fifo) > 3 && midi_from_host_overflow)
|
if (queue_space(symbol_fifo) > 3 && midi_from_host_overflow)
|
||||||
{
|
{
|
||||||
midi_from_host_overflow = 0;
|
midi_from_host_overflow = 0;
|
||||||
midi_send_ack(c_midi);
|
midi_send_ack(c_midi);
|
||||||
@@ -244,7 +246,7 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
// Finished sending byte
|
// Finished sending byte
|
||||||
uout_count++;
|
uout_count++;
|
||||||
outputted_symbol = outputting_symbol;
|
outputted_symbol = outputting_symbol;
|
||||||
if (isempty(symbol_fifo))
|
if (queue_is_empty(symbol_fifo))
|
||||||
{ // FIFO empty
|
{ // FIFO empty
|
||||||
isTX = 0;
|
isTX = 0;
|
||||||
}
|
}
|
||||||
@@ -259,10 +261,10 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
{
|
{
|
||||||
// have we got more data to send
|
// have we got more data to send
|
||||||
//printstr("ack\n");
|
//printstr("ack\n");
|
||||||
if (!isempty(midi_to_host_fifo))
|
if (!queue_is_empty(midi_to_host_fifo))
|
||||||
{
|
{
|
||||||
//printstr("uart->decouple\n");
|
//printstr("uart->decouple\n");
|
||||||
outuint(c_midi, dequeue(midi_to_host_fifo));
|
outuint(c_midi, queue_pop_word(midi_to_host_fifo, midi_to_host_fifo_arr));
|
||||||
th_count++;
|
th_count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -278,7 +280,7 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
int event = byterev(datum);
|
int event = byterev(datum);
|
||||||
mr_count++;
|
mr_count++;
|
||||||
#ifdef MIDI_LOOPBACK
|
#ifdef MIDI_LOOPBACK
|
||||||
if (isempty(midi_to_host_fifo))
|
if (queue_is_empty(midi_to_host_fifo))
|
||||||
{
|
{
|
||||||
// data to send to host
|
// data to send to host
|
||||||
if (!waiting_for_ack)
|
if (!waiting_for_ack)
|
||||||
@@ -292,7 +294,7 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
event = byterev(event);
|
event = byterev(event);
|
||||||
enqueue(midi_to_host_fifo, event);
|
queue_push_word(midi_to_host_fifo, midi_to_host_fifo_arr, event);
|
||||||
}
|
}
|
||||||
midi_send_ack(c_midi);
|
midi_send_ack(c_midi);
|
||||||
}
|
}
|
||||||
@@ -305,10 +307,10 @@ void usb_midi(port ?p_midi_in, port ?p_midi_out,
|
|||||||
for (int i = 0; i != size; i++)
|
for (int i = 0; i != size; i++)
|
||||||
{
|
{
|
||||||
// add symbol to fifo
|
// add symbol to fifo
|
||||||
enqueue(symbol_fifo, midi[i]);
|
queue_push_word(symbol_fifo, symbol_fifo_arr, midi[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space(symbol_fifo) > 3)
|
if (queue_space(symbol_fifo) > 3)
|
||||||
{
|
{
|
||||||
midi_send_ack(c_midi);
|
midi_send_ack(c_midi);
|
||||||
}
|
}
|
||||||
|
|||||||
32
tests/app_queue_test/Makefile
Normal file
32
tests/app_queue_test/Makefile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# The TARGET variable determines what target system the application is
|
||||||
|
# compiled for. It either refers to an XN file in the source directories
|
||||||
|
# or a valid argument for the --target option when compiling
|
||||||
|
TARGET = XP-SKC-SU1
|
||||||
|
|
||||||
|
# The APP_NAME variable determines the name of the final .xe file. It should
|
||||||
|
# not include the .xe postfix. If left blank the name will default to
|
||||||
|
# the project name
|
||||||
|
APP_NAME = app_queue_test
|
||||||
|
|
||||||
|
# The USED_MODULES variable lists other module used by the application.
|
||||||
|
USED_MODULES = module_queue
|
||||||
|
|
||||||
|
# The flags passed to xcc when building the application
|
||||||
|
# You can also set the following to override flags for a particular language:
|
||||||
|
# XCC_XC_FLAGS, XCC_C_FLAGS, XCC_ASM_FLAGS, XCC_CPP_FLAGS
|
||||||
|
# If the variable XCC_MAP_FLAGS is set it overrides the flags passed to
|
||||||
|
# xcc for the final link (mapping) stage.
|
||||||
|
XCC_FLAGS = -O0 -g
|
||||||
|
|
||||||
|
# The VERBOSE variable, if set to 1, enables verbose output from the make system.
|
||||||
|
VERBOSE = 0
|
||||||
|
|
||||||
|
# This change to the module path is so that this application can be in the
|
||||||
|
# tests sub-directory in it's git repo
|
||||||
|
ifeq ($(notdir $(abspath ..)),tests)
|
||||||
|
PATHSEP = $(if $(findstring Windows, $(OS))$(findstring WINDOWS,$(OS)),;,:)
|
||||||
|
XMOS_MODULE_PATH := $(XMOS_MODULE_PATH)$(PATHSEP)../../..
|
||||||
|
endif
|
||||||
|
|
||||||
|
XMOS_MAKE_PATH ?= ../..
|
||||||
|
-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||||
32
tests/app_queue_test/src/app_queue_test.xc
Normal file
32
tests/app_queue_test/src/app_queue_test.xc
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "queue.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define VERIFY(x) do { if (!(x)) _Exit(1); } while(0)
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
queue_t q;
|
||||||
|
unsigned array[4];
|
||||||
|
const unsigned size = ARRAY_SIZE(array);
|
||||||
|
queue_init(q, size);
|
||||||
|
VERIFY(queue_is_empty(q));
|
||||||
|
VERIFY(!queue_is_full(q));
|
||||||
|
VERIFY(queue_items(q) == 0);
|
||||||
|
VERIFY(queue_space(q) == size);
|
||||||
|
queue_push_word(q, array, 1);
|
||||||
|
VERIFY(!queue_is_empty(q));
|
||||||
|
VERIFY(queue_items(q) == 1);
|
||||||
|
VERIFY(queue_space(q) == size - 1);
|
||||||
|
for (unsigned i = 1; i < size; i++) {
|
||||||
|
queue_push_word(q, array, i + 1);
|
||||||
|
}
|
||||||
|
VERIFY(queue_is_full(q));
|
||||||
|
VERIFY(queue_items(q) == size);
|
||||||
|
VERIFY(queue_space(q) == 0);
|
||||||
|
for (unsigned i = 0; i < size; i++) {
|
||||||
|
VERIFY(queue_pop_word(q, array) == i + 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user