no podía responder a mi propia pregunta hasta que yo esperó 8 horas? de todos modos aquí es lo que tengo y funciona !! Hay bastante en esta función. Básicamente es un oscilador de onda sinusoidal que utiliza una LUT para valores sinusoidales. También usa una tabla de valores exponenciales que se asignan usando ADC conectado a un pot para control. Hay un acumulador de fase de 32 bits que crea una rampa que luego se escala para la búsqueda. La tabla sinusoidal (que no incluí mucho) es un valor de 16 bits truncado a un tamaño de tabla de 14 bits. Estoy seguro de que hay muchas optimizaciones para hacer en este código, pero al menos me ayuda a comenzar. Estoy generando 16 muestras de onda sinusoidal a 48k con cada pasada de esta función y llenando un buffer que (fuera de esta función) se transfiere a DMA y se envía a través del códec de Discovery incorporado. Es un sonido muy suave, debo decir. El total de ciclos de instrucción parece estar alrededor de 1200 hasta el momento. Tengo hasta 56000 ciclos si los necesito así que esto es bastante bueno. Una cosa con la que estoy teniendo problemas es escalar la salida sinusoidal. La tabla senoidal es int16_t valores y quiero poder multiplicarla por una fracción para obtener control de volumen. Hasta el momento nada de lo que he intentado obras utilizando smul, etc. mul
@ void get_sine(void)
.align 2 @ Align to word boundary
.global get_sine @ This makes it a real symbol
.thumb_func
.type get_sine STT_FUNC @ Declare get_sine to be a function.
get_sine: @ Start of function definition
push {r4-r7}
ldr r0,=pitch @ get pitch address
ldr r1,=expoLUT @ expo_tab address
ldr r7,[r0,#0] @ pitch val into r7
lsl r7,r7,#2
ldr r7,[r1,r7] @ move lookup expo tab value with r7 into r7
ldr r2,=sineLUT @ sine_tab base addy
ldr r4,=WaveBuffer @ storage array addy
ldr r5,=writePos @ get writepos addr
mov r6,#0 @ clear increment r6
outloop:
ldr r3,=phase @ phase address to r3
ldr r1,[r3,#0] @ get current phase
add r1,r1,r7 @ add current phase and ph_inc
str r1,[r3,#0] @ store phase
lsr r0,r1,#18 @ shift it right by 18 into r0 for sine_tab lookup
lsl r0,r0,#2 @ align it
ldr r0,[r2,r0] @ lookup sine val with r0 into r1
lsl r1,r0,#16 @ shift to left channel
add r0,r0,r1 @ add right channel
ldr r1,[r5,#0] @ get writePos
push {r1} @ push it before align
lsl r1,r1,#2 @ align address 4
str r0,[r4,r1] @ store sine to WaveBuffer
pop {r1} @ pop writepos back
add r1,r1,#1 @ increment array pointer writepos
ldr r3,=1024 @ load BUFFERSIZE compare
cmp r1,r3 @ skip if less than BUFFERSIZE
bne skip
mov r1,#0 @ clr writepos if >=BUFFERSIZE
skip:
str r1,[r5,#0] @ store writepos value
add r6,r6,#1 @ increment loop counter
ldr r0,=dataSize @ get datasize counter addr
ldr r1,[r0,#0] @ get val
add r1,r1,#1 @ increment datasize counter
str r1,[r0,#0] @ store counter
cmp r6,#16 @ compare with 16 (i=0;i<16;i++)
bne outloop
pop {r4-r7}
bx lr
.section .rodata
sineLUT:
@ Array goes in here. Type can be .byte, .hword or .word
@ NOTE! No comma at the end of a line! This is important
.word 0x0000,0x000c,0x0018,0x0024,0x0030,0x003c,0x0048,0x0054
.word 0x0064,0x0070,0x007c,0x0088,0x0094,0x00a0,0x00ac,0x00bc
.word 0x00c8,0x00d4,0x00e0,0x00ec,0x00f8,0x0104,0x0114,0x0120
.word 0x012c,0x0138,0x0144,0x0150,0x015c,0x016c,0x0178,0x0184
.word 0x0190,0x019c,0x01a8,0x01b4,0x01c4,0x01d0,0x01dc,0x01e8
.word 0x01f4,0x0200,0x020c,0x021c,0x0228,0x0234,0x0240,0x024c
.word
¿Lo intentó? ¿Qué no funcionó? Dice que está tratando de llamar a una función de ensamblaje, pero el resto de su pregunta parece que está intentando escribir una. Por favor trata de explicar mejor. –
Definitivamente debería declarar la var global como volátil, pero no he hecho ARM asm por un tiempo, así que no puedo evitar el resto lo siento. – lxop
No hay ninguna razón para declarar una variable global 'volátil' a menos que pueda cambiar fuera del flujo de control del programa. Llamar a una función de ensamblaje no es una razón suficiente para requerir 'volátil'. * Cualquier llamada de función * puede cambiar el valor de global. –