6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Sep 20, 2024 2:37 pm

All times are UTC




Post new topic Reply to topic  [ 544 posts ]  Go to page Previous  1 ... 25, 26, 27, 28, 29, 30, 31 ... 37  Next
Author Message
 Post subject: Re: POC VERSION TWO
PostPosted: Thu Jun 08, 2017 10:09 am 
Offline

Joined: Wed Feb 12, 2014 1:39 am
Posts: 172
Location: Sweden
Thanks for the in-depth posts BDD, I've started playing with the 28L92 myself and had a lot of questions around the best ways to handle the various interrupt reasons but it looks like you've answered them :)


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 08, 2017 9:46 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
LIV2 wrote:
Thanks for the in-depth posts BDD...

You're welcome.

Quote:
...I've started playing with the 28L92 myself and had a lot of questions around the best ways to handle the various interrupt reasons but it looks like you've answered them :)

Sometime in the not-too-distant future I may package the complete driver in a set of source code files so others can use it in anything they build with the 28L92. I've already suffered the pain and agony of figuring out how to get the thing to work. No reason for others to have to re-invent the wheel—unless of course they like duplicating work. :D

Speaking of 'L92 interrupt causes, one of the DUART's features I'm hoping to eventually exploit is its ability to set up pins OP4, OP5, OP6 and OP7 as discrete IRQ outputs, two of them indicating when a receiver interrupts and the other two indicating when a transmitter interrupts. In POC V2.1, the two DUARTs comprising the virtual QUART (vQUART) have their IRQ outputs connected to two inputs on one section three-input AND gate (74AC11) that drives the 65C816's IRQB input. This is a measure I took to avoid a "lazy" IRQ circuit that might cause spurious interrupts to occur. The expansion socket also has a pin wired to the same gate to pick up IRQs from whatever is plugged into the socket (usually the SCSI host adapter).

Unfortunately, this arrangement doesn't indicate from where the interrupt came, only that one occurred. That means the interrupt service routine has to poll all likely sources, which in the case of the vQUART, means at least nine of them: the four receivers, the four transmitters and the counter/timer in DUART A. The SCSI host adapter is another interrupt source, with the interrupt coming from the 53CF94 controller, the DS1511 real-time clock, or both. So potentially 11 sources would have to be checked. While the code I've written to process these IRQs is succinct it does do a fair amount of busy work that could be eliminated with the right hardware.

In a future design that will exploit the DUARTs' discrete IRQ feature, I will wire these outputs to separate inputs on the CPLD, using a resistor network to pull up each input, since the DUART's IRQ outputs are open drain. When a channel interrupts, the CPLD logic will assert IRQB on the MPU, as well as set bits in a read-only status register to indicate which channels are interrupting:

Code:
   vDUART CPLD IRQ STATUS
   ——————————————————————
   xxxxxxxx
   ||||||||
   |||||||+———> 1: channel A RxD
   ||||||+————> 1: channel B RxD
   |||||+—————> 1: channel C RxD
   ||||+——————> 1: channel D RxD
   |||+———————> 1: channel A TxD
   ||+————————> 1: channel B TxD
   |+—————————> 1: channel C TxD
   +——————————> 1: channel D TxD

In the above, channels A and B are channels A and B, respectively, of the first DUART, and channels C and D are channels A and B, respectively, of the second DUART. The CPLD register will be real-time, not latched. Hence if an interrupt source in one of the DUARTs is cleared the corresponding bit in the register will be cleared. Such a scheme is practical because DUART interrupts are cleared by servicing the interrupt source, not by reading a register, as is the case with the 65C22.

So far, I've conjured the following interrupt service routine code framework that utilizes the vQUART status to minimize clock cycle consumption:

Code:
;   process vQUART channel interrupts...
;
         lda HMUBAS+L92IRQ     ;read vQUART status from CPLD...
;
;   ———————————————————————————————————————————————————————————————————
;   HMUBAS is the base address of the "hardware management unit" (HMU),
;   which is a set of registers within the CPLD that is the glue logic
;   for the system.  L92IRQ is a read-only register that reflects the
;   real-time status of the channel IRQ outputs from the 2 DUARTs that
;   comprise the virtual QUART (vQUART).
;   ———————————————————————————————————————————————————————————————————
;
         beq ser_done          ;no channels are interrupting...
