1,186 karma · joined September 26, 2016
I know I could hit cancel, but I am often bad at doing that on time, which leads me to avoid trying out things that require payment details up-front.
Thanks for sharing!
Use nops (or other placeholders to insert "counter increment" fills) on instrumented runs, e.g. in test, that way you don't have to modify the "production" code to measure test coverage.
However in C++, you might be able to mimic the API more clearly, as templating is able to do integer things that Rust can't yet easily today.
I did my error calculations by brute forcing the whole 16-bit range, basically:
for i in (i16::MIN..=i16::MAX) {
let a = (i as f32).sin() as i16;
let b = lut_sin(i);
let diff = abs_diff(a, b);
}
Which found the largest difference to be 4, and I got 0.012% from (4/32768).Since the LUT was constant, doing it quickly on my PC made sense, but for a more dynamic approach, that would make sense too.
Additionally my error max was already enough, where adding 4x the LUT precision would be diminishing returns for my application.
So, in this case (on a tiny microcontroller, not precision equipment), my main optimization factor was speed over everything else. I don't think this is a universal answer, and as other commenters have mentioned, there are other ways to approach this problem!
As to a couple of common questions:
* Why didn't I just use a 1/4 sine LUT? - Because the full sine lut was only 512 bytes, and I had that to spare, which saves me some math per-cycle. I would also hit diminishing returns on a more precise LUT.
* Why didn't I use (some other method)? This one was "good enough", only took 22 CPU cycles per iteration, and linear interpolation was only 5 or so of those 22. Alternatively: I am bad at complex math! But I have worked with fixed point algos before, so I wrote what I knew.
Happy to answer any other questions!I see this article being an address to these criticisms (which are not limited to this forum, I've seen similar arguments on twitter, etc.).
Pointing out shortcomings isn't really impolite or unfair. The author specifically mentioned shortcomings of Rust as well.
Asked work to change it, they did, no more reaction.
Edit: the chemical was "Methylisothiazolinone"
It was a super good read.
I might rebind my i3 keys to match these bindings somehow.
I definitely want to give credit to Andrea Lattuada [1] from the Systems group at ETH Zurich, who I worked with to design the algorithm behind bbqueue, as well as Simon Cooke [2], the original author of the bip-buffer algorithm we based bbqueue on (with some thread-safe changes).
Happy to answer any questions (though my knowledge of Ada/Spark is limited), especially on the algorithm or the Rust implementation. I use it super often for embedded systems, and it also allows for ridiculous performance even on PC/Desktop/Server systems.
[1]: https://twitter.com/utaal [2]: https://twitter.com/FleetingShadow
Let me know if you have any questions!
> since I can't reply to the child I'll just say this: I don't like the math you used, I feel like it's making a point that shouldn't be made in a place where it doesn't need to be made. Of course it's going to be dog slow if you're busy waiting. Wtf? I guess I will just leave it at that.
The entire post is about reducing the CPU time necessary to receive data from an external interface, like a serial port. The following paragraph states:
> Instead of making our CPU waste all of this time waiting around, we allow the hardware to manage the simple sending and receiving process, allowing our CPU to either process other important tasks, or go into sleep mode, saving power or battery life.
The intent for this example was to illustrate the difference between busy waiting and DMA. It is not uncommon on microcontrollers to only have a FIFO depth of one byte, which means if you aren't using interrupts, DMA, or threading, you will lose that data.
In this case, your CPU would be left spinning for an equivalent amount of time to the line rate of the serial port, if you were busy waiting for data.
Feel free to reply here (preferred), or send me an email at james.munns [at] ferrous-systems.com.
I'm currently working on a similar technique (though with smaller blocks, currently ranging 64-1024 bytes - basically any 5 power-of-twos) for a lock-free allocator intended for real time embedded systems. I use a 32-bit word for each 1024 byte "page", and have a tree structure inside of the word (it takes 31 bits to cover 5 power-of-two ranges).
My code (which only allocs and never frees at the moment) is here:
https://github.com/jamesmunns/bbqueue
It uses atomics (and Rust's borrow checker) heavily to safely guarantee lock free behavior, and works pretty darn quick.
Most BLE or WiFi enabled microcontrollers have a binary blob for driving connectivity, or deeply C based code that can be a challenge to integrate idiomatically in Rust.
I am to focus on this in a couple different ways, largely based on either a pub/sub style format for smaller periodic messages, or on a mailbox style format for larger messages (display frames, etc).
I'm still pretty early in the brainstorming process, and this is intended as a hobby/teaching project, but I'd love to have things be useful for everyone using it, and having compatibility APIs are a big way of achieving that.