6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 5:15 pm

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Aug 05, 2006 7:08 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
In an application for a CBM8032 interfacing with "hand-shake" through the "User Port" I have had difficulties with bit 1 of the IFR (register $D) . This bit is controlled by the CA1 pin (raising or falling edge).

According to the data sheet (if I understand it correctly) this bit is reset by either a read or a write to the ORA/IRA (register $1) or by writing a value into the IFR register with bit 7 unset and bit 1 set, typically the value $02. There should be no other way!

Still this bit sometimes shifts from 1 to 0 with my code neither accessing register $1 nor writing to register $D! This happens only intermittently and (appearently) only when register $1 is in output mode.

I guess it is clear that the CBM system code activated by the regular interrupts does not mess around with the 6522 connected to the User Port! But this 6522 is shared between the system and the user! Pins PA0 -PA7, CA1 and CB2 are connected to the User Port while the system uses Port B and CA2 for something else!

Any ideas what this shifting could be caused by? That the bit gets set when it should not can be explained by inductive "cross-talk" (edge-sensitive triggering) but that the bit gets unset????


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Aug 05, 2006 11:50 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Do you use indexed or indirect indexed addressing? Some address modes do a dummy read at the unindexed address before the actual read at the correct address. This could be inadvertently clearing the interrupt flag for you.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Aug 06, 2006 2:55 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
With a "debug setup" I found that the CBM sometimes get stuck in the following wait-loop:

Code:
     PHA            ;VALUE FOR THE OUTPUT REGISTER
     LDA #$02       ;MASK FOR THE CA1 BIT
PB1  AND IFR        ;INTERRUPT FLAG REGISTER
     BEQ PB1        ;BRANCH IF RECIEVER NOT READY FOR DATA
     PLA
     STA IORA       ;WRITING TO THE OUTPUT REGISTER CLEARS THE INTERRUPT BIT IN IFR


From my "error tracing" I can see that there indeed is a CA1 event setting the CA1 bit with my code in the "final" loop above. This event triggers an IRQ as the Interrupt Enable Bit is set. The IRQ code is triggered AFTER the "final" loop has been entered! The IRQ code does a few things including the disabeling of the CA1 interrupt (writing $02 to the the Interrupt Enabeling Register) but it does NOT reset the Interrupt Flag Register. The interrupt code is indeed left with the value $42 in the Interrupt Flag Register! (The value of the Interrupt Flag Register is written to a "debug area" just before leaving the IRQ code)

But back in the wait loop (above) the bit has been reset "by itself", otherwise the processor would have got out of the loop!

After having cleared the IFR bit with

Code:
     STA IORA       ;WRITING TO THE OUTPUT REGISTER CLEARS THE INTERRUPT BIT IN IFR

The CA1 interrupt would have been re-enabled by writing $82 to the Interrupt Enabeling Register. But as the loop never is left this does not happen and the several following CA1 events cannot trigger the IRQ code anymore!

Sometimes it all works fine and I can transfer the data! But in about 1/4 of the of the cases the CBM gets stuck in the loop above.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Aug 06, 2006 8:06 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
The other possibility is that bit 1 in A is being cleared somehow. If you enter the loop with A = $02 and the first match fails surely A now = $00 so you will be stuck in the loop forever.

Either change the AND to BIT or move PB1 back one instruction to the LDA #$02.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 8:22 am 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Thanks for the tip! You are obviously right! It has to be "BIT" and not "AND"! That explains it all! Most of the times the reciever is faster then the CBM and the branch is never taken. But sometimes (in 25% of the cases for some byte!) the branch is taken and the loop gets infinit! This is exactly the case I described above! The CBM is already in the wait loop and the mask has been destroyed when finally the CA1 event comes!

I'll test it tonight with AND => BIT but for sure it will work! (every time)

Well done and thanks again!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 8:27 am 
Offline

Joined: Wed Mar 24, 2004 10:54 am
Posts: 38
Doing "classic" 6522 hardware handshaking on CBM/PET machines is a bit of a nightmare as you have this mismatch of control lines. Namely PA0-7, CA1 and CB2 as the "user port". PB0-7, CA2 and CB1 are used for a variaty of system functions including the 2nd cassette interface, upper/lower case character generator selection, odd bits of the IEEE488 interface (IIRC). Things get even worse if you try doing it using interrupts as some of these system functions involve 6522 register manipulation during the regular 60Hz system IRQ (like upper/lower case selection on the 8032 via CA2) which is a major pain in the ass.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 9:28 am 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Yes, this is precisely the problem! Normally one would use CA1 and CA2 in (automatic) handshake mode with a CA1 event immediately and automatically setting CA2 high ("not ready"). To achieve this using CB2 instead of CA2 one has to set CB2 high with software instructions. And as this has to be done "quasi immediately" an IRQ has to be generated to trigger this "software CB2 raise". When this has been done the CBM then returns to the normal code and the read/write to/from the port can take place when the CBM has got that far. After the read/write the CB2 is then set low with software instructions signaling that the CBM is ready for the next request.

But as "quasi immediately" is not immediately a certain small delay before re-polling the C2 line has to be applied. Otherwise it could be that C2 is low because the IRQ code has not yet done its job, not because the CBM is ready. With "automatic handshake" this is not a concern!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 11:10 am 
Offline

Joined: Wed Mar 24, 2004 10:54 am
Posts: 38
This big problem trying to use IRQs on the "user port" on CBM/PETs is the fact that the system's 60Hz IRQ tramples over so much and twiddles bits in just about all the I/O chips (both 6520s and the 6522 doing clock updates, keyboard scanning and buffer processing, tape drive switch sensing/motor control, IEEE488 processing). This makes it very tricky setting up an interrupt that works without the system software setting or clearing some flag that you're using when you don't want it to or aren't expecting it to.

The most usual solutions in the past have been: add your own 6522, completely kill off the system interupts (not possible on most CBM/PETs since it's triggered from the monitors VRtrace signal), or do it all with software polling. Beyond that you'll need to do a lot of digging inside the system's IRQ routine to see just what it leaves alone and thus safe to use - which is not a lot. :(


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 12:12 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
This is how I do it:

The following CBM adresses are needed:

Code:
IORA   = $E841     ; INPUT OUTPUT REGISTER A
DDRA   = $E843     ; DATA DIRECTION REGISTER A
PCR    = $E84C     ; PERIPHERAL CONTROL REGISTER
IFR    = $E84D     ; INTERRUPT FLAG REGISTER
IER    = $E84E     ; INTERRUPT ENABLE REGISTER
IRQV   = $90       ; IRQ VECTOR IN RAM
BACK   = $E455     ; CBM IRQ CODE


The following subroutines to handle CB2 without touching the bits belonging to the system:

Code:
;SUBROUTINE TO SET CB2 HIGH
;BITS 7, 6 and 5 SET TO 1 AND BIT 0 TO 0
SCB2H LDA PCR     
      AND #$1E
      ORA #$E0
      STA PCR
      RTS
;SUBROUTINE TO SET CB2 LOW
;BITS 7 and 6 SET TO 1 AND BITS 5 AND 0 TO 0
SCB2L LDA PCR     
      AND #$1E
      ORA #$C0
      STA PCR
      RTS


Setting the CBM IRQ vector to point to my code:

Code:
      SEI
;
;  SET IRQ RAM VECTOR TO POINT TO "LL" INSTEAD OF TO "BACK"
;
       LDA #<LL
       STA IRQV
       LDA #>LL
       STA IRQV+1
      CLI


This is my IRQ code to set CB2 high. Note that the CA1 Interrupt Enable must be reset, otherwise the IRQ will stay high and one gets an infinite loop immediately returning to "LL" after after "RTI". Then one has to jump to the CBM code where other possible causes for the IRQ are handled!

Code:
LL    LDA #$80
      BIT IFR
      BEQ LL1       ;IF BIT 7 IS NOT SET THE INTERRUPT IS NOT FROM THE VIA
      LDA #$02
      BIT IFR
      BEQ LL1       ;IF BIT 1 IS NOT SET THE INTERRUPT IS NOT FROM CA1
      STA IER       ;DISABLE CA1 INTERRUPTS (IFR FLAG REMAINS SET)
;SET CB2 HIGH, MEANING: "REQUEST NOT YET FULFILLED".
      JSR SCB2H
LL1   JMP BACK


At the start the CA1 flag should be reset ant interrupt enabled:

Code:
      LDA #$02     ;RESET CA1 FLAG
      STA IFR
      LDA #$82     ;ENABLE CA1 INTERRUPTS
      STA IER
 

The following routine reads and writes bytes from the User Port:

Code:
;
;SUBROUTINE TO GET A BYTE FROM THE PC
;
;WHEN THE PC WRITTEN A BYTE A STROBE IS ISSUED
;
GB   LDA #$02
GB1  BIT IFR        ;READ IFR POLLING FOR DATA (NEG. EDGE "CA2")
     BEQ GB1
     LDA IORA       ;READING CLEARS BIT 1 OF IFR
     PHA
     LDA #$82       ;RE-ENABLE INTERRUPTS
     STA IER
     JSR SCB2L      ;SIGNAL TO PC THAT DATA HAS BEEN TAKEN
     PLA
     RTS
;
;SUBROUTINE TO SEND A BYTE TO THE PC
;
;WHEN THE PC WANTS A BYTE A STROBE IS ISSUED
;
PB   PHA
     LDA #$02
PB1  BIT IFR
     BEQ PB1        ;READY FOR DATA?
     PLA
     STA IORA       ;WRITING CLEARS THE INTERRUPT BIT IN IFR
     LDA #$82       ;RE-ENABLE INTERRUPTS
     STA IER
;SET CB2 LOW, MEANING "DATA NOW AVAILABLE".
     JSR SCB2L
     RTS


In this way one can co-exist with the CBM system!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 1:56 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
One feature of BIT is that it copies b7 and b6 of the target byte to the N and V flag bits. This can be used to test more than one bit with the BIT instruction.

Code:
LL    LDA #$02      ; mask for CA1 interrupt
      BIT IFR
      BPL LL1       ; IF BIT 7 IS NOT SET THE INTERRUPT IS NOT FROM THE VIA

      BEQ LL1       ; IF BIT 1 IS NOT SET THE INTERRUPT IS NOT FROM CA1

      STA IER       ; DISABLE CA1 INTERRUPTS (IFR FLAG REMAINS SET)
;SET CB2 HIGH, MEANING: "REQUEST NOT YET FULFILLED".
      JSR SCB2H
LL1   JMP BACK

This does the same tests on the interrupt bits but with two fewer instructions.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 2:06 pm 
Offline

Joined: Wed Mar 24, 2004 10:54 am
Posts: 38
Hi Mats,

That's great if you're finding the CBM system software isn't stamping on your code as you've written it.

A few things to watch (if you've not came across them already), and definitely to be avoided in the middle of a data transfer are :

- cassette I/O, this alters the IRQ vector and will seriously stamp all over the VIA registers, especially if you use cassette #2.
- switching between lowercase/uppercase and uppcase/grahpics character sets as this will alter the PCR and it may not be done in a subtle way.
- IEEE488 I/O, this will cause some VIA activity but without research I can't off hand say how much as most of the work is done via the PIAs but a couple of lines on the VIA are still used.

Many of the potential problems the above can cause are due to CBM system software not being written co-exist with other software. It assumes it has 100% control of the hardware and can do as it likes when it likes. Things like changing I/O register bits without masking off bits it's not concerned with are subtleties it often lacks.

Enjoy!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Aug 07, 2006 2:58 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Some additional code comments:

The routines PB and GB first reset the CA1 flag and then set CB2 low. It is therefore OK (no harm is done) if the IRQ code calls subroutine "SCB2H" setting CB2 high every time it finds the CA1 bit being set.

This could be done with the code

Code:
LL    LDA IFR
      AND #$02
      BEQ LL1       ;ONLY IF BIT 1 IS SET SHOULD CB2 BE SET HIGH
      STA IER       ;DISABLE CA1 INTERRUPTS (IFR FLAG REMAINS SET)
;SET CB2 HIGH, MEANING: "REQUEST NOT YET FULFILLED".
      JSR SCB2H
LL1   JMP BACK


But if there are many "CBM interrupts" not related to the CA1 some processing time is lost with "unnecessary" SCB2H calls when CB2 has already has been set high but the data not yet been read/written and bit 1 of IFR still is set. One could then save some processing time with

Code:
LL    LDA IFR
      BPL LL1       ;IF BIT 7 IS NOT SET THE INTERRUPT IS NOT FROM THE VIA
      AND #$02
      BEQ LL1       ;ONLY IF BIT 1 IS SET SHOULD CB2 BE SET HIGH
      STA IER       ;DISABLE CA1 INTERRUPTS (IFR FLAG REMAINS SET)
;SET CB2 HIGH, MEANING: "REQUEST NOT YET FULFILLED".
      JSR SCB2H
LL1   JMP BACK


If CB2 already has been set high (and the IER flag been reset) and it is another IFR flag of the VIA that is causing bit 7 of IFR to be set "SCB2H" could still be called unnecessaril.y. But to test for this is certainly not worthwhile (in terms of code efficiency)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Aug 08, 2006 9:27 am 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Some remarks concerning what "ghaytack" writes:

I think CBM has designed a nice system under the environmental condition that hardware is expensive and rare and its usage has to be optimised to the extreme! I am sure they had good reason to "cross-over" ports A and B of the VIA with PA7-PA0, CA1 and CB2 connected to the User Port and the other pins used by the system. CA2 and CB2 have some differences! The Shift Register, for example, can drive CB2 and it might have been thought that this function should be available to the user over the User Port. Possibly the system needs PB7 for a square wave driven by the timer? And PB7-PB07, CB1 and CB2 would in any case not have been a full-worthy replacement for PA7-PA0, CA1 and CA2 as automatic handshaking only applies to WRITE for port B. And to use two VIA, one for the User Port and one for the system, would have been to wasteful in hardware!

The "greediness" in hardware goes so far that even programming constructions like

Code:
L BIT  $1DA9
....
  JMP L+1


which then will be

Code:
   LDA $1D

are used to save some bytes in ROM!

CBM has RAM vectors for IRQ and BRK to allow user IRQ just like in my code. And if the CBM values for these vectors are dynamic there is also no problem. One should then read and store these values before overwriting the vectors and then restore them at the end. And that the system interferes with the "user part" of the VIA I do not believe! Specify this interference more precisely and I will investigate this myself!

What is nasty is that the whole RAM is overwritten/erased at RESET! The only safe "heaven" is the area for cassette buffers, $0300 - $03ED, for which (fortunately) CBM does not consider that a memory check necessary! If a memory check really is needed it could easily have been designed such that the original contents is kept. For the reset of BASIC it should be enough to reset pointers!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 8:46 am 
Offline

Joined: Wed Mar 24, 2004 10:54 am
Posts: 38
Hi Mats,

When looking at the internals of the PET/CBM one should always remember that you are effectively looking at software written 26+ years ago when systems were much more closed and proprietry than now. Plus, as you rightly mention, hardware cost an awful lot more (32K of RAM cost an arm and a foot, having came down in price from an arm and a full leg the previous year, but still less than half what CBM charged you for it). Some design decisions taken back then were as much about keeping costs down and profits up and closing out 3rd party hardware/software as it was about making efficient use of the hardware (sometimes well, sometimes anything but).

"And that the system interferes with the "user part" of the VIA I do not believe! Specify this interference more precisely and I will investigate this myself! " well, obtain a copy of the the books I mentioned in a previous post, plus "PET and the IEEE Interface" (can't remember if that's the exact title, I'd have to take a look at my copy tonight) and knock yourself out having fun discovering the nasties that lurk within old Commodore hardware/software. The chapters on programming relative disk files on Commodore drives in Raeto West's book makes for particularly mind blowing and perverse reading.

All the comments I've made in my posts have been to try and help you be aware that PET/CBM machines are a far from friendly environment to develop all but the simplest of 6502 assembly code, especially if you try and do anything beyond the most basic stuff with the built in I/O chips without ripping out all of the Commodore ROMS and replacing them with your own. They are based on my experiences from having used my first PET back in 1978 (an original 8K old ROM machine with built in cassette deck and "chicklet" keyboard, TIM loaded from tape which is how my experience of the S and L commands in TIM is different from the documentation says) and virtually every model since then upto and including the VIC-20 (what an abortion that was).

There's a lot you can make these machines do, but it can be very frustrating getting them to do it, especially if you're not aware of how the system software works (or doesn't in quite a number of cases).

George


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Aug 11, 2006 10:45 am 
Offline

Joined: Wed Mar 24, 2004 10:54 am
Posts: 38
Hi Mats,

I dug out my copies of Raeto West's "Programming the PET/CBM" and "PET and the IEEE-488 Interface" and re-read the relevant sections to give you more definitive information about what system activities use the 6522 and to what extent. Hopefully I should be able to get this info posted this evening sometime.

I'l also try and track down my disk image for SuperMon to load into my copy of VICE (the dog's wotsits of PET/CBM emulators as it even fully emulates the 6520 and 6522!). I can then do some research on how subtly the system software changes I/O registers and things like IRQ vectors on the 8032. However based on my experience on previous models subtlety is not something Commodore system software is too familiar with. For example, tape I/O changes the IRQ vector several times during operation. When finished it "restores" the IRQ vector contents by writing values it looks up in a ROM table.

George


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 52 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: