Asynchronous events without interrupts?

Go To Last Post
26 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The project I'm currently working on uses an ATmega168, with a main loop that runs at 60 Hz. About 3/4 of a loop iteration is spent refreshing a display. The display output routine is coded in assembler and exact timing is critical for a good picture.

Now I'm adding a PS/2 keyboard interface. I dropped in an interrupt-based keyboard handler I had previously written based on AVR313, and it kinda works. However, if an interrupt is received during the display routine, the picture flickers/scrambles noticeably.

I can't disable interrupts during the display routine because it's so long; almost no keypresses will be received. It doesn't matter how tiny I make the interrupt handler, because a delay of just a few cycles is enough to throw everything off.

So, how should I read signals off a PS/2 keyboard if I can't use interrupts? Currently my idea is to use a second AVR as a buffer; it would receive scancodes asynchronously and stores them in a queue, and the main AVR could pull them out when it's done updating the display. I don't think I can interleave keyboard polls into the display routine, since the my scanline frequency could be lower than the keyboard's clock frequency and I'd likely miss bits.

Anyone have a suggestion that doesn't require another AVR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do a part of the display at a time, and look for keyboard activity between?

I'm assuming

Quote:

About 3/4 of a loop iteration is spent refreshing a display.

that there are some wait time in there? E.g., end-of-line. (I could be mistaken; we don't have much info.) If so, those would be at quite regular intervals and you could poll the interface?

I'd have to refresh (pun intended) myself on PS/2 protocol. No-one is going to type faster than 60Hz. But it is a multi-byte sequence IIRC.

The clock is fairly fast, right? 30-100kHz. Pretty fast for polling; I don't know what you line scan time is.

Hmmm--can the USART in synchronous mode be used?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A scanline is drawn in 64 microseconds (15.625 kHz). From what I've read, PS/2 clock frequency can be anywhere from 10 to 20 kHz. There is some idle time after drawing a line that I could use to poll the keyboard. It *may* work. I'll have to use a logic analyzer to measure the clock frequency of my keyboard.

I plan on using the USART for something else, so I can't really use it for the keyboard.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Given your timing constraints, I vote for the 2nd AVR. You might be able to fit it in an 8-pin device, or certainly a 14-pin. Make your main AVR an SPI master and then you can fetch the data whenever you want.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did some testing, and it looks like I'm going to have to go with a second AVR. While there's enough time between scanlines to poll the keyboard, the probability that a bit will be missed is quite high. Maybe I'll just disassemble a keyboard and scan the switch matrix manually :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think scanning the matrix yourself will be more of a headache then a second AVR interfacing with a standard PS/2 connection ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd stay with one AVR. You have parity bit to see if there's an error. PS/2 protocol has a Resend command. In case of an error you can exercise it until you get the right code.

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Re "using the USART for something else".

1) Wherever are you going to find the time?
2) Mega168 => Mega164 will be less expensive, and much less complex, than adding a second AVR.

3) And if you are at this high level with chip brand/model selection, does the Xmega's streaming DMA help your video?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you do to the screen? Is it a GLCD? Have you thought about doing your screen commands to RAM and then updating the entire screen at once from RAM to LCD? That way the time that you disable interrupts will be lower and the screen update will look great every time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I could be woron but it sounds like you are doing software refresh for the LCD ?

If the display have to run with 60 Hz do it in a interrupt, I do know that long interrupts normaly is bad but here it will work.
Then Do the rest in the 'main' program as often you can.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That seems like an incredibly silly thing to do... refresh an entire LCD in an interrupt? Have you not heard of flags? Foll it in the main would be the best thing to do.

Do you need to refresh the entire LCD? i heard you say things like draw line etc. Seriously have a think about keeping the screen data in ram and modifying that and outputting the final data to the LCD.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the AVR directly drives an LCD or TV screen without a dedicated controller with framebuffer, so then timing is fairly critical.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
If the display have to run with 60 Hz do it in a interrupt, I do know that long interrupts normaly is bad but here it will work.
Then Do the rest in the 'main' program as often you can.

I agree.
You must do the sreen refresh inside the timer interrupt and all other tasks inside the main.

