This is for my multiplexed quad 5x7 display. The device will be a SPI slave and allow daisy chaining the display so it will have its MISO connected to the next displays MOSI and so on.
I am currently using these interrupts:
ISR (PORTC_PORT_vect) - this is for the "register select" pin changing. Any change on the RS pin triggers it.
ISR (PORTE_PORT_vect) - this is for the SS pin. It going high triggers it.
ISR (SPI0_INT_vect) - this is for receiving a byte from SPI and setting the SPI0_DATA to the proper value so that it will shift out the correct byte when the next one is received.
ISR (TCB0_INT_vect) - main display multiplexing interrupt, fires at 700 Hz giving a 7 rows by 100 Hz refresh rate.
ISR (TCB1_INT_vect) - used to turn off the row at a specific time to control brightness of that row, controlled by the TCB0_INT_vect
I've read the interrupt section of the 0-series datasheet and it looks like there is a single level 1 interrupt and then the level 0 interrupts can do a round robin thing if preferred, or the level 0 priority can be altered so a specific interrupt has a higher priority than others.
So this seems to give not only a level 1, but also allows you to make a level 0 the highest level 0 which is interesting.
Obviously I want the rows and brightness adhered to so they will have a solid and reliable display, but honestly the SPI is my bigger concern. The reason is that I want to make it be as fast as possible. The thing is that the display will basically have 3 modes - a command mode (RS is HIGH), a text mode (RS is LOW, configured for text mode), and a graphics mode (RS is LOW, configured for graphics mode). What this means is that it has to have a buffer to shift out the correct value for text/graphics. If in text mode and I send 4 bytes via SPI "1234", then if I shift "5678" then "1234" will be shifted to the subsequent display. To do this I am using a ringbuffer and a pointer which works great, but there is a critical time element when receiving a byte (or an RS pin change) that I have to set the SPI0_DATA register to the correct value to shift out next (before the next SPI value comes in!). In command mode this is no big deal as the value that came in is the next one to be shifted out (SPI0_DATA does not have to be set or changed), but in the data/graphics mode, this happens in two places.
The obvious place is the SPI0_INT_vect where it grabs the value first and then sets the next value to be shifted out based on (RS and mode).
Then the interrupt that handles a RS pin change must also set the SPI0_DATA value correctly as well. If you switch from command mode to text/graphics mode, it must set the next SPI value to go out to the proper value from the ring buffer.
Given this, I'm thinking of making the level 1 priority the SPI0_INT_vect AND then setting the LVL0PRI (for level 0) to make the RS interrupt the highest level 0 interrupt.
Obviously there will need to be timing restrictions that say after changing RS, you must wait X uS before proceeding. Probably also a similar time restriction after sending a SPI byte. Again, the goal is reducing these to the bare minimum amounts.
Do you agree with my strategy? Any better ideas?
Also, the LVL0PRI register is a little confusing in the datasheet. When the default value is 0, it points to figure 12-3 which shows 0 to be the HIGHEST priority. Then it says that if you change it to another vector that that vector will be the LOWEST priority, but the next one will be the highest. To me this does NOT make sense because the second one contracts the first one. Any thoughts about that?