
@; Shared Sound audio buffer fill
@; 27/8/2022

@; audio_t structure element offsets, must agree with definition in main.h
.set size,              0  @; length of circular buffer (samples not bytes)
.set read,              4  @; read index (samples not bytes)
.set write,             8  @; write index (samples not bytes)
.set rate_acc,         12  @; fractional rate step accumulator (Q24)
.set buffer,           16  @; pointer to buffer of length 'size' samples (int's)
.set sys_base,         20  @; system buffer base address
.set sys_end,          24  @; system bufer end address
.set sys_rate,         28  @; system sample rate (Q10)
.set sys_step,         32  @; system fractional step (Q24)
.set sys_lr_vol,       36  @; system left/right volume (Q16 *2)
.set handler_id,       40  @; shared sound handler id

    .text
    .align 2

@; shared sound buffer fill function
@; ---------------------------------
@; on entry:
@; r0 = our parameter, address of audio_t data structure
@; r1 = buffer base          (saved)
@; r2 = buffer end           (saved)
@; r3 = flags
@; r4 = Sample frequency     (saved)
@; r5 = Sample period
@; r6 = Fractional step      (saved)
@; r7 = LR volume            (saved)
@; r8 = Pointer to fill code

    .global audio_buffer_fill
audio_buffer_fill:
    @; First, check if we need to clear the buffer or add to it
    tst r3, #1
    orr r3, r3, #1             @; inform caller we will have written data
    stmfd sp!, {r0-r12,lr}
    bne nozeros
    mov r9, #0
    mov r3, r1  @; buffer base
zeroloop:
    str r9, [r3], #4
    cmp r3, r2
    blt zeroloop
nozeros:
    add r3, r0, #sys_base      @; start from sys_base
    stmia r3, {r1,r2,r4,r6,r7} @; save system parameters
    ldmia r0, {r7-r11}         @; load data structure
    @; r7 = buffer size (samples not bytes)
    @; r8 = read index  (samples not bytes)
    @; r9 = write index (samples not bytes)
    @; r10 = fractional rate accumulator (Q24)
    @; r11 = source buffer start address

samploop:
    cmp r8, r9
    beq exit                   @; source buffer empty (underrun), exit

    ldr r4, [r1]               @; load destination data
    ldr r5, [r11, r8, lsl #2]  @; load source data
    add r4, r4, r5             @; combine, no checks for overflow
    str r4, [r1], #4           @; store new destination data, point to next

    add r10, r10, r6           @; point to next source sample
    add r8, r8, r10, lsr #24   @; using fractional step
    bic r10, r10, #0xFF000000  @; clear integer part, as we've added that to the read index
    cmp r8, r7
    subge r8, r8, r7           @; wrap index

    cmp r1, r2                 @; Check for buffer end
    blt samploop

exit:
    str r8, [r0, #read]        @; update read index
    str r10, [r0, #rate_acc]   @; update fractional rate accumulator
    ldmfd sp!, {r0-r12,pc}     @; exit

