M/C Part 16 ______________________________________________________________ | | | Question 1.... ~Interrupts: what are they and how do you use | | them? EI and DI?~ | |______________________________________________________________| Okay, well there are two ways of getting data from periperals. You can go round in a loop asking each one whether or not it wants you to service it, but this wastes time. The second method is that of interrupting the CPU. There are two little pins on the Z80B's casing that are used for a maskable and a non-maskable interrupt. When one of these lines is tugged the CPU finishes its current instruction and CALLs a servicing routine. The difference between a MI and a NMI is that of priority - you can disable (mask) a MI, but you can't disable the NMI. The NMI routine always starts at #0066. When ROM1 is paged in this supplies the BREAK facility. However, most games and big programs will sit over the ROM, so that you can force the NMI to run a snapshot routine or whatever: Wiz-man tip #1 - If you have your own program sitting over the ROM, you can still use the NMI to get back to BASIC if it locks up, using this routine: ____________________________________________ | | | ORG #0064 | | | | into_rom OUT (lmpr),A | | nmi LD A,31 | | JR into_rom | |____________________________________________| To leave a NMI routine use the command RETN, return from non-maskable interrupt. There are three modes of MI on the Z80B. Life is made easy on the SAM, because we can sit our own routin over the ROM and use mode 1 interrupts which call #0038. On the Speccy you had to use mode 2 for your own uses, which is pretty horrendous, and mode 0 is also pretty much surplus to requirements. DI is the disable interrupts command - it switches MIs off. EI stands for enable interrupts, and switches them on. Because there is only one MI line of the Z80, we need some way of finding out what has generated the interrupt. This is achieved by reading the contents of the status register at port 249. When a bit is driven low, that is the calling device: ______________________________________ | | | D0 Line interrupt | | D1 Comms interrupt | | D2 Midi-in interrupt | | D3 Frame interrupt | | D4 Midi-out interrupt | |______________________________________| The most useful of these are the Line and Frame interrupts. The line interrupt is generated when the TV scan line matches the value in the line register (also at port 249 - write only). Use this to change palettes or screen modes - see last month's menu. Yes, the writing under the logo is in mode 3 with everything else in mode 4. The frame interrupt is similar - it is triggered when the TV scan reaches the bottom of the screen. To end a MI routine you're supposed to use RETI - return from interrupt, but I always use EI, RET which has the same effect. PS. Always remember to leave EVERYTHING exactly as you found it when interrupting. That includes registers and memory ports. ______________________________________________________________ | | | Question 2.... ~Index registers: what is the displacement | | Z80 books talk about? What are their best uses?~ | |______________________________________________________________| A nice, easy one this time. The two index registers IX and IY can be used in nearly all instructions which use HL, in place of the HL part. When using them to address memory like LD A,(HL) you ALWAYS have to add a displacement in the form LD A,(IX+3). Very simply, this makes the CPU look at the address 3 bytes on from the one IX points to. The displacement is always in the range -128 to +127. Best uses? Well, mainly in tables and things. A good example is a directory sector from a disk. After reading it in to, say, #8000, set IX to #8080. If you want to look at the second half of the sector INC IXh (IXh and IXl correspond to higher and lower bytes like HL). To find the file type: LD A,(IX+0-128) which is the same as LD A,(IX-128) as would be seen by the CPU. To avoid confusion: I want the address #8000 which is 0 bytes into the sector and 128 bytes back from IX. If I wanted the sub-directory code, it would be LD A,(IX+254-128) where the code is 254 bytes into the sector. The -128 is to compensate for the fact that IX is 128 bytes into the sector, and it allows the programmer to put in the actual number of bytes, in a more readable form. Remember, IX only works from -128 to +127. _____________________________________________________________ | | | Question 3.... ~The Flags: RET PO?~ | |_____________________________________________________________| Aaargghh! Okay, okay. Here's a list of flags: ______________________________________________________________ | | | Z - Zero. Set if result of arithmetic operation was zero. | | NZ - Not zero, as above. | | C - Carry. Set if arithmetic operation required a borrow. | | NC - No carry, as above. | | M - Negative (!). Indicates bit 7 of accumulator, normally. | | P - Positive, as above. | | PE - Parity Even/ no overflow. | | PO - Parity Odd / overflow. | |______________________________________________________________| Parity is based on the number of 1's in the accumulator. An even number of 1's means even parity. An odd number means odd parity. The parity flag is shared with overflow which indicates a carry from bit 6 to bit 7.