<marcan>
how did you measure the freq? dma frequency?
<povik>
marcan: should i upload the plot somewhere also, or are you handy with gnuplot? :-)
<povik>
yeah, watching the dma data rate
<marcan>
tbh I'm more interested in throwing this into python ;)
<marcan>
what's with the gaps?
<marcan>
859 2816.5058968377184
<marcan>
1118 47902.4243718684
<povik>
see the comment at the top, it is over two arbitrary ranges
<povik>
and within the ranges there are gaps due to the frequency being too low
<povik>
see the iboot value measures as
<povik>
1118 47902.4243718684
<marcan>
ack
<marcan>
that one should be exactly 48000 if they didn't screw it up
<marcan>
so I guess that's your error margin
<povik>
sure, it gives you an idea what's the measurement error
<povik>
...
<povik>
i sped it up and increased the error margin for later values, this is one of them
<marcan>
so one thing to keep in mind is that if there is a PLL or similar cleanup pass after it, the other reg values might affect it and that might cause insanity for some ranges
<marcan>
but let's see
<marcan>
the value is definitely a bitfield
<povik>
great. i was trying to isolate some fields yesterday late in night but with no result
<marcan>
I'm getting the feeling this register is kind of interesting
rkt has quit [Quit: rkt]
<marcan>
okay, this has to be a shift register of some sort
<marcan>
that calculates the lookup table and then computes the divider based on the reg value
<marcan>
matches all of them fine
<marcan>
ignore the last stuff, the div calculation is what matters
<marcan>
I'm not sure where the 4.25 thing comes from, probably other registers
<jix>
marcan: you can use modular exponentiation by squaring to directly compute the n-th step of a lfsr, but for 11 bits I wouldn't bother
mikebeaton[m] has quit [Quit: issued !quit command]
<jix>
without using carryless (i.e. polynomial over F_2) multiplication instructions (which I assume arm also has these days) it might even be slower than the naive approach for 11 bits
<marcan>
heh, yeah, table it is then
<jix>
with those instruction it's probably faster than generating the table, but that's a lot of added complexity
<marcan>
this is a kernel driver, not going to use NEON for this
<maz>
marcan: kernel_neon_begin()/end(). the crypto code is full of it! :-)
<marcan>
yes but it feels very silly for this ;)
<maz>
I'm all for silly things, today...
* rkt
is reviewing today’s chat log with a web brower
<marcan>
povik: the next register is the fractional part, but it's also not just a straight thing
<marcan>
I think it's probably a delta for the accumulator or so
<marcan>
povik, jix: want to take a crack at this relation for the NCO fractional part register? https://mrcn.st/p/8L7N8zW5
<marcan>
it's a weird S shape in a log plot
<jix>
frac = 1 / (np.exp2(23.5 - np.log2(reg)) + 2) # is pretty close
<jix>
but that's just eyeballed, so no idea if that's close enough for what it's used for
<jix>
oh and it's not close for the small values, I assumed they are noise because they jump all over the place in a log plot, but that might not be the case?
<marcan>
yes, the small ones are noisy
<marcan>
there's error in the measurement
<chadmed>
is this lfsr used to derive the dac's sample rate? if so values not between 8000 and 384000 should never ever matter
<marcan>
maybe, but there's no good reason to hardcode it when we know the formula
<marcan>
magic numbers suck
<chadmed>
oh yeah for sure im just saying that noise causing inaccuracy in low values shouldnt be too much of an issue unless the hardware is doing double duty for something else
<marcan>
jix: I wonder how that comes about from the implementation...
<marcan>
chadmed: I mean the noise is just in my measurement
<jix>
marcan: same, do you have a rough idea what it does?
<marcan>
it's supposed to be an NCO
<marcan>
we know the half-integer part is that counter
<marcan>
I would expect further fractions to be the phase accumulator thing
<marcan>
but this does not match what I expect from a phase accumulator
<marcan>
jix: 0.5 - 0.5 / ((reg / (2**22.5)) + 1) makes more sense
<marcan>
(equivalent)
<marcan>
the sqrt(2) factor there bothers me
<marcan>
actually 22.6 matches even better
<jix>
maybe 2**22.??? is just 0x600000 ?
<marcan>
it might just... yeah that
<marcan>
why a factor of 3 then though :D
<marcan>
ahh wait
<marcan>
the other registers are related
<jix>
also 0x60a000 is even closer ... but it also seems to be off by a small factor
<jix>
hmm not a small factor but a small offset... if you use 0x60ae00 and then add 2**(-13) at the end it's really close (but that offset might also be measurement error? no idea how you measure this)
<marcan>
there may be some measurement error, or the other register is messing with things
<jix>
can you do the measurement over a longer interval or so to figure out if the 2**(-13) are just measurement error? I expect it to be... but a constant offset could also be plausible
<marcan>
pretty sure it's error
rkt has quit [Quit: rkt]
<marcan>
ok, so small values take a while to converge, which tells me these are accumulator increments indeed
<marcan>
so basically the logic would be a state flip-flop driving a mux that selects the increment register
<marcan>
hm, sec
<marcan>
yeah, so any time the top bit of the accumulator toggles, the flip-flop toggles
<marcan>
and the flip-frop drives an LSB's worth of divider
<marcan>
and that's all of the data registers then, reg0 is presumably control, might want to poke around the bits there at some point
<marcan>
so the first register is the increment for the ddiv = +0 state, and the second for the ddiv = +0.5 state
<marcan>
which means there's an inverse relationship, if r2 is 2*r1, then it spends half as long at 0.5, so the overall div is 0.16666
<marcan>
povik: and this is how you reverse an NCO without looking at the kext
<marcan>
:-)
<marcan>
ah wait, there was one more register
<marcan>
not sure what that one's about
<marcan>
macos sets these to 0x5ad200 0xff9f5200 0x7f9f5200
<marcan>
maybe the third one is just some initializer, perhaps it needs a control reg kick to set?
<marcan>
hmmm
<marcan>
yes, that's what it is
<marcan>
so you have to stop the NCO first, clearing bit 31 of the control register
<marcan>
then you set bit 31 of the ctl reg and it goes off
<marcan>
that way you can use small incs without having to wait for the accumulator to wrap back across the midpoint
<marcan>
the midpoint is indeed 0x80000000
<marcan>
and top bit 1 means high div and use high-inc
<marcan>
so really that register can just always be set to 0x80000000 I guess, I have no idea why you'd bother with anything else?
<marcan>
(or 0x7fffffff)
<marcan>
>>> 5952000+6336000
<marcan>
12288000
<marcan>
>>> 48000 * 256
<marcan>
12288000
<marcan>
ha.
<jix>
I guess it's always a good idea to avoid small incs anyway... i.e. multiply them by the largest constant that still fits
<marcan>
nah, see what xnu did there
<marcan>
(r1 - r2) == desired_freq
<marcan>
that's gotta make sense mathematically
<jix>
wait is it doing a zigzag around the midpoint or is it always wrapping around in one direction? (or I guess you could do it either if the increment regs are as wide as the accumulator reg)
<marcan>
zigzag
<marcan>
I actually suspect macos has some rounding error here...
<marcan>
hm, wait, no, that's too much
<marcan>
ah, had it backwards
<marcan>
still has some error though
<povik>
marcan: re: this is how you reverse NCO -- 10/10, would give marcan puzzling data again
<povik>
funny thing is yesterday i noticed the similarities in frequency of shifted bit patterns, in couple instances
<povik>
but ruled that out as probably a meaningless coincidence
<povik>
and went on looking for fixed subfields in the registers
<marcan>
jix: yeah I don't know why they use fout as the sum of the params
<marcan>
so I measure 47999.3839 but I calculate that macos should be setting 48000.5586 and I don't know if that's measurement error or what
<marcan>
I'd *think* my timer and this thing would be frequency-locked to some extent, which is a bit weird
<marcan>
unless the input clock is a bit of a lie and not exact
<marcan>
I get a divider of 4.50005766 with the flop one way, and 4.05639163 the other
<marcan>
that doesn't look right
<marcan>
(for the highest freq)
<jix>
uh I think the math for the values you said mac os sets checks out? (also not quite following the last thing you said)
<marcan>
does it?
<jix>
I get that it should set a fractional value of 31/64 and that's what 5952000 / (5952000 + 6336000) reduces to... except wait is it actually the right thing to do? it matches what mac os does but uh not sure
<marcan>
I'm probably doing the math wrong
<marcan>
also I get better numbers with a div6
<marcan>
so I think that must just be a weird artifact of the lowest div
<marcan>
jix: I'm probably getting some 1/x relationships wrong
<jix>
I also totally don't trust that what I'm computing is the right thing, just that it ends up telling me mac os is setting 48k exactly
<jix>
hmm but no it should be fine I think... now let me try to do this the other way around to get from freq to incs
<marcan>
jix: ok, my interpretation of the dither was wrong
<marcan>
it's per output cycle, not input cycle
<marcan>
that's where my error comes from
<jix>
ah yeah, what I did was just to use high_inc and low_inc to directly match the fractional part of the divider period ... and that should check out if it's per output cycle as the formula for the fractional part already takes into account that the longer output cycles are longer
<marcan>
and yeah that works out to 48k from macos
<marcan>
yeah okay and that makes the math make sense
<marcan>
div = (2 * fin // fout)
<marcan>
low_inc = (2 * fin - div * fout)
<marcan>
high_inc = fout - low_inc
<marcan>
simple.
<marcan>
still not sure where that measurement error comes from, but shrug
<marcan>
okay, I should *not* have let myself get nerdsniped with this today :S
<jix>
ah and that's why the difference is fout... by scaling both values by fout you can use an integer division here, that also explains why they're not using a reduced fraction
<marcan>
yeah
<jix>
eh sum, not difference, well depends on how you view it ^^
bps2 has quit [Ping timeout: 480 seconds]
stzsch has quit [Remote host closed the connection]
<marcan>
(also, I just realized I messed up the polynomial earlier; it's x^11 + x^9 + 1)
user982492 has joined #asahi-dev
<marcan>
povik: so to do this "properly" in linux we need two clock drivers: one for the NCOs and one for the clocksels that go after them