Using PHSa as a 0-to-15 multiplier
tonyp12
Posts: 1,951
Question:
After you reset (write to) phsa, the following instruction read of phsa will be 2 ticks higher.
So if frqa is set for 1, after a reset to 0 the following read of phsa be 2.
But I need to make it 4.
This example takes a value and multiply it by 0 to 15 as it keeps adding a phsa value that have kept growing to the ^2 each time.
As you can not tell count-always to div the clock source the total will be 8x on top of 0-15x but not a big deal as I need to align(shift) for Fixed-point arithmetic later on anyway.
I'm trying to create a 4bit (16 level) Attack-Decay-Sustain-Release envelope, so it need to have cycle consistency and be fast
and no single NOP will remain in the end and that phsa auto-increment use this cycle for something productive.
After you reset (write to) phsa, the following instruction read of phsa will be 2 ticks higher.
So if frqa is set for 1, after a reset to 0 the following read of phsa be 2.
But I need to make it 4.
This example takes a value and multiply it by 0 to 15 as it keeps adding a phsa value that have kept growing to the ^2 each time.
As you can not tell count-always to div the clock source the total will be 8x on top of 0-15x but not a big deal as I need to align(shift) for Fixed-point arithmetic later on anyway.
I'm trying to create a 4bit (16 level) Attack-Decay-Sustain-Release envelope, so it need to have cycle consistency and be fast
and no single NOP will remain in the end and that phsa auto-increment use this cycle for something productive.
entry movi CTRA, #%11111_000 ' count always movs label, wavepnt ' get value from sinewave table mov Accumu,#0 label mov frqa, 0-0 ' a value from lookup table, a 1 in this example) mov phsa, #0 ' start at at zero but probably need to change test ADSR, #1 wz ' 4 < a phsa-read yields this, But is 2!!!!!! if_nz add Accumu,phsa ' phsa (8x) 1x ' 8 < a phsa-read yields this....... test ADSR, #2 wz ' 12 if_nz add Accumu,phsa ' phsa (8x) 2x ' 16 nop ' 20 nop ' 24 test ADSR, #4 wz ' 28 if_nz add Accumu,phsa ' phsa (8x) 4x ' 32 nop ' 36 nop ' 40 nop ' instead do something useful ' 44 nop ' 48 nop ' 52 nop ' 56 test ADSR, #8 wz ' 60 if_nz add Accumu,phsa ' phsa (8x) 8x ' 64
Comments
I knew I needed to get a sinewave value *2 in as a start value, and one extra line is not bad.
As long I get good use of replacing the NOPs this must be one of the fastest 0-15x multi,
anyone else with something faster? (consistent cycles is a must)
The trick is to get two cycles in there, and reading psha at cycle 2 and writing that value back at cycle 4 will do the trick as Kuroneko stated above.
The plan is to use a 256 long look-up table (starting at address 0) that contains three independent 10bit waveforms in each long.
Use the 9bits and with use multiplication to amplitude it to 13bit range controlled by the ADSR envelope
The 10th bit is sign flag and will be used with add/sub (eg SUMC probably) it to 14bit accumulator
So 4cogs *3 channels =12 channels going to a master cog that sum them all up before sending it out to DAC or digitally to a i2s audio driver.
Yours don't have the side effect of 8x , but if I decide that 4bit decimal point is what I want anyway when I get free shl out of it, bonus another freed up cycle.
I was trying to get rid of the 3 shl as every cycle is going down with a fight.
But getting something useful done instead of nop could be harder.
Wonder if there is a way to do just three test's with 2bits checked each time and use wc wz,
some type of three branching, probably not.
I was think something weird like:
test ADSR,#%1010 wc wz
if_nc_and_z add Accumu,_wave
test ADSR,#%0101 wc wz
if_c_and_nz shl Accumu, #2
test ADSR,#%0011 wc wz
if_c_and_z sub Accumu,_wave
Explanation: adding a 8x actual wave data, but by doing div2 every time as side effect from getting ADSR data-bits it will be resized down to right values.