| |
Conrad
Registered: Nov 2006 Posts: 849 |
Disk Drive Interrupts
Hello there.
May I ask if it's possible to get your own interrupt routines running on the disk drive using the VIA timer registers?
Since the drive also has an IRQ vector at $fffe/ffff, I've been trying to get my own IRQ routine to run using timer 1, but unfortunately no luck.
Here's the drive source of the IRQ routine I'm using:
DC_IRQ
pha
txa
pha
tya
pha
bit $180D ; interrupt from timer 1? (bit 6)
bvc DC_IRQ_ ; no, skip.
lda $1c00 ; Flash LED to make sure irq runs.
eor #$08
sta $1c00
DC_IRQ_
pla
tay
pla
tax
pla
rti
(This code is similar to the one stored in disk ROM)
I also have FFFF/FFFE vector set at this code location (DC_IRQ).
The problem is I'm not sure which VIA registers to set to enable timer 1 IRQ. I tried setting $180d, $180e and other IRQ related registers (also executing SEI before hand and CLI afterwards) but still nothing.
Could someone please help me which registers to set properly ?
I'm only doing this for tests BTW, just to see if it's possible to do. I'm testing it on 1541-I/II drives.
Cheers if you can help!
Owen. |
|
... 4 posts hidden. Click here to view all posts.... |
| |
tlr
Registered: Sep 2003 Posts: 1790 |
You can get a routine (buffer that is) called on interrupt (IRQ) by placing the $d0 job code (jump) on the required buffer. Higher buffer number has higher priority.
Look here:
http://unusedino.de/ec64/technical/aay/c1541/ro41fe67.htm
http://unusedino.de/ec64/technical/aay/c1541/ro41f2b0.htm
http://unusedino.de/ec64/technical/aay/c1541/ro41f36e.htm
|
| |
Conrad
Registered: Nov 2006 Posts: 849 |
Okay, after a few tests it seems I've got an IRQ to work along side an outside routine. It works on the 1541 I and II at least, because it seems to fail on all other drives, but obviously that's expected since the other drives has different specifications.
After reading closely at the ROM code tlr posted, I've coded up a routine in buffer 4 ($0700) that is executed with jobcode #$d0 - buffer 4 because like tlr said, it's the highest priority. The jobcode is executed through the IRQ interrupt by the ROM routine at $FE67 as normal - however, the routine in $0700 also resets $1c0c so that it runs over and over again, just like IRQs on the c64.
Here's the test code set up in $0500 - the code OUTSIDE the irq and by which is executed via M-E command:
!pseudopc $0500 {
DriveCode_START
sei ;Set interrupt flag
lda #$04 ;Set buffer number to #$04 (buffer 4)
sta $3f ;
lda #$d0 ;Set jobcode $d0 (jump)
sta $04 ;$04 = Jobcode for buffer 4
lda #$00 ;Set irq timer rates...
sta $1c04 ;
lda #$80 ;These can be altered at any rate
sta $1c05 ;except $1c05 must NOT be #$00
lda #$01 ;Set up a random counter to use
sta $1b ;for test.
cli ;Clear int. flag
;Outside-irq code here...
;Turn on rotate motor to allow head movement
lda $1c00
ora #$04
sta $1c00
DC_MoveHead ;Loop location
lda $1b ;See if counter is negative
bpl *-2 ;Loop back if not.
and #$7f ;Set it back to positive
sta $1b ;
;Move head outwards...
lda $1c00
and #$fd ;Probably not the most
;ora #$00 ;efficient way, but it
ora #$02 ;works ;)
sta $1c00
;inc $1c00
;inc $1c00
dec $1c00
dec $1c00
jmp DC_MoveHead ;Jump back to loop
}
Next is the code executed in buffer 4 ($0700) which us called via job code #$d0 in disk ROM code:
!pseudopc $0700 {
lda $1c00 ;Flash LED
eor #$08 ;
sta $1c00 ;
inc $1b ;Increase the counter.
;Value in counter will eventually
;be a negative number, checked
;by the outside IRQ code.
lda $1c0c ;erase bit 1 in $1c0c
and #$fd ;CA2 = %??0
sta $1c0c
ldx $49 ;Restore the stack pointer
txs ;executed from the disk ROM
;($49 was used to store pointer)
rts ;Return from job code
DriveCode_END
}
NOTE: Somewhere in drive ROM IRQ, zeropage $49 was used to store the current stack pointer, so I had to restore it so that IRQ wouldn't mess up (relating to the code in $FE67)
So basically, the following test code does this:
- In the IRQ routine ($0700-), the LED flashes on and off and increases a temporary counter. It then returns from interrupt.
- In the outside routine ($0500-), it checks if the temp counter has reached a negative ($80-$ff) and loops back if not. If negative number, then the drive head is moved by one track and the temp counter is set back to positive (so that the code does not move head forever.)
I hope that wasn't too winded for you lot, but because of your helpful advice I've managed to get it working, so thank you very much for that! :)
BTW, since I'm quite a novice in drive coding I'm not too sure how critical this code can be towards disk-loading routines, but still... it seems to work after a few tests. |
| |
Krill
Registered: Apr 2002 Posts: 2980 |
What will this lead to, if i may ask? :)
And yes, you must not interrupt disk access by interrupts, or you'll face weird behaviour and lots of retries. |
| |
tlr
Registered: Sep 2003 Posts: 1790 |
Krill is correct, you can not have interrupt during disk accesses because disk accesses are time critical code.
However setting the hook up correctly will let you have an interrupt running that automatically gets stalled by a disk access or IEC interrupt.
Just let the $d0 hookroutine do what you need to do, and then make sure it returns to the rest of the interrupt routine after it's done. You can use any buffer because you want the real jobs to be executed anyway.
FDC mode (where the jobs are executed) is just code that runs in the timer interrupt context IIRC, so interrupts are automatically disabled during disk accesses.
IEC interrupts have priority because they are checked first in the interrupt handler.
If you want to have a different timer speed, you probably want to make sure the job code checking gets called at the normal interval by means of a counter.
This could be used for installing a led PWM running in the background of normal operations, or even some naughty code resident in the drive up to drive reset... |
| |
Krill
Registered: Apr 2002 Posts: 2980 |
Okay, but what are you actually coding there? :) |
| |
Graham Account closed
Registered: Dec 2002 Posts: 990 |
Why don't you just use jobcode #$E0 for moving the head? It's easy and safe to use on every drive mechanic. |
| |
Conrad
Registered: Nov 2006 Posts: 849 |
@Krill: Don't worry, I've only been doing these somehow useless routines just to (down to it all) learn how disk drives work.... after a couple days of stress it seems that you were right all along :D
Luckily I've purchased 1540/1541 and 1571 disk-drive in-depth technical service manuals, so I should be able to try out some better methods soon. |
| |
chancer
Registered: Apr 2003 Posts: 347 |
conrad I just was reading thru an old book.. noticed it mentioned a 1540, they recon it was made for the vic 20. the book say the screen must be turned off during the loading, by changing $d011.
with poke 53265,11
and when the things finished loading poke 53265,27
maybe thats of some use to you, maybe total rubbish, but I can't test that.
|
| |
Danzig
Registered: Jun 2002 Posts: 440 |
??? the Off-Topic-Detection-Bell is ringing...
conrad is testing around with DRIVE coding, not with switching the SCREEN on/off :D
|
| |
chancer
Registered: Apr 2003 Posts: 347 |
Quote: ??? the Off-Topic-Detection-Bell is ringing...
conrad is testing around with DRIVE coding, not with switching the SCREEN on/off :D
what is it with certain (not all) alphaflight members? hhmm u went x95, probably explains your attitude.
unless you have a vic 1540 drive,and know 100% about that, then how can you comment, go buy one prove me wrong ;-)
so yer i do think its relivant, or at least trying to be helpful even if its found to be in-correct (unlike your comment), since it's a drive actually designed for the vic 20, that maybe someone might use (chances are small, but who knows)
go and look in a book "com. 64 omnibus - a comprehensive programming handbook" by peter lupton / frazer robinson, page 400 of that.
|
Previous - 1 | 2 - Next |