Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; For compact keyboard, tie /INT low - Ctrl-Caps Lock enables Num Lock (disable with Caps Lock):
- ; 04 4 -> 5a Keypad (
- ; 05 5 -> 5b Keypad )
- ; 06 6 -> 5c Keypad /
- ; 07 7 -> 3d Keypad 7
- ; 08 8 -> 3e Keypad 8
- ; 09 9 -> 3f Keypad 9
- ; 0a 0 -> 5d Keypad *
- ; 16 U -> 2d Keypad 4
- ; 17 I -> 2e Keypad 5
- ; 18 O -> 2f Keypad 6
- ; 19 P -> 4a Keypad -
- ; 26 J -> 1d Keypad 1
- ; 27 K -> 1e Keypad 2
- ; 28 L -> 1f Keypad 3
- ; 29 ; -> 5e Keypad +
- ; 37 M -> 0f Keypad 0
- ; 39 . -> 3c Keypad .
- ; 44 Return -> 43 Enter
- ;
- ; |PA0|PA1|PA2|PA3|PA4|PA5|PA6|PA7|PC0|PC1|PC2|PC3|PC4|PC5|PC6|GND
- ; | 15| 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30
- ; -------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---
- ; PB4 1 |tab| Q | W | E | R | T | Y | U | I | O | P | [ | ] |cr |lt |
- ; PB5 2 |cap| A | S | D | F | G | H | J | K | L | ; | ' | \ |del|rt |
- ; PB6 3 | § | Z | X | C | V | B | N | M | , | . | / | |sp |bs |dn |
- ; PB7 4 |kp*|kp+|kp9|kp6|kp3|kp.|kp8|kp5|kp2|ent|kp7|kp4|kp1|kp0|kp-|
- ; PB3 5 | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | ¥ |up |
- ; PD0 6 | | | | | | | | | | | | | | | |rsh
- ; PB2 7 |esc|kp(|F1 |F2 |F3 |F4 |F5 |kp)|F6 |kp/|F7 |F8 |F9 |F10|hlp|
- ; PD1 8 | | | | | | | | | | | | | | | |ral
- ; PD2 10 | | | | | | | | | | | | | | | |rmt
- ; PD3 11 | | | | | | | | | | | | | | | |ctl
- ; PD4 12 | | | | | | | | | | | | | | | |lsh
- ; PD5 13 | | | | | | | | | | | | | | | |lal
- ; PD7 14 | | | | | | | | | | | | | | | |lmt
- ;
- ; PC7 31 drives caps lock LED
- ; PB1 drives KB_CLOCK
- ; PB0 drives KB_DATA and loops back to TCAP
- ; TCMP drives KB_RESET
- ;
- ; SPI 0x01ca four blinks on caps lock
- ; SCI 0x01ca four blinks on caps lock
- ; TIMER 0x0505
- ; IRQ 0x0570 return immediately
- ; SWI 0x01ca four blinks on caps lock
- ; RESET 0x0102
- ; unsigned char const PB_MASK_KDAT = 0x01;
- ; unsigned char const PB_MASK_KCLK = 0x02;
- ;
- ; unsigned char const PC_MASK_CAPS = 0x80;
- ;
- ; unsigned char const PD_MASK_RSH = 0x01;
- ; unsigned char const PD_MASK_RAL = 0x02;
- ; unsigned char const PD_MASK_RMT = 0x04;
- ; unsigned char const PD_MASK_CTL = 0x08;
- ; unsigned char const PD_MASK_LSH = 0x10;
- ; unsigned char const PD_MASK_LAL = 0x20;
- ; unsigned char const PD_MASK_LMT = 0x80;
- ; unsigned char const PD_MASK_RIGHT = PD_MASK_RSH | PD_MASK_RAL | PD_MASK_RMT;
- ; unsigned char const PD_MASK_LEFT = PD_MASK_LSH | PD_MASK_LAL | PD_MASK_LMT;
- ; unsigned char const PD_MASK_ALL = PD_MASK_RIGHT | PD_MASK_CTL | PD_MASK_LEFT;
- ; unsigned char const PD_MASK_RESET = PD_MASK_RMT | PD_MASK_CTL | PD_MASK_LMT;
- ;
- ; unsigned char const CODE_MASK_DOWN = 0x00;
- ; unsigned char const CODE_MASK_UP = 0x80;
- ; unsigned char const CODE_CAPS_LCK = 0x62;
- ; unsigned char const CODE_RST_WARN = 0x78;
- ; unsigned char const CODE_PREV_BAD = 0xf9;
- ; unsigned char const CODE_KBD_FAIL = 0xfc;
- ; unsigned char const CODE_UP_INIT = 0xfd;
- ; unsigned char const CODE_UP_TERM = 0xfe;
- ;
- ;
- ; unsigned char scan[32]; // 0x0080..0x009f
- ; unsigned char queue_bytes[14]; // 0x00a6..0x00b3
- ; unsigned char queue_tail; // 0x00b4
- ; unsigned char queue_head; // 0x00b5
- ; bool caps_lock; // 0x00b8 & 0x80
- ; bool retransmit; // 0x00b8 & 0x40
- ; bool expect_ack; // 0x00b8 & 0x20
- ; bool first_scan; // 0x00b8 & 0x10
- ; bool resync; // 0x00b8 & 0x08
- ; bool queue_drop; // 0x00b8 & 0x04
- ; bool queue_full; // 0x00b8 & 0x02
- ; bool keys_changed; // 0x00b8 & 0x01
- ; unsigned char prev_code; // 0x00ba
- ; bool num_lock; // 0x00bc & 0x08
- ; unsigned char blink_count; // 0x00bd
- reset_vector:
- ; disable_interrupts(); // disable interrupts while setting up
- ; reset_stack_pointer();
- ; *(unsigned char *)0x1ff1 = 0x01;
- ; COPR = 0x00;
- ; TCR = 0x01; // capture falling edge, drive TCMP high on compare
- ; SCCR2 = SCCR1 = SPCR = 0x00; // disable serial communication
- ; *(unsigned char *)0x1fdf = 0x00;
- ; *(unsigned char *)0x3fdf = 0x00;
- ; PORTC = ~PC_MASK_CAPS; // light Caps Lock LED while initialising
- ; DDRC = DDRA = PORTD = PORTB = PORTA = 0xff; // ports A and C are output, drive all rows high
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK; // drive KDAT and KCLK high
- ; COPR = 0x00;
- ; unsigned char addr;
- ; addr = 0x80;
- ; do
- ; {
- ; if (*(unsigned char *)addr != addr) goto ram_test;
- ; }
- ; while (++addr >= 0xfb);
- ; goto watchdog_pass;
- ; ram_test:
- ; COPR = 0x00;
- ; unsigned char val;
- ; bool msb;
- ; addr = 0x80;
- ; do
- ; {
- ; val = 0xfe;
- ; do
- ; {
- ; *(unsigned char *)addr = val;
- ; if (*(unsigned char *)addr != val) goto ram_fail;
- ; msb = val & 0x80;
- ; val = (val << 1) | 0x01;
- ; }
- ; while (msb);
- ; }
- ; while (++addr);
- ; addr = 0x80;
- ; do
- ; {
- ; val = 0x01;
- ; do
- ; {
- ; *(unsigned char *)addr = val;
- ; if (*(unsigned char *)addr != val) goto ram_fail;
- ; msb = val & 0x80;
- ; val <<= 1;
- ; }
- ; while (!msb);
- ; }
- ; while (++addr);
- ; addr = 0x80;
- ; do { *(unsigned char *)addr = addr; } while (++addr);
- ; addr = 0x80;
- ; do { if (*(unsigned char *)addr != addr) goto memory_fail; } while (++addr);
- ; *(unsigned char *)0x80 = val;
- ; goto program_check;
- ; ram_fail:
- ; goto memory_fail;
- 0102: 9B sei ; disable interrupts
- 0103: 9C rsp ; reset stack pointer
- 0104: A6 01 lda #$01 ; WTF?
- 0106: C7 1F F1 sta $1FF1
- 0109: A6 00 lda #$00 ; reset NCOP
- 010B: C7 1F F0 sta $1FF0
- 010E: A6 01 lda #$01 ; disable timer/capture/compare interrupts, output 1 on next compare match
- 0110: B7 12 sta TCR
- 0112: A6 00 lda #$00 ; disable SPI/SCI
- 0114: B7 0A sta SPCR
- 0116: B7 0E sta SCCR1
- 0118: B7 0F sta SCCR2
- 011A: C7 1F DF sta $1FDF ; WTF?
- 011D: C7 3F DF sta $3FDF
- 0120: A6 7F lda #$7F ; PC7 low, all other digital outputs high
- 0122: B7 02 sta PORTC
- 0124: A6 FF lda #$FF
- 0126: B7 00 sta PORTA
- 0128: B7 01 sta PORTB
- 012A: B7 03 sta PORTD
- 012C: B7 04 sta DDRA ; make ports A and C outputs
- 012E: B7 06 sta DDRC
- 0130: A6 03 lda #$03 ; make PB0 (KB_DATA) and PB1 (KB_CLOCK) outputs
- 0132: B7 05 sta DDRB
- 0134: A6 00 lda #$00 ; reset NCOP
- 0136: C7 1F F0 sta $1FF0
- 0139: AE 80 ldx #$80 ; check that data at 0x80..0xfc matches addresses
- 013B: F3 cpx (x)
- 013C: 26 08 bne $146
- 013E: 5C incx ; ++x
- 013F: A3 FB cpx #$FB ; loop if greater than than 0xfb (note the bug!)
- 0141: 24 F8 bcc $13B
- 0143: CC 02 8A jmp $028A ; goto 0x028a
- 0146: A6 00 lda #$00 ; reset ncop
- 0148: C7 1F F0 sta $1FF0
- 014B: AE 80 ldx #$80
- 014D: A6 FE lda #$FE
- 014F: F7 sta (x)
- 0150: F1 cmpa (x)
- 0151: 26 27 bne $17A
- 0153: 99 sec
- 0154: 49 rola
- 0155: 25 F8 bcs $14F
- 0157: 5C incx
- 0158: 26 F3 bne $14D
- 015A: AE 80 ldx #$80
- 015C: A6 01 lda #$01
- 015E: F7 sta (x)
- 015F: F1 cmpa (x)
- 0160: 26 18 bne $17A
- 0162: 48 asla
- 0163: 24 F9 bcc $15E
- 0165: 5C incx
- 0166: 26 F4 bne $15C
- 0168: AE 80 ldx #$80
- 016A: FF stx (x)
- 016B: 5C incx
- 016C: 26 FC bne $16A
- 016E: AE 80 ldx #$80
- 0170: F3 cpx (x)
- 0171: 26 5F bne $1D2
- 0173: 5C incx
- 0174: 26 FA bne $170
- 0176: B7 80 sta $80
- 0178: 20 0A bra $184
- 017A: CC 01 D2 jmp $01D2
- 017D: D6 01 00 lda (x+$0100)
- 0180: 81 rts
- 0181: 00 00 fdb $0000
- 0183: 08 fcb $08
- ; program_check:
- ; typedef unsigned char (*fetch_func)(unsigned char);
- ; constexpr fetch_func fetch = (fetch_func)0x50;
- ; constexpr unsigned short *sum = (unsigned short *)0x54;
- ; COPR = 0x00;
- ; unsigned char i;
- ; i = 0x07;
- ; do { (unsigned char *)(0x50 + i) = (unsigned char *)(0x017d + i); } while (!--i & 0x80);
- ; i = 0x02;
- ; do
- ; {
- ; do { *sum += fetch_func(i); } while (++i);
- ; ++*(unsigned char *)0x51;
- ; }
- ; while (!(--*(unsigned char *)0x56));
- ; if (*sum != *(unsigned short)0x0100) goto 0x01d6;
- ; COPR = 0x00;
- ; i = 0x80;
- ; do { *(unsigned char *)i = i; } while (++i);
- ; i = 0x80;
- ; do
- ; {
- ; int j = 0;
- ; while (--j) { }
- ; }
- ; while (--i);
- ; goto watchdog_fail;
- 0184: A6 00 lda #$00 ; reset NCOP
- 0186: C7 1F F0 sta $1FF0
- 0189: AE 07 ldx #$07 ; copy a function that fetches a value from program ROM into RAM at 0x50
- 018B: D6 01 7D lda (x+$017D) ; followed by two zeros for checksum and a block count of 8
- 018E: E7 50 sta (x+$50)
- 0190: 5A decx
- 0191: 2A F8 bpl $18B
- 0193: AE 02 ldx #$02 ; sum program ROM from 0x0102 to 0x01ff
- 0195: BD 50 jsr $50
- 0197: BB 55 adda $55
- 0199: B7 55 sta $55
- 019B: 24 02 bcc $19F
- 019D: 3C 54 inc $54
- 019F: 5C incx
- 01A0: 26 F3 bne $195
- 01A2: 3C 51 inc $51 ; increment the high byte of base address in fetch function
- 01A4: 3A 56 dec $56 ; loop if more blocks
- 01A6: 2A ED bpl $195
- 01A8: C1 01 01 cmpa $0101 ; if checksum doesn't match expected value at 0x0100, goto 0x01d6
- 01AB: 26 29 bne $1D6
- 01AD: B6 54 lda $54
- 01AF: C1 01 00 cmpa $0100
- 01B2: 26 22 bne $1D6
- 01B4: A6 00 lda #$00 ; reset NCOP
- 01B6: C7 1F F0 sta $1FF0
- 01B9: AE 80 ldx #$80 ; store values 0x80..0xff in locations 0x00..0xff
- 01BB: FF stx (x)
- 01BC: 5C incx
- 01BD: 26 FC bne $1BB
- 01BF: A6 80 lda #$80 ; nested delay loops waiting for COP reset
- 01C1: 5F clrx
- 01C2: 5A decx
- 01C3: 26 FD bne $1C2
- 01C5: 4A deca
- 01C6: 26 F9 bne $1C1
- 01C8: 20 04 bra $1CE
- ; unexpected_int: // 0x01ca
- ; a = 0x0f;
- ; goto blink_led;
- ; watchdog_fail: // 0x01ce
- ; a = 0x07;
- ; goto blink_led;
- ; memory_fail: // 0x01d2
- ; a = 0x03;
- ; goto blink_led;
- ; program_fail: // 0x01d6
- ; a = 0x01;
- ; blink_led:
- ; disable_interrupts();
- ; unsigned char result = a; // 0x0056
- ; *(unsigned char *)0x80 = a;
- ; *(unsigned char *)0x1ff1 = 0x00;
- ; COPR = 0x00;
- ; // force resynchronisation by clocking out 1 bits
- ; unsigned char status;
- ; do
- ; { // 0x01e5
- ; PORTB = ~PB_MASK_KDAT; // KDAT low (logical 1 as it's active low)
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK; // drive KDAT and KCLK
- ; bit_delay();
- ; PORTB = ~(PB_MASK_KDAT | PB_MASK_KCLK); // clock out the bit
- ; bit_delay();
- ; PORTB = ~PB_MASK_KDAT;
- ; bit_delay();
- ; PORTB = ~0x00; // release KDAT and disable KDAT output (PB0)
- ; DDRB = PB_MASK_KCLK;
- ; unsigned char const high = TRH; // get current timer count
- ; unsigned char const low = TRL;
- ; if (high & TSR) { } // clear timer/capture/compare status
- ; if (high & ICRH) { }
- ; if (high & ICRL { }
- ; if (high & TSR) { }
- ; OCRH = high; // copy timer value to output compare register
- ; OCRL = low;
- ; do { COPR = 0x00; } while (!(status = TSR & 0xc0)); // wait for compare or capture event
- ; if (status & ICRL) { } // clear out input capture flag
- ; }
- ; while (!(status & 0x80)); // loop if it wasn't an input capture event
- ;
- ; // send 0xfc self-test failure code
- ; unsigned char data = ~CODE_KBD_FAIL; // 0x00a3
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK; // drive KDAT and KCLK
- ; unsigned bits = 8;
- ; do
- ; { // 0x022f
- ; data = (data << 1) + ((data & 0x80) ? 1 : 0); // rotate value left (do first because MSB sent last)
- ; unsigned char val = data | 0x7f; // clock out leftmost bit
- ; PORTB = val = (val << 2) | PB_MASK_KCLK | ((val & 0x80) ? PB_MASK_KDAT : 0);
- ; bit_delay();
- ; PORTB = val &= ~PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = val |= PB_MASK_KCLK;
- ; bit_delay();
- ; }
- ; while (--bits); // loop while bits remaining to send
- ;
- ; // loop while blinking LEDs
- ; while (true)
- ; { // 0x0251
- ; DDRC = PORTB = 0xff; // make port C all outputs, release KCLK and KDAT
- ; if (0xff & TSR) { } // clear timer and output compare status
- ; if (0xff & OCRL) { }
- ; unsigned wait;
- ; wait = 2; // wait for two compare events
- ; do
- ; {
- ; do { COPR = 0x00; } while (!(TSR & 0x40));
- ; if (0x00 & OCRL) { }
- ; }
- ; while (!--wait);
- ; result = (result << 1) + ((result & 0x80) ? 1 : 0); // rotate blink pattern left
- ; PORTC = (result | ~PC_MASK_CAPS) ^ PC_MASK_CAPS; // light Caps Lock LED if leftmost bit is set
- ; wait = 2; // wait for two compare events
- ; do
- ; {
- ; do { COPR = 0x00; } while (!(TSR & 0x40));
- ; if (0x00 & OCRL) { }
- ; }
- ; while (!--wait);
- ; PORTC |= PC_MASK_CAPS; // extinguish Caps Lock LED
- ; }
- 01CA: A6 0F lda #$0F
- 01CC: 20 0A bra $1D8
- 01CE: A6 07 lda #$07
- 01D0: 20 06 bra $1D8
- 01D2: A6 03 lda #$03
- 01D4: 20 02 bra $1D8
- 01D6: A6 01 lda #$01
- 01D8: 9B sei ; disable interrupts
- 01D9: B7 56 sta $56 ; stash self-test result at 0x56 and 0x80
- 01DB: B7 80 sta $80
- 01DD: A6 00 lda #$00 ; WTF?
- 01DF: C7 1F F1 sta $1FF1
- 01E2: C7 1F F0 sta $1FF0 ; reset NCOP
- 01E5: A6 FE lda #$FE ; KB_DATA low, KB_CLOCK high, both outputs
- 01E7: B7 01 sta PORTB
- 01E9: A6 03 lda #$03
- 01EB: B7 05 sta DDRB
- 01ED: CD 07 7D jsr $077D ; bit_delay()
- 01F0: A6 FC lda #$FC ; KB_DATA low, KB_CLOCK low
- 01F2: B7 01 sta PORTB ; bit_delay()
- 01F4: CD 07 7D jsr $077D
- 01F7: A6 FE lda #$FE ; KB_DATA low, KB_CLOCK high
- 01F9: B7 01 sta PORTB
- 01FB: CD 07 7D jsr $077D ; bit_delay()
- 01FE: A6 FF lda #$FF ; KB_DATA high, KB_CLOCK high
- 0200: B7 01 sta PORTB
- 0202: A6 02 lda #$02 ; KB_DATA input, KB_CLOCK output
- 0204: B7 05 sta DDRB
- 0206: B6 18 lda TRH ; put current timer contents in a:x
- 0208: BE 19 ldx TRL
- 020A: B5 13 bita TSR ; ensure ICF is clear
- 020C: B5 14 bita ICRH
- 020E: B5 15 bita ICRL
- 0210: B5 13 bita TSR ; store retrieved timer value in OCR (and clear OCF)
- 0212: B7 16 sta OCRH
- 0214: BF 17 stx OCRL
- 0216: A6 00 lda #$00 ; reset NCOP
- 0218: C7 1F F0 sta $1FF0
- 021B: B6 13 lda TSR ; wait for input capture/output compare
- 021D: A4 C0 anda #$C0
- 021F: 27 F5 beq $216
- 0221: 2A C2 bpl $1E5 ; if it wasn't input capture, loop to 0x01e5
- 0223: B5 15 bita ICRL ; read ICRL to clear input capture flag
- 0225: A6 03 lda #$03 ; *(unsigned char)0xa3 = 0x03
- 0227: B7 A3 sta $A3
- 0229: A6 03 lda #$03 ; KB_DATA output, KB_CLOCK output
- 022B: B7 05 sta DDRB
- 022D: AE 08 ldx #$08 ; bit count 8 in x
- 022F: B6 A3 lda $A3 ; rotate data left by one bit
- 0231: 48 asla
- 0232: A9 00 adca #$00
- 0234: B7 A3 sta $A3
- 0236: AA 7F ora #$7F ; PORTB = 0xfe | (data >> 7)
- 0238: 99 sec
- 0239: 49 rola
- 023A: 49 rola
- 023B: B7 01 sta PORTB
- 023D: CD 07 7D jsr $077D ; bit_delay()
- 0240: A4 FD anda #$FD ; pull KB_CLOCK low
- 0242: B7 01 sta PORTB
- 0244: CD 07 7D jsr $077D ; bit_delay()
- 0247: AA 02 ora #$02 ; pull KB_CLOCK high
- 0249: B7 01 sta PORTB
- 024B: CD 07 7D jsr $077D ; bit_delay()
- 024E: 5A decx ; decrement bit count and loop if not zero
- 024F: 26 DE bne $22F
- 0251: A6 FF lda #$FF ; pull KB_CLOCK and KB_DATA high
- 0253: B7 01 sta PORTB
- 0255: B7 06 sta DDRC ; make PORTC outputs
- 0257: B5 13 bita TSR ; ensure OCF is clear by reading TSR followed by OCRL
- 0259: B5 17 bita OCRL
- 025B: AE 02 ldx #$02 ; wait count = 2
- 025D: A6 00 lda #$00 ; reset NCOP
- 025F: C7 1F F0 sta $1FF0
- 0262: 0D 13 F8 brclr 6,TSR,$25D ; loop while OCF is false
- 0265: B5 17 bita OCRL ; read OCRL to clear OCF
- 0267: 5A decx ; decrement wait count and loop if non-zero
- 0268: 26 F3 bne $25D
- 026A: B6 56 lda $56 ; rotate result left one bit
- 026C: 48 asla
- 026D: A9 00 adca #$00
- 026F: B7 56 sta $56
- 0271: AA 7F ora #$7F ; put inverse of MSB of result on caps lock LED
- 0273: A8 80 eora #$80
- 0275: B7 02 sta PORTC
- 0277: AE 02 ldx #$02 ; wait count = 2
- 0279: A6 00 lda #$00
- 027B: C7 1F F0 sta $1FF0 ; wait for output capture and clear flag
- 027E: 0D 13 F8 brclr 6,TSR,$279
- 0281: B5 17 bita OCRL
- 0283: 5A decx ; decrement wait count and loop if non-zero
- 0284: 26 F3 bne $279
- 0286: 1E 02 bset 7,PORTC ; turn off caps lock LED
- 0288: 20 C7 bra $251 ; repeat forever
- ; watchdog_pass: // 0x028a
- ; disable_interrupts();
- ; reset_stack_pointer();
- ; PORTD = PORTC = PORTB = PORTA = 0xff;
- ; DDRC = DDRA = 0xff;
- ; DDRB = 0x03;
- ; unsigned char i = sizeof(scan) - 1; // fill scan state with all keys up
- ; do { scan[i] = 0xff; } while (!(--i & 0x80));
- ; unsigned char sent_modifiers = 0x7f; // 0xa1
- ; unsigned char modifiers = 0x7f; // 0xa0
- ; queue_head = queue_tail = 0x00; // start with transmit queue empty
- ; num_lock = false; // start with standard key map
- ; *(unsigned char *)0xbc = 0x00;
- ; keys_changed = queue_full = queue_drop = resync = retransmit = caps_lock = false;
- ; first_scan = expect_ack = true;
- ; unsigned char high = TRH; // clear timer/capture/compare flags
- ; unsigned char low = TRL;
- ; if (high & TSR) { }
- ; if (high & ICRH) { }
- ; if (high & ICRL) { }
- ; if (high & TSR) { }
- ; OCRH = high; // maximise time to compare interrupt
- ; OCRL = low;
- ; TCR = 0xc3; // capture interrupt on (rising), compare interrupt on (high)
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK; // drive KDAT and KCLK
- ; queue_byte(CODE_UP_INIT); // queue initiate power-up key stream code
- ; while (true)
- ; { // 0x02d4
- ; DDRC = DDRA = PORTB = ~0x00; // make ports A and C outputs, drive KCLK and KDAT high
- ; unsigned char ghosts = 0xff; // 0xb9
- ; unsigned char cols_hit = 0xff; // 0xbb
- ; keys_changed = false; // haven't seen any key changes yet on this scan
- ; unsigned char row = 0; // 0xb7
- ; PORTA = 0x00; // first eight rows low, disable interrupts
- ; disable_interrupts();
- ; PORTC &= PC_MASK_CAPS; // drive other seven rows low, re-enable interrupts
- ; enable_interrupts();
- ; unsigned char i; // spin for 86 machine cycles so inputs can settle
- ; i = 14;
- ; while (--i) { }
- ; if ((PORTB | PB_MASK_KDAT | PB_MASK_KCLK) == ~0x00) // check for case where no matrix keys are down
- ; { // 0x02fd
- ; i = 0; // see if any matrix keys were down on the last scan
- ; do
- ; { // 0x02ff
- ; if (scan[i] != 0xff) goto check_matrix; // if so, check matrix properly
- ; }
- ; while (15 > ++i);
- ; goto check_modifiers; // otherwise check new state of modifiers
- ; }
- ; check_matrix: // 0x030a
- ; do
- ; { // 0x030a
- ; disable_interrupts(); // disable interrups while setting row drive
- ; if (8 <= row)
- ; { // 0x030f
- ; unsigned char pattern = insert_zero(row & 0x07); // this row is on port C - generate pattern
- ; if (!(PORTC & 0x80)) pattern &= 0x7f; // preserve Caps Lock LED state and push to port C buffer
- ; PORTC = pattern;
- ; DDRC = (pattern ^ 0xff) | 0x80; // release other matrix rows rather than driving high
- ; PORTA = 0xff;
- ; DDRA = 0x00;
- ; }
- ; else
- ; { // 0x032d
- ; unsigned char const pattern = insert_zero(row); // this row is on port A - generate pattern
- ; PORTA = pattern; // push to port A buffer
- ; DDRA = pattern ^ 0xff; // release other matrix rows rather than driving high
- ; PORTC |= 0x7f;
- ; DDRC = 0x80;
- ; }
- ; enable_interrupts(); // re-enable interrupts
- ; i = 14; // spin for 86 machine cycles so inputs can settle
- ; while (--i) { }
- ; i = PORTB; // read columns and update/flag if it changed since last scan
- ; if (scan[row] != i)
- ; { // 0x0350
- ; scan[row] = i;
- ; keys_changed = true;
- ; }
- ; unsigned char current = scan[row]; // 0x00a3
- ; ghosts &= cols_hit | current; // update values for ghosting check
- ; cols_hit &= current;
- ; }
- ; while (15 > ++row);
- ; check_modifiers: // 0x036e
- ; unsigned char current = PORTD & PD_MASK_ALL; // get modifier state (active low) in contiguous bits
- ; if (current & 0x80) current |= 0x40;
- ; current &= 0x7f;
- ; if (current != modifiers) // update/flag if it changed since last check
- ; { // 0x037c
- ; modifiers = current;
- ; keys_changed = true;
- ; }
- ; if (keys_changed) // if we see a change, wait for keys to stop bouncing
- ; { // 0x0383
- ; i = 179; // spin for 1792 machine cycles
- ; do { nop(); nop(); } while (--i);
- ; continue;
- ; }
- ;
- ; // keys seem to be stable
- ; row = 0;
- ; do
- ; { // 0x3b9
- ; unsigned char column = 0; // 0xb6
- ; do
- ; { // 0x03bb
- ; unsigned char current = insert_zero(column + 2); // 0x00a3
- ; unsigned char const tmp = scan[row] | current; // 0x00a2
- ; if ((current | scan[16 + row]) != tmp) // if this key didn't change, check the next one
- ; continue;
- ;
- ; unsigned char makebit; // 0x00a2
- ; if (tmp == 0xff)
- ; { // 0x03dd
- ; makebit = CODE_MASK_UP; // key released
- ; }
- ; else
- ; { // 0x03e3
- ; makebit = CODE_MASK_DOWN; // ignore key down if it fails ghosting test
- ; if (((scan[row] ^ 0xff) & current) && ((ghosts | current) ^ 0xff))
- ; continue;
- ; }
- ;
- ; // try to notify the host about this key transition
- ; while (true)
- ; { // 0x03f8
- ; unsigned short const tmp = ((row << 1) && 0xff) + ((row << 2) & 0xff);
- ; unsigned char const offset = column + (tmp & 0xff) + ((tmp >> 8) & 0x01);
- ; unsigned char code;
- ; if (!irq_high() && num_lock) // in compact mode, the keypad can be remapped
- ; code = TRANS_NUM[offset];
- ; else
- ; code = TRANS_STD[offset];
- ;
- ; if (code != CODE_CAPS_LCK) // if it's not Caps Lock, combine with make/break and queue
- ; { // 0x0414
- ; if (!queue_byte(code | makebit)) break;
- ; do { COPR = 0x00; } while (queue_full); // if the queue was full, spin and retry when there's space
- ; continue;
- ; }
- ; else if (makebit & 0x80) // don't send Caps Lock release code here
- ; {
- ; break;
- ; }
- ;
- ; // in compact mode, Caps Lock is used for remapping the numeric keypad over the main keyboard
- ; if (!irq_high())
- ; { // 0x041e
- ; if (((PORTD & PD_MASK_ALL) ^ PD_MASK_ALL) == PD_MASK_CTL)
- ; { // 0x0428
- ; num_lock = true; // this was Ctrl-Caps Lock, remap numeric keypad
- ; blink_count = 0;
- ; if (!caps_lock) break; // if Caps Lock was off, this doesn't turn it on
- ; }
- ; else if (num_lock)
- ; { // 0x0434
- ; disable_interrupts(); // Caps Lock disables numeric keypad remapping
- ; num_lock = false;
- ; caps_lock = false;
- ; PORTC |= PC_MASK_CAPS; // extinguish Caps Lock LED
- ; enable_interrupts();
- ; break;
- ; }
- ; }
- ;
- ; // send the logical Caps Lock transition
- ; if (queue_byte(TRANS_STD[offset]) | (caps_lock ? CODE_MASK_UP : CODE_MASK_DOWN))
- ; { // 0x044a
- ; do { COPR = 0x00; } while (queue_full); // no space in queue - spin until there is and retry
- ; }
- ; else
- ; { // 0x0455
- ; disable_interrupts(); // update caps lock state and LED
- ; unsigned char const tmp = (caps_lock = !caps_lock) ? 0x00 : PC_MASK_CAPS_LOCK;
- ; enable_interrupts();
- ; PORTC = tmp | ~PC_MASK_CAPS_LOCK;
- ; break;
- ; }
- ; }
- ; scan[16 + row] ^= ~insert_zero(column + 2); // update state of keys sent to host
- ; }
- ; while (++column < 6);
- ; COPR = 0x00;
- ; }
- ; while (++row < 15);
- ;
- ; // update modifiers with dedicated input lines
- ; unsigned char bit = 0; // 0xb6
- ; do
- ; { // 0x0482
- ; unsigned char current = insert_zero(bit); // 0xa3
- ; unsigned char state = modifiers | current; // 0xa2
- ; if ((sent_modifiers | current) != state) // if it doesn't match what we last sent, get it queued
- ; { // 0x04b5
- ; state = (state ^ 0xff) ? CODE_MASK_DOWN : CODE_MASK_UP;
- ; while (queue_byte(TRANS_MOD[bit] | state)) // if the queue is full, spin until it isn't and retry
- ; { // 0x04cf
- ; do { COPR = 0x00; } while (queue_full);
- ; }
- ; sent_modifiers ^= insert_zero(bit) ^ 0xff; // track the state we've sent to the host
- ; }
- ; }
- ; while (7 > ++bit);
- ;
- ; if (first_scan)
- ; { // 0x04ef
- ; first_scan = false;
- ; while (queue_byte(CODE_UP_TERM))
- ; { // 0x04f8
- ; do { COPR = 0x00; } while (queue_full);
- ; }
- ; }
- ; }
- 028A: 9B sei ; disable interrupts
- 028B: 9C rsp ; reset stack pointer
- 028C: A6 FF lda #$FF ; set all I/O port latches to 0xff
- 028E: B7 00 sta PORTA
- 0290: B7 01 sta PORTB
- 0292: B7 02 sta PORTC
- 0294: B7 03 sta PORTD
- 0296: B7 04 sta DDRA ; make ports A and B outputs
- 0298: B7 06 sta DDRC
- 029A: A6 03 lda #$03 ; make PB0 (KB_DATA) and PB1 (KB_CLOCK) outputs
- 029C: B7 05 sta DDRB
- 029E: A6 FF lda #$FF ; fill previos scan storage with 0xff
- 02A0: AE 1F ldx #$1F
- 02A2: E7 80 sta (x+$80)
- 02A4: 5A decx
- 02A5: 2A FB bpl $2A2
- 02A7: A6 7F lda #$7F
- 02A9: B7 A1 sta $A1
- 02AB: B7 A0 sta $A0 ; modifiers = 0x7f
- 02AD: 3F B4 clr $B4
- 02AF: 3F B5 clr $B5
- 02B1: 3F BC clr $BC
- 02B3: A6 30 lda #$30
- 02B5: B7 B8 sta $B8
- 02B7: B6 18 lda TRH ; get current timer value in a:x
- 02B9: BE 19 ldx TRL
- 02BB: B5 13 bita TSR ; read TSR followed by ICRH and ICRL to reset ICF
- 02BD: B5 14 bita ICRH
- 02BF: B5 15 bita ICRL
- 02C1: B5 13 bita TSR ; read TSR then set OCRH to a and OCRL to x to reset OCF
- 02C3: B7 16 sta OCRH
- 02C5: BF 17 stx OCRL
- 02C7: A6 C3 lda #$C3 ; set ICIE/OCIE, clear TOIE, set IEDG, set OLVL
- 02C9: B7 12 sta TCR
- 02CB: A6 02 lda #$02 ; make KB_CLOCK output, make KB_DATA input
- 02CD: B7 05 sta DDRB
- 02CF: A6 FD lda #$FD ; queue_byte(0xfd)
- 02D1: CD 03 8D jsr $038D
- 02D4: A6 FF lda #$FF ; all lines of port B high, ports A and C all outputs
- 02D6: B7 01 sta PORTB
- 02D8: B7 04 sta DDRA
- 02DA: B7 06 sta DDRC
- 02DC: B7 B9 sta $B9 ; ghosts = cols_hit = 0xff
- 02DE: B7 BB sta $BB
- 02E0: 11 B8 bclr 0,$B8
- 02E2: 3F B7 clr $B7 ; row = 0;
- 02E4: A6 00 lda #$00 ; drive first eight rows low
- 02E6: B7 00 sta PORTA
- 02E8: 9B sei ; disable interrupts
- 02E9: B6 02 lda PORTC ; drive other seven rows low (leave caps lock LED alone)
- 02EB: A4 80 anda #$80
- 02ED: B7 02 sta PORTC
- 02EF: 9A cli ; enable interrupts
- 02F0: A6 0E lda #$0E ; fourteen loops (allow inputs to settle)
- 02F2: 4A deca
- 02F3: 26 FD bne $2F2
- 02F5: B6 01 lda PORTB ; if any matrix keys are down goto 0x030a
- 02F7: AA 03 ora #$03
- 02F9: A1 FF cmpa #$FF
- 02FB: 26 0D bne $30A
- 02FD: AE 00 ldx #$00 ; if any matrix keys were down on previous scan goto 0x030a
- 02FF: E1 80 cmpa (x+$80)
- 0301: 26 07 bne $30A
- 0303: 5C incx
- 0304: A3 0F cpx #$0F
- 0306: 2B F7 bmi $2FF
- 0308: 20 64 bra $36E ; no matrix keys released, goto 0x036e
- 030A: 9B sei ; disable interrupts while setting row drive
- 030B: B6 B7 lda $B7 ; if row less than 8 goto 0x032d
- 030D: A1 08 cmpa #$08
- 030F: 2B 1C bmi $32D
- 0311: A4 07 anda #$07 ; insert_zero(row & 0x07)
- 0313: CD 07 84 jsr $0784
- 0316: 0E 02 02 brset 7,PORTC,$31B ; drive this row low, drop drive to other lines besides caps lock LED
- 0319: A4 7F anda #$7F
- 031B: B7 02 sta PORTC
- 031D: A8 FF eora #$FF
- 031F: AA 80 ora #$80
- 0321: B7 06 sta DDRC
- 0323: A6 FF lda #$FF
- 0325: B7 00 sta PORTA
- 0327: A6 00 lda #$00
- 0329: B7 04 sta DDRA
- 032B: 20 13 bra $340
- 032D: CD 07 84 jsr $0784 ; insert_zero(row)
- 0330: B7 00 sta PORTA ; drive this row low, drop drive to other lines besides caps lock LED
- 0332: A8 FF eora #$FF
- 0334: B7 04 sta DDRA
- 0336: B6 02 lda PORTC
- 0338: AA 7F ora #$7F
- 033A: B7 02 sta PORTC
- 033C: A6 80 lda #$80
- 033E: B7 06 sta DDRC
- 0340: 9A cli ; re-enable interrupts
- 0341: A6 0E lda #$0E ; fourteen loops (allow inputs to settle)
- 0343: 4A deca
- 0344: 26 FD bne $343
- 0346: BE B7 ldx $B7 ; compare value from previous scan to current state
- 0348: B6 01 lda PORTB
- 034A: AA 03 ora #$03
- 034C: E1 80 cmpa (x+$80)
- 034E: 27 04 beq $354
- 0350: E7 80 sta (x+$80) ; update and set keys_changed if changed
- 0352: 10 B8 bset 0,$B8
- 0354: E6 80 lda (x+$80) ; *(unsigned char *)0xa3 = scan[row]
- 0356: B7 A3 sta $A3
- 0358: B6 BB lda $BB ; ghosts &= cols_hit | *(unsigned char *)0xa3
- 035A: BA A3 ora $A3
- 035C: B4 B9 anda $B9
- 035E: B7 B9 sta $B9
- 0360: B6 BB lda $BB ; cols_hit &= *(unsigned char)0xa3
- 0362: B4 A3 anda $A3
- 0364: B7 BB sta $BB
- 0366: 3C B7 inc $B7 ; increment row and loop if less than 15
- 0368: B6 B7 lda $B7
- 036A: A1 0F cmpa #$0F
- 036C: 2B 9C bmi $30A
- 036E: B6 03 lda PORTD ; get modifier state, shift left Amiga into bit 6
- 0370: A4 BF anda #$BF
- 0372: 2A 02 bpl $376
- 0374: AA 40 ora #$40
- 0376: A4 7F anda #$7F
- 0378: B1 A0 cmpa $A0 ; if changed update and set keys_changed
- 037A: 27 04 beq $380
- 037C: B7 A0 sta $A0
- 037E: 10 B8 bset 0,$B8
- 0380: 01 B8 34 brclr 0,$B8,$3B7 ; if (!keys_changed) goto 0x03b7
- 0383: A6 B3 lda #$B3 ; loop for a while (debounce?)
- 0385: 9D nop
- 0386: 9D nop
- 0387: 4A deca
- 0388: 26 FB bne $385
- 038A: CC 02 D4 jmp $02D4 ; jump back to key scanning loop
- ; // returns 0xff if byte dropped, or 0x00 otherwise
- ; unsigned char queue_byte(unsigned char val)
- ; {
- ; disable_interrupts();
- ; unsigned char data = val; // 0x00a3
- ; if (queue_full)
- ; {
- ; queue_drop = true;
- ; enable_interrupts();
- ; return 0xff;
- ; }
- ; queue_bytes[queue_tail++] = data;
- ; if (queue_tail >= sizeof(queue_bytes))
- ; queue_tail = 0;
- ; if (val == queue_head)
- ; queue_full = true;
- ; force_capture_interrupt();
- ; enable_interrupts();
- ; return 0x00;
- ; }
- 038D: 9B sei
- 038E: B7 A3 sta $A3
- 0390: 03 B8 06 brclr 1,$B8,$399
- 0393: 14 B8 bset 2,$B8
- 0395: 9A cli
- 0396: A6 FF lda #$FF
- 0398: 81 rts
- 0399: BE B4 ldx $B4
- 039B: B6 A3 lda $A3
- 039D: E7 A6 sta (x+$A6)
- 039F: 3C B4 inc $B4
- 03A1: B6 B4 lda $B4
- 03A3: A1 0E cmpa #$0E
- 03A5: 2B 03 bmi $3AA
- 03A7: 4F clra
- 03A8: B7 B4 sta $B4
- 03AA: B1 B5 cmpa $B5
- 03AC: 26 02 bne $3B0
- 03AE: 12 B8 bset 1,$B8
- 03B0: CD 07 56 jsr $0756
- 03B3: 9A cli
- 03B4: A6 00 lda #$00
- 03B6: 81 rts
- 03B7: 3F B7 clr $B7 ; set row and column to zero
- 03B9: 3F B6 clr $B6
- 03BB: BE B7 ldx $B7
- 03BD: B6 B6 lda $B6
- 03BF: AB 02 adda #$02 ; current = insert_zero(column + 2)
- 03C1: CD 07 84 jsr $0784
- 03C4: B7 A3 sta $A3
- 03C6: E6 80 lda (x+$80) ; if ((current | scan[16 + row]) == (current | scan[row])) goto 0x484
- 03C8: BA A3 ora $A3
- 03CA: B7 A2 sta $A2
- 03CC: E6 90 lda (x+$90)
- 03CE: BA A3 ora $A3
- 03D0: B1 A2 cmpa $A2
- 03D2: 26 03 bne $3D7
- 03D4: CC 04 84 jmp $0484
- 03D7: B6 A2 lda $A2 ; if ((current | scan[row]) ^ 0xff) goto 0x03e3
- 03D9: A8 FF eora #$FF
- 03DB: 26 06 bne $3E3
- 03DD: A6 80 lda #$80 ; key up, store 0x80
- 03DF: B7 A2 sta $A2
- 03E1: 20 15 bra $3F8
- 03E3: 3F A2 clr $A2 ; else store 0x00
- 03E5: E6 80 lda (x+$80) ; if (!((scan[row] ^ 0xff) & current)) goto 0x03f8
- 03E7: A8 FF eora #$FF
- 03E9: B4 A3 anda $A3
- 03EB: 27 0B beq $3F8
- 03ED: B6 B9 lda $B9 ; if (!((ghosts | current) ^ 0xff)) goto 0x03f8
- 03EF: BA A3 ora $A3
- 03F1: A8 FF eora #$FF
- 03F3: 27 03 beq $3F8
- 03F5: CC 04 84 jmp $0484 ; goto 0x0484
- 03F8: B6 B7 lda $B7 ; tmp = (unsigned short)((row << 1) && 0xff) + ((row << 2) & 0xff)
- 03FA: 48 asla
- 03FB: B7 A3 sta $A3
- 03FD: 48 asla
- 03FE: BB A3 adda $A3
- 0400: B9 B6 adca $B6 ; x = column + (tmp & 0xff) + ((tmp >> 8) & 0x01)
- 0402: 97 tax
- 0403: 2F 08 bih $40D ; if (!irq_high() && num_lock)
- 0405: 07 BC 05 brclr 3,$BC,$40D
- 0408: D6 07 F0 lda (x+$07F0) ; fetch code from x + 0x07f0
- 040B: 20 03 bra $410
- 040D: D6 07 8F lda (x+$078F) ; else fetch code from x + 0x078f
- 0410: A1 62 cmpa #$62 ; if code is not 0x62 (caps lock), bitwise or with make/break bit and goto 0x0465
- 0412: 27 04 beq $418
- 0414: BA A2 ora $A2
- 0416: 20 4D bra $465
- 0418: B6 A2 lda $A2 ; if make bit is set goto 0x0475
- 041A: 2B 59 bmi $475
- 041C: 2F 20 bih $43E ; if (irq_high()) goto 0x043e
- 041E: B6 03 lda PORTD ; if control is only modifier pressed
- 0420: A4 BF anda #$BF
- 0422: A8 BF eora #$BF
- 0424: A1 08 cmpa #$08
- 0426: 26 09 bne $431
- 0428: 16 BC bset 3,$BC ; num_lock = true
- 042A: 3F BD clr $BD ; blink_count = 0
- 042C: 0E B8 0F brset 7,$B8,$43E ; if (caps_lock) goto 0x043e
- 042F: 20 44 bra $475 ; goto 0x0475
- 0431: 07 BC 0A brclr 3,$BC,$43E ; if (num_lock)
- 0434: 9B sei ; disable interrupts
- 0435: 17 BC bclr 3,$BC ; num_lock = false
- 0437: 1F B8 bclr 7,$B8 ; caps_lock = false
- 0439: 1E 02 bset 7,PORTC ; turn off caps lock LED
- 043B: 9A cli
- 043C: 20 37 bra $475 ; goto 0x0475
- 043E: B6 B8 lda $B8 ; if (queue_byte(*(unsigned char *)(0x78f + x) | (*(unsigned char *)0xb8 & 0x80)))
- 0440: A4 80 anda #$80
- 0442: DA 07 8F ora (x+$078F)
- 0445: CD 03 8D jsr $038D
- 0448: 27 0B beq $455
- 044A: A6 00 lda #$00 ; repeatedly reset reset NCOP while transmit queue is full
- 044C: C7 1F F0 sta $1FF0
- 044F: 02 B8 F8 brset 1,$B8,$44A
- 0452: CC 03 F8 jmp $03F8 ; loop to 0x03f8
- 0455: 9B sei ; disable interrupts
- 0456: B6 B8 lda $B8 ; a = *(unsigned char *)0xb8 ^= 0x80
- 0458: A8 80 eora #$80
- 045A: B7 B8 sta $B8
- 045C: 9A cli ; enable interrupts
- 045D: A8 80 eora #$80 ; PORTC = (a ^ 0x80) | 0x7f
- 045F: AA 7F ora #$7F
- 0461: B7 02 sta PORTC
- 0463: 20 10 bra $475 ; goto 0x0475
- 0465: CD 03 8D jsr $038D ; if (!queue_byte(code)) goto 0x0475
- 0468: 27 0B beq $475
- 046A: A6 00 lda #$00 ; repeatedly reset reset NCOP while transmit queue is full
- 046C: C7 1F F0 sta $1FF0
- 046F: 02 B8 F8 brset 1,$B8,$46A
- 0472: CC 03 F8 jmp $03F8 ; loop to 0x03f8
- 0475: BE B7 ldx $B7 ; scan[16 + row] ^= ~insert_zero(column + 2)
- 0477: B6 B6 lda $B6
- 0479: AB 02 adda #$02
- 047B: CD 07 84 jsr $0784
- 047E: A8 FF eora #$FF
- 0480: E8 90 eora (x+$90)
- 0482: E7 90 sta (x+$90)
- 0484: 3C B6 inc $B6 ; increment column and loop to 0x03bb if less than 6
- 0486: B6 B6 lda $B6
- 0488: A1 06 cmpa #$06
- 048A: 2A 03 bpl $48F
- 048C: CC 03 BB jmp $03BB
- 048F: A6 00 lda #$00 ; reset NCOP
- 0491: C7 1F F0 sta $1FF0
- 0494: 3C B7 inc $B7 ; increment row and loop to 0x3b9 if less than 15
- 0496: B6 B7 lda $B7
- 0498: A1 0F cmpa #$0F
- 049A: 2A 03 bpl $49F
- 049C: CC 03 B9 jmp $03B9
- 049F: 4F clra ; bit = 0
- 04A0: B7 B6 sta $B6
- 04A2: B6 B6 lda $B6 ; current = insert_zero(bit)
- 04A4: CD 07 84 jsr $0784
- 04A7: B7 A3 sta $A3
- 04A9: BA A0 ora $A0 ; state = modifiers | current
- 04AB: B7 A2 sta $A2
- 04AD: B6 A1 lda $A1 ; if ((sent_modifiers | current) != state) goto 0x04e4
- 04AF: BA A3 ora $A3
- 04B1: B1 A2 cmpa $A2
- 04B3: 27 2F beq $4E4
- 04B5: B6 A2 lda $A2 ; if (state ^ 0xff)
- 04B7: A8 FF eora #$FF
- 04B9: 27 04 beq $4BF
- 04BB: 3F A2 clr $A2 ; state = 0x00
- 04BD: 20 04 bra $4C3 ; else
- 04BF: A6 80 lda #$80 ; state = 0x80
- 04C1: B7 A2 sta $A2
- 04C3: BE B6 ldx $B6 ; while (queue_byte(TRANS_MOD[bit] | state))
- 04C5: D6 07 E9 lda (x+$07E9)
- 04C8: BA A2 ora $A2
- 04CA: CD 03 8D jsr $038D
- 04CD: 27 0A beq $4D9
- 04CF: A6 00 lda #$00 ; repeatedly reset reset NCOP while transmit queue is full
- 04D1: C7 1F F0 sta $1FF0
- 04D4: 02 B8 F8 brset 1,$B8,$4CF
- 04D7: 20 EA bra $4C3
- 04D9: B6 B6 lda $B6 ; sent_modifiers ^= insert_zero(bit) ^ 0xff
- 04DB: CD 07 84 jsr $0784
- 04DE: A8 FF eora #$FF
- 04E0: B8 A1 eora $A1
- 04E2: B7 A1 sta $A1
- 04E4: 3C B6 inc $B6 ; increment bit and loop to 0x04a2 if less than 7
- 04E6: B6 B6 lda $B6
- 04E8: A1 07 cmpa #$07
- 04EA: 2B B6 bmi $4A2
- 04EC: 09 B8 13 brclr 4,$B8,$502 ; if (!first_scan) goto 0x0502
- 04EF: 19 B8 bclr 4,$B8
- 04F1: A6 FE lda #$FE ; while (queue_byte(CODE_UP_TERM))
- 04F3: CD 03 8D jsr $038D
- 04F6: 27 0A beq $502
- 04F8: A6 00 lda #$00 ; repeatedly reset reset NCOP while transmit queue is full
- 04FA: C7 1F F0 sta $1FF0
- 04FD: 02 B8 F8 brset 1,$B8,$4F8
- 0500: 20 EF bra $4F1
- 0502: CC 02 D4 jmp $02D4
- ; void timer_handler()
- ; { // 0x0505
- ; PORTB = 0xff; // ensure KDAT and KCLK are both high
- ; if (PORTD & PD_MASK_RESET) // check for C-A-A reset combo
- ; { // 0x050f
- ; unsigned char const status = TSR;
- ; if (status & 0xc0) // check for capture or compare event
- ; { // 0x0515
- ; if (!(status & 0x80)) // check absence of capture flag (must be compare)
- ; { // 0x051a
- ; if (status & TSR) { } // clear out the compare flag
- ; if (status & OCRL) { }
- ; if (expect_ack) // if we were sending data, this is a timeout
- ; { // 0x0521
- ; resync = true; // acknowledge timeout - start resynchronisation
- ; PORTB = ~PORTB_MASK_KDAT; // clock out a logical 1 bit
- ; DDRB = PORTB_MASK_KDAT | PORTB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = ~(PORTB_MASK_KDAT | PORTB_MASK_KCLK);
- ; bit_delay();
- ; PORTB = ~PORTB_MASK_KDAT;
- ; bit_delay();
- ; DDRB = PORTB_MASK_KCLK;
- ; unsigned char const high = TRH, low = TRL; // get current timer value
- ; if (high & TSR) { } // clear timer/capture/compare status
- ; if (high & ICRH) { }
- ; if (high & ICRL) { }
- ; if (high & TSR) { }
- ; OCRH = high; // copy timer value to output compare register
- ; OCRL = low;
- ; }
- ; }
- ; else // handle capture event (KDAT edge detected)
- ; { // 0x06bb
- ; if (status & TSR) { } // clear out the compare flag
- ; if (status & ICRL) { }
- ; unsigned char code; // 0xa5
- ; if (resync) // are we currently trying to resynchronise?
- ; { // 0x06c2
- ; code = queue_bytes[queue_head]; // check whether next queued code is start of stuck keys
- ; if (CODE_UP_INIT == code)
- ; { // 0x06ca
- ; resync = false;
- ; }
- ; else
- ; { // 0x06ce
- ; resync = false; // if not, tell the host the last code was bad
- ; retransmit = true;
- ; code = CODE_PREV_BAD;
- ; goto send_code;
- ; }
- ; }
- ; if (retransmit) // if we have a code to retransmit, fetch it
- ; { // 0x06d9
- ; retransmit = false;
- ; code = prev_code;
- ; }
- ; else
- ; { // 0x06df
- ; if (queue_drop) // notify host of buffer overflow if necessary
- ; { // 0x06e2
- ; queue_drop = false;
- ; code = CODE_BUF_OFLOW;
- ; }
- ; else if ((queue_head == queue_tail) && !expect_ack)
- ; { // 0x06f4
- ; return; // nothing queued, return from interrupt
- ; }
- ; else
- ; { // 0x06f5
- ; queue_full = false; // pull a byte off the queue
- ; code = queue_bytes[queue_head++];
- ; if (queue_head >= sizeof(queue_bytes))
- ; queue_head = 0;
- ; }
- ; prev_code = code; // store code in case retransmission is necessary
- ; }
- ; send_code: // 0x0709
- ; code = ~code; // invert the code and clock it out
- ; unsigned i = 8; // 0xa4
- ; do
- ; { // 0x0711
- ; code = (code << 1) + ((code & 0x80) ? 1 : 0); // rotate value left (do first because MSB sent last)
- ; unsigned char val = data | 0x7f; // clock out leftmost bit
- ; PORTB = val = (val << 2) | PB_MASK_KCLK | ((val & 0x80) ? PB_MASK_KDAT : 0);
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = val &= ~PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = val |= PB_MASK_KCLK;
- ; bit_delay();
- ; }
- ; while (--i);
- ; PORTB = ~0x00; // release KDAT cleanly
- ; bit_delay();
- ; DDRB = PB_MASK_KCLK;
- ;
- ; // set acknowledge timeout
- ; expect_ack = true; // expect a response
- ; unsigned char const high = TRH; // get current timer value
- ; unsigned char const low = TRL;
- ; if (high & TSR) { } // clear timer and capture status
- ; if (high & ICRH) { }
- ; if (high & ICRL) { }
- ; if (high & TSR) { }
- ; OCRH = high; // copy timer value to output compare register
- ; OCRL = low;
- ; return; // return from interrupt
- ; }
- ; }
- ;
- ; // blink Caps Lock LED while numeric keypad is remapped over main keyboard (31/32 duty cycle)
- ; if (!irq_high() && num_lock)
- ; { // 0x055c
- ; unsigned char tmp = blink_count + 1; // increment counter wrapping at 32
- ; if (tmp >= 32) tmp = 0;
- ; blink_count = tmp;
- ; if (!tmp) PORTC |= PC_MASK_CAPS; // extinguish at 0
- ; if (tmp == 1) PORTC &= ~PC_MASK_CAPS; // light at 1
- ; }
- ; }
- ; else
- ; { // 0x0571
- ; disable_interrupts(); // C-A-A detected - request host reset
- ; if (expect_ack) // ensure we're not waiting on an acknowledge
- ; { // 0x5eb
- ; unsigned char count = 9; // 0xa2
- ; unsigned char const high = TRH; // get current timer value
- ; unsigned char const low = TRL;
- ; if (high & TSR) { } // clear timer and capture status
- ; if (high & ICRH) { }
- ; if (high & ICRL) { }
- ; if (high & TSR) { }
- ; OCRH = high; // copy timer value to output compare register
- ; OCRL = low;
- ; unsigned char status;
- ; while (true)
- ; { // 0x05ff
- ; do // wait for input capture or output compare event
- ; { // 0x05ff
- ; PORTB = ~0x00; // drive KCLK high and release KDAT
- ; DDRB = PB_MASK_KCLK;
- ; COPR = 0x00;
- ; }
- ; while (!(status = TSR & 0xc0));
- ; if (status & 0x80) // check for input capture event (acknowledge)
- ; { // 0x0614
- ; if (status & ICRL) { } // clear input capture flag
- ; expect_ack = false; // no longer something to be acknowledged
- ; break;
- ; }
- ; else
- ; {
- ; if (status & OCRL) { } // clear output compare flag
- ; if (!--count) // decrement counter and give up waiting if it reaches zero
- ; { // 0x061d
- ; goto hard_reset;
- ; }
- ; else
- ; { // 0x0621
- ; PORTB = ~PB_MASK_KDAT; // clock out a logical 1 bit
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = ~(PB_MASK_KDAT | PB_MASK_KCLK);
- ; bit_delay();
- ; PORTB = ~PB_MASK_KDAT;
- ; bit_delay();
- ; status = PORTB = ~0x00;
- ; bit_delay();
- ; if (status & TSR)
- ; }
- ; }
- ; }
- ; }
- ;
- ; // send first reset warning and wait for standard acknowledge
- ; send_reset_warning(); // send first high-level reset warning
- ; unsigned char const high = TRH; // get current timer value
- ; unsigned char const low = TRL;
- ; if (high & TSR) { } // clear timer and capture status
- ; if (high & ICRH) { }
- ; if (high & ICRL) { }
- ; if (high & TSR) { }
- ; OCRH = high; // copy timer value to output compare register
- ; OCRL = low;
- ; DDRB = PB_MASK_KCLK; // release KDAT
- ; unsigned wait = 2; // 0xa2
- ; PORTB = ~0x00;
- ; unsigned char status;
- ; while (true) // wait for compare or capture event
- ; { // 0x0594
- ; do { COPR = 0x00; } while (!(status = TSR & 0xc0));
- ; if (status & 0x80) break; // if it was compare (KDAT transition), go to next step
- ; if (status & OCRL) { } // clear output compare flag
- ; if (!--wait) goto hard_reset; // if we see two compare events in a row, give up waiting
- ; }
- ; if (status & ICRL) { } // clear input capture flag
- ;
- ; // send second reset warning and wait for KDAT to be asserted
- ; send_reset_warning(); // send second high-level reset warning
- ; wait = 2; // wait for up to two more compare events
- ; while (true) // wait for compare event or acknowledge
- ; { // 0x05b7
- ; PORTB = ~0x00; // drive KCLK high
- ; status = COPR = 0x00;
- ; if (!(PORTB & PB_MASK_KDAT)) // break if we see KDAT pulled low (acknowledge)
- ; {
- ; break;
- ; }
- ; else if (TSR & 0x40) // check for compare event
- ; {
- ; if (status & OCRL) { } // clear output compare flag
- ; if (!--wait) goto hard_reset; // if we see two compare events in a row, give up waiting
- ; }
- ; }
- ;
- ; // wait for the host to clean up before it releases KDAT
- ; wait = 68;
- ; while (true)
- ; { // 0x05d3
- ; PORTB = ~0x00;
- ; status = COPR = 0x00;
- ; if (!(PORTB & PB_MASK_KDAT)) // break if KDAT is released (ready for hard reset)
- ; {
- ; break;
- ; }
- ; else if (TSR & 0x40) // check for compare event
- ; {
- ; if (status & OCRL) { } // clear output compare flag
- ; if (!--wait) break; // if we see 68 compare events in a row, give up waiting
- ; }
- ; }
- ;
- ; hard_reset: // 0x0682
- ; do
- ; {
- ; disable_interrupts();
- ; TCR = 0x00; // capture falling edge, drive TCMP low on compare
- ; unsigned short cmp = TRL + 16; // trigger compare in 16 counts
- ; cmp += (unsigned short)TRH << 8;
- ; OCRH = (unsigned char)(cmp >> 8);
- ; OCRL = (unsigned char)cmp;
- ; wait = 10; // do delay loop ten times
- ; do
- ; { // 0x0698
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK; // drive KCLK low and KDAT high
- ; PORTB = ~PB_MASK_KCLK;
- ; COPR = 0x00;
- ; unsigned i = 65; // spin for 100,427 machine cycles
- ; do
- ; { // 0x06a8
- ; unsigned j = 0;
- ; while (--j) { }
- ; }
- ; while (--i);
- ; }
- ; while (--wait);
- ; }
- ; while (!(PORTD & PD_MASK_RESET)); // check that C-A-A combo is still held
- ; goto reset_vector;
- ; }
- ; }
- 0505: A6 FF lda #$FF ; drive KB_CLOCK and KB_DATA high
- 0507: B7 01 sta PORTB
- 0509: B6 03 lda PORTD ; if Ctrl, left Amiga and right Amiga are down, goto 0x0571
- 050B: A4 8C anda #$8C
- 050D: 27 62 beq $571
- 050F: B6 13 lda TSR ; if both OCF and ICF are low (TOF interrupt) goto 0x0557
- 0511: A4 C0 anda #$C0
- 0513: 27 42 beq $557
- 0515: 2A 03 bpl $51A ; if ICF is high goto 0x06bb
- 0517: CC 06 BB jmp $06BB
- 051A: B5 13 bita TSR ; read TSR followed by OCRL to clear OCF
- 051C: B5 17 bita OCRL
- 051E: 0B B8 36 brclr 5,$B8,$557 ; if bit 5 of 0x00b8 is clear, goto 0x0557
- 0521: 16 B8 bset 3,$B8 ; set bit 3 of 0x00b8
- 0523: A6 FE lda #$FE ; pull KB_CLOCK high and KB_DATA low, make KB_DATA and KB_CLOCK outputs
- 0525: B7 01 sta PORTB
- 0527: A6 03 lda #$03
- 0529: B7 05 sta DDRB
- 052B: CD 07 7D jsr $077D ; bit_delay()
- 052E: A6 FC lda #$FC ; pull KB_CLOCK and KB_DATA low
- 0530: B7 01 sta PORTB
- 0532: CD 07 7D jsr $077D ; bit_delay()
- 0535: A6 FE lda #$FE ; pull KB_CLOCK high and KB_DATA low
- 0537: B7 01 sta PORTB
- 0539: CD 07 7D jsr $077D ; bit_delay()
- 053C: A6 FF lda #$FF ; pull KB_CLOCK and KB_DATA low
- 053E: B7 01 sta PORTB
- 0540: CD 07 7D jsr $077D ; bit_delay()
- 0543: A6 02 lda #$02 ; make KB_CLOCK an output and KB_DATA an input
- 0545: B7 05 sta DDRB
- 0547: B6 18 lda TRH ; get current timer value in a:x
- 0549: BE 19 ldx TRL
- 054B: B5 13 bita TSR ; read TSR followed by ICRH and ICRL to ensure ICF is cleared
- 054D: B5 14 bita ICRH
- 054F: B5 15 bita ICRL
- 0551: B5 13 bita TSR ; read TSR, then store timer value in OCR (clear OCF, maximise time to output compare)
- 0553: B7 16 sta OCRH
- 0555: BF 17 stx OCRL
- 0557: 2F 17 bih $570 ; if /INT is high or num_lock flag is clear, goto 0x0570 (return from interrupt)
- 0559: 07 BC 14 brclr 3,$BC,$570
- 055C: B6 BD lda $BD ; increment blink_count, wrapping at 0x20
- 055E: 4C inca
- 055F: A1 20 cmpa #$20
- 0561: 25 01 bcs $564
- 0563: 4F clra
- 0564: B7 BD sta $BD
- 0566: 26 02 bne $56A ; if it wrapped around, drive caps lock LED high
- 0568: 1E 02 bset 7,PORTC
- 056A: A1 01 cmpa #$01 ; if value was 0x01, drive caps lock LED low
- 056C: 26 02 bne $570
- 056E: 1F 02 bclr 7,PORTC
- ; void irq_handler() { }
- 0570: 80 rti
- 0571: 9B sei ; disable interrupts
- 0572: B6 B8 lda $B8 ; if (expect_ack) goto 0x05eb
- 0574: A4 20 anda #$20
- 0576: 27 03 beq $57B
- 0578: CC 05 EB jmp $05EB
- 057B: CD 06 47 jsr $0647 ; send_reset_warning();
- 057E: B6 18 lda TRH ; a:x = TR
- 0580: BE 19 ldx TRL
- 0582: B5 13 bita TSR ; read TSR followed by ICRH and ICRL to clear ICF
- 0584: B5 14 bita ICRH
- 0586: B5 15 bita ICRL
- 0588: B5 13 bita TSR ; read TSR, then store timer value in OCR (clear OCF, maximise time to output compare)
- 058A: B7 16 sta OCRH
- 058C: BF 17 stx OCRL
- 058E: A6 02 lda #$02 ; KB_CLOCK output
- 0590: B7 05 sta DDRB
- 0592: B7 A2 sta $A2 ; set wait count at 0xa2 to 2
- 0594: A6 FF lda #$FF ; drive KB_CLOCK high
- 0596: B7 01 sta PORTB
- 0598: A6 00 lda #$00 ; reset NCOP
- 059A: C7 1F F0 sta $1FF0
- 059D: B6 13 lda TSR ; wait for input capture/output compare
- 059F: A4 C0 anda #$C0
- 05A1: 27 F1 beq $594
- 05A3: 2B 09 bmi $5AE ; if it was input capture, goto 0x05ae
- 05A5: B5 17 bita OCRL
- 05A7: 3A A2 dec $A2 ; decrement wait count at 0xa2 loop to 0x0594 if not zero
- 05A9: 26 E9 bne $594
- 05AB: CC 06 82 jmp $0682 ; goto 0x0682
- 05AE: B5 15 bita ICRL ; read ICRL to reset input capture flag
- 05B0: CD 06 47 jsr $0647 ; send_reset_warning()
- 05B3: A6 02 lda #$02 ; set wait count at 0xa2 to 2
- 05B5: B7 A2 sta $A2
- 05B7: A6 FF lda #$FF ; drive KB_CLOCK high
- 05B9: B7 01 sta PORTB
- 05BB: A6 00 lda #$00 ; reset NCOP
- 05BD: C7 1F F0 sta $1FF0
- 05C0: 01 01 0C brclr 0,PORTB,$5CF ; if KB_DATA is low (acknowledge), goto 0x05cf
- 05C3: 0D 13 F1 brclr 6,TSR,$5B7 ; if no compare event has occurred, loop to 0x05b7
- 05C6: B5 17 bita OCRL ; read OCRL to clear output compare flag
- 05C8: 3A A2 dec $A2 ; decrement wait count at 0xa2 loop to 0x05b7 if not zero
- 05CA: 26 EB bne $5B7
- 05CC: CC 06 82 jmp $0682 ; goto 0x0682
- 05CF: A6 44 lda #$44 ; wait = 68
- 05D1: B7 A2 sta $A2
- 05D3: A6 FF lda #$FF ; drive KB_CLOCK high
- 05D5: B7 01 sta PORTB
- 05D7: A6 00 lda #$00 ; reset NCOP
- 05D9: C7 1F F0 sta $1FF0
- 05DC: 00 01 09 brset 0,PORTB,$5E8 ; if KB_DATA is high, goto 0x05e8 (will jump to 0x0682)
- 05DF: 0D 13 F1 brclr 6,TSR,$5D3 ; if no compare event has occurred, loop to 0x05d3
- 05E2: B5 17 bita OCRL ; read OCRL to clear output compare flag
- 05E4: 3A A2 dec $A2
- 05E6: 26 EB bne $5D3
- 05E8: CC 06 82 jmp $0682
- 05EB: A6 09 lda #$09 ; count = 9;
- 05ED: B7 A2 sta $A2
- 05EF: B6 18 lda TRH ; a:x = TR
- 05F1: BE 19 ldx TRL
- 05F3: B5 13 bita TSR ; read TSR followed by ICRH and ICRL to clear ICF
- 05F5: B5 14 bita ICRH
- 05F7: B5 15 bita ICRL
- 05F9: B5 13 bita TSR ; read TSR, then store timer value in OCR (clear OCF, maximise time to output compare)
- 05FB: B7 16 sta OCRH
- 05FD: BF 17 stx OCRL
- 05FF: A6 FF lda #$FF ; drive KB_CLOCK high and release KB_DATA
- 0601: B7 01 sta PORTB
- 0603: A6 02 lda #$02
- 0605: B7 05 sta DDRB
- 0607: A6 00 lda #$00 ; reset NCOP
- 0609: C7 1F F0 sta $1FF0
- 060C: B6 13 lda TSR ; loop to 0x05ff if no input capture/output compare event seen
- 060E: A4 C0 anda #$C0
- 0610: 27 ED beq $5FF
- 0612: 2A 07 bpl $61B ; if input capture event was seen
- 0614: B5 15 bita ICRL ; read ICRL to clear input capture flag
- 0616: 1B B8 bclr 5,$B8 ; expect_ack = false
- 0618: CC 05 7B jmp $057B ; goto 0x057b
- 061B: B5 17 bita OCRL ; read OCRL to clear output compare flag
- 061D: 3A A2 dec $A2 ; if (!--count) goto 0x0682
- 061F: 27 61 beq $682
- 0621: A6 FE lda #$FE ; drive KB_DATA low
- 0623: B7 01 sta PORTB
- 0625: A6 03 lda #$03 ; KB_DATA output, KB_CLOCK output
- 0627: B7 05 sta DDRB
- 0629: CD 07 7D jsr $077D ; bit_delay()
- 062C: A6 FC lda #$FC ; drive KB_DATA and KB_CLOCK low
- 062E: B7 01 sta PORTB
- 0630: CD 07 7D jsr $077D ; bit_delay()
- 0633: A6 FE lda #$FE ; release KB_CLOCK
- 0635: B7 01 sta PORTB
- 0637: CD 07 7D jsr $077D ; bit_delay()
- 063A: A6 FF lda #$FF ; release KB_DATA
- 063C: B7 01 sta PORTB
- 063E: CD 07 7D jsr $077D ; bit_delay()
- 0641: B5 13 bita TSR ; read TSR followed by ICRL to clear input capture flag
- 0643: B5 15 bita ICRL
- 0645: 20 B8 bra $5FF ; loop to 0x05ff
- ; // send reset warning code to host
- ; void send_reset_warning()
- ; {
- ; unsigned char code = ~CODE_RST_WARN; // 0xa5
- ; unsigned i = 8; // 0xa4
- ; do
- ; { // 0x064f
- ; code = (code << 1) + ((code & 0x80) ? 1 : 0); // rotate value left (do first because MSB sent last)
- ; unsigned char val = data | 0x7f; // clock out leftmost bit
- ; PORTB = val = (val << 2) | PB_MASK_KCLK | ((val & 0x80) ? PB_MASK_KDAT : 0);
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = val &= ~PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = val |= PB_MASK_KCLK;
- ; bit_delay();
- ; }
- ; while (--i);
- ; PORTB = ~0x00; // release KDAT cleanly
- ; bit_delay();
- ; DDRB = PB_MASK_KCLK;
- ; }
- 0647: A6 87 lda #$87 ; code = ~CODE_RST_WARN
- 0649: B7 A5 sta $A5
- 064B: A6 08 lda #$08 ; set bit counter at 0xa4 to 8
- 064D: B7 A4 sta $A4
- 064F: B6 A5 lda $A5 ; rotate code left by one bit
- 0651: 48 asla
- 0652: A9 00 adca #$00
- 0654: B7 A5 sta $A5
- 0656: AA 7F ora #$7F ; PORTB = 0xfe | (data >> 7)
- 0658: 99 sec
- 0659: 49 rola
- 065A: 49 rola
- 065B: B7 01 sta PORTB
- 065D: AE 03 ldx #$03 ; KB_DATA output, KB_CLOCK output
- 065F: BF 05 stx DDRB
- 0661: CD 07 7D jsr $077D ; bit_delay()
- 0664: A4 FD anda #$FD ; pull KB_CLOCK low
- 0666: B7 01 sta PORTB
- 0668: CD 07 7D jsr $077D ; bit_delay()
- 066B: AA 02 ora #$02 ; pull KB_CLOCK high
- 066D: B7 01 sta PORTB
- 066F: CD 07 7D jsr $077D ; bit_delay()
- 0672: 3A A4 dec $A4 ; decrement bit counter at 0xa4 and loop to 0x064f if not zero
- 0674: 26 D9 bne $64F
- 0676: A6 FF lda #$FF ; pull KB_CLOCK and KB_DATA high
- 0678: B7 01 sta PORTB
- 067A: CD 07 7D jsr $077D ; bit_delay()
- 067D: A6 02 lda #$02 ; release KB_DATA
- 067F: B7 05 sta DDRB
- 0681: 81 rts ; return
- 0682: 9B sei ; disable interrupts
- 0683: A6 00 lda #$00
- 0685: B7 12 sta TCR ; disable timer/capture/compare interrupts, capture falling edge, drive TCMP low on compare
- 0687: B6 19 lda TRL
- 0689: AB 10 adda #$10
- 068B: 97 tax ; a:x = TR + 16
- 068C: B6 18 lda TRH
- 068E: A9 00 adca #$00
- 0690: B7 16 sta OCRH ; OCRH = a
- 0692: BF 17 stx OCRL ; OCRL = x
- 0694: A6 0A lda #$0A ; wait = 10
- 0696: B7 A2 sta $A2
- 0698: A6 03 lda #$03 ; KB_DATA output, KB_CLOCK output
- 069A: B7 05 sta DDRB
- 069C: A6 FD lda #$FD ; drive KB_CLOCK low
- 069E: B7 01 sta PORTB
- 06A0: A6 00 lda #$00 ; reset NCOP
- 06A2: C7 1F F0 sta $1FF0
- 06A5: A6 41 lda #$41 ; load counter with 65
- 06A7: 5F clrx ; spin 256 iterations decrementing x
- 06A8: 5A decx
- 06A9: 26 FD bne $6A8 ; decrement counter and loop to 0x06a8 if not zero
- 06AB: 4A deca
- 06AC: 26 F9 bne $6A7
- 06AE: 3A A2 dec $A2 ; decrement wait and loop to 0x0698 if not zero
- 06B0: 26 E6 bne $698
- 06B2: B6 03 lda PORTD ; if C-A-A is still held down, loop to 0x0682
- 06B4: A4 8C anda #$8C
- 06B6: 27 CA beq $682
- 06B8: CC 01 02 jmp $0102
- 06BB: B5 13 bita TSR ; read TSR followed by ICRL to clear ICF
- 06BD: B5 15 bita ICRL
- 06BF: 07 B8 14 brclr 3,$B8,$6D6 ; if (resync)
- 06C2: BE B5 ldx $B5 ; if ((a = queue_bytes[queue_head]) == 0xfd)
- 06C4: E6 A6 lda (x+$A6)
- 06C6: A1 FD cmpa #$FD
- 06C8: 26 04 bne $6CE
- 06CA: 17 B8 bclr 3,$B8 ; resync = false
- 06CC: 20 08 bra $6D6 ; else
- 06CE: 17 B8 bclr 3,$B8 ; resync = false
- 06D0: 1C B8 bset 6,$B8 ; retransmit = true
- 06D2: A6 F9 lda #$F9 ; a = 0xf9
- 06D4: 20 33 bra $709 ; goto 0x0709
- 06D6: 0D B8 06 brclr 6,$B8,$6DF ; if (retransmit)
- 06D9: 1D B8 bclr 6,$B8 ; retransmit = false
- 06DB: B6 BA lda $BA ; a = prev_code
- 06DD: 20 2A bra $709 ; goto 0x0709
- 06DF: 05 B8 06 brclr 2,$B8,$6E8 ; if (queue_drop)
- 06E2: 15 B8 bclr 2,$B8 ; queue_drop = false
- 06E4: A6 FA lda #$FA ; a = 0xfa
- 06E6: 20 1F bra $707 ; else
- 06E8: B6 B5 lda $B5 ; a = x = queue_head
- 06EA: 97 tax
- 06EB: B1 B4 cmpa $B4 ; if ((a == queue_tail) && !expect_ack) return from interrupt
- 06ED: 26 06 bne $6F5
- 06EF: 02 B8 03 brset 1,$B8,$6F5
- 06F2: 1B B8 bclr 5,$B8
- 06F4: 80 rti
- 06F5: 13 B8 bclr 1,$B8 ; queue_full = false
- 06F7: E6 A6 lda (x+$A6) ; *(unsigned char *)0xa5 = queue_bytes[queue_head++]
- 06F9: B7 A5 sta $A5
- 06FB: 3C B5 inc $B5
- 06FD: B6 B5 lda $B5 ; if (queue_head >= sizeof(queue_bytes))
- 06FF: A1 0E cmpa #$0E
- 0701: 2B 02 bmi $705
- 0703: 3F B5 clr $B5 ; queue_head = 0
- 0705: B6 A5 lda $A5 ; a = *(unsigned char *)0xa5
- 0707: B7 BA sta $BA ; prev_code = a
- 0709: A8 FF eora #$FF ; code = ~a
- 070B: B7 A5 sta $A5
- 070D: A6 08 lda #$08 ; set bit counter at 0xa4 to 8
- 070F: B7 A4 sta $A4
- 0711: B6 A5 lda $A5 ; rotate code left by one bit
- 0713: 48 asla
- 0714: A9 00 adca #$00
- 0716: B7 A5 sta $A5
- 0718: AA 7F ora #$7F ; PORTB = 0xfe | (data >> 7)
- 071A: 99 sec
- 071B: 49 rola
- 071C: 49 rola
- 071D: B7 01 sta PORTB
- 071F: AE 03 ldx #$03 ; KB_DATA output, KB_CLOCK output
- 0721: BF 05 stx DDRB
- 0723: CD 07 7D jsr $077D ; bit_delay()
- 0726: A4 FD anda #$FD ; pull KB_CLOCK low
- 0728: B7 01 sta PORTB
- 072A: CD 07 7D jsr $077D ; bit_delay()
- 072D: AA 02 ora #$02 ; pull KB_CLOCK high
- 072F: B7 01 sta PORTB
- 0731: CD 07 7D jsr $077D ; bit_delay()
- 0734: 3A A4 dec $A4 ; decrement bit counter at 0xa4 and loop to 0x0711 if not zero
- 0736: 26 D9 bne $711
- 0738: A6 FF lda #$FF ; pull KB_CLOCK and KB_DATA high
- 073A: B7 01 sta PORTB
- 073C: CD 07 7D jsr $077D ; bit_delay()
- 073F: A6 02 lda #$02 ; release KB_DATA
- 0741: B7 05 sta DDRB
- 0743: 1A B8 bset 5,$B8
- 0745: B6 18 lda TRH ; a:x = TR
- 0747: BE 19 ldx TRL
- 0749: B5 13 bita TSR ; clear input capture flag
- 074B: B5 14 bita ICRH
- 074D: B5 15 bita ICRL
- 074F: B5 13 bita TSR
- 0751: B7 16 sta OCRH ; OCRH = a
- 0753: BF 17 stx OCRL ; OCRL = x
- 0755: 80 rti ; return from interrupt
- ; // pulse KDAT low if we don't already have data queued to force a capture interrupt
- ; void force_capture_interrupt()
- ; {
- ; if (!expect_ack)
- ; { // 0x075d
- ; PORTB = ~0x00; // drive KCLK and KDAT high
- ; DDRB = PB_MASK_KDAT | PB_MASK_KCLK;
- ; bit_delay();
- ; PORTB = ~PB_MASK_KDAT; // pulse KDAT low
- ; bit_delay();
- ; PORTB = ~0x00;
- ; bit_delay();
- ; DDRB = PB_MASK_KCLK; // release KDAT
- ; expect_ack = true;
- ; }
- ; }
- 0756: B6 B8 lda $B8
- 0758: A4 20 anda #$20
- 075A: 27 01 beq $75D
- 075C: 81 rts
- 075D: A6 FF lda #$FF
- 075F: B7 01 sta PORTB
- 0761: A6 03 lda #$03
- 0763: B7 05 sta DDRB
- 0765: CD 07 7D jsr $077D
- 0768: A6 FE lda #$FE
- 076A: B7 01 sta PORTB
- 076C: CD 07 7D jsr $077D
- 076F: A6 FF lda #$FF
- 0771: B7 01 sta PORTB
- 0773: CD 07 7D jsr $077D
- 0776: A6 02 lda #$02
- 0778: B7 05 sta DDRB
- 077A: 1A B8 bset 5,$B8
- 077C: 81 rts
- ; // 18 machine cycle delay plus JSR overhead
- ; void bit_delay()
- ; {
- ; nop();
- ; nop();
- ; nop();
- ; nop();
- ; nop();
- ; nop();
- ; }
- 077D: 9D nop
- 077E: 9D nop
- 077F: 9D nop
- 0780: 9D nop
- 0781: 9D nop
- 0782: 9D nop
- 0783: 81 rts
- ; // calculates (unsigned char)~(1 << (val % 9))
- ; unsigned char insert_zero(unsigned char val)
- ; {
- ; unsigned char result = 0xff;
- ; bool msb = false;
- ; do
- ; {
- ; unsigned char const tmp = msb ? 0x01 : 0x00;
- ; msb = result & 0x80;
- ; result = (result << 1) | tmp;
- ; }
- ; while (!(--val & 0x80));
- ; return result;
- ; }
- 0784: B7 A2 sta $A2
- 0786: A6 FF lda #$FF
- 0788: 98 clc
- 0789: 49 rola
- 078A: 3A A2 dec $A2
- 078C: 2A FB bpl $789
- 078E: 81 rts
- ; unsigned char const TRANS_STD[90] = {
- ; 0x45, 0x00, 0x42, 0x62, 0x30, 0x5d,
- ; 0x5a, 0x01, 0x10, 0x20, 0x31, 0x5e,
- ; 0x50, 0x02, 0x11, 0x21, 0x32, 0x3f,
- ; 0x51, 0x03, 0x12, 0x22, 0x33, 0x2f,
- ; 0x52, 0x04, 0x13, 0x23, 0x34, 0x1f,
- ; 0x53, 0x05, 0x14, 0x24, 0x35, 0x3c,
- ; 0x54, 0x06, 0x15, 0x25, 0x36, 0x3e,
- ; 0x5b, 0x07, 0x16, 0x26, 0x37, 0x2e,
- ; 0x55, 0x08, 0x17, 0x27, 0x38, 0x1e,
- ; 0x5c, 0x09, 0x18, 0x28, 0x39, 0x43,
- ; 0x56, 0x0a, 0x19, 0x29, 0x3a, 0x3d,
- ; 0x57, 0x0b, 0x1a, 0x2a, 0x3b, 0x2d,
- ; 0x58, 0x0c, 0x1b, 0x2b, 0x40, 0x1d,
- ; 0x59, 0x0d, 0x44, 0x46, 0x41, 0x0f,
- ; 0x5f, 0x4c, 0x4f, 0x4e, 0x4d, 0x4a };
- 078F: 45 00 42 db $45,$00,$42
- 0792: 62 30 5D db $62,$30,$5D
- 0795: 5A 01 10 db $5A,$01,$10
- 0798: 20 31 5E db $20,$31,$5E
- 079B: 50 02 11 db $50,$02,$11
- 079E: 21 32 3F db $21,$32,$3F
- 07A1: 51 03 12 db $51,$03,$12
- 07A4: 22 33 2F db $22,$33,$2F
- 07A7: 52 04 13 db $52,$04,$13
- 07AA: 23 34 1F db $23,$34,$1f
- 07AD: 53 05 14 db $53,$05,$14
- 07B0: 24 35 3C db $24,$35,$3C
- 07B3: 54 06 15 db $54,$06,$15
- 07B6: 25 36 3E db $25,$36,$3E
- 07B9: 5B 07 16 db $5B,$07,$16
- 07BC: 26 37 2E db $26,$37,$2E
- 07BF: 55 08 17 db $55,$08,$17
- 07C2: 27 38 1E db $27,$38,$1E
- 07C5: 5C 09 18 db $5C,$09,$18
- 07C8: 28 39 43 db $28,$39,$43
- 07CB: 56 0A 19 db $56,$0A,$19
- 07CE: 29 3A 3D db $29,$3A,$3D
- 07D1: 57 0B 1A db $57,$0B,$1A
- 07D4: 2A 3B 2D db $2A,$3B,$2D
- 07D7: 58 0C 1B db $58,$0C,$1B
- 07DA: 2B 40 1D db $2B,$40,$1D
- 07DD: 59 0D 44 db $59,$0D,$44
- 07E0: 46 41 0F db $46,$41,$0F
- 07E3: 5F 4C 4F db $5F,$4C,$4F
- 07E6: 4E 4D 4A db $4E,$4D,$4A
- ; unsigned char const TRANS_MOD[7] = { 0x61, 0x65, 0x67, 0x63, 0x60, 0x64, 0x66 };
- 07E9: 61 65 67 db $61,$65,$67
- 07EC: 63 60 64 db $63,$60,$64
- 07EF: 66 db $66
- ; unsigned char const TRANS_NUM[90] = {
- ; 0x45, 0x00, 0x42, 0x62, 0x30, 0x5d,
- ; 0x5a, 0x01, 0x10, 0x20, 0x31, 0x5e,
- ; 0x50, 0x02, 0x11, 0x21, 0x32, 0x3f,
- ; 0x51, 0x03, 0x12, 0x22, 0x33, 0x2f,
- ; 0x52, 0x5a, 0x13, 0x23, 0x34, 0x1f,
- ; 0x53, 0x5b, 0x14, 0x24, 0x35, 0x3c,
- ; 0x54, 0x5c, 0x15, 0x25, 0x36, 0x3e,
- ; 0x5b, 0x3d, 0x2d, 0x1d, 0x0f, 0x2e,
- ; 0x55, 0x3e, 0x2e, 0x1e, 0x38, 0x1e,
- ; 0x5c, 0x3f, 0x2f, 0x1f, 0x3c, 0x43,
- ; 0x56, 0x5d, 0x4a, 0x5e, 0x3a, 0x3d,
- ; 0x57, 0x0b, 0x1a, 0x2a, 0x3b, 0x2d,
- ; 0x58, 0x0c, 0x1b, 0x2b, 0x40, 0x1d,
- ; 0x59, 0x0d, 0x43, 0x46, 0x41, 0x0f,
- ; 0x5f, 0x4c, 0x4f, 0x4e, 0x4d, 0x4a };
- 07F0: 45 00 42 db $45,$00,$42
- 07F3: 62 30 5D db $62,$30,$5D
- 07F6: 5A 01 10 db $5A,$01,$10
- 07F9: 20 31 5E db $20,$31,$5E
- 07FC: 50 02 11 db $50,$02,$11
- 07FF: 21 32 3F db $21,$32,$3F
- 0802: 51 03 12 db $51,$03,$12
- 0805: 22 33 2F db $22,$33,$2F
- 0808: 52 5A 13 db $52,$5A,$13
- 080B: 23 34 1F db $23,$34,$1F
- 080E: 53 5B 14 db $53,$5B,$14
- 0811: 24 35 3C db $24,$35,$3C
- 0814: 54 5C 15 db $54,$5C,$15
- 0817: 25 36 3E db $25,$36,$3E
- 081A: 5B 3D 2D db $5B,$3D,$2D
- 081D: 1D 0F 2E db $1D,$0F,$2E
- 0820: 55 3E 2E db $55,$3E,$2E
- 0823: 1E 38 1E db $1E,$38,$1E
- 0826: 5C 3F 2F db $5C,$3F,$2F
- 0829: 1F 3C 43 db $1F,$3C,$43
- 082C: 56 5D 4A db $56,$5D,$4A
- 082F: 5E 3A 3D db $5E,$3A,$3D
- 0832: 57 0B 1A db $57,$0B,$1A
- 0835: 2A 3B 2D db $2A,$3B,$2D
- 0838: 58 0C 1B db $58,$0C,$1B
- 083B: 2B 40 1D db $2B,$40,$1D
- 083E: 59 0D 43 db $59,$0D,$43
- 0841: 46 41 0F db $46,$41,$0F
- 0844: 5F 4C 4F db $5F,$4C,$4F
- 0847: 4E 4D 4A db $4E,$4D 4A
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement