1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

talking to CTK 571 synthesizer

Discussion in 'PC Hardware' started by Allan Adler, Oct 31, 2007.

  1. Allan Adler

    Arno Wagner Guest

    It used to be, but by now these things take so little chip
    area that they get intergrated into the soundchip. This thing
    is maybe 5000 transistors or so (at least thats my guess).
    Do that. If you live in a larger city, there is usually one
    electronics parts shop. Otherwise there should be some mail-order
    companies that do not charge too much for shipping and are fast.
    To give you an idea, my supplier here does next day shipping
    and charges around 5 USD per shipment. If you are at MIT, baybe
    ask the students organizations in the EE department. They usually
    know the best sources for electronics parts as they need them for
    term projects.

    Arno
     
    Arno Wagner, Nov 10, 2007
    #21
    1. Advertisements

  2. Allan Adler

    Arno Wagner Guest

    Ah, yes. There is the base address of the UART, which you have
    already found. Thet wpuld be the MPU401 base adress or the like.
    The datasheet lists the register locations relative to that base
    address. Just add the two.

    Arno
     
    Arno Wagner, Nov 10, 2007
    #22
    1. Advertisements

  3. Allan Adler

    Allan Adler Guest

    I've started reading the data sheets and have some fuzzy ideas about
    what is going on. I'll read some more tomorrow. The registers are
    selected by the three pins A2 A1 A0, which might be what you have in
    mind for the offset, and by the most significant bit (called DLAB) of
    the LCR register. I don't know if that bit counts as one of the bits of
    the offset. There are 11 registers, so one needs 4 bits to refer to
    all of them. However, the LCR register is itself selected using only
    A2 A1 A0, independently of the value of LDAB. I don't know whether that
    means the LCR register has two offsets differing by 8. Anyway, the situation
    seems to be that one might have to read/write a register in order to
    read /writea register.

    There are a couple of diagrams (pp.13,14) showing typical applications.
    I'm assuming for the moment that the one on p.14 is the one to keep in
    mind for programming the UART.

    I read a little about the various registers today. Tomorrow I'm going to
    focus on reading the timing diagrams carefully on pp.8-12, in the hope
    that this will make it easier to figure out the order in which things have
    to be done in programs.
     
    Allan Adler, Nov 11, 2007
    #23
  4. Allan Adler

    Allan Adler Guest

    The most accessible shop for me is Radio Shack, which I consider expensive.
    I tried looking at other places and was shocked to learn a couple of decades
    ago that a little shop was charging $28 for a Z80 chip, when the catalogues
    I had listed it for just a couple of dollars. The proprietor told me that
    if he didn't charge that much he couldn't pay his rent. There is a lot of
    overhead for just being able to walk in and buy what you need. But I was
    also told about the same time that in Japan there were "supermarkets" where
    one could find bins of every chip, connector, etc., one could want.

    It's been a long time since I bought electronics stuff and I no longer have
    any equipment other than a soldering iron. I need to keep my expenses in
    this project to a minimum, even though I like to acquire electronics
    equipment and parts.

    I'll find out when people throw their trash away and make it a point to
    walk around and see whether they have thrown out any electronics I can
    scavenge connectors, resistors, diodes and other parts from. A discarded
    PC at least has a power supply and would save me the trouble and expense
    of building one. Several months ago I found a discarded printer and helped
    myself to its printer cable. If I were working on the printer port instead
    of the joystick port, my problem of finding connectors would be solved.
    There is probably a lot of good stuff out there that I am too ignorant
    to realize is full of useful parts to scavenge.
    Which company is that? Do they have a minimum order?
    Read my disclaimer.
     
    Allan Adler, Nov 11, 2007
    #24
  5. Allan Adler

    Arno Wagner Guest

    It is Swiss, or rather European: www.distrelec.ch
    That was just an example.
    Ahh, sorry. Missed the part about you not being near Boston.

    Arno
     
    Arno Wagner, Nov 11, 2007
    #25
  6. Allan Adler

    Arno Wagner Guest

    Good ^^
    The offset is A0 + A1 * 2 + A2 * 4 (with AX being 0 or 1)
    No, only those addressable externally. The CPU will actually
    apply the three LSBs in the out/in address operand directly
    to A0,A1,A2. Also you can only write/read bytes, not words or
    longer, since the UAR is actually a historic artefact from 8 bit
    CPU times.
    That is no accident. Good eye there.
    Basically yes. And you have sort of two modes, one with DLAB = 0 and
    one with DLAB = 1.
    Sounds good. I made this journey to knowledge something like
    20 years ago with only the datasheet. Very interesting, and
    when you have really understood one of these datasheets,
    you can understand most others with relatively low effort.

    Arno
     
    Arno Wagner, Nov 11, 2007
    #26
  7. Allan Adler

    Allan Adler Guest

    I'll report on this in a new thread with subject line "Fresh Air", since
    its implications go way beyond the topic of this thread.
     
    Allan Adler, Nov 12, 2007
    #27
  8. Allan Adler

    Allan Adler Guest

    Thanks. Here is my current state of confusion. The serial output line
    (pin 12 of the game port) seems to be the same as the SOUT pin of the
    UART. This output line comes from the Transmitter Shift Register (TSR),
    which is not one of the 11 accesible registers. There is a bidirectional
    arrow joining it to the Transmitter Timing and Control Register (TTCR), also
    not an accessible register, and a horizontal line, without arrows, joining
    the TSR to the Transmitter Holding Register (THR), which *is* one of the
    accessible registers. The THR is selected by address 0 with DLAB 0. However,
    there are actually two accessible registers selected by address 0 with DLAB 0,
    the THR and the Receiver Buffer Register (RBR). THR is for output and RBR
    is for input. So, there has to be a way to tell the UART whether one is
    reading or writing. This is apparently controlled by DOSTR-bar going
    high, for write, or DISTR-bar going high, for reading. Now, the
    application information on p.14 has the pins DISTR and DOSTR grounded
    and has DOSTR-bar tied to the WR-bar pin on some unexplained device called
    the TCU and the DISTR-bar tied to the RO-bar of the TCU. Since we know
    nothing about the TSU except that it connects to the CPU through PHI1 and
    PHI2 (whatever they are), it is hard to know what to do from the CPU to tell
    the UART to write or read via DOSTR-bar or DISTR-bar.

    On the other hand, DOSTR-bar and DISTR-bar in the diagram on p.3 don't show
    arrows on DOSTR-bar and DISTR-bar pins, so maybe that means they are
    bidirectional. And even if they are available for input, it is possible that
    there are other ways to indicate a read or a write. For example, the
    Interrupt Enable Register (IER, with address 1 and DLAB 0) has its lower
    4 bits assigned to indicate various interrupts. Bit 1 is the Enable
    Transmitter Holdering Register Empty Interrupt (ETBE), so maybe writing
    to IER is part of the solution. Also, the Line Status Register (LSR,
    selected by address 5) has its bit 5 indicating something about the
    Transmitter Holding Register (THRE). And there might be others.

    So, I'll look more closely at that kind of information tomorrow.
    What does CPU register AX have to do with this?
    In addition to selecting the register with A0,A1,A2, there are also the
    lines CS0,CS1,CS2 that select the UART itself when CS0+2*CS1+4*CS2=3.
    These depend, according to the application figure on p.14, on address
    lines 16 to 23 from the CPU.
    I read the timing diagrams for the write cycle and read cycle and found
    them helpful. I'll read the transmitter, receiver and modem diagrams
    tomorrow. There is something very basic I don't understand about the
    UART and I don't know what it is yet.

    I own a copy of Steve Ciarcia's book, Build Your Own Z80 Computer. Its
    appendix C7 is a spec sheet for a COM2502 and COM 2017 UART. It's much
    simpler than the device we are discussing and the spec sheet is much
    shorter. However, it has one appealing feature, namely flow charts for
    the receiver and the transmitter function. It still has terminology
    such as Transmitter Shift Register. Anyway, I'm hoping that by comparing
    this spec sheet with the one we're discussing and also by studying the
    flow charts, I might start to make sense of this.
     
    Allan Adler, Nov 12, 2007
    #28
  9. Allan Adler

    Arno Wagner Guest

    Well, unless you build hardware. On the software sie it is easy:
    Do a port output to write and a port input to read. The former
    will write the THR, while the latter will read the RBR.

    Also not that for the UART variants with FIFOs, reading will
    read and remove the last element in the input fifo, while writing
    will add a new first element in the output FIFO. I think you
    have to explicitely enable the FIFO on these devices.
    No. Probably an error in rendering.
    The interrupt stuff is important, unless you want
    to do intense polling.
    These are actually used to place it at the base address.
    You will find out.
    Good idea. There is some universal functionality in there, and
    some device specific. So firt understand the general princible,
    and only then the details become important.

    Arno
     
    Arno Wagner, Nov 13, 2007
    #29
  10. Allan Adler

    Allan Adler Guest

    That's so simple. Thanks.
    I'll look for mention of FIFO in the spec sheet.
    OK. I'm not quite there yet.
    I copied the transmitter flowchart, looked up the entities that are mentioned
    in it, copied the block diagram for the transmitter and am in the middle
    of copying the block diagram for the chip as a whole. Some items from different
    figures have similar names but might or might not be the same. The advantages
    of copying out the information is that I gain passive knowledge of it and also
    that I can mark it up in my notebook in ways that make it convenient to refer
    to it. I started stepping through the flow chart and immediately had the
    problem of not recognizing what in the block diagrams was being referred to.
    I'll puzzle over that some more tomorrow.

    I decided I should also bring with me my copy of M.Morris Mano's book on
    digital logic and computer design and my copy of the 2d edition of the
    TTL Data Book from Texas Instruments. What I'd like to do is try to imagine
    how to convert the block diagrams into an actual design of a UART from
    components in the TTL Data Book, for example, just in case it is not already
    in there itself. That should do a lot to clarify the universal functionality.
     
    Allan Adler, Nov 13, 2007
    #30
  11. Allan Adler

    Arno Wagner Guest

    I think that is a good approach. An UART is still simple enough
    for that to be feasible.

    Arno
     
    Arno Wagner, Nov 13, 2007
    #31
  12. Allan Adler

    Allan Adler Guest

    I did some searching on the net for uart design and found that this seems
    to be a standard lab exercise in some courses, but maybe not with real
    chips. Also, I found some stuff on languages for carrying out such designs.
    One article on the topic mentions compiling down to Register Transfer Language,
    which is one of the things I was planning to look at in M.Morris Mano's book
    (RTL, not compiling down to it), but also gives the impression that RTL itself
    isn't flexible enough. It has references to online sources of information
    about some of these languages, but I don't know whether any of them is
    available for free or could be installed on my system. One lab I found online
    refers students to the Xilinx library. I haven't tried to access it yet.
    But I'll try the design with TTL chips naively in my own way and not get
    distracted with these other interesting tools.

    Since the primary goal is to write the toot sector, I gave priority today
    to trying to make sense of interrupts on the UART. Thanks to your helpful
    remark about how to write to the registers, I think I have a plan but I'm
    not sure it is correct. I'll write the actual program tomorrow. Here is
    the plan: Of course, I have to write to the THR. On p.24 of the spec sheet,
    it says that the ACE transmitter consists of the THR and a transmitter
    shift register. Timing is suppled by the baud out clock signal. For the
    moment, I'll assume the baud rate is what it needs to be for MIDI. If
    not, there will be something else to do before what I'm about to describe,
    namely writing to some registers that control the divisor of the clock rate.
    Transmitter control is a function of the Line Control Register (LCR). I
    think I want 8 bit words to be sent, so bits 1,2 of the LCR should be 1.
    Since writing THR requires DLAB to be 0, and since DLAB is bit 7 of the
    LCR, I certainly want bit 7 to be 0. I'm assuming that the other bits
    don't matter unless I want to worry about them. So, I basically want to
    write 0x3 to the LCR. The bytes I want to send to the Casio CTK 571
    are 0x90 0x40 0x7F. I don't want them to arrive in the THR before they
    are ready to be transmitted, so I think I want to enable the Transmitter
    Holdering Register Empty interrupt by setting bit 1 of the Interrupt
    Enable Register (IER). So, I want to write 0x2 to IER. In order to detect
    when that interrupt has been triggered, I need to look at the register IIR
    until bits 2,1,0 of it are respectively 0,1,0. Therefore, the plan is:
    (1) Write to LCR (Port 0x333) and put 0x3 in it.
    (2) Write to IER (Port 0x331) and put 0x2 in it.
    (3) Write to THR (Port 0x330) and put 0x90 in it.
    (4) Repeatedly read IIR (Port 0x332) until it contains 010 in the 3 least
    significant bits.
    (5) When it contains 010, that signifies that THR is empty. Then write
    0x40 to THR (Port 0x333).
    (6) Repeatedly read IIR (Port 0x332) until it contains 010 in the 3 least
    significant bits.
    (7) When it contains 010, that signifies that THR is empty. Then write
    0x7F to THR (Port 0x333).
     
    Allan Adler, Nov 14, 2007
    #32
  13. Allan Adler

    Arno Wagner Guest

    I have a bit (very limited) experience with some design languages.
    My impression is that they confuse the issue. I think they are
    more write-only languages and only intended to be read by machines.
    I think for the first experiments you should poll whether the
    data has been sent in a loop. Interrupts add their own level
    of complexity, better get to that later. Writing an
    interrupt service routine can be tricky.
    Actually you need to install an interrupt service routine, that
    will be called by your computer's hardware when the interrupt
    is sent. Maybe you can disable interrupt output (hardware
    ouput line) and poll the IIR nonetheless.
    Sounds reasonable. Also a good first test setup. I assume
    0x90 0x40 0x7F plays a note.

    Arno
     
    Arno Wagner, Nov 14, 2007
    #33
  14. Allan Adler

    Allan Adler Guest

    I guess I'm confused about one very basic point. I have been under the
    impression that the interrupt that the empty THR generates is an interrupt
    internal to the UART itself. According to that view, the IIR won't show that
    the THR is empty unless the interrupt is enabled. But you seem to be saying
    that the interrupt is an interrupt that the CPU deals with. If so, what should
    be the location of its interrupt vector?
    I hope to try it out this evening. Yes, 0x90 0x40 0x7F plays a note, or
    so I'm told:
    http://www.borg.com/~jglatt/tech/midispec.htm
    0x90 is note on in channel 0
    0x40 is the note
    0x7F is the duration
     
    Allan Adler, Nov 14, 2007
    #34
  15. Allan Adler

    Arno Wagner Guest

    The UART is not complicated enough to need internal interrupts.
    It just couts bits sent and then sets something to signify
    "THR empty". That could be the bit in the IIR, I don't remember.

    The interrupt vector can be set by the BIOS, if I remember
    correctly. I do not really have experience with PC interrupt
    handling.

    Arno
     
    Arno Wagner, Nov 15, 2007
    #35
  16. Allan Adler

    Allan Adler Guest

    Yes, I think it is.
    I'll take another look at the documentation and see whether I can find
    a pin that actually signals an interrupt to the CPU.

    I wrote the following boot sector program to implement the plan I described
    last time. It doesn't work. I don't know why it doesn't work. More on that
    below.

    entry start:
    mov al,#0x3
    mov dx,#0x333
    out dx,al
    mov al,#0x2
    mov dx,#0x331
    out dx,al
    mov al,#0x90
    mov dx,#0x330
    call seekint
    mov al,#0x40
    mov dx,#0x330
    out dx,al
    call seekint
    mov al,#0x7f
    mov dx,#0x330
    out dx,al
    loop1: jmp loop1
    seekint:
    mov dx,#0x332
    in al,dx
    cmp al,#0x2
    jnz seekint
    ret

    The next thing I want to do is to see whether I can read various registers
    on the UART and print the contents on the screen. I scavenged some of the
    as86 subroutines from the lilo-22.8 source and have done some simple
    experiments with them to make sure they work. For example, the subroutine
    say will print a string and the routine wout will print the contents
    of the AX register as a string of 4 hex digits and the command LAHF will
    load the lower 8 bits of the flags register into AH. So, I have some
    techniques for printing whatever information I can extract from the UART
    in a boot sector program.
     
    Allan Adler, Nov 15, 2007
    #36
  17. Allan Adler

    Allan Adler Guest

    Yes, there is. So, it is desirable to find the interrupt service routine.
    I looked at Gilluwe's book, The Undocumented PC, and, in the chapter on
    designing adapter cards, he explains that the BIOS sets up the interrupt
    vectors. So, to find the interrupt vector, it is necessary to read the BIOS
    for the sound card. That is consistent with other things I've been trying
    to do.

    I want to capture the entire upper memory and write it to a floppy disk.
    Once I do that, I can use dd under Linux and write C programs to analyze
    it and locate the BIOSes in it. Then I can try to disassemble them, or at
    least the ones I'm interested in, such as the one for the sound card. That
    should put me in a better position to write the toot sector with some
    comprehension of what I'm doing.

    Since I'm trying to get better at writing boot sector programs, I'm hoping
    to do this using a boot sector program. I've already done some simple
    experiments writing stuff to the screen by writing to the screen buffer,
    as in Krishnakumar's article, Writing Your Own Toy OS, Part I. As an
    exercise in writing from memory to a diskette, I'm trying to write a simple
    boot sector program to capture 8 x 512 bytes starting at location
    0xb800:0000 and write them to 8 sectors on a floppy. Based on what I've
    read about interrupt 13h in Gilluwe's book, I think I want to call that
    interrupt with AX=0x803, BX=0, CX=0x300, DX=0, so I did that. Inspection of
    the floppy using dd and od -bc showed that nothing had been written (I should
    probably also mention that I decided earlier to fill the entire diskette up
    with 0's before writing the boot sector). Then I used a subroutine wout from
    the lilo-22.8 distribution to write the contents of AX to the screen and found
    that it was 0x0400. According to Gilluwe's book, Table 10-3, that means that
    either the sector wasn't found or that it was past the last cylinder. That
    sounds like an unsuccessful operation to me. I then executed the assembly
    language command lahf to write the lower 8 bits of the flag register to
    AH and then called wout again. The output was 0x4600, so the carry flag is
    0 and that means the operation was successful. Since I don't have a lot of
    confidence in my own code, I tried it using the subroutine dsk_do_rw from
    the lilo-22.8 distribution (for some reason, a comment in the code for
    dsk_do_rw says that read is 0, write is 1 and read-only test is 2, which
    seems to contradict Gilluwe's values for the int 13h functions). The results
    were the same.

    If someone has code for a simple boot sector program that will copy the
    8 x 512 bytes starting at b800:0000 to the first 8 sectors on track three
    of the floppy, would you please post it?

    I should say that I copied the code for wout by hand and made at least one
    typo, which affects the way ordinary digits are printed, and need to try all
    this again by actually copying the relevant source files to this PC and
    extracting the code without typing it myself. But I think the results I'm
    getting are accurate. (The bug is that it writes 0123456789 as
    I decided the simplest UART register to write to would be the Scratch
    Register. So, I wrote a simple boot sector program that reads the Scratch
    Register and calls wout to print the contents, then writes to the Scratch
    Register, then reads it again and prints out the contents. Here is the
    program.
    entry start
    start:
    mov dx,#0x337
    in al,dx
    call wout
    mov dx,#0x337
    mov ax,#0xABCD
    out dx,al
    mov dx,#0x337
    in al,dx
    call wout
    loop1: jmp loop1

    The first call to wout prints 79FF, which is really 02FF in view of the
    bug in my copy of wout. The second call to wout prints ABFF, which is
    really ABFF, since this buggy wout does print hex A-F correctly. What matters
    is the FF in AL. If the write to the Scratch Register had been successful,
    the second call to wout should have printed ABCD. This experiment shows that
    the write had absolutely no effect on the Scratch Register. It also supports
    the view that there is no alternative to locating sound card's BIOS in memory
    and disassembling it. So, everything now seems to hinge on capturing the upper
    memory on the floppy.
     
    Allan Adler, Nov 16, 2007
    #37
  18. Allan Adler

    Arno Wagner Guest

    That would be the INT pin and on chips wioth FIFO (16c550) also
    the rxrdy and txrdy pins.
    Good approach. LILO is pretty reliable in my experience and can
    ouput diagnostics even at start of booting.

    Arno
     
    Arno Wagner, Nov 16, 2007
    #38
  19. Allan Adler

    Allan Adler Guest

    That was almost right. The contents of CL is the sector number, which runs
    from 1 to 18 on a 1.44 MB floppy, so putting 0 in CL is an error. I changed
    CX to 0x301 and now the program runs fine. Tomorrow I'll write a boot
    sector program to capture all of the upper memory area and write it to
    the floppy in prescribed places.

    What I find strange is that the bytes that got written to the floppy were
    all equal to 0xFF, which I don't believe is the actual content of the area
    of memory I was reading, namely the screen buffer, to which I had previously
    written 128 A's, B's and C's with blue backgrounds.
    OK, I did so and now wout works fine.

    More when I have captured the upper memory area...
     
    Allan Adler, Nov 17, 2007
    #39
  20. Allan Adler

    Allan Adler Guest

    I wrote the program and it seems to work but also seems not to work.
    It writes to sectors 1-16 of tracks 1-48 on side 0 (i.e. head = 0) of
    the floppy. The code is below. The routine abc writes 128 a's, b's and
    c's to the top of the screen by writing directly to the screen buffer.
    The routine hello calls the lilo routine say to write "Hello, World!"
    to the screen. The routine wout is also from lilo and writes the contents
    of AX in a form recognizable as hex digits. The routine dsk_do_rw is a
    wrapper for calling int 13h and is also scavenged from lilo. The various
    calls to wout let me check what the contents are of the es register,
    the return codes from the writes to the floppy and the lower byte of
    the flags register. Based on the wout output, it appears that the program
    works. From the Linux partition of the same machine, I executed
    dd if=/dev/fd0 of=flop bs=512
    to capture the floppy and then
    od -bc flop > dump
    to get a dump of the file flop (I might prefer hex, but octal is ok).
    One nice feature of the dump is that if there are a lot of repetitions
    of the same line, only the first is shown. From the file dump I can tell
    that 48 writes were indeed done and seem to be in the right places on
    the floppy (based on a guess as to how dd copies the sectors of the
    floppy to the file flop). So, in that sense, the program seems to work.

    The sense in which the program doesn't seem to work is that, without
    exception, the bytes written are all FFh. It is inconceivable that
    the upper memory area consists entirely of FF's since the screen itself
    has various characters on it, including the 128 a's, b's and c's, and their
    ascii codes should be part of upper memory.

    In an earlier version of the program, I accidentally had the line
    add ax,#0x400
    instead of
    add ax,#0x200
    and this did result in the last 24 writes producing stuff other than FFh,
    but I don't think that counts. The upper memory area is from 0xA0000
    to 0xFFFFF.

    Here is the boot sector program. If anyone has any idea what is wrong with
    the program, please let me know. The assembler is as86.

    entry start
    start:
    call abc
    call hello
    call capump
    jmp loop1
    capuma:
    mov bp,#48
    mov ax,#0xa000
    mov cx,#0x101
    capuma1:
    push ax
    mov es,ax
    push es
    pop ax
    call wout
    mov bx,#0
    mov dx,#0
    mov ax,#0x310
    call dsk_do_rw
    call wout
    lahf
    call wout
    pop ax
    add ax,#0x200
    inc ch
    dec bp
    jnz capuma1
    exit_capuma:
    ret
    loop1: jmp loop1
     
    Allan Adler, Nov 18, 2007
    #40
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.