;
;   ———————————————————————————————————————————————————————————————————————
;   If the status is zero, no channels are interrupting & hence there is no
;   reason to enter the channel servicing part of the interrupt handler &
;   waste a bunch of clock cycles.
;   ———————————————————————————————————————————————————————————————————————
;
;
;   RxD processing loop...
;
rxdloop  ldy #NXPNCHAN-1       ;starting channel index...
;
;   —————————————————————————————————————————————————
;   NXPNCHAN is the number of communications channels
;   built into the hardware.
;   —————————————————————————————————————————————————
;
.0000010 lsr a                 ;test channel RxD
         bcc .0000020          ;not interrupting
;
         pha                   ;save vQUART status
         tya                   ;current channel index
         asl a                 ;generate corresponding...
         tax                   ;channel offset
;
;   ——————————————————————————————————————————————————————————————————————
;   At this point, the channel receiver is serviced, using the direct page
;   pointer array set up during POST to access the appropriate device reg-
;   isters.  After the receiver has been serviced the loop code will cont-
;   inue as follows.
;   ——————————————————————————————————————————————————————————————————————
;
         pla                   ;recover vQUART status
;
.0000020 dey                   ;all channels checked?
         bpl .0000010          ;no, loop
;
;   ————————————————————————————————————————————————————————————————————————
;   The receivers have been checked & serviced so now it's the transmitters'
;   turn to be serviced.  All TxD status bits have been shifted into the low
;   nybble in the accumulator, which means the same basic loop structure may
;   be used to service the transmitters.  However, we first determine if any
;   transmitters need servicing before entering the loop.
;   ————————————————————————————————————————————————————————————————————————
;
txdloop  tay                   ;any transmitters interrupting?
         beq ser_done          ;no, we're done with serial I/O
;
         ldy #NXPNCHAN-1       ;starting channel index
;
.0000010 lsr a                 ;test channel TxD
         bcc .0000020          ;not interrupting
;
         pha                   ;save vQUART status
         tya                   ;current channel index
         asl a                 ;generate corresponding...
         tax                   ;channel offset
;
;   ——————————————————————————————————————————————————————————————————————
;   At this point, code services the channel transmitter, using the direct
;   page pointer array set up during POST to access the appropriate device
;   registers.  After the transmitter has been serviced the loop code con-
;   tinues as follows.
;   ——————————————————————————————————————————————————————————————————————
;
         pla                   ;recover vQUART status
;
.0000020 dey                   ;all channels checked?
         bpl .0000010          ;no, loop
;
ser_done ;...serial processing completed —— program continues...

Unlike the serial drivers for POC V1.1 and POC V2.1, the above structure avoids repetitive reading of the DUARTs' interrupt status registers to determine if a channel is interrupting. In fact, the code doesn't even touch the DUARTs unless the status gotten from the CPLD (HMUBAS+L92IRQ) says a DUART channel interrupted. I/O device access incurs a wait-state, which is a somewhat expensive operation in terms of wall clock time (accesses to the HMU in the CPLD do not get wait-stated). Naturally, I'm trying to avoid that as much as possible so the MPU isn't tied up too much executing interrupt handler code.

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


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 16, 2017 9:13 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
Progress has been slow on POC V2.1 as of late. The SMD stuff was soldered to the PCB back in June, but the unit had to collect dust until now as I again underwent more treatment of my left eye. Vision has slightly improved, enough so that I was able to resume some electronics bench work.

Attachment:
File comment: POC V2.1, partially assembled.
pocv2.1_powertest02.gif
pocv2.1_powertest02.gif [ 2.22 MiB | Viewed 1567 times ]

In the above photo, the partially completed unit is being checked for basic power distribution after undergoing an ohmmeter check for egregious faults. This was also a check for proper operation of the reset circuits. Proper voltages appear at all four serial ports, which means the two MAX-238 transceivers are alive and I correctly installed all the tantalum charge pump capacitors. :shock: So far, so good.

Installed active devices in the above photo are the two 512K SRAMs (near bottom right), two MAX-238 transceivers (left), a NAND gate being used as an inverter (near bottom left), the IRQ AND gate (immediately above the left hand DIP socket), the UARTs' X1 clock generator (bottom left) and the two Maxim DS1813 reset generators (right side above MPU socket), one of which is used to dampen the NMI circuit. I see a response when I manually negate each of the IRQ AND gate inputs, as well as the NMI circuit, so I'm good there.

Remaining assembly work is to install all the bypass capacitors, and the 10 pin JTAG port header, which I forgot to order along with the other parts.

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


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 21, 2017 5:01 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
POC V2.1 is fully assembled and passes all preliminary checks. Remaining are programming the CPLD and writing test code to see if the hardware works. Then will come time to see if she goes or blows. :D

Attachment:
File comment: POC V2.1's official portrait.
pocv2.1_top_01.gif
pocv2.1_top_01.gif [ 1.66 MiB | Viewed 1519 times ]
Attachment:
File comment: Close-up of SRAM, 1024KB total.
pocv2.1_top_sram.gif
pocv2.1_top_sram.gif [ 780.95 KiB | Viewed 1519 times ]
Attachment:
File comment: Close-Up of the two MAX-238 transceivers.
pocv2.1_top_max238.gif
pocv2.1_top_max238.gif [ 867.85 KiB | Viewed 1519 times ]
Attachment:
File comment: Close-up of the power jack, which is the 3-1/2" floppy disk type.
pocv2.1_power_in.gif
pocv2.1_power_in.gif [ 661.37 KiB | Viewed 1519 times ]
Attachment:
File comment: Close-up of the four-port serial output jack. The console port is on the left end.
pocv2.1_serial_out.gif
pocv2.1_serial_out.gif [ 1.04 MiB | Viewed 1519 times ]

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


Last edited by BigDumbDinosaur on Sat Oct 21, 2017 2:18 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Sat Oct 21, 2017 2:10 pm 
Offline
User avatar

Joined: Sun Oct 18, 2015 11:02 pm
Posts: 428
Location: Toronto, ON
This looks great BDD! It also reminded me how many things I borrowed from your design for my own test SBC, even down to the power connector :). Thanks for sharing the details and best of luck bringing it up.

_________________
C74-6502 Website: https://c74project.com


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Sun Oct 22, 2017 3:11 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Good to see you're back able to work on it again, BDD.


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Sun Oct 22, 2017 10:23 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
whartung wrote:
Good to see you're back able to work on it again, BDD.

It's still a struggle. Getting leads lined up with holes in the PCB is a challenger.

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


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 10, 2017 8:07 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
BigDumbDinosaur wrote:
POC V2.1 is fully assembled and passes all preliminary checks. Remaining are programming the CPLD and writing test code to see if the hardware works. Then will come time to see if she goes or blows. :D

Thinks got delayed some more due to a little medical problem that popped up on October 30, necessitating a stay in the hospital. I'm back home and have resumed on POC V2. The CPLD has been programmed through the onboard JTAG port, a test ROM (version 0.0.0) has been burned and a test run has been conducted for signs of life.

The ROM is programmed to act as a NOP generator. At reset, the ROM is mapped in from $00E000-$00FFFFF. So I merely assembled a bunch of $EA bytes from $00E000-$00FFDB. At $00FFDC is JMP $E000. The hardware reset vector points to $E000, causing the 65C816 run a gazilion NOPs, jump back to $E000, and around-and-around we go. Very simple and capable of simultaneously proving several circuit functions.

I placed a logic probe on the /RD (read data) line, ducked under the bench and flipped the switch (actually, I didn't duck—I'm fearless when it comes to five volts).
Attachment:
File comment: POC V2.1 Initial Test Setup
pocv2_1_initial01.gif
pocv2_1_initial01.gif [ 858.6 KiB | Viewed 1381 times ]
Attachment:
File comment: Logic Probe Connected into Expansion Socket
pocv2_1_initial02.gif
pocv2_1_initial02.gif [ 1.17 MiB | Viewed 1381 times ]
As soon as the MPU came out of reset the logic probe started showing activity, which meant /RD was being pulsed. The logic for /RD is RWB && Ø2, so that meant the MPU had to be reading instructions from somewhere.
Attachment:
File comment: Logic Probe Showing System Activity
pocv2_1_initial03.gif
pocv2_1_initial03.gif [ 949.21 KiB | Viewed 1381 times ]
A check of pin 20 on the ROM, which is /CE, showed activity. The /CEs of the DUARTs and SRAMS were all high, as were the expansion socket's I/O select pins. Based upon that, my conclusion is the core CPLD device select logic is working and instructions are coming from ROM.

I also checked a number of other control signals and could see what appeared to be proper activity, especially /RDY, which should be cycling due to ROM accesses being wait-stated.

Given what I've seen so far, it appears the POC V2.1 is functional at a basic level. In other words, she goes and didn't blow. :D Next step will be to create ROM version 0.1.0, which will determine if the console display can be written and read.

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


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Fri Nov 10, 2017 8:28 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1382
Glad the stay in the hospital wasn't so long... and nice to see some initial power-up progress on POC V2. I've not yet ventured into the 65C816 yet, but it's on my list once I get a couple other 65xx projects completed. Looking forward to seeing the rest of POC V2 coming to life.

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


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Fri Nov 10, 2017 6:02 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
floobydust wrote:
Glad the stay in the hospital wasn't so long... and nice to see some initial power-up progress on POC V2. I've not yet ventured into the 65C816 yet, but it's on my list once I get a couple other 65xx projects completed. Looking forward to seeing the rest of POC V2 coming to life.

I hope to work on it some more this weekend. My latest medical malfunction is soon going to keep me home-bound for a while and limit me to light activities, which ought to give me plenty of time to play with this latest iteration of POC.

Before I progress to ROM version 0.1.0, I'm going to create ROM version 0.0.1 to verify some other circuit functions. V0.0.1 will write the ROM's $EA pattern into RAM and then jump to the RAM version. That will run and when the top of "base RAM" (RAM appearing at $000000-$00BFFF) is reached, will jump into ROM to continue executing NOPs. The top of ROM will cause a jump back into RAM, and so forth. Such code will exercise more of the CPLD logic and at least prove that part of RAM is functional.

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


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Fri Nov 10, 2017 7:54 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Progress is progress, hope you heal up and feel better soon BD!


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Sat Nov 11, 2017 2:59 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
BigDumbDinosaur wrote:
Before I progress to ROM version 0.1.0, I'm going to create ROM version 0.0.1 to verify some other circuit functions...code will exercise more of the CPLD logic and at least prove that part of RAM is functional.

Okay, that step is completed. The code to do this is really simple:

Code:
00147    ;================================================================================
00148    ;
00149    ;POC V2 MACHINE ARCHITECTURE
00150    ;
00151    ;           +—————————————————————+ $0FFFFF
00152    ;           |                     |
00153    ;           |                     |
00154    ;           |   EXRAM  (960 KB)   |
00155    ;           |                     |
00156    ;           |                     |
00157    ;   +———————+—————————————————————+ $010000
00158    ;   |       |                     |
00159    ;   | HIRAM |    HIROM (8 KB)     |
00160    ;   |       |                     |
00161    ;   +———————+—————————————————————+ $00E000
00162    ;           |  HMUBAS (0.25 KB)   |
00163    ;           +—————————————————————+ $00DF00
00164    ;           |                     |
00165    ;           |   D8RAM (1.75 KB)   |
00166    ;           |                     |
00167    ;   +———————+—————————————————————+ $00D800
00168    ;   |       |                     |
00169    ;   | IORAM | I/O hardware (2 KB) |
00170    ;   |       |                     |
00171    ;   +———————+—————————————————————+ $00D000
00172    ;   |       |                     |
00173    ;   | LOROM |    LORAM (4 KB)     |
00174    ;   |       |                     |
00175    ;   +———————+—————————————————————+ $00C000
00176    ;           |                     |
00177    ;           |   BASRAM (48 KB)    |
00178    ;           |                     |
00179    ;           +—————————————————————+ $000000
00180    ;
00181      0000             basram   =$000000              ;base RAM
00182      C000             loram    =$00c000              ;low RAM, aka C-RAM
00183      D000             ioblk    =$00d000              ;I/O hardware
00184      D800             d8ram    =$00d800              ;"protected" RAM
00185      DF00             hmubas   =$00df00              ;hardware management
00186      E000             hirom    =$00e000              ;high ROM, aka E-ROM
00187      0000             exram    =$010000              ;extended RAM
00188    ;
00189    ;
00190    ;   overlays, selectable thru HMU...
00191    ;
00192      C000             lorom    =loram                ;low ROM ($00C000)
00193      D000             ioram    =ioblk                ;I/O RAM ($00D000)
00194      E000             hiram    =hirom                ;high RAM ($00E000)
00195    ;
00196    ;
00197    ;   memory type definitions...
00198    ;
00199      0000             zeropag  =$000000              ;physical direct page
00200      0100             absolut  =$000100              ;absolute bank $00 RAM
00201    ;
00202    ;
00203    ;   memory map segment sizes...
00204    ;
00205      0000             s_bank   =exram-zeropag        ;bank
00206      C000             s_basram =loram-basram         ;base RAM
00207      0700             s_d8ram  =hmubas-d8ram         ;D8RAM
00208      2000             s_hirom  =exram-hirom          ;high ROM
00209      0100             s_hmubas =hirom-hmubas         ;hardware management
00210      0800             s_ioblk  =d8ram-ioblk          ;I/O block
00211      1000             s_loram  =ioblk-loram          ;low RAM
00212      0800             s_ioram  =s_ioblk              ;I/O RAM
00213      2000             s_hiram  =s_hirom              ;high RAM
00214    ;
00215    ;
00216    ;   I/O device mapping...
00217    ;
00218      D000             io_a     =ioblk+$0000          ;device A select
00219      D100             io_b     =ioblk+$0100          ;device B select
00220      D200             io_c     =ioblk+$0200          ;device C select
00221      D300             io_d     =ioblk+$0300          ;device D select
00222      D400             io_e     =ioblk+$0400          ;device E select
00223      D500             io_f     =ioblk+$0500          ;device F select
00224      D600             io_g     =ioblk+$0600          ;device G select
00225      D700             io_h     =ioblk+$0700          ;device H select
00226    ;
00227    ;
00228    ;   65C816 hardware vectors...
00229    ;
00230      FFE0             nm_mpuv  =$00ffe0              ;'816 mode base address
00231      FFF0             em_mpuv  =$00fff0              ;'C02 mode base address
00232      FFE4             nm_copv  =$00ffe4              ;COP, '816 mode
00233      FFE6             nm_brkv  =$00ffe6              ;BRK, '816 mode
00234      FFE8             nm_abtv  =$00ffe8              ;abort, '816 mode
00235      FFEA             nm_nmiv  =$00ffea              ;NMI, '816 mode
00236      FFEE             nm_irqv  =$00ffee              ;IRQ, '816 mode
00237      FFF6             em_brkv  =$00fff6              ;BRK, 'C02 mode
00238      FFF8             em_abtv  =$00fff8              ;abort, 'C02 mode
00239      FFFA             em_nmiv  =$00fffa              ;NMI, 'C02 mode
00240      FFFC             em_rstv  =$00fffc              ;reset
00241      FFFE             em_irqv  =$00fffe              ;IRQ, 'C02 mode
00242    ;
00243    ;
00244    ;   miscellaneous addresses...
00245    ;
00246      FFF0             bankchk  =em_mpuv              ;...
00247    ;
00248    ;   ————————————————————————————————————————————————————————————————————————
00249    ;   During the extended RAM bank enumeration test, a null will be written to
00250    ;   the BANKCHK location, after which it will be read back.  If the bank ex-
00251    ;   ists a null will be returned.  Otherwise, the contents of BANKCHK, which
00252    ;   is located in the MPU vector area of HIROM will   be returned.  By design,
00253    ;   reading BANKCHK in bank $00 will return $FFFF.
00254    ;   ————————————————————————————————————————————————————————————————————————
00255    ;
00256      0100             basramck =absolut              ;start of base RAM testing
00257    ;
00258       .end
00259      0003             s_jmpabs =3                    ;size of JMP ABS
00260      00EA             mp_nop   =$ea                  ;NOP instruction opcode
00261      CFFD             stophere =ioblk-s_jmpabs       ;end of NOP test space
00262    ;         
00263    ;================================================================================
00264    ;
00265    ;MAIN TEST CODE
00266    ;
00267    E000                  *=hirom
00268    ;
00269    E000  A9 EA                 lda #mp_nop
00270    E002  A2 00                 ldx #<absolut
00271    E004  A0 01                 ldy #>absolut
00272    ;
00273    E006  86 00        main     stx zeropag
00274    E008  84 01                 sty zeropag+1
00275    E00A  92 00                 sta (zeropag)
00276    E00C  E8                    inx
00277    E00D  D0 01                 bne .0000010
00278    ;
00279    E00F  C8                    iny
00280    ;
00281    E010  C0 CF        .0000010 cpy #>stophere
00282    E012  90 F2                 bcc main
00283    ;
00284    E014  E0 FD                 cpx #<stophere
00285    E016  90 EE                 bcc main
00286    ;
00287    E018  A2 02                 ldx #s_jmpabs-1
00288    ;
00289    E01A  BD 23 E0     .0000020 lda jmpabs,x
00290    E01D  9D FD CF              sta stophere,x
00291    E020  CA                    dex
00292    E021  10 F7                 bpl .0000020
00293    ;
00294    E023  4C 00 01     jmpabs   jmp absolut


The above runs a endlessly runs gazillion NOPs, as the first ROM did, but entirely in RAM. During testing, I monitored A0 and RDY. As soon as the MPU jumped into RAM RDY stayed high, which it is supposed to do. So it looks like it works.

Attachment:
File comment: Set Up to Test from RAM
testing_from_ram01.gif
testing_from_ram01.gif [ 1.03 MiB | Viewed 1327 times ]
Attachment:
File comment: Monitoring A0 Line
monitoring_ab01.gif
monitoring_ab01.gif [ 1.26 MiB | Viewed 1327 times ]
Attachment:
File comment: Monitoring RDY
monitoring_rdy01.gif
monitoring_rdy01.gif [ 974.55 KiB | Viewed 1327 times ]

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


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 15, 2017 6:56 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
Further testing has determined that I can read and write both of POC V2.1's DUARTs, which means I should be able to produce a display on the console screen and read the console keyboard. It was relatively easy to take the interrupt part of POC V1.1's serial I/O (SIO) driver and adapt it to V2. Some minor rework was required to adapt the foreground part of the driver. Accordingly, I'm working up some firmware that I hope to have ready to go in a few days. While doing so, I have a bit of a conundrum to resolve.

V1 has two SIO channels, A and B, indexed as 0 and 1—channel 0 is the console. There are four BIOS API calls for doing SIO: read from channel A, write to channel A, read from channel B and write to channel B. That arrangement has worked well and in fact, came about because all of the firmware, which includes the machine language monitor, as well as reset, interrupt code and the BIOS, has to fit within 8 KB of ROM. In contrast, V2 has 8 KB of ROM devoted to the BIOS, interrupt handlers and reset code, and a separate 4 KB ROM segment into which the M/L monitor will be loaded. So I have more elbow room for BIOS API refinements, among which could be the consolidation of the SIO functions into two calls, using channel indexing to select the desired input or output path.

V2 has four SIO channels, 0, 1, 2 and 3, hence there are theoretically eight separate API functions for serial I/O, four read and four write. Internally, the code that does SIO is common to all channels—internal indexing selects direct page pointers that select the correct data structures and hardware registers. The indirect indexing principle that selects a channel has been tested on POC V1.1, so I know it works. The question will be how to set the channel index when an SIO API call is made.

Before going any further, the general form of an API call with V2 is:

Code:
         pea #<api_num>        ;push API index
         cop $00               ;call API ("trap")

where <API_NUM> is a 1-based index that ultimately selects the code to be run. Registers are loaded with parameters as required for the call. Returns likewise are passed in the registers, and carry is used to signal "success" or "failure."

Internally, the code that does the SIO processing works with a table that points at the data structures and hardware registers associated with each channel. So I started thinking about a different way of accepting SIO calls that might be more convenient for application programming and came up with several ways in which I could set up a call to, say, write a datum to serial channel C:

Code:
         lda #datum            ;load datum
         pea #_siowrtc_        ;push write channel C API number
         cop $00               ;write to channel C

The API index would have to be different for each channel. That could be a problem within, say, a general purpose character string printing function. How do you tell it which channel should get the output? The API number corresponding to the desired channel could be pushed via a register with each call, but then that register gets clobbered.

Another method would be:

Code:
         lda #datum            ;load datum
         ldx #siochcix         ;channel C's index
         pea #_siowrt_         ;push write API number
         cop $00               ;write to channel C

Here a single API is used for all channels and the channel index is passed as a parameter to the call, improving generality. However, .X would have to be preserved by the caller if its value is important and if it is being used in a loop that is calling the API, would have to be loaded with the channel index at each call.

