Here is the history,
Original idea by Jim Brain http://cbm-hackers.2304266.n4.nabble.com/Switchless-ROMs-td4662130.html Here is my take on it http://cbm-hackers.2304266.n4.nabble.com/Wireless-switchless-kernal-mod-td4665833.html https://www.youtube.com/watch?v=gwpgLJTUj-I The adapter I built principally works by doing some kind of covert channel communication through /KERNAL chip selection line. C64 toggles the line doing a one cycle kernal read access in a certain fashion. This method works in new boards equipped with 64 pin Sharp ICs which serves as PLA and integration of other stuff like color ram. But it doesn't work on old boards. The reason is : Even if you turn off kernal access by turning off interrupts and not calling any kernal routines there is constant /KERNAL chip selections. Here are my findings, 1. In similar scenario /BASIC line is clean. 2. /KERNAL line is clean if KERNAL is switched off using processor port. (Obviously this is not enough for my adapter to work) 3. The duration of these sporadic chip selects are around 41.67 ns and aligns with PHI2 high. (I don't know if it's accurate since I measure this with a 24mhz logic analyzer) 4. Turning off VIC display doesn't help. 5. Signal is dependent on what is displayed on the screen. If screen is empty then it even goes to full 1mhz 0.5us low / 0.5 high with 41us intervals between these accesses. Long Full 1 mhz (Full 1mhz | 41us no access)*25 This directly resembles screen generation of VIC-II chip, 25 gaps corresponds to specific badlines. This final finding gets me thinking I'm possibly measuring it wrong. I'm doing this measurement directly on 906114-01 PLA's pin #16, /KERNAL. What do you think? Regards, Nejat |
It's probably because the PLA combinatorial logic is not registered. If
one path is faster (or the inputs are faster), the output can cycle through some invalid states as the inputs settle. The larger PLA might register the outputs, not sure. I am just trying to think of a way you could overcome this. I am wondering if you can use a specific address of KERNAL ROM as the trigger, like $ffff Jim |
In reply to this post by nejat76
On 08/07/2018 01:37, Nejat Dilek wrote:
> This directly resembles screen generation of VIC-II chip, 25 gaps > corresponds to specific badlines. Things you could try. 1. leaving the screen on and use FLD on the entire screen (change y scroll so it never matches the low 3 bits of the line counter) so there are no bad lines. 2. line crunch, so every scanline is a bad line. 3. multiplexing 8 sprites all the way down the screen (can't remember the name given to that effect). On it's own and with 1 & 2. This might not solve the issue, but it might give you enough control over kernal line to achieve the communication. |
In reply to this post by Jim Brain
Den Sun, 8 Jul 2018 00:48:29 -0500 skrev Jim Brain <[hidden email]>:
> It's probably because the PLA combinatorial logic is not registered. > If one path is faster (or the inputs are faster), the output can > cycle through some invalid states as the inputs settle. Agree. > The larger PLA might register the outputs, not sure. > > I am just trying to think of a way you could overcome this. I am > wondering if you can use a specific address of KERNAL ROM as the > trigger, like $ffff Or require a longer _KERNAL pulse than this false pulse? -- (\_/) Copy the bunny to your mails to help (O.o) him achieve world domination. (> <) Come join the dark side. /_|_\ We have cookies. |
In reply to this post by nejat76
On 07/08/2018 02:37 AM, Nejat Dilek wrote:
> > Here are my findings, > > 1. In similar scenario /BASIC line is clean. > > 2. /KERNAL line is clean if KERNAL is switched off using processor > port. (Obviously this is not enough for my adapter to work) > > 3. The duration of these sporadic chip selects are around 41.67 ns and > aligns with PHI2 high. (I don't know if it's accurate since I measure > this with a 24mhz logic analyzer) > > 4. Turning off VIC display doesn't help. > > 5. Signal is dependent on what is displayed on the screen. If screen > is empty then it even goes to full 1mhz 0.5us low / 0.5 high with 41us > intervals between these accesses. You might want to also take a look at the Char-ROM output of the PLA, that one also shows interesting things. Remember that the original PLA for the C64 was a Signetics 82S100. It is purely combinational with a delay in the range of 50ns , no registers involved. Commodore also used the Fairchild 93459, which is a clone of the 82S100 and the 906114-01 is a mask programmed clone of the 82S100. Gerrit |
In reply to this post by Jim Brain
On Sun, Jul 8, 2018 at 8:48 AM, Jim Brain <[hidden email]> wrote:
> It's probably because the PLA combinatorial logic is not registered. If one > path is faster (or the inputs are faster), the output can cycle through some > invalid states as the inputs settle. > > The larger PLA might register the outputs, not sure. This explains 41ns sporadic selections. I simplified the code and can't see full cycle selections any more. Maybe it was my mistake in either coding or measuring. Sharp PLA on 250469 boards indeed have clean /KERNAL selection line. > > I am just trying to think of a way you could overcome this. I am wondering > if you can use a specific address of KERNAL ROM as the trigger, like $ffff > > Jim Previously I tried choosing specific addresses for triggering but it didn't work. As you've wrote this I gave it a go again and this time I chose a low address line (A4) mainly because my sid socket was empty and had no easy access (my room is a mess) to higher address line. Of course it didn't work :) But then I thought why not choose the triggering address with A4=0 and the code that modulates this (which might just catch a sporadic Kernal selection) running through addresses where A4 =1. That did indeed work :) Overall I disable all roms off, I only enable it briefly* where I modulate the Kernal selection line. It becomes that unwanted selection has A4=1, intended selection has A4=0. By the way, in this code there is proof that accesses to processor port ($0001) just don't drive the address bus with that address. ( *not necessary though as long as code running in addresses where A4=1) May look gibberish on email but here is the code (damn pastie is blocked in my country) Regards, Nejat MODULATION_ADDRESS = $F000 ; A4 is low ;-- Complex Interface Adapter -- CIA_1_BASE = $DC00 CIA_2_BASE = $DD00 ;-- CIA Registers -- CIA_INT_MASK = $0D ;-- Video Interface Controller -- VIC_CONTROL_1 = $D011 VIC_INT_CONTROL = $D01A VIC_INT_ACK = $D019 VIC_BORDER_COLOR = $D020 VIC_SCREEN_COLOR = $D021 ;-- Processor -- PROCESSOR_PORT = $01 PP_CONFIG_ALL_RAM = $34 ; RAM visible in $A000-$BFFF, $E000-$FFFF, $D000-$DFFF PP_CONFIG_RAM_ON_ROM = $35 ; RAM visible in $A000-$BFFF, $E000-$FFFF PP_CONFIG_RAM_ON_BASIC = $36 ; RAM visible in $A000-$BFFF PP_CONFIG_DEFAULT = $37 ; $A000-$BFFF, $E000-$FFFF is ROM, default config. *=$080E SEI CLD JSR TurnOffInterrupts JSR SwitchRamOnRom JSR DisableDisplay LOOP LDX #$FF - DEX BNE - JSR Modulate JMP LOOP TurnOffInterrupts ASL VIC_INT_ACK LDA #$00 STA VIC_INT_CONTROL LDA #$7f ; $7f = %01111111 STA CIA_1_BASE + CIA_INT_MASK ; Turn off CIA 1 interrupts STA CIA_2_BASE + CIA_INT_MASK ; Turn off CIA 2 interrupts LDA CIA_1_BASE + CIA_INT_MASK ; cancel all CIA-IRQs in queue/unprocessed LDA CIA_2_BASE + CIA_INT_MASK ; cancel all CIA-IRQs in queue/unprocessed RTS DisableDisplay LDA VIC_CONTROL_1 AND #$EF STA VIC_CONTROL_1 RTS SwitchRamOnRom LDA #PP_CONFIG_RAM_ON_ROM STA PROCESSOR_PORT RTS *=$0910 ;A4 is high Modulate LDY #PP_CONFIG_RAM_ON_ROM LDA #PP_CONFIG_DEFAULT STA PROCESSOR_PORT LDA MODULATION_ADDRESS STY PROCESSOR_PORT RTS |
In reply to this post by Gerrit Heitsch
On Sun, Jul 8, 2018 at 7:14 PM, Gerrit Heitsch
<[hidden email]> wrote: > On 07/08/2018 02:37 AM, Nejat Dilek wrote: > > > You might want to also take a look at the Char-ROM output of the PLA, that > one also shows interesting things. > > Gerrit > I will. Actually, finding that it follows the VIC's work from PHI low I just noticed that next to /KERNAL line there is /CHAROM. The first thought coming to my mind that they interfered with each other. I tried modulating the kernal changing CHAREN signal previously but it didn't work. Also previously I tested code that employed custom charset, that didn't work either. I'll have a closer look later sampling the shared input of /KERNAL and /CHAROM. On Sun, Jul 8, 2018 at 6:50 PM, Mia Magnusson <[hidden email]> wrote: > > Or require a longer _KERNAL pulse than this false pulse? > How? I use this pulse to interrupt an attiny85. Even if I check for the signal again in the interrupt it's all open to every kind of race conditions since this false signal pops up quite randomly (unless tamed) before and/or after intended access. Side note : I don't want to code this in assembly, I prefer C if I can :) Any other hardware means to filter out 41nsec pulses from 500nsec pulses by the way? (Hmm, maybe using some logic gates with >41nsec propagation delays) Regards, Nejat |
> On 2018-07-09, at 00:59, Nejat Dilek <[hidden email]> wrote: > >> Or require a longer _KERNAL pulse than this false pulse? > > How? I use this pulse to interrupt an attiny85. Even if I check for > the signal again in the interrupt it's all open to every kind of race > conditions since this false signal pops up quite randomly (unless > tamed) before and/or after intended access. As long as the assumption is that valid pulse is always longer than the longest spurious one, you can use the "software debouncing" - similar to what is sometimes used to debounce relatively fast switches, without adding significant capacitance, Schmitt triggers, etc. I used it more than once with good results. > Side note : I don't want > to code this in assembly, I prefer C if I can :) It can be done in C :-) > Any other hardware means to filter out 41nsec pulses from 500nsec > pulses by the way? (Hmm, maybe using some logic gates with >41nsec > propagation delays) I'd say the software method is cheaper and should do as well. -- SD! - http://e4aws.silverdr.com/ |
In reply to this post by nejat76
Den Mon, 9 Jul 2018 01:59:35 +0300 skrev Nejat Dilek <[hidden email]>:
> On Sun, Jul 8, 2018 at 6:50 PM, Mia Magnusson <[hidden email]> wrote: > > > > Or require a longer _KERNAL pulse than this false pulse? > > > > How? I use this pulse to interrupt an attiny85. Even if I check for > the signal again in the interrupt it's all open to every kind of race > conditions since this false signal pops up quite randomly (unless > tamed) before and/or after intended access. Side note : I don't want > to code this in assembly, I prefer C if I can :) If the CPU is fast enough to reliable sample the input not longer than 500nS and not shorter than 41nS after an interrupt has been triggered, a software solution would work. If the input isn't active after 41nS but before 500nS, just ignore the interrupt and be sure to return to a state accepting interrupts fast enough so it can trigger on a real pulse. > Any other hardware means to filter out 41nsec pulses from 500nsec > pulses by the way? (Hmm, maybe using some logic gates with >41nsec > propagation delays) A simple low pass filter will do. 500nS is more than 10 times longer than 41nS so even a simple 6dB/octave RC filter should do the trick. Depending on the signal quality requirements on the interrupt input you might need a schmidt trigger (a 74xx14, 4093 or similar) between the low pass filter and the interrupt input. -- (\_/) Copy the bunny to your mails to help (O.o) him achieve world domination. (> <) Come join the dark side. /_|_\ We have cookies. |
In reply to this post by silverdr@wfmh.org.pl
> On 2018-07-10, at 19:54, [hidden email] wrote: > >>> Or require a longer _KERNAL pulse than this false pulse? >> >> How? I use this pulse to interrupt an attiny85. Even if I check for >> the signal again in the interrupt it's all open to every kind of race >> conditions since this false signal pops up quite randomly (unless >> tamed) before and/or after intended access. > > As long as the assumption is that valid pulse is always longer than the longest spurious one, and - as Mia mentioned - your sampling is fast enough.. -- SD! - http://e4aws.silverdr.com/ |
In reply to this post by silverdr@wfmh.org.pl
On 7/10/2018 12:54 PM, [hidden email] wrote:
> >> On 2018-07-09, at 00:59, Nejat Dilek <[hidden email]> wrote: >> >>> Or require a longer _KERNAL pulse than this false pulse? >> How? I use this pulse to interrupt an attiny85. Even if I check for >> the signal again in the interrupt it's all open to every kind of race >> conditions since this false signal pops up quite randomly (unless >> tamed) before and/or after intended access. > As long as the assumption is that valid pulse is always longer than the longest spurious one, you can use the "software debouncing" - similar to what is sometimes used to debounce relatively fast switches, without adding significant capacitance, Schmitt triggers, etc. I used it more than once with good results. I think it will require moving from an interrupt driven approach on the AVR (used now), to a polling approach: while(PINC & _BV(PIN5)) {} // or whatever if(!(PINC & _BV(PIN5)) { // real signal. } An instruction on the 16MHz AVR takes at least 62.5nS, so the next comparison will push you beyond the 42nS issue. |
> On 2018-07-10, at 20:43, Jim Brain <[hidden email]> wrote: > >>>> Or require a longer _KERNAL pulse than this false pulse? >>> How? I use this pulse to interrupt an attiny85. Even if I check for >>> the signal again in the interrupt it's all open to every kind of race >>> conditions since this false signal pops up quite randomly (unless >>> tamed) before and/or after intended access. >> As long as the assumption is that valid pulse is always longer than the longest spurious one, you can use the "software debouncing" - similar to what is sometimes used to debounce relatively fast switches, without adding significant capacitance, Schmitt triggers, etc. I used it more than once with good results. > I think it will require moving from an interrupt driven approach on the AVR (used now), to a polling approach: Depends on the IRQ latency there but I am afraid in this situation this may be required. > while(PINC & _BV(PIN5)) {} // or whatever > if(!(PINC & _BV(PIN5)) { > // real signal. > } > > An instruction on the 16MHz AVR takes at least 62.5nS, so the next comparison will push you beyond the 42nS issue. Which further simplifies things greatly. What would be the longest for the above? -- SD! - http://e4aws.silverdr.com/ |
On Tue, Jul 10, 2018 at 8:54 PM, <[hidden email]> wrote:
> > >> On 2018-07-09, at 00:59, Nejat Dilek <[hidden email]> wrote: >> >>> Or require a longer _KERNAL pulse than this false pulse? >> >> How? I use this pulse to interrupt an attiny85. Even if I check for >> the signal again in the interrupt it's all open to every kind of race >> conditions since this false signal pops up quite randomly (unless >> tamed) before and/or after intended access. >As long as the assumption is that valid pulse is always longer than the longest spurious one, you can use the "software debouncing" - similar to what is sometimes used to debounce relatively fast switches, without adding significant capacitance, Schmitt triggers, etc. I used it more than once with good results. > In my tests I encountered 500ns pulses too but I can't confirm it before doing another test. >> Side note : I don't want >> to code this in assembly, I prefer C if I can :) > > It can be done in C :-) I have a timer interrupt too which complicates things a bit. On Tue, Jul 10, 2018 at 9:06 PM, Mia Magnusson <[hidden email]> wrote: > Den Mon, 9 Jul 2018 01:59:35 +0300 skrev Nejat Dilek <[hidden email]>: > > If the CPU is fast enough to reliable sample the input not longer than > 500nS and not shorter than 41nS after an interrupt has been triggered, > a software solution would work. If the input isn't active after 41nS > but before 500nS, just ignore the interrupt and be sure to return to a > state accepting interrupts fast enough so it can trigger on a real > pulse. I'm using 16mhz internal clock with Attiny85, sure it's fast but it has a big interrupt latency. I also have another timer interrupt going on. Making the two interrupts behave in this scenario would be a bit problematic. > >> Any other hardware means to filter out 41nsec pulses from 500nsec >> pulses by the way? (Hmm, maybe using some logic gates with >41nsec >> propagation delays) > > A simple low pass filter will do. 500nS is more than 10 times longer > than 41nS so even a simple 6dB/octave RC filter should do the trick. Tested this with 10pf capactior and 1.5K resistor, used an online calculator for 10mhz cutoff frequency. Signal looked clean on the logic analyzer but it didn't work. Is this cutoff frequency reasonable? > > Depending on the signal quality requirements on the interrupt input you > might need a schmidt trigger (a 74xx14, 4093 or similar) between the > low pass filter and the interrupt input. I'll test this too just for the sake of it. If simple RC worked though it would be a better candidate than using a 74hc1g32 2 input or gate. On Tue, Jul 10, 2018 at 9:43 PM, Jim Brain <[hidden email]> wrote: > On 7/10/2018 12:54 PM, [hidden email] wrote: >> >> >> >> As long as the assumption is that valid pulse is always longer than the >> longest spurious one, you can use the "software debouncing" - similar to >> what is sometimes used to debounce relatively fast switches, without adding >> significant capacitance, Schmitt triggers, etc. I used it more than once >> with good results. > > I think it will require moving from an interrupt driven approach on the AVR > (used now), to a polling approach: > > while(PINC & _BV(PIN5)) {} // or whatever > if(!(PINC & _BV(PIN5)) { > // real signal. > } > > An instruction on the 16MHz AVR takes at least 62.5nS, so the next > comparison will push you beyond the 42nS issue. > I also have a timer interrupt. I just can't pile the whole resources of the cpu to deal with this task. I want to port this hardware and of course the firmware to be used along with other machines like Amiga. If I go down the route of writing very strict timing spesific code than it would be harder for me to port and maintain the code. By the way, I still have hope that I could pull this off using c64 software without extra hardware & without changing the attiny85's firmware. It's possibly related to one or more input term of this below equations which I might workaround with a clever routine. !KERNAL = (_HIRAM & A15 & A14 & A13 & !_AEC & R__W & _GAME # _HIRAM & A15 & A14 & A13 & !_AEC & R__W & !_EXROM & !_GAME ); I've not measured yet but I suspect the culprit here is _AEC. If I change the _HIRAM using process port I know both selections doesn't occur. It's not a switching signal. _GAME is pulled up and it's also not a switching signal. The finding with the badlines directly suggests that _AEC would be the culprit. Address lines here possibly not controlled by either VIC or 6510 so they are pulled up. For this problem to occur, VIC should be leaving the bus to the 6510 a little bit late possibly. Some possible routes : a. Try to time a routine around VIC tricks as smf suggested earlier. I don't think this would alone be a solution. This phenomenon occurs when either VIC or 6510 doesn't master the bus. VIC can't see kernal rom so the accesses should be made by the cpu, upon VIC leaving bus to the 6510 this spurious access will occur. When AEC is low CPU can't access the bus, other times it's always toggling (to share the bus between VIC and 6510) causing this phenomenon. b. Do not generate extra kernal read access to assert /KERNAL but just use this unintended 41ns selection. This would be a solution if Attiny85 can sample that 41ns pulse. I don't see any other c64 side software solution by the way if negated AEC signal is indeed the culprit. (This changes the tone of my above hopeful sentence as I've both written and contemplated about it) Regards, Nejat |
In reply to this post by silverdr@wfmh.org.pl
On 7/10/2018 3:19 PM,
[hidden email] wrote:
On 2018-07-10, at 20:43, Jim Brain [hidden email] wrote:Or require a longer _KERNAL pulse than this false pulse?How? I use this pulse to interrupt an attiny85. Even if I check for the signal again in the interrupt it's all open to every kind of race conditions since this false signal pops up quite randomly (unless tamed) before and/or after intended access.As long as the assumption is that valid pulse is always longer than the longest spurious one, you can use the "software debouncing" - similar to what is sometimes used to debounce relatively fast switches, without adding significant capacitance, Schmitt triggers, etc. I used it more than once with good results.I think it will require moving from an interrupt driven approach on the AVR (used now), to a polling approach:Depends on the IRQ latency there but I am afraid in this situation this may be required.while(PINC & _BV(PIN5)) {} // or whatever if(!(PINC & _BV(PIN5)) { // real signal. } An instruction on the 16MHz AVR takes at least 62.5nS, so the next comparison will push you beyond the 42nS issue.Which further simplifies things greatly. What would be the longest for the above? I'd say you'd need to do a test to see. I suspect it's 1 cycle to copy PINC to registerSTART 1 cycle to copy the compare value 1 cycle to do the compare 1 cycle to copy PINCEND
1 cycle to compare
So, 187.5nS
But, if the compiller optimizes and move the
compare value load above the PINC load, it would be 125nS
-- Jim Brain [hidden email] www.jbrain.com |
In reply to this post by nejat76
Den Wed, 11 Jul 2018 01:46:48 +0300 skrev Nejat Dilek
<[hidden email]>: > On Tue, Jul 10, 2018 at 9:06 PM, Mia Magnusson <[hidden email]> wrote: > > Den Mon, 9 Jul 2018 01:59:35 +0300 skrev Nejat Dilek > > <[hidden email]>: > > > > If the CPU is fast enough to reliable sample the input not longer > > than 500nS and not shorter than 41nS after an interrupt has been > > triggered, a software solution would work. If the input isn't > > active after 41nS but before 500nS, just ignore the interrupt and > > be sure to return to a state accepting interrupts fast enough so it > > can trigger on a real pulse. > > I'm using 16mhz internal clock with Attiny85, sure it's fast but it > has a big interrupt latency. > I also have another timer interrupt going on. Making the two > interrupts behave in this scenario would be a bit problematic. Is there any way to disable the timer interrupt and replace it by polling the timer? > >> Any other hardware means to filter out 41nsec pulses from 500nsec > >> pulses by the way? (Hmm, maybe using some logic gates with >41nsec > >> propagation delays) > > > > A simple low pass filter will do. 500nS is more than 10 times longer > > than 41nS so even a simple 6dB/octave RC filter should do the trick. > > Tested this with 10pf capactior and 1.5K resistor, used an online > calculator for 10mhz cutoff frequency. Signal looked clean on the > logic analyzer but it didn't work. > Is this cutoff frequency reasonable? The wanted cutoff frequency depends on what's the lowest signal levels that's treated as a real digital signal by the input the filter drives. You'd have to experiment with a trimmer or calculate fall/rise times for the voltage change required for the signal to be treated as a logic level change. > > Depending on the signal quality requirements on the interrupt input > > you might need a schmidt trigger (a 74xx14, 4093 or similar) > > between the low pass filter and the interrupt input. > > I'll test this too just for the sake of it. If simple RC worked though > it would be a better candidate than using a 74hc1g32 2 input or gate. Look at the data sheet for specifications of the input you're using. Worst case it has a rather large voltage span of unspecified behavior, then you'd need a schmidt trigger for the behavior to be repeatable if you "mass produce" your circuit. You might get away with not using a schmidt trigger if you buy enough IC's and are sure that they are from the same batch, but that's relying on unspecified behavior. If you are lucky, the behavior is well-specified though. -- (\_/) Copy the bunny to your mails to help (O.o) him achieve world domination. (> <) Come join the dark side. /_|_\ We have cookies. |
Free forum by Nabble | Edit this page |