--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To view this discussion, visit https://groups.google.com/d/msgid/rc2014-z80/32600f80-ea0c-49c9-be5d-908e65599eebn%40googlegroups.com.
More and more, I feel the urge to have a 50Hz timer tick source in my setup. To play tunes in timer instead of delay mode. For multitasking when I get around to trying Fuzix. And to avoid Nyan Cat being 20% more hectic than intended (I hacked the source to advance the PT3 based on the 60Hz from the TMS).The common and most old-school approach seems to be to use a CTC? But then I’ve also read someone (I think that was Steven Cox?) mention that the CTC is incovenient in IM1 since there is no way of knowing whether it actually fired an interrupt.A viable solution there would be to use another CTC channel to count the timer interrups, and then check whether that count has changed?
You must use interrupts mode 2 (IM2) in order to use CTC as you intended to do...Ladislau
Alan, would you mind expanding a bit on how to configure the CTC counters? With a 7.3728MHz system clock, you can use a :256 prescaler so you clock the first register at 28800Hz. The first register could be configured to divide by another :64, giving 450Hz. Then the second register can reset after 9 ticks and send an interrupt, giving 50Hz. But if you want to actually count those interrupts in hardware, you would need a 3rd counter right? Or am I missing something?
Wow, many interesting thoughts here! I love this forum.Since the topic has been brought up, here’s one nice way of getting the zero crossings off the mains signal, using an optoisolator instead of a clamp or a transformer, etc: Isolated High Quality Mains Voltage Zero Crossing Detector. I’ve used it successfully in an Arduino-based AC dimmer circuit.
I’ve understood that the difficulty around a CTC and IM2 is that with IM1 the CTC has no way of telling you that it was the one raising the interrupt. Meaning that if you are going to use the CTC with IM1, then you had better have some counter that you can read to see what happened.
Alan, would you mind expanding a bit on how to configure the CTC counters? With a 7.3728MHz system clock, you can use a :256 prescaler so you clock the first register at 28800Hz. The first register could be configured to divide by another :64, giving 450Hz. Then the second register can reset after 9 ticks and send an interrupt, giving 50Hz. But if you want to actually count those interrupts in hardware, you would need a 3rd counter right? Or am I missing something?
Sergey, I think you clock your CTC with 1/8 of the RC2014 clock in the first place? But you still only produce periodic interrupts that might get masked?
I’m thinking that dividing the system clock by 1024, maybe using a 4040 or 4060 would give a very attractive 7200Hz that could be divided down to things like 30, 50, 60, 100Hz with only one 8 bit counter.
The mode 2 daisy chain can be implemented on backplanes designed with that in mind. Alternatively, each module can have IEO and IEI available on header pins on the back edge of the module for linking with Dupont wires. My SIO, CTC and PIO modules offer both options. On suitable backplanes they are nice and neat, but on standard backplanes there are messy wires between modules.Steve
I’m still thinking about this. One bit I haven’t managed to understand from the data sheet is how long an interrupt signalAre there some bus signals a device should catch after which it should release the interrupt? I think some parts (e.g. the TMS9918 if I understood it correctly) will pull the interrupt line low and keep it there until the CPU clears a flag in the device.
- must be
- should be
- can be asserted
Is that correct? Is it the proper and expected behaviour of interrupt raising hardware?
- The CPU can read the 8 bit counter using an IO read. Whenever it does, the "interrupt raised" flip-flop is asynchronously reset.
Reading the 8 bit counter would allow checking if an interrupt was due to a timer tick (if it changed since the last interrupt), and would also ensure that no tick is missed even if interrupts are disabled for up to 5 seconds.
If the counter isn’t needed, one could devise a variant where the "interrupt raised" flip-flop is put on the bus on an IO read, and at the same time cleared. I think that might require an extra latch between the flip-flop and the bus.
Be carefull with that asynchronous reset, if you reset the counter when /RD is low you will always read the counter is zero. If you reset the counter when /RD is high it will never count. You want to reset only on the rising edge of /RD.
- The CPU can read the 8 bit counter using an IO read. Whenever it does, the "interrupt raised" flip-flop is asynchronously reset.
That gets fun for timing as you need to reset it on the M1 cycle after to be totally safe and sure the CPU read it.A lot of home micros cheated and simply wired the \INT line to the vertical blank itself and coded the handlers to do things like the keyboard scan so that \INT had already gone high when the handler finished.
Reading the 8 bit counter would allow checking if an interrupt was due to a timer tick (if it changed since the last interrupt), and would also ensure that no tick is missed even if interrupts are disabled for up to 5 seconds.Except for the freaky corner case where you read the counter, it ticks up one and the next cycle resets it 8) It's an absolute pain to do this race free.
If the counter isn’t needed, one could devise a variant where the "interrupt raised" flip-flop is put on the bus on an IO read, and at the same time cleared. I think that might require an extra latch between the flip-flop and the bus.Without a counter it's just a 74HCT74 and some decode - you kick it one way on an IRQ and the other way when the event decode happens.
Again you've then got the tiny race if you take exactly 1/50th of a second.
Even the TMS9918 is actually racey unless you are careful - a status read at the wrong moment can lose the interrupt signal entirely for a frame.
I’m confused here. Do you mean if I were to read the counter outside of the interrupt handler? Then yes, I suppose that might reset the "interrupt raised" flip flop before the interrupt is seen by the CPU. So to be on the safe side, reading the counter and resetting the interrupt should be two separate IO writes.
Again you've then got the tiny race if you take exactly 1/50th of a second.You mean 20ms in the interrupt handler? I think at that point the code has more serious problems :-D
Even the TMS9918 is actually racey unless you are careful - a status read at the wrong moment can lose the interrupt signal entirely for a frame.So basically, if you’re relying on interrupts, then you should read the status only from the interrupt handler, right?
If you are resetting it then you have a bunch of cases that are nasty includingStart ReadCPU starts reading 0x1FInterrupt arrivesCounter goes to 0x20Counter is reset, count is lost
If you are not resetting it then life is a *lot* easier.
Again you've then got the tiny race if you take exactly 1/50th of a second.You mean 20ms in the interrupt handler? I think at that point the code has more serious problems :-DWait until you try and drive a floppy disk, then ask the question again. If you have a counter you are pretty much admitting that this will be an issue.
Even the TMS9918 is actually racey unless you are careful - a status read at the wrong moment can lose the interrupt signal entirely for a frame.So basically, if you’re relying on interrupts, then you should read the status only from the interrupt handler, right?Yes but if you've got multiple interrupt sources there are tiny tiny windows where it is unfixable I believe because you can actually lose the TMS9918A interrupt probing it in a different interrupt.