Still another method would be:

Code:
         lda #datum            ;load datum
         pea #siochcix         ;push channel C's index
         pea #_siowrt_         ;push write API index
         cop $00               ;write to channel C

The only difference between this one and the previous method is how the channel index is passed to the API.

I pondered this for some time and then thought about how I/O was done in eight bit Commodore computers. A single "kernal" call, CHROUT, is used to write to anything and a complementary call, CHRIN, is used to read from anything. In order to tell the kernel from where to get input or where to send output, the CHKIN (input) and CHKOUT (output) calls are used. For example, once CHKOUT has been called and has returned error-free, output through CHROUT will "magically" go to the selected device or file. Typical code for doing so would be as follows:

Code:
;Commodore chkout function call...
;
         ldx #5                ;file descriptor
         jsr chkout            ;set it as output
         bcs error
;
         lda #'A'              ;write 'A'
         jsr chrout            ;will go to file opened on 5

When done, a call to CLRCHN will break the connections set up with CHKIN and CHKOUT, restoring I/O to the screen and keyboard. Obviously, this arrangement produces a degree of generality: a general purpose output subroutine can print anywhere. All the caller has to do is say where to print.

In V2, something similar could be arranged:

Code:
         lda #siochcix         ;channel C's index
         pea #_sioout_         ;set SIO channel API number
         cop $00               ;set channel C as output
         bcs error             ;channel index out of range
;
;    At this point, we can endlessly write to channel C, as the BIOS will be
;    configured to write to the channel we've selected.  The following code
;    writes 40 'A's to channel C...
;
         lda #'A'
         ldx #40
;
loop     pea #_siowrt_         ;SIO write API index
         cop $00               ;write to 'C' to channel A
         dex                   ;repeat...
         bne loop              ;39 times
;
;
;    restore default SIO channel...
;
         pea #_siodef_         ;default SIO channel's API index
         cop $00               ;channel A becomes default

The default SIO channel is channel A (0), which is the console. So it's convenient to have a quick call to re-select the default. A similar arrangement to the above would be required to handle input, using the same calling methodology.

SIO API calls read and write circular FIFOs (hardware access is via IRQs), which can happen very fast once the required pointers have been selected. As the channel index doesn't have to be passed with each SIO input or output call, the BIOS primitives code that process the call don't have as much work to do—no channel pointer setup has to be done—and hence should run faster.

There is more complexity in having separate calls to set input and output paths. Also, more direct page storage will be consumed to keep track of which channel is current input and which channel is current output. That said, I'm looking ahead to when a version of POC gets built with eight serial channels. Whatever method I used to select a channel for I/O will have to be sufficiently flexible to handle that many channels. So some planning ahead is probably in order.

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


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Thu Nov 16, 2017 1:20 am 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Well, I've been fond of the Atari's CIO system, as it's an actual, generic and extensible I/O subsystem with drivers. So, you make the same calls whether you want to read a byte from the keyboard, serial I/O, or disk drive.

But, obviously, it comes at a cost in complexity and RAM, as any more general purpose system would. For example, it has dedicated RAM for 8 channels (0-7) described in I/O Control Blocks of 16 bytes each, so there's 128b of RAM right away. But it's accessed via X and the channel number x 16 . So Channel 1 is $10.

https://www.atarimax.com/freenet/freene ... cle.php?30

More fully detailed in the Technical Reference Notes: http://www.atarimania.com/documents/ata ... -notes.pdf


Top
 Profile  
Reply with quote  
 Post subject: Re: POC VERSION TWO
PostPosted: Thu Nov 16, 2017 3:12 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8389
Location: Midwestern USA
whartung wrote:
Well, I've been fond of the Atari's CIO system, as it's an actual, generic and extensible I/O subsystem with drivers.

Atari's CIO works on the same principle as Commodore's eight bit kernel, just with different procedures.

In POC V2.1's case, there are only two serial I/O operations (read and write) that I need to abstract in the BIOS API, so the CIO method would be unnecessarily bulky. I'm kind of leaning toward the Commodore method, as it is simple to implement. What is an unknown right now is if there are performance implications that might favor some other method.

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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 544 posts ]  Go to page Previous  1 ... 25, 26, 27, 28, 29, 30, 31 ... 37  Next

All times are UTC


Who is online

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