Cc65: CC65 and User Port question

Created on 3 Sep 2019  路  9Comments  路  Source: cc65/cc65

Can someone tell me why this code isn't working? It will connect, but wont send any data. Set up for 1200 baud.
The same thing, in BASIC (with OPEN, GET#, and PRINT#) does send things.

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#include <cc65.h>
#include <serial.h>

void main(void)
{
   char c;
   int err = 0;
   int t = 0;

   char rs232filename[2] = { '\x08', '\x00'};
   err = cbm_open(2, 2, 0, rs232filename);
   if (err == 0)
   {
      cputs("sending data");
      for (t=0;t<3;t++)
         cbm_write(2,"g",1);
      cbm_close(2);
   }
   else
   {
      cprintf("Error opening modem = %d", err);
   }
}
question

Most helpful comment

How about a bigger ASM program? How to do step 1?

; C64 (and maybe VIC-20) code

RIBUF := $F7
ROBUF := $F9

.bss

; RS232 buffers
inbuf:  .res    $0100
outbuf: .res    $0100

.code

...
...
; Pre-allocate the RS232 buffers.
        lda     #<inbuf
        sta     RIBUF
        lda     #>inbuf
        sta     RIBUF+1
        lda     #<outbuf
        sta     ROBUF
        lda     #>outbuf
        sta     ROBUF+1
; Open the RS232 device.
...
...
...
; De-allocate the buffers.
        lda     #$00
        sta     RIBUF+1
        sta     ROBUF+1
; Close the RS232 device.
...

All 9 comments

The Kernal's RS-232 driver uses two RAM-page buffers. Normally, they're put at the top of BASIC's RAM space. That's why the docs warn you to open that device at the beginning of your BASIC program; it erases the variables when it takes away 512 bytes of string space. (The Kernal always returns an "error" code after openning that device, so that BASIC will know what to do.) Those buffers are managed by an NMI interrupt handler.

A machine-language program must do three things about those buffers:

  1. It must pre-allocate space for them. Otherwise, they would "stomp" on the heap.
  2. It must accept an error-code of 0xF0 as meaning "RS232 was openned OK".
  3. It must wait until the transmitter buffer is empty before closing the device file.

Your test program is small, and doesn't use the heap; therefore, it doesn't need to worry about step #1. But, it does need to wait for those 'g's to be sent:

#define ENABL (*(signed char *)0x02A1)
...
   // Wait for RS232 transmission to stop.
   do ; while (ENABL & 0x01 != 0x00);

@greg-king5 Please add this to the docs somehow.

@greg-king5 thank you for the infos!
How about a bigger ASM program? How to do step 1?

0x02A1 is the "Temporary area for saving original value of CIA#2 interrupt control register, at memory address $DD0D, during RS232 input/output" as per C64 memory map.

What is the address with this role for PLUS/4? I should make a portable program

How about a bigger ASM program? How to do step 1?

; C64 (and maybe VIC-20) code

RIBUF := $F7
ROBUF := $F9

.bss

; RS232 buffers
inbuf:  .res    $0100
outbuf: .res    $0100

.code

...
...
; Pre-allocate the RS232 buffers.
        lda     #<inbuf
        sta     RIBUF
        lda     #>inbuf
        sta     RIBUF+1
        lda     #<outbuf
        sta     ROBUF
        lda     #>outbuf
        sta     ROBUF+1
; Open the RS232 device.
...
...
...
; De-allocate the buffers.
        lda     #$00
        sta     RIBUF+1
        sta     ROBUF+1
; Close the RS232 device.
...

What's the equivalent for PLUS/4 for:

#define ENABL (*(signed char *)0x02A1)
...
   // Wait for RS232 transmission to stop.
   do ; while (ENABL & 0x01 != 0x00);

?

I haven't studied the Plus/4 Kernal. The only info that I have comes from _C16/PLUS 4 REFERENCE BOOK_, from ANCO. It suggests that $07D4 has the flag that's needed; but, I don't know how the Kernal uses that variable.

The book does show that the Plus/4 is like the C128. They don't need steps 1 and 2 (they have reserved areas for their buffers).

Just tried to use $07D4 with every bit (one per time, of course):

do ; while (ENABL & 0x01 != 0x00);
do ; while (ENABL & 0x02 != 0x00);
do ; while (ENABL & 0x04 != 0x00);
do ; while (ENABL & 0x08 != 0x00);
do ; while (ENABL & 0x10 != 0x00);
do ; while (ENABL & 0x20 != 0x00);
do ; while (ENABL & 0x40 != 0x00);
do ; while (ENABL & 0x80 != 0x00);

All these have no effect :(

"The plus/4 schematic clearly shows that 6551 pin 9 (CTS) is permanently grounded. So CTS is always true at the 6551. Any manipulation of CTS is done when $FD01 is copied to RAM at $07D4. Where it retains its bit #4 location. During the IRQ cycle, $FD01 is copied to working RAM at $07D4. Code at $EA89 shows toggling of Bit 4 as CTS."
http://plus4world.powweb.com/forum/27332

Was this page helpful?
0 / 5 - 0 ratings