Weiß nicht ob das Teil jemand hier kennt. (siehe Anhang)
Die Platine mit einer recht dubiosen Bezeichnung gab es von cbm8bit 2010 zu kaufen.
Damit konnte man mittels den F-Tasten eine KERNAL-Umschaltung ansteuern.
Ich hab mal den ASM Code hochgeladen dazu. Kann vielleicht jemand der sich da auskennt nachschauen ob damit mehr als zwei Ausgänge angesteuert werden können. Mehr als 4 Schaltzustände.
Der Code ist zwar gut dokumentiert und soweit ich rauslese werden die F-Tasten 1,3,5,7 abgefragt, aber der ATMEL ist auf der Platine mit PC1, PC2, PC3 auf die Stiftleiste beschalten. PC3 bringt jedoch nur ein Dauer-LO
Mit SHIFT-F... ändert das auch nichts. Also entweder wurde das nicht integriert oder man muß eine andere Tastenkombi benutzen.
Also man drückt zuerst eine Sekunde die RESTORE Taste und kann dann mittels den F-Tasten den KERNAL wechseln.
- ;********************************************************************************************
- ;*
- ;* Project ~ C64 Auto Kernal selector with Reset Output --- MEGA8 VERSION ---
- ;*
- ;* Monitors the C64 Keyboard for certain key presses during start up.
- ;* If within the first 2 seconds of running either F1, F3, F5 or F7 are pressed this
- ;* device will cause the C64 to Reset and configure the EPROM outputs to enable different
- ;* Kernal's to become active on a 27256 EPROM upon coming out of Reset.
- ;* It will also store the Kernal setting (in EEPROM) for the next powerup so the C64 will
- ;* always start up with the last Kernal selected.
- ;* After a 2 second timer has expired this device will ignore the F1-F7 keys and monitor the
- ;* Restore Key. If the restore key is held down for 2 seconds then the reset output will be turned on.
- ;* Initially I wanted to monitor something like 'CTRL C= Run/Stop' , but this won't work when many games
- ;* are running because the keyboard scanning is halted, or at a different rate to the normal kernal.
- ;*
- ;* With the C64 Kernal in control, the keyboard IRQ fires every 16.66ms (16,666uS) for 40uS.
- ;* Each key column poll is low for 150uS, stepping through PA0-PA7 sequentially for a max of 1200uS (or about that).
- ;*
- ;* Uses an ATMEL AVR Mega8 with the internal 8MHz (4MHz sytem) clock/2 enabled.
- ;*
- ;* You are free to use any part of this code for your own projects, but please give credit where it is due.
- ;* Please note though, this is offered up to assist your learning, I'm not a teacher, so please don't ask for a programming tutorial.
- ;*
- ;* Revision History:
- ;* Rev# Date Who Comments
- ;* ----- ----------- ----------- --------------------------------------------
- ;* 2.10 06-Nov-2010 Ross Myers Re-written to suit the final 'Zzyzx' v2.1 PCB design
- ;* ----- ----------- ----------- --------------------------------------------
- ;*
- ;* ATmega8 memory use summary [bytes]:
- ;* Segment Begin End Code Data Used Size Use%
- ;* ---------------------------------------------------------------
- ;* [.cseg] 0x000000 0x0001d2 466 0 466 8192 5.7%
- ;* [.dseg] 0x000060 0x000060 0 0 0 1024 0.0%
- ;* [.eseg] 0x000000 0x000000 0 0 0 512 0.0%
- ;
- ;******************************************************
- .include "m8def.inc"
- .equ C64Reset1 = 0 ; PortC, Bit0, Reset C64 Output
- .equ EPROMSel1 = 1 ; PortC, Bit1, EPROM Select Output 1
- .equ EPROMSel2 = 2 ; PortC, Bit2, EPROM Select Output 2
- .equ EPROMSel3 = 3 ; PortC, Bit3, EPROM Select Output 3
- .equ OptionIn = 4 ; PortC, Bit4, Option Input (not currently used)
- .equ RestoreKey = 5 ; PortC, Bit5, Restore key monitor
- ;--------------------------------------
- ; Reset and Interrupt Vectors for ATMega8
- ;
- rjmp Reset ; Reset Handler
- reti ; External Interrupt Request 0
- reti ; External Interrupt Request 1
- reti ; Timer/Counter2 Compare Match
- reti ; Timer/Counter2 Overflow
- reti ; Timer/Counter1 Capture Event
- reti ; Timer/Counter1 Compare Match A
- reti ; Timer/Counter1 Compare Match B
- reti ; Timer/Counter1 Overflow
- reti ; Timer/Counter0 Overflow
- reti ; Serial Transfer Complete
- reti ; USART, Rx Complete
- reti ; USART Data Register Empty
- reti ; USART, Tx Complete
- reti ; ADC Conversion Complete
- reti ; EEPROM Ready
- reti ; Analog Comparator
- reti ; 2-wire Serial Interface
- reti ; Store Program Memory Ready
- ;******************************************************
- ; Main entry point after Reset
- ;
- Reset:
- cli ; Disable Interrupts, we aren't using any
- ldi r16,LOW(RAMEND) ; Init Stack Pointer
- ldi r17,HIGH(RAMEND)
- out SPL,r16
- out SPH,r17
- ; Turn off WDT
- in r16,MCUSR ; Clear the Watchdog System Reset Flag (WDRF)
- andi r16,0b1111_0111
- in r17,0 ; Clear the WDE control bit
- out MCUSR,r16
- sts WDTCSR,r17
- ;--------------------------------------
- ; Init Port C (Inputs/Outputs)
- ; Port C, bit 0 = Output - C64Reset1 (Reset C64 Output)
- ; " , bit 1 = Output - EPROMSel1 (EPROM Select Output 1)
- ; " , bit 2 = Output - EPROMSel2 (EPROM Select Output 2)
- ; " , bit 3 = Output - EPROMSel3 (EPROM Select Output 3)
- ; " , bit 4 = Input - OptionIn (Option Input, not currently used)
- ; " , bit 5 = Input - RestoreKey (Restore key monitor)
- ; " , bit 6 = Not Used, this is the AVR's reset pin
- ; " , bit 7 = Not on the Mega8
- ;
- ldi r16,0b0111_0000 ; C64 Reset active until AVR is ready, EPROM Selects Low, Inputs pulled up
- ldi r17,0b0000_1111 ; Load immediate to configure port in/out settings, 0 = Input, 1 = Output
- out PORTC,r16 ; Control the input / output states
- out DDRC,r17 ; Configure Port C
- ;--------------------------------------
- ; Init both Port B & D as high impedance inputs, these two ports monitor the C64's keyboard / CIA
- ;
- ldi r16,$FF
- ldi r17,$00
- out PORTB,r16 ; Port B, Pullup
- out PORTD,r16 ; Port D, Pullup
- out DDRB,r17 ; Port B all Inputs
- out DDRD,r17 ; Port D all Inputs
- ;--------------------------------------
- ; Default Kernal selection to 1 if Restore key is held down at power up
- ;--------------------------------------
- in r24,PINC ; Get AVR PortC states
- andi r24,0b0010_0000 ; Check for the 'Restore' key pressed, 0 = Pressed, 1 = Not pressed
- brne SetKernalInit ; If 'Restore' key not pressed then don't default kernal select to 1, Else...
- ldi r16,$10 ; Simulate F1 key was pressed
- clr r4
- rjmp FxKeyPressed ; Default EEPROM Value back to Bank 1
- ;--------------------------------------
- ; Get Kernal selection from EEPROM and output to Port
- ;--------------------------------------
- SetKernalInit:
- rcall SwitchKernal ; Switch Kernal Outputs
- ;--------------------------------------
- ; Setup Counters in General Purpose registers
- ;--------------------------------------
- SkipKernalSel:
- clr r0 ; Clear 8bit C64 IRQ counter, used to ignore F1-F7 keys (max 4.25 seconds after C64 is running)
- clr r1 ; Clear Ignore Function keys flag
- clr r2 ; Clear Counter used to time 'Restore' key pressed for reset
- ;--------------------------------------
- ; Release C64 Reset Output
- ;--------------------------------------
- sbi PORTC,C64Reset1 ; Turn off C64 Reset Output #1
- cbi DDRC,C64Reset1 ; Set as Input so any external reset doesn't drive against the AVR pin
- ;--------------------------------------
- ; Main loop, just loop around here until the C64 keyboard IRQ fires (pin change happens)
- ;--------------------------------------
- Loop:
- in r24,PINC ; Get AVR PortC states
- andi r24,0b0010_0000 ; Check for the 'Restore' key pressed, 0 = Pressed, 1 = Not pressed
- breq CheckResetTime ; If 'Restore' key pressed then check for how long, Else...
- in r24,PIND ; Get PortD (Key Col) states
- andi r24,1 ; Just checking bit 0 on the C64's CIA will be fine
- breq KeyCheckTime ; If the pin has gone low then the keyboard IRQ has triggered so check for key press, Else...
- rjmp Loop ; Do nothing until C64 starts the keyboard scan again
- CheckResetTime:
- rjmp DetermineReset ; Check if restore key is being held long enough to force a reset, will return to 'Loop' if not
- ; held long enough to force a reset or will do an AVR warm reset if the C64 gets reset
- KeyCheckTime:
- rcall PinChanged ; Check if key was pressed during the scan about to start
- rjmp Loop ; Return and wait for next scan
- ;******************************************************
- ; Switch Kernal (EPROM banks)
- ; Stored EEPROM Values are as follows:
- ; $000 = Bank 1, with Aux out off
- ; $001 = Bank 2, with Aux out off
- ; $010 = Bank 3, with Aux out off
- ; $011 = Bank 4, with Aux out off
- ; $100 = Bank 1, with Aux out on
- ; $101 = Bank 2, with Aux out on
- ; $110 = Bank 3, with Aux out on
- ; $111 = Bank 4, with Aux out on
- ;
- SwitchKernal:
- ldi r16,0
- ldi r17,64 ; Point to byte 64 in EEPROM (desired Kernal select byte location)
- out EEARH,r16
- out EEARL,r17 ; Load the EEPROM Address Register
- sbi EECR,EERE ; Enable EEPROM Read
- EEReadWait:
- sbic EECR,EERE ; Wait until Data has been read from EEPROM
- rjmp EEReadWait ; " " "
- in r20,EEDR ; Move desired Kernal select byte into r20
- andi r20,0b0000_0111 ; Isolate just the EPROM select bits
- tst r20 ; Check for Bank 1, Aux Off selection (0b000)
- breq EPROMSel00
- cpi r20,$01 ; Check for Bank 2, Aux Off selection (0b001)
- breq EPROMSel01
- cpi r20,$02 ; Check for Bank 3, Aux Off selection (0b010)
- breq EPROMSel02
- cpi r20,$03 ; Check for Bank 4, Aux Off selection (0b011)
- breq EPROMSel03
- cpi r20,$04 ; Check for Bank 1, Aux On selection (0b100)
- breq EPROMSel04
- cpi r20,$05 ; Check for Bank 2, Aux On selection (0b101)
- breq EPROMSel05
- cpi r20,$06 ; Check for Bank 3, Aux On selection (0b101)
- breq EPROMSel06
- rjmp EPROMSel07 ; Assume Bank 4, Aux On selection (0b111)
- EPROMSel00:
- cbi PORTC,EPROMSel1 ; EPROM Bank select 1
- cbi PORTC,EPROMSel2 ;
- cbi PORTC,EPROMSel3 ; Aux Off
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel01:
- sbi PORTC,EPROMSel1 ; EPROM Bank select 2
- cbi PORTC,EPROMSel2 ;
- cbi PORTC,EPROMSel3 ; Aux Off
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel02:
- cbi PORTC,EPROMSel1 ; EPROM Bank select 3
- sbi PORTC,EPROMSel2 ;
- cbi PORTC,EPROMSel3 ; Aux Off
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel03:
- sbi PORTC,EPROMSel1 ; EPROM Bank select 4
- sbi PORTC,EPROMSel2 ;
- cbi PORTC,EPROMSel3 ; Aux Off
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel04:
- cbi PORTC,EPROMSel1 ; EPROM Bank select 1
- cbi PORTC,EPROMSel2 ;
- sbi PORTC,EPROMSel3 ; Aux On
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel05:
- sbi PORTC,EPROMSel1 ; EPROM Bank select 2
- cbi PORTC,EPROMSel2 ;
- sbi PORTC,EPROMSel3 ; Aux On
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel06:
- cbi PORTC,EPROMSel1 ; EPROM Bank select 3
- sbi PORTC,EPROMSel2 ;
- sbi PORTC,EPROMSel3 ; Aux On
- rjmp EPROMSelExit ; Exit with desired bank selected
- EPROMSel07:
- sbi PORTC,EPROMSel1 ; EPROM Bank select 4
- sbi PORTC,EPROMSel2 ;
- sbi PORTC,EPROMSel3 ; Aux On
- EPROMSelExit:
- ret ; Return from Subroutine
- ;******************************************************
- ; Control C64 Reset
- ;
- ResetC64:
- sbi DDRC,C64Reset1 ; Set as Output
- cbi PORTC,C64Reset1 ; Turn on C64 Reset Output #1 (hold low)
- ldi r23,200 ; Hold Reset low for 2mS
- rcall DelayXuS ; Do delay
- ret ; Return from Subroutine
- ;******************************************************
- ; 10uS Delay routine @ 4MHz Clock (well, close enough to 10uS)
- ; Enter with r23 loaded with the number of 10uS delays to do (10 - 2,550 uS total), 10uS = 0.000010 Seconds
- ;
- DelayXuS:
- ldi r22,$0C
- DelayXusLoop:
- dec r22
- brne DelayXusLoop
- dec r23
- brne DelayXuS
- ret
- ;******************************************************
- ; Pin Change process
- ;
- PinChanged:
- ldi r21,8 ; Number of loops to perform the entire column scan
- ldi YH,$01 ; Point Y at $0100 (SRAM)
- ldi YL,$00 ; " " "
- inc r0 ; Add 1 to C64 IRQ Counter per 16.66mS
- mov r22,r0 ; Store back to counter
- cpi r22,120 ; Check if C64 has been running for 2 seconds (120 = 2sec / 16.66mS)
- brlo GetKeyValues ; If not, then still look for Function Key presses to select Kernal, Else...
- ldi r22,$AA ; Flag ignore Functions keys
- mov r1,r22 ; Store in r1 for use elsewhere in the program
- ; Read the AVR Port B which is monitoring the C64 key presses and store values in SRAM,
- GetKeyValues:
- ldi r23,15 ; Delay for 150uS
- rcall DelayXuS ; This delay will put us in the first column scan to see if a key is pressed
- in r24,PINB ; Get AVR PortB states (Key Row - Port B on C64 CIA)
- com r24 ; Invert value so we get 1,2,3 etc, not $FF,$FE......
- st Y+,r24 ; Save Port B state to RAM, Increment to next RAM address
- dec r21 ; Decrement number of check loops
- brne GetKeyValues ; If all port bits not checked then branch back, else...
- rcall DetermineKey ; Captured all keyscans, now check which keys were pressed
- ret ; Go back to Main Loop and wait for next C64 keyboard IRQ
- ;--------------------------------------
- ; Figure out which key was pressed, need to do some key debounce too
- ;--------------------------------------
- ;
- DetermineKey:
- tst r1 ; Get C64 Max IRQ Counter value
- brne DetermineKeyExit ; Ignore function keys now if set, Else...
- ; Get shift key values before the Fx keys
- ;--------------------------------------
- PortABit1:
- ldi YH,$01 ; Point Y at $0101 (SRAM)
- ldi YL,$01 ; " " "
- ld r16,Y ; Get value from RAM address ($0101) to check for 3,W,A,4,Z,S,E, or LSh keys pressed
- andi r16,0b1000_0000 ; Isolate Left Shift / Shift Lock Key (not monitored on v2.0 PCB)
- lsr r16
- lsr r16
- lsr r16
- lsr r16
- lsr r16 ; Shift bit to add to ROM select directly
- mov r4,r16 ; Save result to r4
- ;--------------------------------------
- PortABit0:
- ldi YH,$01 ; Point Y at $0100 (SRAM)
- ldi YL,$00 ; " " "
- ld r16,Y ; Get value from RAM address ($0100) to check for Ins,Ret,LR-Cur,F7,F1,F3,F5 or UD-Cur keys pressed
- andi r16,0b0111_1000 ; Isolate just the 'F' keys
- tst r16 ; Was any key pressed?
- brne FxKeyPressed ; Branch if yes, Else...
- rjmp DetermineKeyExit ; Don't bother checking any other keys
- ;--------------------------------------
- PortABit2:
- ldi YH,$01 ; Point Y at $0102 (SRAM)
- ldi YL,$02 ; " " "
- ld r16,Y ; Get value from RAM address ($0102) to check for 5,R,D,6,C,F,T or X keys pressed
- ;--------------------------------------
- PortABit3:
- ldi YH,$01 ; Point Y at $0103 (SRAM)
- ldi YL,$03 ; " " "
- ld r16,Y ; Get value from RAM address ($0103) to check for 7,Y,G,8,B,H,U or V keys pressed
- ;--------------------------------------
- PortABit4:
- ldi YH,$01 ; Point Y at $0104 (SRAM)
- ldi YL,$04 ; " " "
- ld r16,Y ; Get value from RAM address ($0104) to check for 9,I,J,O,M,K,O or N keys pressed
- ;--------------------------------------
- PortABit5:
- ldi YH,$01 ; Point Y at $0105 (SRAM)
- ldi YL,$05 ; " " "
- ld r16,Y ; Get value from RAM address ($0105) to check for +,P,L,-,.,:,@ or , keys pressed
- ;--------------------------------------
- PortABit6:
- ldi YH,$01 ; Point Y at $0106 (SRAM)
- ldi YL,$06 ; " " "
- ld r16,Y ; Get value from RAM address ($0106) to check for Pound,*,;,Clr,RSh,=,up or / keys pressed
- ; ldi YH,$01 ; Point Y at $0106 (SRAM)
- ; ldi YL,$06 ; " " "
- ; ld r16,Y ; Get value from RAM address ($0106) to check for Pound,*,;,Clr,RSh,=,up or / keys pressed
- ; andi r16,0b0001_0000 ; Isolate Right Shift Key
- ; lsr r16
- ; lsr r16 ; Shift bit to add to ROM select directly
- ; mov r5,r16 ; Save result to r5
- ;--------------------------------------
- PortABit7:
- ldi YH,$01 ; Point Y at $0107 (SRAM)
- ldi YL,$07 ; " " "
- ld r16,Y ; Get value from RAM address ($0107) to check for 1,Left,Ctrl,2,Spc,C=,Q or Run keys pressed
- DetermineKeyExit:
- ret
- ;******************************************************
- ; Function Key has been pressed, so process which one and reset.
- ;
- FxKeyPressed:
- cpi r16,$08 ; Check if F7 was pressed
- breq KeyRow1Bit3 ;
- cpi r16,$10 ; Check if F1 was pressed
- breq KeyRow1Bit4 ;
- cpi r16,$20 ; Check if F3 was pressed
- breq KeyRow1Bit5 ;
- ; If none of these, must be F5 pressed
- KeyRow1Bit6:
- ldi r20,02 ; Select Bank 3 ;
- rjmp PortABit0Exit
- KeyRow1Bit3:
- ldi r20,03 ; Select Bank 4
- rjmp PortABit0Exit
- KeyRow1Bit4:
- ldi r20,00 ; Select Bank 1
- rjmp PortABit0Exit
- KeyRow1Bit5:
- ldi r20,01 ; Select Bank 2
- PortABit0Exit:
- add r20,r4 ; Add in shift keys state bit which controls EPROMSel3 output
- cli ; Ensure we disable Interrupts (again!) during this operation
- EEWrite:
- sbic EECR,EEWE ; Wait until EEWE is ready
- rjmp EEWrite ; " " "
- ldi r16,0
- ldi r17,64 ; Point to byte 64 in EEPROM (desired Kernal select byte location)
- out EEARH,r16
- out EEARL,r17 ; Load the EEPROM Address Register
- out EEDR,r20 ; Put data in to EEPROM Data Reg
- sbi EECR,EEMWE ; Write new byte to EEPROM
- sbi EECR,EEWE ; Start eeprom write by setting EEWE
- EEWait:
- sbic EECR,EEWE ; Wait for write to complete
- rjmp EEWait
- rcall ResetC64 ; Reset C64 with new EPROM bank selected upon next startup
- rjmp SetKernalInit ; Go back to the very start
- ;******************************************************
- ; Here the C64's 'Restore' key is monitored, if the key is held down for 2 seconds at any time the C64 is reset.
- ;
- DetermineReset:
- inc r2 ; Add 1, per 100mS
- mov r22,r2 ; Get C64 Reset Counter value
- cpi r22,80 ; Check if 'Restore' key has been held for approx 2 seconds
- breq ResetTime ; Branch if yes, Else...
- rcall DelayXmS ; Do a 100mS delay to determine if 'Restore' key is still pressed
- in r24,PINC ; Get AVR PortC states
- andi r24,0b0010_0000 ; Check for the 'Restore' key pressed, 0 = Pressed, 1 = Not pressed
- brne NoReset ; If 'Restore' key still not pressed then no reset needed, Else...
- rjmp DetermineReset ; Go back and keep checking the 'Restore' key state
- NoReset:
- clr r2 ; Clear Counter used to time 'Restore' key pressed for reset
- rjmp Loop ; No reset needed, go back to key press monitoring
- ResetTime:
- rcall ResetC64 ; Reset C64
- rjmp SetKernalInit ; Go back to the start
- ;******************************************************
- ; 100mS Delay routine @ 4MHz Clock (well, close enough to 100mS)
- ;
- DelayXmS:
- ldi r17,$A5
- XmSLoop0:
- ldi r18,$C9
- XmSLoop1:
- dec r18
- brne XmSLoop1
- dec r17
- brne XmSLoop0
- ret
- ;* You are free to use any part of this code for your own projects, but please give credit where it is due.
- ;* Please note though, this is offered up to assist your learning, I'm not a teacher, so please don't ask for a programming tutorial.