6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Apr 23, 2024 10:37 pm

All times are UTC




Post new topic Reply to topic  [ 48 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Sat Feb 11, 2012 11:28 pm 
Offline

Joined: Fri Mar 26, 2010 12:43 am
Posts: 12
Hey,

I'm doing a software serial routines for a 1Mhz 65xx device that needs to communicate at 57600 bit/s. But my receive code does not work.

57600 gives 17 cycles per bit.

Data comes in negated and it comes in on portb's D6. Protocol is
Startbit-Databits-Stopbit (8N1)
#cycle is a macro that inserts n cycles of code (not touching registers, flags may be touched) and .rept is a repeating macro.

Here's the code. Resulting byte should be in A. Bit sampling is always at 17 cycle interval (or so I believe)

Anyone can see where I've gone wrong?

Code:
readbyte               bit     portb           ; data comes in on portb.6
                       bvc     readbyte     ; startbit?

                       #cycle #25              ; wait ~ 1,5 bit time

                       .rept 8  ;read the bits

                       bit     portb
                       bvc     ?bt1
                       clc
                       ror     @
                       bvs     ?nx
?bt1                   sec
                       ror     @

                       #cycle #3
?nx
                       #cycle #4
                      .endr

                       rts


Any hints would be appreciated.
Cheers


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Feb 11, 2012 11:54 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1679
Location: Sacramento, CA
Can you give some samples, i.e.:

expect $41 but get $28

Try sending A,B,D,H which are $41,$42,$44,$48.

That will help decode the bit manipulation that's going on.

Daryl


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 12:00 am 
Offline

Joined: Fri Mar 26, 2010 12:43 am
Posts: 12
Hi Daryl,

Thanks for reply. Here's the bytes.

sent: 0x41
rcvd: 0x00

sent: 0x42
rcvd: 0x80

sent: 0x44
rcvd: 0x00

sent: 0x48
rcvd: 0x80


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 1:21 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8427
Location: Southern California
Do you get the same result every time?  Are there interrupts that could be cutting in on your cycle count?  What is being done with each byte as it comes in, and is that action quick enough to get back to being ready for the next byte coming in?  I see you're doing a JSR-RTS for each byte.  That alone takes most of the time of a stop bit, leaving you with almost no time to store one received byte in an array and get back to watching for the start bit of the next byte.  17 cycles is a little off, but not really enough to cause problems.  If it were, then since you're straightlining it, you could vary the delays a little bit from one bit to the next so the error would not accumulate.  Edit: I meant to add:  Do any branches cross page boundaries?  That adds another cycle too.

A 6551 adds parts but sure makes it easier for the computer to do other things in the background at the same time.  Although it won't do that bit rate from the internal clock generated from the 1.8432MHz crystal, it is able to go much faster than that with an external clock source, like a 6522's PB7 set up to toggle automatically on each T1 timeout with a free-running T1.

_________________
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?


Last edited by GARTHWILSON on Sun Feb 12, 2012 1:55 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 1:34 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3346
Location: Ontario, Canada
It looks to me as if
Code:
                       #cycle #3
should be
Code:
                       #cycle #2


-- Jeff


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 1:35 am 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
I make the two paths through the macro one cycle different.

Also, depending on exactly when the start bit starts, you could already be 3 to 7 cycles into the bit before you get to #cycle #25 and then another 3 or 4 cycles before the bit instruction in the macro tests the port again.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 11:23 am 
Offline

Joined: Fri Mar 26, 2010 12:43 am
Posts: 12
Thanks for the replies...

Garth: There's no concern about jsr/rts because this does not even happen. I send the bytes through the terminal from the keyboard. One at a time.
So the routine waits for my byte forever, reads it bit by bit when it comes and exits. then again waits for the byte, I send the byte etc. This isn't real stream of bytes at the moment. Just one byte. then another.
Also I made sure bvc and bvs branches do not cross pages.
No interrupts as well.

DrJefyll: Did you count the loops right? bxx branches take 2 or 3 cycles depending on taken/not taken condition. #3 cycle seems right to me. But please elaborate,perhaps I'm missing something.

leeeeee: that's a good point. I'll try to account for that.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 11:29 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
You could replace the bit setting code with a straight sequence, like
Code:
lda portb           ; Fetch inverted signal into A
eor #$40
asl a               ; Shift bit into C
asl a
ror @               ; And into result byte

Might make the timing easier to calculate.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 12, 2012 3:48 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3346
Location: Ontario, Canada
These are all good points that've been made. There are a few details I'd like to clarify.
Regarding the instruction
Code:
                       bit     portb           ; data comes in on portb.6
...I assume Absolute addressing mode is used -- that the IO port is not located in Zero Page. In other words the instruction consumes 4 cycles (not 3) -- is that right?

Also, I'm a little uncertain about
Code:
                       ror     @
Are you RORing the Accumulator or a memory location? If memory, is the addressing mode Absolute or Zero-Page? I will use the assumption it's the Accumulator. (I think Bitwise assumes it's memory, which also would work. (And I like his branch-less approach!)


As for timing with your original routine, I've marked below the cycle counts for both paths:
Code:
readbyte               bit     portb           ; data comes in on portb.6
                       bvc     readbyte     ; startbit?

                       #cycle #25              ; wait ~ 1,5 bit time

                       .rept 8  ;read the bits

         4  4          bit     portb
         3  2          bvc     ?bt1
         -  2          clc
         -  2          ror     @
         -  3          bvs     ?nx
?bt1     2  -          sec
         2  -          ror     @

         3  -          #cycle #3          ;<---- ???
?nx
         4  4          #cycle #4
                      .endr

                       rts
If you add up the totals you'll see they differ by one cycle -- hence my suggestion to change #cycle #3 to #cycle #2.


Following up on leeeeee's second point, I'd suggest that
Code:
                       #cycle #25              ; wait ~ 1,5 bit time
be changed to
Code:
                       #cycle #16              ; wait ~ 1,5 bit time minus 9~
Waiting for the Start Bit is an uncertain business. By the time the code notices it's arrived, up to 6 cycles may already have elapsed. I don't know any perfect way to deal with that -- I would simply average that uncertainty for a "typical" figure of 3. Then add the final (successful) test for the Start Bit, which consumes 4~ for bit portb and 2~ for bvc readbyte. That brings us up to 9 cycles. Add #cycle #16 and you get 25 -- the 1.5 bit-times you wanted.

cheers,

Jeff


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 4:01 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Code:
lda portb           ; Fetch inverted signal into A
eor #$40
asl a               ; Shift bit into C
asl a
ror @               ; And into result byte


You could also leave out the eor #$40, and invert the byte at the end.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 4:32 pm 
Offline

Joined: Fri Mar 26, 2010 12:43 am
Posts: 12
Thank you all...

Dr Jefyll: ror @ is accumulator. portb is absolute on non-zero page. your assumptions were ok. The missing cycle is also correct.
Thanks.

BTW, i've managed to do it with branchless approach as BitWise suggested, and used the Alert's tip. It works now for single bytes.
Now I need to throw it into a tight loop of reading N bytes.
But that's easier.

Code:
; pom is a zpage 1 byte variable

?r              bit     portb   
                bvc     ?r             

                #cycle #15

                .rept 8

                lda     portb   ;4
                asl     @       ;2
                asl     @       ;2
                ror     pom     ;5
                #cycle #4
                .endr
                lda     pom
                eor     #$ff
                rts


cheers


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 12, 2012 4:40 pm 
Offline

Joined: Tue Nov 18, 2003 8:41 pm
Posts: 250
Dr Jefyll wrote:
Waiting for the Start Bit is an uncertain business. By the time the code notices it's arrived, up to 6 cycles may already have elapsed.


Shouldn't that be 7 cycles (the branch would have been taken on the previous pass)?


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 12, 2012 6:48 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3346
Location: Ontario, Canada
bogax wrote:
Shouldn't that be 7 cycles (the branch would have been taken on the previous pass)?
Thanks, Bogax. Yes, certainly each unsuccessful iteration takes 7 cycles total -- I don't have an issue with that. But for the maximum resulting delay I got six by thinking, "there's the bus cycle during which the port reads false -- and we count the six cycles it takes to loop around and try again." Silly me -- that's incorrect. The deadline or decision point is of infinitesimal duration; it doesn't occupy a complete bus cycle. :oops:

Therefore the time before the Start Bit is recognized ranges from virtually 0~ to virtually 7~, for a typical delay of 3.5. For our calculations we can round that up to 4~ or down to 3~. If we're being fussy, the choice to round up or down should be aimed at canceling whatever other fractional-cycle timing error we can identify. For example we're using 25~ to represent 1.5 bit-times, when in fact 1.5 * 17 = 25.5 cycles. Since 25.5 got rounded down to 25 (an error of -0.5), 3.5 should get rounded up to 4 (for a complementary error of +0.5).

-- Jeff


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 12, 2012 7:45 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
I would suggest the following changes ..

Code:
; pom is a zpage 1 byte variable

?r              bit     portb
                bvc     ?r

                #cycle #11

                .rept 8

                #cycle #4
                lda     portb   ;4
                asl     @       ;2
                asl     @       ;2
                ror     pom     ;5
                .endr

                lda     pom
                eor     #$ff
                rts

That will give you four extra cycles to do something with the byte once you have it.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Feb 13, 2012 3:55 am 
Offline

Joined: Tue Nov 18, 2003 8:41 pm
Posts: 250
Following on Leeeeee's suggestion.

IFF bit 6 is the only thing changing on the port you might be able to
do this:

Code:
?r              bit     portb
                bvc     ?r

                #cycle #8

                .rept 7

                #cycle #5
                eor     portb   ;4
                ora     #$40    ;2
                eor     portb   ;4
                ror     @       ;2
                .endr

                #cycle #5
                eor     portb   ;4
                ora     #$40    ;2
                eor     portb   ;4
                rol     @       ;2

                rts


However it spreads the port read out over 6 cycles and reduces
the margin for jitter/misalignment


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 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: