6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Oct 05, 2024 6:22 pm

All times are UTC




Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: 6522 VIA partial shifts?
PostPosted: Fri Apr 15, 2022 11:53 am 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
Can the 6522 shift register do more or less than 8 shifts?

I'm thinking of replacing my 3 chip PS/2 keyboard solution of inverter + two external '595's with a simple software solution:

1) Use the 6522 shift register, mode 011
2) Ignore the IRQ after 8 shifts and just reset it.
3) Instead use T2/PB6 input counting set to 9 counts
4) Read the shift register during the 9 count IRQ, which should mean the start bit has been shifted out but the parity and stop bit hasn't been shiftet in yet == 8 data bits.
5) Reset the shift register after I have what I need and get ready for new data

Any reason this won't work? As far as I know the shift register keeps data until it's shifted out, right?

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 15, 2022 12:38 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
I'm pretty sure it's just a circular buffer. If you don't provide new data, but are using an external clock, it will keep shifting out the last 8 bit pattern you provided. For input if you don't read it in time the oldest bit will be lost when the next bit is shifted in. The interrupts are there to help you know when it's been 8 shifts since you last did something to it, so it's up to you whether you use them or not.


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 15, 2022 12:53 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
gfoot wrote:
I'm pretty sure it's just a circular buffer. If you don't provide new data, but are using an external clock, it will keep shifting out the last 8 bit pattern you provided. For input if you don't read it in time the oldest bit will be lost when the next bit is shifted in. The interrupts are there to help you know when it's been 8 shifts since you last did something to it, so it's up to you whether you use them or not.


That’s how I understand it as well. And if I keep my own count, I should be able to squeeze in a sampling of the shift register at clock number 9 even though clock 10 and 11 will eventually corrupt the data I need.
At 10-15khz ps/2 clock it shouldn’t be a problem to sample before the data is gone.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 15, 2022 4:10 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1041
Location: near Heidelberg, Germany
The 6526 shift register was used for RS232 in a way like you suggest, to achieve 9600 baud RS232 on a C64 userport (that, with bit banging would only go up to 2400 baud)

For output, it would first output start bit + 7 data bits, plus in a second byte, the 8th data bit and the stop bit(s), with the rest being filled up with 1s.

For input, another input would be used as trigger on the start bit (via NMI), then the timer would be set, and 8 data bits being shifted in based on timer (not on external clock).

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 15, 2022 5:17 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
AndersNielsen wrote:
5) Reset the shift register after I have what I need and get ready for new data

FWIW, I discovered the hard way that a VIA timer doesn't necessarily reset as you might expect it to do. Dunno if the shift reg might have similar quirks, but it's something to be on guard for.

Briefly, I had a situation where the entire machine (including the VIA) had had a hardware reset; then there was some code that programmed T1 of the VIA for square wave output on PB7. (It's all part of the boot sequence on this machine.)

I wanted to test an alternative version of the code, and ideally I should've done a hardware reset before running the test. But a hardware reset of just the VIA alone would've been awkward, so instead I settled for simply writing zeros to the ACR. I figured that would put the timer in the same state as that which follows a hardware reset... but I was mistaken. (Sometimes it would work; other times not. Perhaps this had to do with whether PB7 happened to be high or low at the time, but IDK -- I didn't investigate.)

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 15, 2022 8:53 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
fachat wrote:
The 6526 shift register was used for RS232 in a way like you suggest, to achieve 9600 baud RS232 on a C64 userport (that, with bit banging would only go up to 2400 baud)

For output, it would first output start bit + 7 data bits, plus in a second byte, the 8th data bit and the stop bit(s), with the rest being filled up with 1s.

For input, another input would be used as trigger on the start bit (via NMI), then the timer would be set, and 8 data bits being shifted in based on timer (not on external clock).


Really should be plenty of ways to do this - I also thought about using T1 for async. There’s even an example for that in the mos6522 datasheet.
I guess it’s time to do some tests and see where I can get away with fewest pins and least cpu cycles.

@jeff Reading or writing th SR should both clear the IRQ and I suppose the internal shift counter as well. Must confirm.
Maybe your T1 issue was that you didn’t start it by writing T1CH? (After setting ACR)
I have noticed some fuzzy things for that mode while playing with my tape interface.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 1:01 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
Well... Certainly doesn't work yet. I have the clock signal connected to both CB1 and PB6, and data to CB2

Code:
       
 t2_irq:
        lda kbbit
        cmp #2
        beq count9 ; If we only counted to 2 then reset counter to 9
        lda SR1 ; If we counted to 9 then fall through and save SR and reset counter to 2
        sta $0B
        lda #2
        sta kbbit
        sta T2CL
        lda #0
        sta T2CH
        beq newcount ; BRA
        count9:
        lda #9
        sta kbbit
        sta T2CL
        lda #0
        sta T2CH
;        bit SR1 ; Superfluous?

        newcount:
        pla
        rti


I'm getting seemingly random data - rarely the correct code, sometimes a value that's been shifted too far or too little. Like the code for "O" is $44 - this sometimes comes through as $88 or $22 or $11.
Could this work? Where am I most likely to miss clocks to cause misalignment?

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 7:32 pm 
Offline

Joined: Sat Feb 19, 2022 10:14 pm
Posts: 147
I don't see anything wrong with your code. I suppose there is some more to the interrupt service routine, but it would have to be rather long to interfere with receiving the scan code, unless you're running at 1 MHz, where it could start to get tight. Unfortunately, this method doesn't allow you to check the start, stop and parity bits. I save all bits to a circular buffer and use those to keep things in sync. There should be sufficient time between keystrokes to process it. I've offloaded this to an ATtiny85 (an 8-pin DIP) and only send the final ascii byte to the 65c22 shift register.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 8:10 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
tmr4 wrote:
I don't see anything wrong with your code. I suppose there is some more to the interrupt service routine, but it would have to be rather long to interfere with receiving the scan code, unless you're running at 1 MHz, where it could start to get tight. Unfortunately, this method doesn't allow you to check the start, stop and parity bits. I save all bits to a circular buffer and use those to keep things in sync. There should be sufficient time between keystrokes to process it. I've offloaded this to an ATtiny85 (an 8-pin DIP) and only send the final ascii byte to the 65c22 shift register.


It’s running at 2MHz and I made sure it’s first in line. Could be the mode 011 bug that’s messing with the framing… but then it should work some times a least.

viewtopic.php?t=5058 had some suggestions - including Dieters/Eaters version I’m using now..

I’m tempted to use the shift register irq and then simply block in the ISR until the SR changes and I have the final bit… Probably a bad idea.
Or fetch 8 bits in the ISR and the last one in the main loop.. haven’t thought that one through.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 8:36 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
Are you sure about which edges trigger shifting and counting? Can you show the 6522 initialisation code, especially ACR, PCR, and IER setup, plus how you are kicking off the read?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 9:04 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
gfoot wrote:
Are you sure about which edges trigger shifting and counting? Can you show the 6522 initialisation code, especially ACR, PCR, and IER setup, plus how you are kicking off the read?

The SR considers the data valid on the clock's rising edge, in all modes. According to the data sheet, T2 can count negative pulses on PB6, and it seems to mean it counts on the falling edge. I have not used that feature yet myself to speak from experience.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 9:10 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
gfoot wrote:
Are you sure about which edges trigger shifting and counting? Can you show the 6522 initialisation code, especially ACR, PCR, and IER setup, plus how you are kicking off the read?


Sure! I'll take any help I can get.

Enters IRQ SR like this:

Code:
  ;IFR is IRQ Tl T2 CBl CB2 SR CA1 CA2
irq:
  pha
  lda #%00100000 ; We need T2 to fire super fast, so we check it first.;
  and IFR
  bne t2_irq


Inits like this:
Code:
         
; After reset
lda #$01  ; CA1 positive active edge (Testing with the keyboard connected the "old" way)
sta PCR
lda #%11100010  ; Set CA1 + T2 + T1
          sta IER
          LDA #%01101100
          STA ACR             ; T1 continuous, T2 count, PB7 disabled, Shift In External
          lda #9
          sta kbbit

          lda #9
          sta T2CL
          lda #0
          sta T2CH
          bit SR1

PCR should be low edge trigger for CB1 when 0.
ACR should be mode 011
IER has T1, T2 and CA1 enabled.

I don't think it's a problem that the kb is also connected the old way - that just reads ORA on CA1 high edge IRQ. (Triggers well after kb is done clocking). My T1 timekeeping triggers every 7998 clocks.

@GarthWilson
The edge could have something to say, but then I would expect to see the same data when pressing a key, but simply incorrect? Also - if the edge is incorrect I would assume changing the PB6 count would be sufficient... Maybe.. Another thing to watch out for.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 18, 2022 9:22 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
GARTHWILSON wrote:
gfoot wrote:
Are you sure about which edges trigger shifting and counting? Can you show the 6522 initialisation code, especially ACR, PCR, and IER setup, plus how you are kicking off the read?

The SR considers the data valid on the clock's rising edge, in all modes. According to the data sheet, T2 can count negative pulses on PB6, and it seems to mean it counts on the falling edge. I have not used that feature yet myself to speak from experience.


Oh! I just caught what you meant.

"Note that data is shifted during the first system clock cycle following the leading edge of the CB1 shift pulse. For this reason, data must be held stable during the first full cycle following CB1 going high."

The illustration then shows that data is shifted at point A - which is the second phi2 low period after the CB1 rising edge. Data is certainly still valid there. But maybe the PB6 count should be 10 to be sure 9 bits have been shifted.. Maybe?

Edit: After staring at a timing diagram for 10 minutes I’m pretty certain I should be sampling the SR after 10 PB6 low edge counts == 9 shifts.
Testing that tomorrow.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 19, 2022 10:12 am 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
Mmmkaaay... This is not as easy as I would've hoped.

PS/2 is LSB first, 6522 Shift register is MSB first - from mode 010, that I missed before:

Quote:
Data is shifted first into bit 0 and is then shifted into the next higher
order bit of the shift register on the trailing edge of each clock pulse.


I noticed because I tried the SR IRQ route instead and got confused if I should use ROL or ROR for shifting in the last bit. ROL it is.

The best idea to get this approach working is to bit juggle the bits to the correct order - inline for speed.

So this is my current attempt ISR for the shift register:
Code:
       
        lda SR1
        sta $0B
        getlastbit:
        lda SR1
        cmp $0b
        beq getlastbit
        LDA #%01000000      ; Let's disable the shift register after the last bit and reenable in main loop after half a second (for debugging)
        STA ACR             ; T1 continuous - disable T2 and Shift register
        and #1
        beq notset
        sec
        bcs rotatelastbit ; BRA
        notset:
        clc
        rotatelastbit:
        lda $0b
        rol
        sta $0b ; LSB is in MSB :/
       
; I could probably do this bit shuffling in the main loop I guess
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB
        rol $0b ; MSB to C
        ror $0c ; C to MSB

        pla
        rti


It actually kind of works... Sometimes... I'm getting $44 half the time, but also a lot of $22 and $24. Other scan codes seem to confirm that it's kind of working.. The dreaded 011 mode bug is looming though. Was really hoping I didn't have to bring out extra hardware, but of course I have a '74 somewhere..
Currently I'm re-enabling the shift register when my cursor is blinking

Edit:
Since I had the MSB/LSB error before, I'll go back to the PB6 counting method again - reversing the shift register mig be what was missing.

Edit2: I finally did the sensible thing and used an output pin for debugging and connected my scope to that and the clock.. It's certainly not sampling the SR at the right time. It's basically rotating right every time I press a key.

Edit3: This actually seems to work. My debug pin tells me it's sampling SR right before the 10th rising edge. (Which is later than what I would expect with PB6 count being set to 9 and not 10)

Code:
        t2_irq:
        lda kbbit
        cmp #2
        beq count10 ; If we only counted to 2 then reset counter to 9
        lda SR1 ; If we counted to 10 then fall through and save SR and reset counter to 2
                 ; T1 continuous - disable Shift register
        sta $0b ; LSB is in MSB :/
        lda #$81
        sta $5000 ; Ouput only register debug

          LDA #%01100000
          STA ACR

           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB
           rol $0b ; MSB to C
           ror $0c ; C to MSB

        lda #2
        sta kbbit
        sta T2CL
        lda #0
        sta T2CH
        lda #1
        sta $5000 ; OOR debug
        beq newcount ; BRA
        count10:
        LDA #%01101100
        STA ACR             ; T1+T2, reenable Shift register
        lda #9
        sta kbbit
        sta T2CL
        lda #0
        sta T2CH
;        bit SR1 ; Superfluous?

        newcount:
        pla
        rti


In the main loop I reset the T2 counter every half second to kill the creeping framing errors.

Time to try a 74'74.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 19, 2022 11:46 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
If you must juggle bits, avoid doing it in the ISR if at all possible. Do it in the code putting it into the buffer or retrieving it from the buffer instead. Try to make your ISR as short and fast as you can.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 27 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: