Turns out I made a mistake and never ordered the first round of boards. It's an irrelevant oops, since I would have just had to scrap them on arrival.
This morning I ordered new boards with the super-swift service from OSHPark. I thought about going with the 2 oz copper instead, but since the high current traces on this board are so broad and short, I can go without the heavier copper and I want my boards stat. I haven't bothered uploading new pictures yet, because almost all the changes are with traces and aren't particularly visible on board level images.
There is one change of note, and that's that I went to a three pin programming header. The ATTiny816 is designed to be programmed through the reset line alone, not through the SPI port like previous generations of AVRs. This lets me switch to an 0.1" pitch programming header, which means less futzing with wires and more just plugging the thing into my programmer.
I also ordered an ATTin817 Xplained Mini and a couple of encoders for delivery Friday, because I am not having a great time figuring out how to make the encoder logic work the way I want it to.
A quadrature encoder has four state transitions per pulse. That means that you can, in principle, quadruple the resolution of a given encoder by taking measurements at each transition -- a 48 pulse per revolution encoder now counts 192 times per revolution with just a bit of software. However, this is a bit more difficult in practice.
The most straightforward way to approach this is to connect each phase of the encoder to a separate interrupt pin, set them to transition on rising and falling edges, and use a timer to measure the times of transition. This is fine as far as it goes, but is subject to jitter if there are any other interrupts in the system, such as a main loop timing interrupt, and depending on how interrupts are scheduled, may result in some steps being dropped entirely. That jitter doesn't matter much if you are controlling only position with no velocity control or differential terms in the control loop. However, we will be controlling velocity, and the noise in the velocity measurement caused by jitter is to be avoided. So we're going to take a somewhat harder road.
There are two subsystems/peripherals that make it possible to do something better with the '816. The Timer/Counter B has a frequency measurement mode that copies out the counter value and fires an interrupt on the rising edge of a single input. That would not be enough by itself without some off-chip glue logic, but the '816 has something called Configurable Custom Logic (CCL) on the chip.
The CCL has two configurable three input lookup tables (LUTs). They can be configured to any of the 256 possible three input logic truth tables. Two of the inputs of each LUT can come from input pins -- if you remember from the last update, phases A & B of the encoder are wired to the inputs of LUT0. Each LUT has an optional filter and an optional rising edge detector. The outputs of the two LUTs may optionally be connected to a sequential logic element -- either a JK flipflop, a D flipflop, a D latch, or an RS latch. Finally, the output of the sequential logic element can be fed back to either LUT, and each LUT can also take the output of the other LUT as an input.
I'm reasonably certain that somewhere in all this is a way to create what I really need, which is an internal signal that provides a rising edge on each transition of the two input pins. Tonight I will draw it out and post further.