6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Jun 04, 2024 10:57 am

All times are UTC




Post new topic Reply to topic  [ 82 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6
Author Message
PostPosted: Sun Nov 08, 2020 7:55 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8198
Location: Midwestern USA
Shawn Odekirk wrote:
BigDumbDinosaur wrote:
Once I've finished lunch I think I'll go out and play with my train.

Me watching video
...
"There's a tunnel!"
...
"And a bridge!"
...
"And another bridge!"

Three bridges, actually. :shock:

At least there weren't any derailments. As I recall, the track was rough in places from the effects of recent rains—you can see the locomotive rocking as it went over the uneven sections. I can tell you from personal experience that rerailing a 1000 pound locomotive can be...er...interesting. :D

Quote:
So cool! Thanks for sharing! After reading the description I watched again to see the ABS in action.

Glad you liked it. There are several other train videos on my channel. One, in particular, is of my buddy Carl at the controls highballing past the camera at a scale 70 MPH whilst hauling a short freight train.

Quote:
I also watched your POC V1 Demonstration video. I would have watched it sooner had I known about your YouTube channel.

One of these days I plan to redo that video. I shot it with an el cheapo camera that my wife had bought at Walmart, which could only do 320 × 200 resolution. With my current POC setup now using a WYSE thin client as a console, the potential exists (I think) to capture in real time what being displayed on the screen. I don't know what is required to do it but it would make for a much better display and a better video.

Quote:
I had planned to work on my BIOS and monitor, but now I've spent an hour watching 1.6" scale train videos on YouTube! No regrets!

Large-scale model railroading is quite a bit of fun, albeit a somewhat expensive hobby. I got into it about 20 years ago and although I was forced to slow down quite a bit when major medical maladies materialized 13 years ago (which indirectly led to me building POC V1.0 in late 2009), I was able to continue with help from some friends. I maintain a build log on the Chaski site with quite a bit of illustrated discussion on how I designed and built the locomotive. My most recent medical problems have slowed me down again, but somehow I manage to keep going.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 08, 2020 1:39 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1432
Location: Scotland
BigDumbDinosaur wrote:
Quote:
I had planned to work on my BIOS and monitor, but now I've spent an hour watching 1.6" scale train videos on YouTube! No regrets!

Large-scale model railroading is quite a bit of fun, albeit a somewhat expensive hobby. I got into it about 20 years ago and although I was forced to slow down quite a bit when major medical maladies materialized 13 years ago (which indirectly led to me building POC V1.0 in late 2009), I was able to continue with help from some friends. I maintain a build log on the Chaski site with quite a bit of illustrated discussion on how I designed and built the locomotive. My most recent medical problems have slowed me down again, but somehow I manage to keep going.


And they say money can't buy happiness... I've been riding for 45+ years, but 18 months back took a couple of part-loans which I've recently had to stop riding but have just taken on a full-loan with view to buy horse... Which for now is free, but there is livery, feed, tack, rugs and other horsey "stuff" I've had to get from scratch... and it's late season, so the weather is getting poor, so opportunities to go riding are limited.. (and if we get on OK, then there will be a purchase fee too...)

FWIW; The camera I use is a GoPro Hero 8 Black. I got it last year on their 'Black Friday' deal complete with SD card, 'selfie stick', 2nd battery and a bunch of mounting adapters - one of which is now fixed to my riding hat. I also use an app. called Open Camera on my android phone which is generally more feature-full than the standard camera app. and lets you do stuff like fix the exposure, etc. which is good for doing desk shots, etc.

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 08, 2020 6:57 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8198
Location: Midwestern USA
drogon wrote:
And they say money can't buy happiness...

Maybe not...but money is running a close second to whatever can. :D

Quote:
I've been riding for 45+ years...have just taken on a full-loan with view to buy horse... Which for now is free, but there is livery, feed, tack, rugs and other horsey "stuff" I've had to get from scratch...

Yep! Horses are not inexpensive by any means. A dog is much cheaper, but you can't ride one. On the other hand, horses aren't really up for playing Frisbee...

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 15, 2020 10:20 pm 
Offline
User avatar

Joined: Sun Nov 27, 2011 12:03 pm
Posts: 229
Location: Amsterdam, Netherlands
BigDumbDinosaur wrote:
A dog is much cheaper, but you can't ride one. On the other hand, horses aren't really up for playing Frisbee...

You've never seen Secretariat catching frisbees on the Late Show with Craig Ferguson, have you. :lol:


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 18, 2020 1:37 am 
Offline
User avatar

Joined: Mon Mar 23, 2020 4:02 pm
Posts: 52
Location: Parker, CO
I have been working on my BIOS a bit, and have the basics for writing to and reading from the SC28L92 DUART. The DUART is configured with 16-byte FIFOs and to interrupt only when the transmitter FIFO is empty and the receiver FIFO is full. I am currently using 128-byte transmit and receive queues. My code is mostly based on the examples BigDumbDinosaur presented in his "Driving the NXP SC28L91 UART", and his comments to a couple of floobydust's posts.

Here is my code to write a byte to the TX queue.
Code:
putc
        pha                     ;save the registers
        phx
        phy
        tax                     ;save a copy of the datum
        lda tx_put              ;fetch TX queue "put" index
        inc A                   ;increment it
        and #%01111111          ;wrap it
.check_tx_queue
        cmp tx_get              ;compare to the TX queue "get" index
        beq .check_tx_queue     ;TX queue is full - loop until it's not
        tay                     ;save the wrapped index
        txa                     ;restore the datum
        ldx tx_put              ;fetch the TX queue "put" index
        sta tx_queue,x          ;write the datum to the TX queue
        sty tx_put              ;update the TX queue "put" index
        lda #%00000100          ;enable the transmitter
        sta UART_CRA
        ply                     ;restore the registers
        plx
        pla
        rts

Here is my code to get a byte from the RX queue.
Code:
getc
        sec                     ;assume no data present
        phx                     ;save the registers
        phy
        ldx rx_get              ;fetch the RX queue "get" index
        cpx rx_put              ;compare to the RX queue "put" index
        beq .rx_queue_empty     ;the RX queue is empty
        ldy rx_queue,x          ;read the datum from the RX FIFO
        txa                     
        inc A                   ;increment the RX queue "get" index
        and #%01111111          ;and wrap it
        sta rx_get              ;save the wrapped index
        tya
        clc                     ;datum successfully read from queue
.rx_queue_empty
        ply
        plx
        rts

And here is my interrupt handler.
Code:
irq_handler
        pha                     ;save the registers
        phx
        phy

        ;; To Do - check for BRK

        lda UART_ISR            ;is the UART interrupting?
        beq .not_uart

.check_counter
        bit #%00001000          ;is the counter interrupting?
        beq .not_counter

.check_break
        lda UART_ISR
.not_counter
        bit #%00000100          ;is this a break change interrupt?
        beq .not_break

.check_rx
        lda UART_ISR
.not_break
        bit #%00000010          ;is the receiver interrupting?
        beq .not_rx
.check_rx_ready       
        lda UART_SRA            ;is the receiver ready?
        bit #%00000001
        beq .check_tx
        ldy UART_RXA            ;read the datum from the receiver
        lda rx_put              ;fetch the Rx queue "put" index
        inc A                   ;increment it
        and #%01111111          ;wrap it
        cmp rx_get              ;compare to the Rx queue "get" index
        beq .check_rx_ready     ;Rx queue is full
        ldx rx_put              ;fetch the Rx queue "put" index again
        tya                     ;transfer the datum to the A register
        sta rx_queue,x          ;write the data to the Rx queue
        txa                     ;transfer the Rx queue "put" index to the A register
        inc A                   ;increment it
        and #%01111111          ;wrap it
        sta rx_put              ;save it
        bra .check_rx_ready

.check_tx
        lda UART_ISR
.not_rx
        bit #%00000001          ;is the transmitter interrupting?
        beq .not_tx
        ldx tx_get              ;fetch the Tx queue "get" index
.check_tx_queue
        cpx tx_put              ;compare to the Tx queue "put" index
        beq .tx_queue_empty     ;the Tx queue is empty
.check_tx_ready
        lda UART_SRA            ;check if the transmitter is ready
        bit #%00000100
        beq .tx_not_ready       ;the transmitter is not ready
        lda tx_queue,x          ;get the datum from the Tx queue
        sta UART_TXA            ;write the datum to the transmitter
        txa                     
        inc A                   ;increment the Tx queue "get" index
        and #%01111111          ;wrap it
        tax
        bra .check_tx_queue     ;check if there is more data in the Tx queue
.tx_queue_empty
        lda #%00001000          ;disable transmitter
        sta UART_CRA
.tx_not_ready
        stx tx_get              ;update the Tx queue "get" index
       
.not_tx
.not_uart
        ply                     ;restore the registers
        plx
        pla
        rti                     ;return from the interrupt

I would really appreciate comments and criticism (hopefully constructive). I am sure there are many opportunities for improvement.
One area that I am not completely happy with is the code to wrap the read and write pointers to 128-bytes. I am considering using 256-byte queues just because the code is so much cleaner.
I also welcome comments regarding style. Are there things I could do differently that would make my source more attractive and easier to understand? I plan to add comment headers to each routine showing how they are used and any side effects they may have.

Thanks,
Shawn


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 18, 2020 3:48 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
Nice to see the progress..... I think I for one would like to see more of the actual equates for your variables, etc. (what memory locations are used, i.e., page zero or other RAM). Also, are you using the UART channel for a console or for basic data transfer? If the Receiver FIFO is setup to only interrupt when it's full, using it as a console doesn't work, as you need to fill up the FIFO with console data before an interrupt is generated, i.e., you're typing blind with no visible feedback (or activity) until you send 16 bytes over.

On the interrupt handler, you shouldn't need to reload the UART_ISR multiple times. Load it once, then use the BIT instruction to see if any interrupts are pending, then handle them via your priority. It's easier and somewhat quicker to use the BIT instruction to check and use BNE to handle the active interrupt. If it's not active, you just drop into the next BIT test until you run out, which becomes your ISR exit.

Managing a 128 byte queue is still easy, just strip off the high order bit of the index. If you're using a 65C02, you can use the RMB7 instruction (if the variables are in page zero). Also, if using a 65C02, memory is still tight and there's likely little need to dedicate a full page of memory (256 bytes) to transmit and receive queues. It appears you're only two pointers for the queue, a head and tail. I also use a count variable. This makes it easy and fast to determine if you have any data waiting in the receive queue and the same if the transmit queue is full. But both schemes work, so whichever you prefer.

As you're looking to handle the software break condition, I would suggest using a pre- and post-process routine to figure that out and use some RAM vectors to point to the actual ISR and Break handlers. This also allows you to insert other ISRs later with relative ease, plus you can prioritize them without making a lot of changes to your existing ISR(s).

Hope this qualifies as constructive ;-)

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 18, 2020 5:17 am 
Offline
User avatar

Joined: Mon Mar 23, 2020 4:02 pm
Posts: 52
Location: Parker, CO
floobydust wrote:
I think I for one would like to see more of the actual equates for your variables, etc. (what memory locations are used, i.e., page zero or other RAM).
Good point. I'll try to remember to include my equates in the future. The memory usage is still in flux. I need to decide things like "Do I want to use the lower addresses of page zero for the BIOS and monitor and leave the upper addresses for the user, or vice versa?"

floobydust wrote:
Also, are you using the UART channel for a console or for basic data transfer? If the Receiver FIFO is setup to only interrupt when it's full, using it as a console doesn't work, as you need to fill up the FIFO with console data before an interrupt is generated, i.e., you're typing blind with no visible feedback (or activity) until you send 16 bytes over.
I am using the UART for a console. The SC28L92 has an Rx watchdog timer that takes care of this problem.
From the SC28L92 data sheet:
Quote:
When enabled, the watchdog timer will generate a receiver interrupt if the receiver FIFO has not been accessed within 64 bit times of the receiver 1x clock. The watchdog timer is used to alert the control processor that data is in the Rx FIFO that has not been read. This situation will occur when the byte count of the last part of a message is not large enough to generate an interrupt.
The watchdog timer presents itself as a receiver interrupt with the RxRDY bit set in SR and ISR.
It's a really useful feature.

