Page 2 of 2

Re: How to read bits from tape

Posted: Mon Apr 01, 2019 6:42 am
by nippur72
I got it! :D

Thanks to this post and this github repo by @pixel I got a better understanding.

Basically you program the VIA chip to trigger an interrupt when the cassette bit changes; the VIA counter contains the length of the received pulse.

I finally wrote the monitor program I wanted to write back in 2006. It's published here. It changes 36878 and 36879 when a pulse is received.

The monitor will be very useful as I'm playing with a FPGA (Mistica board) and want to implement real tape loading in the existing VIC-20 implementation. I need it as a debug tool.

Code: Select all

   processor 6502

   include <macros.lm>
   include <macros_16.lm>

   include <vic20.lm>
   
   org BASIC_RAM

   basic start
      10 sys {tapemon}
   basic end

dim tape_old_irq as word

const IRQ = $314
const VIA2_COUNTER = $9124
const VIA2_ACR     = $912b
const VIA2_PCR     = $912e

const TIMER_VALUE = $ffff

const COLOR1 = 3*16+3+8
const COLOR2 = 1*16+1+8

sub tapemon()

   ; not sure: disable all interrupts
   sei
   lda #$7f
   sta $911e  ; VIA 1 Interrupt Enable Register
   sta $912e  ; VIA 2 Interrupt Enable Register
   sta $912d  ; VIA 1 Interrupt Flag Register

   ; Start tape motor
   lda $911c
   and #$fd
   sta $911c

   ; Set IRQ vector
   ld16 tape_old_irq, IRQ
   ld16 IRQ, #bit_received

   ; Initialise VIA2 Timer 1 (cassette tape read)
   ld16 VIA2_COUNTER, TIMER_VALUE   ; Restart timer
   ld VIA2_ACR, #%00000000          ; One-shot mode
   ld VIA2_PCR, #%10000010          ; CA1 IRQ enable (tape pulse)

   ; Let the IRQ handler do everything
   cli
   clc   
   do : loop while not carry

; this routine gets triggered when the edge of the tape bit 
; is detected or when the timer counter underflows

bit_received:
   
   ; an actual bit decoding routine should look at underflow bit
   ; lda $912d       ; Get timer underflow bit.
   ; asl             ; Move underflow bit into carry.
   ; asl             ;
   ; it should also look into the counter value?

   ; color effect   
   lda $900f
   if a=#COLOR1 then 
      ld a, #COLOR2
   else
      ld a, #COLOR1
   end if
   sta $900f
       
   ; sound effect
   lda 36878
   if a=#15 then 
      ld a, #0
   else
      ld a, #15
   end if
   sta 36878

   ld16 VIA2_COUNTER, TIMER_VALUE        ; Restart timer.

   ; not sure: prepare for re-trigger?
   lda #$7f
   sta $912d

   ; complete the interrupt routine
   jmp $eb18

end sub

Re: How to read bits from tape

Posted: Mon Apr 01, 2019 9:36 am
by nippur72
ops wrote:I have disassembled Anirog fast loader, see https://github.com/ops/anirog-copy
Interesting, it doesn't seem to use IRQ at all...

Re: How to read bits from tape

Posted: Mon Apr 01, 2019 10:14 am
by nippur72
I have a new simpler version based on the Anirog loader, but still not easy to understand :(

Code: Select all

   sei
   lda #$27
   sta $9128
   ldx #$01

loop:
   lda #$02
   do
      bit     $912D
   loop while zero

   ; ???
   lda $912D
   stx $9129
   bit $9121   
   asl     
   asl     
   asl     

   ; color effect   
   lda $900f
   if a=#COLOR1 then 
      ld a, #COLOR2
   else
      ld a, #COLOR1
   end if
   sta $900f

   ; sound effect
   lda 36878
   if a=#15 then 
      ld a, #0
   else
      ld a, #15
   end if
   sta 36878
   
   jmp loop

Re: How to read bits from tape

Posted: Tue Apr 09, 2019 6:08 pm
by Forbidden64
nippur72 wrote:@Forbidden64, was him Luigi Di Fraia ?

Ya, that is the guy. Somewhere, i can't find it, he did a complete analysis of Rabbit's fast loader for the VIC-20.

Interestingly though, the 6522 seems to allow for automatic control of all this stuff. They just didn't use it likely because Chuck Peddle had hand tuned the original datasette operation with an oscilloscope and tuned it in software. He later said that he got burned out on programming from doing that project.

Since Chuck was gone, they had to do a reverse engineer to mirror a compatible version of what he had done. So my understanding is they tried successfully to reproduce what he had done in software. That said, the VIA is highly capable and doesn't necessarily require bit banging. The 6526 does though on the c64 because from my understanding, the shift register doesn't work internally. I'm sure eslapion would know better than I on that portion.

Re: How to read bits from tape

Posted: Fri Apr 26, 2019 9:15 am
by nippur72
one more question: the cassette write bit is on port B of the secondo VIA (bit 3) which is also shared with keyboard column read ... how can I separate the two cases, e.g. how can I tell I am "saving" and thus the bit 3 is meaningful vs I am not "saving" and I am scanning the keyboard.

I see that during save the keyboard doesn't affect this bit.... how this is done?

Re: How to read bits from tape

Posted: Fri Apr 26, 2019 9:59 am
by Mike
During KERNAL tape operations, the IRQ is re-vectored and doesn't anymore scan the keyboard - except for the STOP key.

Re: How to read bits from tape

Posted: Mon Apr 29, 2019 6:08 am
by highinfidelity
Now that the issue has been settled - I don't even understand if this is somehow related, but I remember that on the VIC20 manual, among the last "technical" pages, there was a sample program that was supposed to read data from tape by "buffering" them. The text pretended that the tape would stop-and-go intermittently, which should have been a clear demonstration that the VIC was actually "buffering" from the Datassette. I was very curious to see that happening, but the program was either incomplete or was supposed to be used in an environment about which I had no knowledge, and I could never actually see that "buffering" stop-and-go. Did anyone else tried or remember what I'm talking about?

Re: How to read bits from tape

Posted: Mon Apr 29, 2019 10:44 am
by Mike
The examples in the User's Guide for storing/retrieving tape data files work fine as is.

The tape buffer takes 192 bytes and is only written when full or when the file is closed. Likewise, on read first the buffer is filled (upon the first GET# or INPUT# on an empty buffer) and then the tape is stopped until a GET# or INPUT# has consumed all the data in the tape buffer - which then starts the motor again, reads the next data block from tape, and once again stops the motor.

Note those data files can only be read back by an OPEN, GET#/INPUT#, CLOSE sequence (or the equivalent KERNAL calls OPEN, CHKIN, CHRIN/GETIN, CLRCHN, CLOSE). They're not compatible with the KERNAL LOAD routine.

With KERNAL SAVE/LOAD on tape no buffering takes place, the bytes are directly written in a single block from memory to tape or read from tape to memory (... O.K., there's also the second copy of the header and payload being stored, and used for error checking on LOAD/VERIFY but I just mention this in passing ...).