diff --git a/Makefile b/Makefile index d470c6e..56ddff9 100755 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ Jr = \ f256/audio.asm \ f256/clock.asm \ f256/console.asm \ + f256/cpu.asm \ f256/dips.asm \ f256/fat32.asm \ f256/flash.asm \ diff --git a/f256/audio.asm b/f256/audio.asm index 7524d6c..81e6aea 100755 --- a/f256/audio.asm +++ b/f256/audio.asm @@ -288,47 +288,6 @@ playnote: sec ; Convert the note character to an index bra loop ; -; Wait for about 1ms -; -wait_1ms: phx - phy - - ; Inner loop is 6 clocks per iteration or 1us - ; Run the inner loop ~1000 times for 1ms - - ldx #3 -wait_outr: ldy #$ff -wait_inner: nop - dey - bne wait_inner - dex - bne wait_outr - - ply - plx - rts - -; -; Wait for 100ms -; -wait_100ms: phx - ldx #100 -wait100l: jsr wait_1ms - dex - bne wait100l - plx - rts - -; -; Wait for some 10ths of seconds -; -; X = number of 10ths of a second to wait -; -wait_tens: jsr wait_100ms - dex - bne wait_tens - rts -; ; Assignment of notes to frequency ; NOTE: in general, this table should support 10-bit values ; we're using just one octave here, so we can get away with bytes @@ -511,59 +470,20 @@ clr_loop: sta SID_LEFT,x stz SID_LEFT+4 stz SID_RIGHT+4 - rts -; -; Wait forever -; - -loop: nop - bra loop - - -; -; Wait for about 1ms -; -wait_1ms: phx - phy - - ; Inner loop is 6 clocks per iteration or 1us - ; Run the inner loop ~1000 times for 1ms - - ldx #3 -wait_outr: ldy #$ff -wait_inner: nop - dey - bne wait_inner - dex - bne wait_outr - - ply - plx rts -; -; Wait for 100ms -; -wait_100ms: phx - ldx #100 -wait100l: jsr wait_1ms - dex - bne wait100l - plx - rts + .endn ; ; Wait for some 10ths of seconds ; ; X = number of 10ths of a second to wait ; -wait_tens: jsr wait_100ms +wait_tens: jsr cpu.wait_100ms dex bne wait_tens rts - .endn - .send .endn .endn diff --git a/f256/cpu.asm b/f256/cpu.asm new file mode 100755 index 0000000..97e5ed6 --- /dev/null +++ b/f256/cpu.asm @@ -0,0 +1,135 @@ +; This file is part of the TinyCore MicroKernel for the Foenix F256. +; Copyright 2022, 2023 Jessie Oberreuter . +; Copyright 2026 Wildbits Computing Company +; SPDX-License-Identifier: GPL-3.0-only + + .cpu "w65c02" + + .namespace platform +cpu .namespace + + + .section dp +self .namespace +wait_count .byte ? + .endn + .send + +; See comment blocks for `wait_20us` and below +WAIT_COUNT_6_3MHz = 21 +WAIT_COUNT_12_6MHz = 47 + + .section global + +init + ; Initialize the `wait_count` + lda #WAIT_COUNT_6_3MHz + jsr is_2x + bcc + + lda #WAIT_COUNT_12_6MHz + + sta self.wait_count + + clc + rts + +is_2x + ; The 7th bit of the machine ID indicates a 2x core; shift it into + ; carry and return + lda $d6a7 + asl a + rts + + +; Wait for approximately but no less than 20 microseconds (including the caller's `jsr`) +wait_20us ; [jsr] 6 cycles + phx ; 3 cycles + ldx self.wait_count ; 3 cycles + - dex ; 2 cycles + bne - ; 2 + 1 if branch is taken + plx ; 4 cycles + rts ; 6 cycles + ; = (21 + 5 * wait_count) cycles +; +; At 6.3 MHz: 1 cycle = 0.15873us +; 20us = 126 cycles +; 21 + 5 * wait_count = 126 +; 5 * wait_count = 105 +; wait_count = 21 + +; +; At 12.6 MHz: 1 cycle = 0.07937us +; 20us = 252 cycles +; 21 + 5 * wait_count = 252 +; 5 * wait_count = 231 +; wait_count = 46.2 +; use 47 to uphold the "no less than 20us" contract + + +wait_x_20us .macro x + phx + ldx #\x + - jsr platform.cpu.wait_20us + dex + bne - + plx + .endmacro + +; Wait for approximately but no less than 100 microseconds +wait_100us + .wait_x_20us 5 + rts + +; Wait for approximately but no less than 1 ms +wait_1ms + .wait_x_20us 50 + rts + +; Wait for approximately but no less than `X` ms +wait_x_ms + - jsr wait_1ms + dex + bne - + rts + +.namespace self +; Wait for approximately but no less than `YX` ms; `Y` is a biased page count, +; not the raw high byte; see `wait_ms` for the encoding +wait_yx_ms + - jsr wait_1ms + dex + bne - + dey + bne - + rts +.endn + + +; Wait for approximately but no less than the specified number of ms +wait_ms .macro ms + .cerror \ms <= 0, "Expected a positive number" + .cerror \ms > $FF00, "Can't wait for longer than ", $FF00, " ms at a time" + .if \ms > 255 + phx + phy + ldx #<\ms + ldy #(>\ms) + ((<\ms) != 0 ? 1 : 0) + jsr platform.cpu.self.wait_yx_ms + ply + plx + .else + phx + ldx #\ms + jsr platform.cpu.wait_x_ms + plx + .endif + .endmacro + +; Wait for approximately but no less than 100 ms +wait_100ms + .wait_ms 100 + rts + + .send + + .endn + .endn diff --git a/f256/iec.asm b/f256/iec.asm index 97a097d..42ce3e0 100755 --- a/f256/iec.asm +++ b/f256/iec.asm @@ -156,16 +156,16 @@ _out init .proc - jsr sleep_1ms + jsr cpu.wait_1ms stz io_ctrl jsr release_ATN jsr release_DATA jsr release_SREQ ;jsr release_CLOCK ; IDLE state jsr assert_CLOCK ; IDLE state - jsr sleep_1ms - jsr sleep_1ms - jsr sleep_1ms + jsr cpu.wait_1ms + jsr cpu.wait_1ms + jsr cpu.wait_1ms clc rts .pend @@ -183,7 +183,6 @@ self .namespace eoi_pending .byte ? rx_eoi .fill 0 ; shared with mark mark .byte ? -sleep20 .byte ? jiffy .byte ? ; jiffy support (0: no/not tested, <0: jiffy detected) slow .byte ? ; <0: suppress JiffyDOS for the current command. ; The fast protocol corrupts the drive's command- @@ -210,14 +209,6 @@ init ; Initialize the port and make sure ATN and SREQ aren't stuck. ; Carry set on error. - pha - lda #20 - bit $d6a7 ; MID - bpl _iec_init - lda #50 -_iec_init - sta self.sleep20 - pla jsr platform.iec.port.init DBG_CALL debug_init stz self.slow @@ -234,7 +225,7 @@ _iec_init jsr platform.iec.port.read_ATN bcc _err - jsr sleep_1ms + jsr cpu.wait_1ms clc rts @@ -281,7 +272,7 @@ TALK_SA ldy #0 _wait jsr platform.iec.port.read_CLOCK bcc _ok - jsr sleep_20us + jsr cpu.wait_20us iny bne _wait dex @@ -361,9 +352,9 @@ atn_release sei jsr platform.iec.port.release_ATN - jsr sleep_20us - jsr sleep_20us - jsr sleep_20us + jsr cpu.wait_20us + jsr cpu.wait_20us + jsr cpu.wait_20us jsr platform.iec.port.release_CLOCK jsr platform.iec.port.release_DATA cli @@ -384,7 +375,7 @@ atn_common cli ; Now give the devices ~1ms to start listening. - jsr sleep_1ms + jsr cpu.wait_1ms ; If no one is listening, there's nothing on ; the bus, so signal an error. @@ -427,7 +418,7 @@ send_common ; There must be at least 100us between bytes. - jsr sleep_100us + jsr cpu.wait_100us jsr platform.iec.port.read_ATN bcc _not_jiffy @@ -453,7 +444,7 @@ _not_jiffy _wait ; We're still asserting DATA. cli - jsr sleep_20us + jsr cpu.wait_20us ; If the other listeners are ready, we need to respond ; quickly, so disable interrupts and "peek" at the @@ -495,13 +486,13 @@ _Tye jsr platform.iec.port.read_DATA ; The drive should hold DATA for at least 60us. Give it ; 20us, and then repeat our ersatz listener trick. - jsr sleep_20us + jsr cpu.wait_20us jsr platform.iec.port.assert_DATA bra _wait _send ; Give the listeners time to notice that the've all ack'd - jsr sleep_20us ; NOT on the C64 + jsr cpu.wait_20us ; NOT on the C64 ; Now start pushing out the bits. Note that the timing ; is not critical, but each clock state must last at @@ -526,7 +517,7 @@ _send_bit ; Clock out the next bit jsr platform.iec.port.assert_CLOCK - jsr sleep_20us + jsr cpu.wait_20us lsr a bcs _one bcc _zero @@ -537,11 +528,11 @@ _one jsr platform.iec.port.release_DATA _clock ; Toggle the clock; interrupts are fine here cli - jsr sleep_20us ; TODO: Maybe extend this. + jsr cpu.wait_20us ; TODO: Maybe extend this. - jsr sleep_20us ; 1541 needs this. + jsr cpu.wait_20us ; 1541 needs this. jsr platform.iec.port.release_CLOCK - jsr sleep_20us + jsr cpu.wait_20us jsr platform.iec.port.release_DATA dex bpl _loop @@ -576,7 +567,7 @@ _ack jsr platform.iec.port.read_DATA lda #50 _ack jsr platform.iec.port.read_DATA bcc _done - jsr sleep_20us + jsr cpu.wait_20us dec a bne _ack sec @@ -584,35 +575,6 @@ _ack jsr platform.iec.port.read_DATA _done rts -sleep_20us - phx - ldx self.sleep20 -_loop dex - bne _loop - plx - rts - -sleep_100us - phx - ldx #5 -_loop jsr sleep_20us - dex - bne _loop - plx - rts - -sleep_300us - jsr sleep_100us - jsr sleep_100us - jsr sleep_100us - rts - -sleep_1ms - jsr sleep_300us - jsr sleep_300us - jsr sleep_300us - jmp sleep_100us - recv_data @@ -658,9 +620,9 @@ _eoi ; Ack the EOI; we can enable IRQs for this. jsr platform.iec.port.assert_DATA cli - jsr sleep_20us - jsr sleep_20us - jsr sleep_20us + jsr cpu.wait_20us + jsr cpu.wait_20us + jsr cpu.wait_20us ; Set the EOI flag. dec self.rx_eoi ; TODO: error on second round @@ -691,17 +653,17 @@ _wait_rise jsr platform.iec.port.read_CLOCK plx ; Ack - jsr sleep_20us + jsr cpu.wait_20us jsr platform.iec.port.assert_DATA cli ; Drives /usually/ work with a lot less, but ; I see failures on the SD2IEC on a status check ; after file-not-found when debugging is turned off. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. - jsr sleep_20us ; Seems to be missing the ack. + jsr cpu.wait_20us ; Seems to be missing the ack. + jsr cpu.wait_20us ; Seems to be missing the ack. + jsr cpu.wait_20us ; Seems to be missing the ack. + jsr cpu.wait_20us ; Seems to be missing the ack. ;DBG_CALL debug_ACK DBG_CALL debug_write diff --git a/f256/jiffy.asm b/f256/jiffy.asm index 63e4f4a..1ad22a2 100755 --- a/f256/jiffy.asm +++ b/f256/jiffy.asm @@ -205,7 +205,7 @@ _ack ;DBG_CALL debug_ACK _end jsr platform.iec.port.assert_CLOCK ; back to idle state asserting CLOCK - jsr sleep_20us + jsr cpu.wait_20us ply plx @@ -250,7 +250,7 @@ _wait1 jsr platform.iec.port.read_CLOCK ldy #0 _wait2 jsr platform.iec.port.read_CLOCK bcs _ready - jsr sleep_20us + jsr cpu.wait_20us iny bne _wait2 inx diff --git a/f256/jr.asm b/f256/jr.asm index c30baa8..dd97bc9 100755 --- a/f256/jr.asm +++ b/f256/jr.asm @@ -202,6 +202,9 @@ _zero stz Stack,x ldx #$ff txs + ; Initialize CPU-specific platform state + jsr cpu.init + ; Initialize the SPI flash so we can read its startup data jsr spi_flash.init diff --git a/f256/k2_lcd.asm b/f256/k2_lcd.asm index 8f2cd1d..1532166 100755 --- a/f256/k2_lcd.asm +++ b/f256/k2_lcd.asm @@ -174,13 +174,13 @@ lcd_cmd .macro cmd, data LCD_1_69_Init ; ST7789V requires waiting for 120ms after releasing reset before sending SLPOUT - .wait_ms 120 + .platform.cpu.wait_ms 120 ; Turn off sleep mode .lcd_cmd SLPOUT, [] ; Wait 5ms for supply voltages and clock circuits to stabilize - .wait_ms 5 + .platform.cpu.wait_ms 5 ; LCD raster format: top-to-bottom, left-to-right, RGB .lcd_cmd MADCTL, [$00] @@ -251,8 +251,8 @@ Splash_LCD_Download: ; Tell the LCD to expect raster data .lcd_cmd RAMWR, [] - ; The raster is stored bottom-up. Start at its last row and walk - ; backward one 480-byte row at a time. + ; The raster is stored bottom-up. Start at its last row and walk + ; backward one 480-byte row at a time. lda #LCD_LAST_ROW @@ -283,7 +283,7 @@ _main_loop: ora rows_remaining+1 beq _out - ; Advance to the preceding row in the bottom-up raster + ; Advance to the preceding row in the bottom-up raster sec lda platform.spi_flash.src sbc #