floobydust wrote:
On the interrupt handler, you shouldn't need to reload the UART_ISR multiple times. Load it once, then use the BIT instruction to see if any interrupts are pending, then handle them via your priority. It's easier and somewhat quicker to use the BIT instruction to check and use BNE to handle the active interrupt. If it's not active, you just drop into the next BIT test until you run out, which becomes your ISR exit.
The interrupt handler only reloads the UART_ISR if the A register is used in the processing of an interrupt. For example, if the SC28L92 counter is not interrupting, we branch directly to the BIT test for the UART receiver without reloading UART_ISR. If the receiver is interrupting, we handle it. Since the A register is used during the processing of the receiver interrupt we need to reload UART_ISR to be able to check if the transmitter is also interrupting.

floobydust wrote:
Managing a 128 byte queue is still easy, just strip off the high order bit of the index. If you're using a 65C02, you can use the RMB7 instruction (if the variables are in page zero).
This is one of my weak spots. I know the basic 6502 instructions, but I need to become more comfortable with instructions like RMB7. I've seen it used in your code, and I have a basic understanding of what it does, but I need to learn when I should use it.

floobydust wrote:
As you're looking to handle the software break condition, I would suggest using a pre- and post-process routine to figure that out and use some RAM vectors to point to the actual ISR and Break handlers. This also allows you to insert other ISRs later with relative ease, plus you can prioritize them without making a lot of changes to your existing ISR(s).
I've seen examples of interrupt vectors in your code, and think I understand how they work, but I haven't gotten there in my code yet. They seem like a good thing, and I plan to incorporate them before I am done.

floobydust wrote:
Hope this qualifies as constructive ;-)
It's absolutely constructive! Thank you!

Shawn


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

All times are UTC


Who is online

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