Serial IO on Raspberry Pi with BBCSDL

Discussions related to network, internet and socket programming; also to serial, parallel, Bluetooth, USB etc.
Post Reply
SteveF
Posts: 1
Joined: Tue 18 Dec 2018, 20:23

Serial IO on Raspberry Pi with BBCSDL

Post by SteveF » Tue 18 Dec 2018, 21:17

I have been working on serial communications on Raspberry Pi using BBCSDL and have made some progress. Seeing some other questions about this I wanted to post my results for others but am not certain if content and formatting are correct. I am looking for some feedback and will try to get this into shape. Thanks for any help or suggestions.

The hardware setup is very simple. I am using an FTDI USB to serial converter on the Raspberry Pi side since that is by far the easiest. I am using a model 3 B+ and the FTDI converter was immediately recognized as ttyUSB0. I think that would be the case on any Pi except maybe Pi Zero. On the PC side the serial connection is plugged into a serial port.

I am posting 4 short test programs. There are 2 pairs, each with a PC side and a Raspberry Pi side. I tried to attach the programs but received a wrong file extension message so I am just embedding them in this post since they are so short.

First pair: PCsertest1.bas and RPisertest1.bas
RPisertest1.bas: A basic file, runs under BBCSDL. Opens the port and an output file to log results. Sends all possible bytes from 0 to 255 sequentially and then reads same byte echoed back by PC program and logs it. Exits after sending 0xFF. The program is located in /home/pi/Desktop/BBC/examples on my setup. BBCSDL is located in /home/pi/Desktop/BBC.
There are some statements in the program just to test various commands such as STR$, GET$, etc. As you can see the program as structured does not rely on being able to read the number of characters in the input buffer.

REM a test of serial port on Raspberry Pi 11/6/2018 SF
REM This program sends every ASCII character from 0 to 255, prints and logs the echoed characters and then quits

OSCLI "ldattach " + "-1 -8 -n -s 9600 0 /dev/ttyUSB0 " + ";"
OSCLI "stty " + "raw " + ";"

1 serial% = OPENUP("/dev/ttyUSB0.")
2 fileout% = OPENOUT("/home/pi/Desktop/BBC/examples/sertestoutpi.txt")

3 t% = 0
testbuf% = 0
fileout$ = STR$(fileout%)
serial$ = STR$(serial%)
4 PRINT#fileout%,fileout$," ",serial$," "
5 BPUT#fileout%,"Transmitting and Receiving Data"+CHR$(13)+CHR$(10)

6 FOR i% = 0 TO 255
7 BPUT#serial%,i%
10 t% = 0
t% = BGET#serial%
t$ = STR$(t%)
15 PRINT t$;" ";
16 PRINT#fileout%, t$
17 BPUT#fileout%, 32
20 NEXT i%

21 CLOSE#serial%
22 CLOSE#fileout%
23 END

PCsertest1.bas: This is the PC end of the test running under BBC BASIC V6.02a. It opens the port and a log file and then waits for a character. The timeout delay is set very long so that you can easily start PCsertest1.bas and then start the test program on the Pi. When the last byte (0xFF) is received the program terminates.

REM THIS IS THE PC END OF THE TEST PROGRAM FOR BBC BASIC SERIAL COMMS ON RASPBERRY PI
REM 11/6/2018 SF
serial% = OPENUP("COM1: baud=9600 parity=N data=8 stop=1")
fileout% = OPENOUT("C:\Sensigent\software\sertestoutpc.txt")
t% = 0
timeout% = 0
serial$ = STR$(serial%)
fileout$ = STR$(fileout%)
PRINT#fileout%,serial$,fileout$
BPUT#fileout%, "Receiving and Transmitting at PC"+CHR$(13)+CHR$(10)

10 testbuf = EXT#serial%
IF testbuf > 0 THEN
t% = BGET#serial%
PRINT t%;" ";
t$ = STR$(t%)
PRINT#fileout%, t$
BPUT#fileout%, 32
BPUT#serial%,t%
timeout% = 0
ENDIF
timeout% = timeout% + 1
IF timeout% > 3000000 THEN GOTO 20
IF t% <> 255 THEN GOTO 10

20 PRINT "Done"
CLOSE#serial%
CLOSE#fileout%
END

Second pair: PCsertest2.bas and RPisertest2.bas
PCsertest2.bas: Also running under BBC BASIC V6.02a. Since the first set of test already demonstrated all ASCII characters can be sent/received the PC side just sends the number of characters commanded by the user.

REM PC side for a test of serial port on Raspberry Pi
REM This one sends a specified number of characters each time through the loop
REM User inputs the number of characters to send. Entering 0 terminates program

10 serial% = OPENUP("COM1: baud=9600 parity=N data=8 stop=1")
PRINT "channel # ", serial%, " handle ", @hfile%(serial%)

20 INPUT k%
c% = 41
FOR i% = 0 TO k%-1
BPUT#serial%,c%
NEXT i%

IF k% > 0 THEN GOTO 20
CLOSE#serial%
END

RPisertest2.bas:
The Raspberry Pi side either checks and prints the number of characters in the buffer, or checks and, if non-zero, gets the characters in the buffer and prints them. This test program demonstrates the use of system calls to find the file designator and to determine the number of characters waiting in the serial input buffer.

REM THIS IS THE Pi END OF THE TEST PROGRAM FOR BBC BASIC SERIAL COMMS ON RASPBERRY PI
REM 11/27/2018 SF

REM Command line to open port, set parameters, and set line discipline to raw (no changes to characters)
OSCLI "ldattach " + "-1 -8 -n -s 9600 0 /dev/ttyUSB0 " + ";"
OSCLI "stty " + "raw " + ";"

REM Open the port and find the file designator used to check the input buffer for characters
serial% = OPENUP("/dev/ttyUSB0.")
SYS "fileno", @hfile%(serial%)!28 TO fildes%

REM "magic number" that tells IOCtl what you actually want to do, in this case check the serial buffer
FIONREAD = &541B

10 PRINT " "
PRINT "Channel # = "; serial%;" File Des = "; fildes%

tb% = 0
t% = 99

PRINT " "
PRINT " c = check buffer size , g = check buffer and get all chars, q = quit "

INPUT k$

IF k$ = "q" THEN GOTO 80

REM Use ioctl from command line to find number of characters in serial buffer
SYS "ioctl", fildes%, FIONREAD, ^tb% TO t%

PRINT "tb%=";tb%;" t%=";t%

IF k$="c" OR tb%=0 THEN GOTO 10

FOR i% = 1 TO tb%
c% = BGET#serial%
PRINT " Character # ";i%;" is ";c%
NEXT i%

GOTO 10

80 PRINT "Done"
CLOSE#serial%
END

That's it. I will check again in a few days to see if there is any feedback. Thanks.

guest
Posts: 268
Joined: Mon 02 Apr 2018, 09:12

Re: Serial IO on Raspberry Pi with BBCSDL

Post by guest » Tue 18 Dec 2018, 22:52

SteveF wrote:
Tue 18 Dec 2018, 21:17
That's it. I will check again in a few days to see if there is any feedback. Thanks.
Listing the programs in [code] [/code] tags would have made them easier to read (and easier to copy/paste); one of the advantages of the forum is the ability to include formatted code listings in posts. Perhaps the admin might consider adding them to your message (if you don't).

There are examples of some pretty poor coding practices in the programs you listed: looping using 100% CPU time unnecessarily, implementing a timeout not actually based on time, and using GOTOs. I'm sure you are well aware how undesirable they are, but since these are simply demo programs illustrating a principle they may perhaps be forgiven. Just so long as you don't do the same things in a 'real' application! ;)

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Serial IO on Raspberry Pi with BBCSDL

Post by Zaphod » Wed 19 Dec 2018, 19:41

To expand on Richard's comments it looks like you are a newcomer to BBC BASIC and many of the programming methods that are available to you.
So here are a few hints.
The 'Code' insert command is the 5th icon on the toolbar. That makes the code look like this below if you just paste your code between the tags.

Code: Select all

      REM THIS IS THE Pi END OF THE TEST PROGRAM FOR BBC BASIC SERIAL COMMS ON RASPBERRY PI
      REM 11/27/2018 SF

      REM Command line to open port, set parameters, and set line discipline to raw (no changes to characters)
      OSCLI "ldattach " + "-1 -8 -n -s 9600 0 /dev/ttyUSB0 " + ";"
      OSCLI "stty " + "raw " + ";"

      REM Open the port and find the file designator used to check the input buffer for characters
      serial% = OPENUP("/dev/ttyUSB0.")
      SYS "fileno", @hfile%(serial%)!28 TO fildes%

      REM "magic number" that tells IOCtl what you actually want to do, in this case check the serial buffer
      FIONREAD = &541B

      REPEAT
        PRINT " "
        PRINT "Channel # = "; serial%;" File Des = "; fildes%
        tb% = 0
        t% = 99
        PRINT " "
        PRINT " c = check buffer size , g = check buffer and get all chars, q = quit "
        INPUT k$
        IF k$ = "q" THEN
          PRINT "Done"
          CLOSE#serial%
          END
        ENDIF
        REM Use ioctl from command line to find number of characters in serial buffer
        SYS "ioctl", fildes%, FIONREAD, ^tb% TO t%
        PRINT "tb%=";tb%;" t%=";t%
        IF k$<>"c" AND tb%<>0 THEN
          FOR i% = 1 TO tb%
            c% = BGET#serial%
            PRINT " Character # ";i%;" is ";c%
          NEXT i%
        ENDIF
        WAIT 1
      UNTIL FALSE

      PRINT "Escape"
      CLOSE#serial%
      END
Then there is the code itself. I cannot make any comment about its function as I don't have the hardware to run it on but I will make a couple of suggestions about programming style. We have all written code like that and years later we look at it and cringe, it is part of the learning process.
I have taken your program and I think have kept the same logic but now using a REPEAT to do the looping. And so that it does not zip around that loop at silly speed wasting CPU cycles and power I have added a WAIT statement. This hands control back to other threads or just sits idle for a wee while.
The arguments against GOTO are many but particularly it can lead to difficult to read code and makes it easy to make logical mistakes. Structured programming helps keep the logic more linear as it were. The indentation in the IDE also helps you see the loops and logical steps that GOTO obscures.
It does take a little thought to start with but quickly becomes second nature. For instance if you ever see a need to jump back to the start then a WHILE or REPEAT loop will probably do that better and more efficiently. If you ever see yourself using IF THEN GOTO to jump over some code then you can just invert the logic of the test make it into a multi-lined IF THEN and put the ENDIF where you wanted to jump to. Richard's additions to BBC BASIC allow you to EXIT from the structures if need be, and then the code 'falls through' to the code beyond that structure.
In this little code snippet the input of a "g" seems to be ignored. I imagine this is just 'work in progress'.
I think a little time looking at the example programs will be helpful with regards to the points above and also look at what happens when your code is run by people that will try all the silly inputs that you never thought of. Things like validating inputs and checking and reporting error conditions will be found on most of Richard's examples.
I hope this helps and welcome to the fold...

Z

Post Reply