nie mógł odpowiedzieć na moje własne pytanie, dopóki nie czekał 8 godzin? tak czy inaczej tutaj jest to, co mam i działa! W tej funkcji dzieje się całkiem sporo. Jest to zasadniczo oscylator fali sinusoidalnej, który używa wartości LUT dla wartości sinusoidalnych. Używa również tabeli wartości wykładniczych, które są przypisane za pomocą ADC podłączonego do puli do kontroli. Jest akumulator z 32-bitową fazą, który tworzy rampę, która jest następnie skalowana do wyszukiwania. Tabela sinusów (której nie zawierałem zbyt wiele) to wartości 16-bitowe obcięte do rozmiaru stołu 14-bitowego. Jestem pewien, że w tym kodzie jest wiele optymalizacji, ale przynajmniej to mnie uruchomi. Generuję 16 próbek fali sinusoidalnej @ 48k przy każdym przejściu tej funkcji i wypełnianiu bufora, który (poza tą funkcją) jest przesyłany do DMA i przesyłany przez pokładowy kodek Discovery. Bardzo gładko brzmi, muszę powiedzieć. Łączne cykle instrukcji wydają się wynosić około 1200 . Mam do 56 000 cykli, jeśli ich potrzebuję, więc jest całkiem niezła. Jedną z rzeczy, z którą mam problemy jest skalowanie wyjścia sinusoidalnego. Tabela sinusowa ma wartości int16_t i chcę ją pomnożyć przez ułamek, aby uzyskać kontrolę głośności. Do tej pory nic Próbowałem prace przy użyciu smul, mul itp
@ 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
Spróbowałeś? Co nie działało? Mówisz, że próbujesz wywołać funkcję zespołu, ale reszta twojego pytania brzmi tak, jakbyś próbowała je napisać. Spróbuj wyjaśnić lepiej. –
Powinieneś zadeklarować globalny var jako zmienny, ale nie robiłem ARM-a od dłuższego czasu, więc nie mogę pomóc z resztą przepraszam. – lxop
Nie ma powodu, aby zadeklarować zmienną globalną 'volatile', chyba że może ona zmienić się poza kontrolą sterowania programem. Wywołanie funkcji złożenia samo w sobie nie jest wystarczającym powodem, aby wymagać 'volatile'. * Dowolne * wywołanie funkcji może zmienić wartość globalną. –