Hi Guys,
I'm new to this forum but quite not an absolute beginner with SPIN chips. I was trying to read documentation several times but I still can't understand the exact math behind LOG and EXP opcodes because it lacks examples of S4.19 stored numbers. No, I understand, what lofarithmic scale is; the issue is likely about value storage format. Let me explain what I mean.
As far as I understand, LOG 1, 0 operation takes the binary logarithm of a number, divides this by an internal constant (16?) and stores the number in S4.19 format. EXP 1, 0 does the opposite operation.
What I'm after is to perform "-1" order math operations in logarithmic scale to achieve code-efficient multiplications and variable divisions. So, what EXACTLY should I add to a number in logarithmic scale to multiply it by exactly 2 after exponentiation?
I assume that it's something like this:
in s.23 format the MSb is sign, and each n bit is a fraction of 1 equal to 1/2^(23-n)
sof 0, %0 0100000 00000000 00000000 ; 0.25
log 1, 0 ; log2(0.25) = -2. if this number is /16 = -2/16 = -1/8 = %1 0000 001 00000000 00000000
; Assuming, that exp(log(a)+2) = a*2, I should add 2 to the number to multiply it, but sof internal math is in s1.23 format, so I had to apply a proper scale:
sof 1, 2/16 ; 0x810000 + 0x100000 = 0x910000 = %1 0011 000 00000000 00000000 = -3.
exp 1, 0 ; do I apply 2^-3? But it's 1/8 = 0.125, so does it divides the number by 2 and I had to actually subtract 1/8 instead of adding?
Unfortunatelly, since FV-1 has AC-coupled outputs, I have no idea how to experimentally prove this theory.
Why it's so important?
For example, I want to perform manual CHO RDA from arbitrary location.
For this, I need to split a real number into sections of sign, 15 bits of address and 9 available bits of interpolation coefficient. To apply this coefficient I had first to perform 15x sof -2, 0 operations + one sof -1, 0, but I believe, this can be achievable using only 2 operations with log/exp. Since the number is obviously small, i believe, it may be multiplied by 32768 using log, exp and 4x sof operations. Unfortunately, technical documentation is not too much detailed to explain, how logged numbers are stored in accumulator.
Have tried to use search on "log" but was unable to notice the answer.
WIll appreciate any help or links to more deep reading besides assembler manual, AN0001 and AN0002.
Thanks.
log/exp exact coefficients
Moderator: frank
Re: log/exp exact coefficients
It is all a trick of where we consider the binary point in the number. For example the 24-bit hex value 0x400000 is 0.5 if we consider it S.23 or 8.0 in S4.19 so 1.0 in S4.19 would be 0x080000 and -1.0 would be 0xF80000 in S4.19
Frank Thomson
Experimental Noize
Experimental Noize
Re: log/exp exact coefficients
It seems that I have lot of errors in the example:
sof 0, %0 0100000 00000000 00000000 ; 0.25
log 1, 0 ; log2(0.25) = -2 = %1 1101 111 11111111 11111111
; Assuming, that exp(log2(a)+log2(2)) = a*2, I should add log2(2)=1 to the number to multiply it, but sof internal math is in s1.23 format, so I had to apply a proper scale:
sof 1, 1/16 ; 0xefffff + 0x080000 = 0xf7ffff = %1 1110 111 11111111 11111111 = -1.
exp 1, 0 ; 2^-1 = 0.5. It seems that we actually multiplied 0.25 by 2.
Is this correct?
There's another problem. If minimal stored logarithm is -16, it seems that argument's resolution should be within 16 bits, which means that we can't directly process the least significant byte from a 24-bit value and have to apply 8x sof -1, 0 operations.
Or, maybe, it may be compressed via log 1/8, 0? What comes next: multiplication before bit shifting and s4.19 conversion, or first it's stored, then multiplied?
It should be like this:sof 0, %0 0100000 00000000 00000000 ; 0.25
log 1, 0 ; log2(0.25) = -2. if this number is /16 = -2/16 = -1/8 = %1 0000 001 00000000 00000000
; Assuming, that exp(log(a)+2) = a*2, I should add 2 to the number to multiply it, but sof internal math is in s1.23 format, so I had to apply a proper scale:
sof 1, 2/16 ; 0x810000 + 0x100000 = 0x910000 = %1 0011 000 00000000 00000000 = -3.
exp 1, 0 ; do I apply 2^-3? But it's 1/8 = 0.125, so does it divides the number by 2 and I had to actually subtract 1/8 instead of adding?
sof 0, %0 0100000 00000000 00000000 ; 0.25
log 1, 0 ; log2(0.25) = -2 = %1 1101 111 11111111 11111111
; Assuming, that exp(log2(a)+log2(2)) = a*2, I should add log2(2)=1 to the number to multiply it, but sof internal math is in s1.23 format, so I had to apply a proper scale:
sof 1, 1/16 ; 0xefffff + 0x080000 = 0xf7ffff = %1 1110 111 11111111 11111111 = -1.
exp 1, 0 ; 2^-1 = 0.5. It seems that we actually multiplied 0.25 by 2.
Is this correct?
There's another problem. If minimal stored logarithm is -16, it seems that argument's resolution should be within 16 bits, which means that we can't directly process the least significant byte from a 24-bit value and have to apply 8x sof -1, 0 operations.
Or, maybe, it may be compressed via log 1/8, 0? What comes next: multiplication before bit shifting and s4.19 conversion, or first it's stored, then multiplied?
Re: log/exp exact coefficients
According to info in the manual, the log function maps to S4.19 so if the ACC has anything smaller
than 0.00001526 is will presumably map to -16 by the log() operation.
In other words, it seems the log() function isn't going to work on the bottom 8 bits of the 24 bits in the ACC.
I am assuming those bits are effectively masked out by the log() operation.
So I don't think 4 SOFs will be enough for your interpolation factor calculation.
You would need 8 SOFs to shift the lowest bits 8 places to the left so that the log() function sees them,
and you can then try a log() and exp() for the remaining shifts. So this sort of thing...
I not sure how well this approach is going to work though, because the bits in a logarithm are mainly
affected by the most significant bits in the ACC before the log() operation.
than 0.00001526 is will presumably map to -16 by the log() operation.
In other words, it seems the log() function isn't going to work on the bottom 8 bits of the 24 bits in the ACC.
I am assuming those bits are effectively masked out by the log() operation.
So I don't think 4 SOFs will be enough for your interpolation factor calculation.
You would need 8 SOFs to shift the lowest bits 8 places to the left so that the log() function sees them,
and you can then try a log() and exp() for the remaining shifts. So this sort of thing...
Code: Select all
; ACC has something in the bottom 8 bits out of 24.
; We want to left-shift it by 15 bits.
; Do the first 8 left-shifts using SOF doublings
SOF -2,0
SOF -2,0
SOF -2,0
SOF -2,0
SOF -2,0
SOF -2,0
SOF -2,0
SOF -2,0
LOG 1,7.0 ; log() and add 7 to get a further left-shift of 7 places after exp()
EXP 1,0 ; Done
affected by the most significant bits in the ACC before the log() operation.
Re: log/exp exact coefficients
Thank you for the example.DrAlx wrote: ↑Wed Apr 24, 2019 7:25 amI not sure how well this approach is going to work though, because the bits in a logarithm are mainlyCode: Select all
; ACC has something in the bottom 8 bits out of 24. ; We want to left-shift it by 15 bits. ; Do the first 8 left-shifts using SOF doublings SOF -2,0 SOF -2,0 SOF -2,0 SOF -2,0 SOF -2,0 SOF -2,0 SOF -2,0 SOF -2,0 LOG 1,7.0 ; log() and add 7 to get a further left-shift of 7 places after exp() EXP 1,0 ; Done
affected by the most significant bits in the ACC before the log() operation.
I have made an investigation on the "manual CHO RDA" technique and found that log/exp has insufficient precision for bit shifting operation.
I have made a zipper-free variable time delay algorithm:
Code: Select all
; Code example for fractional rmpa read.
equ potfil reg0
equ xfade_l reg1
equ xfade_r reg2
equ temp reg31
start:
ldax adcl ; Send ADC-L input to the delay line
wra 0, 0
rdax pot0, 1 ; Take value of the pot 0
rdfx potfil, 0.001 ; Apply low-pass filtering
wrax potfil, 1
and 0x0000ff ; Trim bits 23-8
sof -2, 0 ; Logical shift left by 15 bits
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -2, 0
sof -1, 0
wrax xfade_r,1 ; Store 2nd cross-fade coefficient
xor 0x7fffff ; 1-x
wrax xfade_l,0 ; Store 1st cross-fade coefficient
ldax potfil ; Calculate 1st interpolated value
wrax addr_ptr,0
rmpa 1
mulx xfade_l
wrax temp, 0 ; Store this value
or %00000000_00000001_00000000 ; Prepare incremented address
rdax potfil, 1 ; Repeat the procedure with +1RAM address
wrax addr_ptr,0
rmpa 1
mulx xfade_r ; ... and 2nd cross-fade coefficient
rdax temp, 1 ; Add values together
wrax dacl, 1 ; Output to both L and R channels
wrax dacr, 0
Re: log/exp exact coefficients
i don't fully analize your example, but POT is 9 bits, so last 14 bits are zeroes, and you get any low bits only because of 1st order LPF.
Another thing is , potetentiometer will have zipper noise because of scratches. Simple LPF will not resolve scratching 100% correctly.
One else: you multiply 15 times to -2, so result signum will be inverted and you will get negative result.
XOR - is not subtraction. For correct subtract you may use smthing like
CLR
OR 0x7FffFF
rdax reg_value , -1
or some kind of that
Another thing is , potetentiometer will have zipper noise because of scratches. Simple LPF will not resolve scratching 100% correctly.
One else: you multiply 15 times to -2, so result signum will be inverted and you will get negative result.
XOR - is not subtraction. For correct subtract you may use smthing like
CLR
OR 0x7FffFF
rdax reg_value , -1
or some kind of that
Re: log/exp exact coefficients
XOR 7fffff is just a replacement for SOF -1, 2047/2048:
The number 0.25 is represented as
00100000_00000000_00000000 ; 0.25
01111111_11111111_11111111 ; xor 7f_ff_ff
01011111_11111111_11111111 ; = (1-2^-23)-0.25
As for the 9-bit pot and filtering, zipper noise is not exactly because of scratches, but more likely because of 1) low pot resolution, and 2) discrete jumps between samples in the delay line (instead of linear scanning through all samples with the VARIABLE sampling rate. In fact, when you change the voltage at PotX inputs, they become an oversampled stream of discretely changing values, so the result is exactly like scratching a vinyl record. The point of filtering the pot is exactly to add some slew between adjacent pot values and let DSP make closer jumps. In my last example, I also apply primitive linear interpolation that helps to remove the jitter effect, which also generates the zipper noise. But the only true way to completely remove the jitter will be:
1. Restricted rate of changing the pot value.
2. Successive scan through each adjacent sample in the delay line with oversampling, 4-pole LP filtering and decimation to let the DSP scan through multiple samples per cycle.
Then this will really work more like pulling a tape than like scratching through tracks of a vinyl disc.
Re: log/exp exact coefficients
now understood about xor, thanks.