Reading serial port peripherals [SOLVED]

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
1337
DCEmu Newbie
DCEmu Newbie
Posts: 7
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Tue Nov 29, 2022 7:09 am
Location: Where sailors hang out
Has thanked: 9 times
Been thanked: 3 times

Reading serial port peripherals [SOLVED]

Post by 1337 »

I manually compiled Kallisti OS on my PC and also have a broadband module in my DC.
How do you read the serial port at the back? Say I have an I2C gyro module on an Arduino Nano that works over serial port baud rate 9600 and I want to stream roll, pitch, yaw data over into the console. Can I connect GND, 5V, TX on the Arduino to RX on the Dreamcast and read the gyro data for use in a game? What is the library to do that?
Last edited by 1337 on Wed Dec 28, 2022 3:35 pm, edited 1 time in total.
User avatar
ThePerfectK
Insane DCEmu
Insane DCEmu
Posts: 147
Joined: Thu Apr 27, 2006 10:15 am
Has thanked: 27 times
Been thanked: 35 times

Re: Reading serial port peripherals

Post by ThePerfectK »

there is a libary in kernel/arch/dreamcast/include/dc that is intended for scif (serial communication inferface with FIFO). Here is the header: http://gamedev.allusion.net/docs/kos-cu ... if_8h.html

And more appropriately, here's the source, as used by dcload: https://github.com/Kochise/dreamcast-do ... oad/scif.c

Renesas manual on serial communication: https://www.renesas.com/us/en/document/ ... anguage=en

these would be the best places to start reading.
These users thanked the author ThePerfectK for the post (total 4):
|darc|legit nyckIan Robinson1337
Still Thinking!~~
1337
DCEmu Newbie
DCEmu Newbie
Posts: 7
Joined: Tue Nov 29, 2022 7:09 am
Location: Where sailors hang out
Has thanked: 9 times
Been thanked: 3 times

Re: Reading serial port peripherals

Post by 1337 »

I made my own serial cable using the top half of a HDMI connector and one of those cheap red breakout boards. The dc-tool-serial client program works on my PC and successfully uploads binaries to the Dreamcast at 115200 baud rate. I run the latest Ubuntu Debian-based distro, the serial board appears as "/dev/ttyUSB0" in the system.

The scif.h and scif.c in the dc-load-serial program (what runs on the Dreamcast) is somewhat different to what's included with KOS, regardless I gave it a try but it doesn't seem to work.

I copy my *.cdi file onto an SD card, then run it from GDEMU so that there's no possibility of something like the debug console blocking the serial port.

At the beginning of the program I initialise the serial port at 9600 baud rate:

Code: Select all

void Initialize()
{
    scif_init();
    scif_set_parameters(9600, 1);
}
Then, inside the program loop, I try to read one character from the stream of data but it's just saying "-1" which is the state when there's no data:
read_char-1.png

Code: Select all

void Update()
{
    dbgio_dev_select("fb");//switch to on-screen printing
    printf("Char read: %d", scif_read());
    printf("\n");
}
To see if "-1" changes to anything else, I tried sending a binary using dc-tool-serial at baud rate of 9600:
(As I know this program can definitely talk to the DC)

Code: Select all

sudo ./dc-tool-ser -t /dev/ttyUSB0 -b 9600 -x /home/user/Desktop/dreamcast/game/demo.elf
I also tried directly sending stuff to the serial port:

Code: Select all

echo 'A' > /dev/ttyUSB0 9600
Are there more code examples of someone using the SCIF functions?

Could it be that the use of dbgio to print text on screen disables reading from serial (as it's a debugging library)?

I'm trying to make a free game with a serial port peripheral, like the maracas, it reports location and rotation as a string of text.

Update:
When I use the scif_read, get_char and buffer read functions I don't get anything, so I deconstructed scif.c and looked at the hardware register involved:

Code: Select all

/* receive fifo data register */
#define SCFRDR2 (volatile unsigned char *)  0xffe80014

Code: Select all

scif_flush();
scif_init();
scif_set_parameters(9600, 0);

Code: Select all

printf("Register: %x", *SCFRDR2);
And I can see the register changing live on screen in my Dreamcast game every time I send a character from my PC over command line:
register.png
So the hardware is working, but I don't know why the libraries aren't.
Now I need to figure out how to read a string.

Update;
I printed all of the registers onto the screen to understand what's happening in the background.

Code: Select all

    /* serial mode register */
    printf("Serial mode:");
    printf("%x\n", *SCSMR2);

    /* bit rate register */
    printf("Bit rate:");
    printf("%x\n", *SCBRR2);

    /* serial control register */
    printf("Serial control:");
    printf("%x\n", *SCSCR2);

    /* transmit fifo data register */
    printf("Transmit fifo:");
    printf("%x\n", *SCFTDR2);

    /* serial status register */
    printf("Serial status:");
    printf("%x\n", *SCFSR2);

    /* receive fifo data register */
    printf("Receive fifo data:");
    printf("%x\n", *SCFRDR2);

    /* fifo control register */
    printf("Fifo control:");
    printf("%x\n", *SCFCR2);

    /* fifo data count register */
    printf("Fifo data count:");
    printf("%x\n", *SCFDR2);

    /* serial port register */
    printf("Serial port:");
    printf("%x\n", *SCSPTR2);

    /* line status register */
    printf("Line status:");
    printf("%x\n", *SCLSR2);
The FIFO register SCFRDR2 is where the data is received

If I just send a string of text out the serial port the whole port gets jammed and no more data can be sent.

Code: Select all

root@machine:/home/user# printf 'something' > /dev/ttyUSB0 9600
In the blocked state, the FIFO register SCFRDR2 stops flashing numbers and the line status register SCLSR2 changes from 0 to 1.

So the only reliable way to send data to the DC is to do it in single bytes like this:

Code: Select all

root@machine:/home/user# printf '\x86' > /dev/ttyUSB0 9600
Or this:

Code: Select all

root@machine:/home/user# printf 'A' > /dev/ttyUSB0 9600
But after a while the SCFRDR2 register stops changing (without line status flipping to 1)
And it only starts changing again once a new line command is passed with, say '\n'.

So the only reliable way of sending data I found is by passing single bytes terminated by a new line.

Say, this:

Code: Select all

root@machine:/home/user# printf '%b' '\x86' > /dev/ttyUSB0 9600
Or this:

Code: Select all

root@machine:/home/user# printf 'A\n' > /dev/ttyUSB0 9600
I tried the above approx. 500 times and it works consistently, nothing else does.

Update
I can see now where the problem is

Code: Select all

scif_set_parameters(9600, 1);
The baud rate isn't 9600, it's somewhere between 57600 and 76800, I determined this by installing PuTTy and trying different speed values. When I set the speed to 57600 and then with he PuTTy window open press and hold number 1 on the PC's keyboard, I can see the Dreamcast display '31' under 'Recive fifo data" on screen, When I press 2 I get 32 and other corresponding ASCII codes:
https://www.rapidtables.com/code/text/ascii-table.html
This problem is specific to this program, when I use dc-load-serial *.cdi it can easily read data from the PC at 115200 baud and doesn't complain about anything.
The bit rate register on the Dreamcast reads '1a'.

Update
When I booted into my game again with the PuTTy window open and serial cable connected to the Dreamcast - I got KallistiOS debug messages printed. My guess was correct, the debugging console is enabled and it's interfering with the serial port by forcing its own baud rate. So as long as I use the scif_read() function at 57600 baud, reading the serial port works perfectly fine. Though I would prefer to set and use 115200 baud but don't see the setting in KallistiOS, maybe I need to dig deeper.
scif.c by the way has a funny comment:

Code: Select all

/* Initialize the SCIF port; baud_rate must be at least 9600 and
   no more than 57600. 115200 does NOT work for most PCs. */
/* recv trigger to 1 byte */
Maybe that was written 20 years ago, I have no problem pushing binaries to the console at 115200 baud.
Anyway, I hope this post will be useful to someone who finds it via Google (maybe it will be me in 2 years :grin: )
These users thanked the author 1337 for the post:
ThePerfectK
User avatar
ThePerfectK
Insane DCEmu
Insane DCEmu
Posts: 147
Joined: Thu Apr 27, 2006 10:15 am
Has thanked: 27 times
Been thanked: 35 times

Re: Reading serial port peripherals [SOLVED]

Post by ThePerfectK »

Thank you so much for not only diving into this topic, but keeping the thread updated with not just your successes, but also your failures. That stuff helps so much, there have been so many topics that I've been able to work out only because decades ago some people took the time to document their efforts. If you don't mind, I'd like to clean up your posts and make a wiki entry about serial port communication!
These users thanked the author ThePerfectK for the post (total 3):
|darc|GyroVorbis1337
Still Thinking!~~
1337
DCEmu Newbie
DCEmu Newbie
Posts: 7
Joined: Tue Nov 29, 2022 7:09 am
Location: Where sailors hang out
Has thanked: 9 times
Been thanked: 3 times

Re: Reading serial port peripherals [SOLVED]

Post by 1337 »

ThePerfectK wrote: Thu Jan 05, 2023 3:27 pm If you don't mind, I'd like to clean up your posts and make a wiki entry about serial port communication!
Please go ahead. I will publish the source code once the project is completed. I'm just embarrassed to do it now as it's more hacking than proper programming.
These users thanked the author 1337 for the post:
GyroVorbis
Post Reply