There ist an Atmel application note to achieve cycle accurate timing inside the timer interrupt.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
That seems like an incredibly silly thing to do... refresh an entire LCD in an interrupt? Have you not heard of flags? Foll it in the main would be the best thing to do.

To disable interrupt in big parts of your main program using is even more ugly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It wouldn't need to be a big part of the main, and no, i dont see how that could/would be worse. Enlighten me

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Neddly - swings and roundabouts. Having the interrupt run the task in the background might makes things a little esier for the rest of the app in this instance. Whilst having a long ISR is generally frowned upon, sometimes its the way to go. Desparate measures for desparate problems!

As for the problem itself, you might need to poll the uart in the refresh interrupt - as long as you do it faster than the data is coming in there'll be no problem - at least you control when it happens. Net result is you still need to process the data but you can spread the processing out so you don't impact the display refresh negatively.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd flip the whole design around.

I would use the dedicated micro for the LCD controller, and use the Main micro for the project to read the keyboard, do the USART serial I/O, and send the data to the dedicated LCD Driver micro. Your LCD micro reads in and buffers the data it needs for the display. The other, (Main), micro handles all of the rest of the project.

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Probably should have made this clearer from the start; I'm not using an LCD, I'm drawing a raster scan on an oscilloscope. The microcontroller is generating horizontal and vertical sync pulses, as well as an intensity output.

In order to get a perfect display, the MCU has to output a pixel exactly every 5 cycles. There is some time left over at the end of a scanline; the beam needs a couple microseconds to return to the left side of the screen. However, servicing an interrupt in the middle of a display cycle throws off the timing for a frame, causing a visible glitch.

Trying to poll the PS/2 lines at 10+ kHz just seems silly, especially since this would have to be done not only during the display routine, but after the display finishes and the MCU is updating the program logic. This would require something like polling the keyboard during the display routine, turning on a pin-change interrupt after it finishes, then disabling interrupts before drawing the next frame. I tried something like this and it dropped bits left and right.

It seems much more straightforward to use an ATtiny as a keypress buffer that can be read synchronously. The 'tiny is connected to the keyboard lines and stores scancodes in a queue. Every 1/60 of a second, the main MCU pulls scancodes (or ASCII values) out of the queue until it's empty. I could program a bunch of these and save them for future projects.

A second USART might also be a viable single-chip option. I have some 644's on order, so I'll investigate that as well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds right to me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Say, interrupt happens on line sync. Poll PS2 lines, run the line. After the visible screen area ends, keep polling PS2, instead of display routine handle the input and do other tasks. As long as your PS2-poller takes fixed time, you're fine. Crazy, but it appears that your project is born of a need for challenge, so it fits :)

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

autorelease wrote:
In order to get a perfect display, the MCU has to output a pixel exactly every 5 cycles. There is some time left over at the end of a scanline; the beam needs a couple microseconds to return to the left side of the screen. However, servicing an interrupt in the middle of a display cycle throws off the timing for a frame, causing a visible glitch.
How much flash do you have left:
ld Rx,
1 cycle PS/2 instruction
sbic Rx,7
out PINy, Rmask

3 cycles of PS/2 instructions
sbic Rx,6
out PINy, Rmask

six more groups of three a lot like the last

ld Rx,
...

Note that ld, sbic, and out do not affect SREG.

Edit: corrected tipo
Edit: added Rmask to correct logic

Iluvatar is the better part of Valar.

Last Edited: Tue. Dec 15, 2009 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I looked at AVR313 and that quikly generate the question have any one made a PS2 receiver that use the SPI port ? and then at the end of each line poll the receive flag.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But the framing is USART framing.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can the (U)S(A)RT part do it ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And if you use SPI you will just miss Parity and Stop
So the only problem would be that the receiver has to be flushed for every char.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the suggestions. I wound up using an ATtiny45 as a keyboard buffer and ASCII decoder, and everything works just fine. The master communicates with it over SPI, popping characters out of the ATtiny's buffer until none are left, at which point the ATtiny sends a null byte. The ATtiny handles Shift and Ctrl keys as well as extended scancodes (like the function and arrow keys). The code fits easily into 2K of ROM.

This should also make it much easier to interface with a PS/2 keyboard in future projects. I can post the source if it would be of use to anyone.