Re: Commodore joystick ports

From: Hársfalvi Levente (
Date: 2004-11-03 17:56:56


Thinking it over, t1 doesn't even have to be touched... it's well 
enough, if -- upon the input capture interrupt -- the needed pulse width 
is added to the value read from ICR, and written to OCR1x . Another 
advantage of this is, that no "calculated" or experimental offsets must 
be added to the value; cpu originate delays simply don't count.

However, I slowly realise that fullfilling both 1.) generating fast 
transitions, ie. low delays caused by the external series resistor, ie. 
low external resistor value and 2.) releasing the output _before_ the 
start of the next SID measurement cycle could be tricky, or better said, 
would need some extra effort =). "Releasing" the outputs, = setting both 
  OC pins to input a few cycles after the second output capture event, 
triggered by one of the OCR interrupts could be possible, ...but at the 
highest pulse widths, the end of this irq service and the start of the 
next measurement cycle's IRQ service would be very close to each other. 
...For the cycle exact timing, it's none of a problem, as the above 
method could handle this still well (a great advantage... =) ). The 
critical part is to deactivate the output, before the end of the SID's 
512th cycle, so the start of the new cycle can be captured.

Another little quirk is the "reset" of the two OC pins to 0, so they can 
be turned to "1" by the output capture event. This could be solved by an 
"extra" OC event in the IC interrupt handler, still when the OC outputs 
are set to inputs. ...So, extending the idea (it either works or not, 
theoretical experiment |-))) ) :

Init: enable t1, input capture event, ic polarity (falling edge), ic 
interrupt, etc... set both output capture pins to input, but write '1' 
to the ports (this way, a weak pull-up will be activated in the chip).

Upon input capture interrupt:
-- Enable "toggle portbit" for both output capture events. Add a few 
cycles offset to the value read from _t1_ and write this to OCR1a. (This 
will bring the oc1a pin to low). After that, calculate the real value of 
the pulse moment from the value calculated by (probably) the main 
routine, and the value read from ICR. Write this to OCR1a. Do the same 
with OC1b. Set both pins to output. Compare the two cycle length values 
(the originals), and enable the OC interrupt of the higher one. Clear OC 
interrupt flags. Finally, subtract a previously stored ICR value from 
the current ICR value, and store it as the last measured full cycle 
length for the main program. Then store the current ICR value in place 
of the previous ICR value.

-- In the OC interrupt routine (this needs that both OC1x interrupt 
vectors point to the same routine) set both output pins to input. The 
actual time it takes to charge up the SID capacitors is a function of 
the series resistor used, and so is the number of cycles (nops) that 
need to be added to the interrupt handler to ensure a 0-->1 transition 
for the SID. On the other hand, the higher the external resistor, the 
less chances to generate the highest values without overrun problems. As 
I think it over, the IRQ itself will also need some cycles to execute. 
If the deactivating was put right after the register saves, it could 
well happen just few (6-10) cycles after the OC1x event, so -- provided 
that the caps charge up in this short time -- 254 is within reach. 255 
would be tricky; would really depend on the charging current and the 
number of cycles it takes in the IRQ to shut down the outputs (a 
trickier interrupt handler could probably help this, but I'm not sure). 
Finally, disable further OC interrupts.

It's still a little dependent on the inhibition of all but the above 
interrupt sources (the IC interrupt isn't anymore, but the OC interrupt 
-- the de-activation of the outputs -- is).

Best regards!,


       Message was sent through the cbm-hackers mailing list

Archive generated by hypermail pre-2.1.8.