more JiffyDOS code - low nibble TX, general turbo dispatcher

This commit is contained in:
FeralChild64 committed 2019-11-18 19:03:05 +01:00
1 parent 28bc07ea23
commit d0fd34e79f
10 files changed
+422 -293

No files matched your search

+4
View File
@@ -14,7 +14,11 @@ ACPTR:
jsr kernalstatus_reset
#if CONFIG_IEC
#if CONFIG_IEC_JIFFYDOS
jmp iec_rx_dispatch
#else // no turbo supported
jmp iec_rx_byte
#endif
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+4
View File
@@ -33,7 +33,11 @@ ciout_store_in_buffer:
ciout_send_byte:
clc // don't send with EOI
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else // no turbo supported
jsr iec_tx_byte
#endif
inc C3PO // iec_tx_byte sets it to 0, but we still have something to send
jmp ciout_store_in_buffer
+173 -184
View File
@@ -1,184 +1,173 @@
//
// JiffyDOS protocol support for IEC
//
// XXX finish this
#if CONFIG_IEC_JIFFYDOS
// JiffyDOS timing regime is very strict - before transmitting anything
// we need to disable sprites and (if screen is not disabled) wait for
// appropriate moment, so that no badline interruption can happen
iec_tx_byte_jiffydos:
// We need to preserve 3 lowest bits of CIA2_PRA - as they encode
// Use C3PO for this, as afterwards we have to set there 0 nevertheless
lda CIA2_PRA
and #%00000111
sta C3PO
// Hide sprites, store their previous status on stack
jsr jiffydos_hide_sprites
pha
// Prepare nibbles to send
lda TBTCNT
and #$0F
pha
lda TBTCNT
and #$F0
pha
// Wait till receiver is ready
jsr iec_wait_for_data_release
__jd_check1:
// Wait till it is safe to send data
jsr jiffydos_wait_line
// Notify device that we are going to send byte by releasing everything
// Cycles: 3 + 4 = 7
lda C3PO
sta CIA2_PRA
// Send high nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21
pla // retrieve high nibble from stack
ora C3PO // restore VIC-II and RS-232 bits
sta CIA2_PRA // bits 4 and 5 on CLK/DATA
ror // move bits 6 and 7 to positions 4 and 5
ror
and #%00110000 // clear everything but CLK/DATA
sta CIA2_PRA // bits 6 and 7 on CLK/DATA
// Send low nibble; cycles: XXX
// XXX something strange seems to happen with low nibble:
// $0 -> $00
// $1 -> $80 = $10 + $70
// $2 -> $20
// $3 -> $A0 = $30 + $70
// $4 -> $40
// $5 -> $C0 = $50 + $70
// $6 -> $60
// $7 -> $E0 = $70 + $70
// $8 -> $10 = $80 - $70
// $9 -> $90
// $A -> $30 = $A0 - $70
// $B -> $B0
// $C -> $50 = $C0 - $70
// $D -> $D0
// $E -> $70 = $E0 - $70
// $F -> $F0
// XXX why??? how this is calculated???
// XXX EOI signalled by early CLK (20us delay for non-CLK?)
// Re-enable sprites
pla
lda VIC_SPENA
// Mark TX buffer as empty
lda #$00
sta C3PO
rts
iec_rx_byte_jiffydos:
// Hide sprites, store their previous status on stack
jsr jiffydos_hide_sprites
pha
// Wait until device is ready to send
jsr iec_wait_for_clk_release
// Prepare 'start sending' message
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
pha
// Wait for appropriate moment
jsr jiffydos_wait_line
// Ask device to start sending bits
pla
sta CIA2_PRA
// XXX retrieve byte
// Re-enable sprites
pla
lda VIC_SPENA
rts
jiffydos_wait_line:
lda VIC_SCROLY
and #$10
beq jiffydos_wait_line_done // screen is disabled, no need to watch for badlines
// To give the transfer routine as much time as possible,
// wait till a badline
// XXX this is probably overkill, most likely it is enough to avoid 2 (3?) lines
// before badline - to be adjusted in the future
!:
sec
lda VIC_SCROLY
sbc VIC_RASTER
and #$07 // we want 8 lowest bits
bne !-
jiffydos_wait_line_done:
rts
__jd_check2:
jiffydos_hide_sprites:
lda VIC_SPENA
ldx #$00
stx VIC_SPENA
rts
.function SAME_PAGE_CHECK(label_1, label_2)
{
#if PASS_SIZETEST
.return (label_1 - label_1 % 256) == (label_2 - label_2 % 256)
#else
.return true
#endif
}
.if (!SAME_PAGE_CHECK(__jd_check1, __jd_check2))
{
// To meet the strict JiffyDOS timing, we need to make sure
// it does not span across multiple pages, as this would add
// 1 cycle to some jump instructions - maybe this wont cause
// problems, but better safe than sorry.
.error "JiffyDOS code can't span across multiple pages"
}
#endif // CONFIG_IEC_JIFFYDOS
//
// JiffyDOS protocol support for IEC
//
// XXX finish this
#if CONFIG_IEC_JIFFYDOS
// JiffyDOS timing regime is very strict - before transmitting anything
// we need to disable sprites and (if screen is not disabled) wait for
// appropriate moment, so that no badline interruption can happen
iec_tx_byte_jiffydos:
// We need to preserve 3 lowest bits of CIA2_PRA - as they encode
// Use C3PO for this, as afterwards we have to set there 0 nevertheless
lda CIA2_PRA
and #%00000111
sta C3PO
// Hide sprites, store their previous status on stack
jsr jiffydos_hide_sprites
pha
// Prepare nibbles to send
lda TBTCNT
and #$0F
tax
lda iec_jiffydos_bittable, X // low nibble has to be encoded
pha
lda TBTCNT
and #$F0
pha
// Wait till receiver is ready
jsr iec_wait_for_data_release
__jd_check1:
// Wait till it is safe to send data
jsr jiffydos_wait_line
// Notify device that we are going to send byte by releasing everything
// Cycles: 3 + 4 = 7
lda C3PO
sta CIA2_PRA
// Send high nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21
pla // retrieve high nibble from stack
ora C3PO // restore VIC-II and RS-232 bits
sta CIA2_PRA // bits 4 and 5 on CLK/DATA
ror // move bits 6 and 7 to positions 4 and 5
ror
and #%00110000 // clear everything but CLK/DATA
sta CIA2_PRA // bits 6 and 7 on CLK/DATA
// Send low nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21
pla // retrieve low nibble from stack
ora C3PO // restore VIC-II and RS-232 bits
sta CIA2_PRA
ror
ror
and #%00110000 // clear everything but CLK/DATA
sta CIA2_PRA
// XXX EOI signalled by early CLK (20us delay for non-CLK?)
// Re-enable sprites
pla
lda VIC_SPENA
// Mark TX buffer as empty
lda #$00
sta C3PO
rts
iec_rx_byte_jiffydos:
// Hide sprites, store their previous status on stack
jsr jiffydos_hide_sprites
pha
// Wait until device is ready to send
jsr iec_wait_for_clk_release
// Prepare 'start sending' message
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
pha
// Wait for appropriate moment
jsr jiffydos_wait_line
// Ask device to start sending bits
pla
sta CIA2_PRA
// XXX retrieve byte
// Re-enable sprites
pla
lda VIC_SPENA
rts
jiffydos_wait_line:
lda VIC_SCROLY
and #$10
beq jiffydos_wait_line_done // screen is disabled, no need to watch for badlines
// To give the transfer routine as much time as possible,
// wait till a badline
// XXX this is probably overkill, most likely it is enough to avoid 2 (3?) lines
// before badline - to be adjusted in the future
!:
sec
lda VIC_SCROLY
sbc VIC_RASTER
and #$07 // we want 8 lowest bits
bne !-
jiffydos_wait_line_done:
rts
__jd_check2:
jiffydos_hide_sprites:
lda VIC_SPENA
ldx #$00
stx VIC_SPENA
rts
.function SAME_PAGE_CHECK(label_1, label_2)
{
#if PASS_SIZETEST
.return (label_1 - label_1 % 256) == (label_2 - label_2 % 256)
#else
.return true
#endif
}
.if (!SAME_PAGE_CHECK(__jd_check1, __jd_check2))
{
// To meet the strict JiffyDOS timing, we need to make sure
// it does not span across multiple pages, as this would add
// 1 cycle to some jump instructions - maybe this wont cause
// problems, but better safe than sorry.
.error "JiffyDOS code can't span across multiple pages"
}
#endif // CONFIG_IEC_JIFFYDOS
+33
View File
@@ -0,0 +1,33 @@
//
// Helper table for encoding lower nibble for JiffyyDOS,
// values found by observing the actual transfer
//
#if CONFIG_IEC_JIFFYDOS
// XXX consider calculating the values on-the-fly
iec_jiffydos_bittable:
.byte $00
.byte $80 // $10 + $70
.byte $20
.byte $A0 // $30 + $70
.byte $40
.byte $C0 // $50 + $70
.byte $60
.byte $E0 // $70 + $70
.byte $10 // $80 - $70
.byte $90
.byte $30 // $A0 - $70
.byte $B0
.byte $50 // $C0 - $70
.byte $D0
.byte $70 // $E0 - $70
.byte $F0
#endif // CONFIG_IEC_JIFFYDOS
+32
View File
@@ -0,0 +1,32 @@
//
// Arbitration code for normal/turbo transfer
//
#if CONFIG_IEC_JIFFYDOS
iec_rx_dispatch:
lda IECPROTO
#if CONFIG_IEC_JIFFYDOS
cmp #$01
beq iec_rx_dispatch_jiffydos
#endif // CONFIG_IEC_JIFFYDOS
// FALLTROUGH
iec_rx_dispatch_normal:
plp
jmp iec_rx_byte
#if CONFIG_IEC_JIFFYDOS
iec_rx_dispatch_jiffydos:
plp
jmp iec_rx_byte_jiffydos
#endif // CONFIG_IEC_JIFFYDOS
#endif // any turbo supported
+7 -7
View File
@@ -68,21 +68,21 @@ iec_tx_common_sendbit:
cpx #$00
bne !+ // branch if not sending the last bit
ldy #$1B // 400us is nearly 410 cycles on NTSC
// loop iteration below is 15 cycles,
ldy #$25 // 400us is nearly 410 cycles on NTSC
// loop iteration below is 11 cycles,
// and several cycles were already used
iec_jiffydos_detect_loop:
lda CIA2_PRA // 4 cycles
bpl iec_jiffydos_detected // 2 cycles
dey // 2 cycles
bne iec_jiffydos_detect_loop // 2 cycles
bne iec_jiffydos_detect_loop // 3 cycles if branch
lda #$00 // 2 cycles
beq iec_jiffydos_store_proto // 3 cycles, branch always
lda #$00 // normal protocol
skip_2_bytes_trash_nvz
iec_jiffydos_detected:
panic #$FF // WHOAAAA! He wants to speak jiffy, but I do not know this language yet!
lda #$01 // JiffyDOS protocol
iec_jiffydos_store_proto:
sta IECPROTO
+33
View File
@@ -0,0 +1,33 @@
//
// Arbitration code for normal/turbo transfer
//
#if CONFIG_IEC_JIFFYDOS
iec_tx_dispatch:
php // preserve C flag for EOI indication
lda IECPROTO
#if CONFIG_IEC_JIFFYDOS
cmp #$01
beq iec_tx_dispatch_jiffydos
#endif // CONFIG_IEC_JIFFYDOS
// FALLTROUGH
iec_tx_dispatch_normal:
plp
jmp iec_tx_byte
#if CONFIG_IEC_JIFFYDOS
iec_tx_dispatch_jiffydos:
plp
jmp iec_tx_byte_jiffydos
#endif // CONFIG_IEC_JIFFYDOS
#endif // any turbo supported
+12
View File
@@ -71,10 +71,18 @@ load_iec:
// Get load address
#if CONFIG_IEC_JIFFYDOS
jsr iec_rx_dispatch
#else // no turbo supported
jsr iec_rx_byte
#endif
bcs load_iec_file_not_found
sta EAL+0
#if CONFIG_IEC_JIFFYDOS
jsr iec_rx_dispatch
#else // no turbo supported
jsr iec_rx_byte
#endif
bcs load_iec_file_not_found
sta EAL+1
@@ -92,7 +100,11 @@ load_iec:
iec_load_loop:
// We are now ready to receive bytes
#if CONFIG_IEC_JIFFYDOS
jsr iec_rx_dispatch
#else // no turbo supported
jsr iec_rx_byte
#endif
bcs load_iec_error
// Handle the byte (store in memory / verify)
+114 -102
View File
@@ -1,102 +1,114 @@
//
// IEC part of the SAVE routine
//
#if CONFIG_IEC
save_iec_dev_not_found:
jmp lvs_device_not_found_error
save_iec:
// Check file name
lda FNLEN
beq_far kernalerror_FILE_NAME_MISSING
// Display SAVING
jsr lvs_display_saving
// Call device to LISTEN
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
// Open channel 1 (reserved for file writing)
lda #$01
jsr iec_cmd_open
bcs save_iec_dev_not_found
// Send file name
jsr iec_send_file_name
bcs save_iec_dev_not_found
// Call device to LISTEN once again
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
lda #$61 // open channel / data (p3) , required according to p13
sta TBTCNT
jsr iec_tx_command
bcs save_iec_dev_not_found
// Save start address
lda STAL+0
sta TBTCNT
clc
jsr iec_tx_byte
lda STAL+1
sta TBTCNT
clc
jsr iec_tx_byte
jsr lvs_setup_MEMUSS
ldy #$00
iec_save_loop:
// Retrieve byte to send
#if CONFIG_MEMORY_MODEL_60K
ldx #<MEMUSS+0
jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (MEMUSS),y
#endif
// Send the byte
sta TBTCNT
clc
jsr iec_tx_byte
// Next iteration
jsr lvs_advance_MEMUSS_check_EAL
bne iec_save_loop
iec_save_loop_end:
// Close file on drive
lda FA
jsr UNLSN
lda FA
jsr LISTEN
lda #$E1 // CLOSE command
sta TBTCNT
jsr iec_tx_command
jsr iec_tx_command_finalize
// Tell drive to unlisten
lda FA
jsr UNLSN
// Return success
clc
rts
#endif // CONFIG_IEC
//
// IEC part of the SAVE routine
//
#if CONFIG_IEC
save_iec_dev_not_found:
jmp lvs_device_not_found_error
save_iec:
// Check file name
lda FNLEN
beq_far kernalerror_FILE_NAME_MISSING
// Display SAVING
jsr lvs_display_saving
// Call device to LISTEN
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
// Open channel 1 (reserved for file writing)
lda #$01
jsr iec_cmd_open
bcs save_iec_dev_not_found
// Send file name
jsr iec_send_file_name
bcs save_iec_dev_not_found
// Call device to LISTEN once again
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
lda #$61 // open channel / data (p3) , required according to p13
sta TBTCNT
jsr iec_tx_command
bcs save_iec_dev_not_found
// Save start address
lda STAL+0
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else // no turbo supported
jsr iec_tx_byte
#endif
lda STAL+1
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else // no turbo supported
jsr iec_tx_byte
#endif
jsr lvs_setup_MEMUSS
ldy #$00
iec_save_loop:
// Retrieve byte to send
#if CONFIG_MEMORY_MODEL_60K
ldx #<MEMUSS+0
jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (MEMUSS),y
#endif
// Send the byte
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else // no turbo supported
jsr iec_tx_byte
#endif
// Next iteration
jsr lvs_advance_MEMUSS_check_EAL
bne iec_save_loop
iec_save_loop_end:
// Close file on drive
lda FA
jsr UNLSN
lda FA
jsr LISTEN
lda #$E1 // CLOSE command
sta TBTCNT
jsr iec_tx_command
jsr iec_tx_command_finalize
// Tell drive to unlisten
lda FA
jsr UNLSN
// Return success
clc
rts
#endif // CONFIG_IEC
+10
View File
@@ -26,6 +26,16 @@ TALK:
// Encode and execute the command
ora #$40
#if CONFIG_IEC_JIFFYDOS
// XXX temporary, until receiving is implemented too
sta TBTCNT
lda #$00 // standard protocol
sta IECPROTO
jmp iec_tx_command
#endif // CONFIG_IEC_JIFFYDOS
common_talk_listen: // common part of TALK and LISTEN
sta TBTCNT