Hello all,
I have setup my SSC on an appleII+ (clone), played a bit with terminal login and so on. The physical switches are set to 9600 bps, 8N1. It works well, however I decided to take it a bit further and catch some json coming from the other end of the SCC. I have troubles integrating the serial data in a BASIC program. Let's assume the following string which is passed over serial:
{"test":"1234,56,78"}
and the following BASIC code to read this string over serial on the AppleII side:
10 print chr$(4);"IN#2"
15 j$=""
20 GET A$
40 J$=J$+A$
50 print j$
60 goto 20
The above code works as expected on the virtual][ when sending the string over file pipe and prints the full j$ string, however, when I run this on real hardware some bizzare things happen - only curly bracket comma and numbers appear and only fraction of the input chars show(e.g. not all numbers appear). No letters are shown at all. The sending hardware is set to 9600pbs, 8N1 just like the apple2 end.
As per Applesoft Basic manual, It might be the collon ":" in the string which breaks the GET. Same thing about the colon is stated for INPUT command. If I replace the GET with INPUT, then, the whole string appears, however INPUT requires CR at the end, hence INPUT is useless in automated data sending. If I press CR manually, the collon breaks the var (same as with GET).
So my questions is, how do I accept the full string in BASIC?
It's worth mentioning other things which I noticed. If I switch manually to Terminal mode (Ctrl-A T) the string appears fine, but it's not automated process, also BASIC can't read in terminal mode?
It seems sending chr$(1);"T" to enable Terminal mode with BASIC doesn't work. The cursor is not changing to flashing underscore.
I tried PEEK-ing the char register $27 with peek(39), as per SSC manual to get the char in the buffer, but either I'm not doing it right or it's not the way to get the chars from SCC.
I'll appreciate any help on this as it's driving me crazy for a week now :)
I'll check my SSC notes, but why does line 15 declare a lower-case j$ while the other lines reference upper-case J$?
Are you using 80 column-mode for upper and lower-case text with an 80-column memory expansion card? Not to mention Apple II BASIC doesn't support lowercase.
It's all caps in the test code, I've misspelled the declaration and the print statement just here.
I have some further findings on this. I believe there's something in the way SSC (or BASIC) processes small letters, despite setting lowercase to capitals translation in the firmware with "0T" option. It seems I receive sporadig chars but it's either the open curly brace, comma or digit (not the first occuring one though), then it it just stops. I've never received an alpabet char. I haven't tried with sending capital letters though. However, it's my understanding that small letter chars would be acceptable by SCC and BASIC.
When I switch SCC to terminal mode in 40 col mode, the SCC apparently translates the chars to caps, as curly braces turn to "[ ]" and letters turn to caps, so I guess it's on the BASIC side.
I'm using 40 col mode on the IIe clone. However I've got lowercase letters in this mode as well. Could it be incorrect 7bit-8bit codepage interpretation in BASIC itself?
There are lots of different issues that can cause problems here, so it is good to narrow things down if you can. I am using KEGS with slot 1 connected to a terminal. If I run the program:
10 PRINT CHR$ (4);"IN#1"
15 J$ = ""
20 GET A$
40 J$ = J$ + A$
50 PRINT J$
60 GOTO 20
And, I paste {"test":"1234,56,78"} into my Terminal, I get
{
{"
{"t
{"te
{"tes
{"test
{"test"
{"test":
{"test":"
{"test":"1
{"test":"12
{"test":"123
{"test":"1234
{"test":"1234,
{"test":"1234,5
{"test":"1234,56
{"test":"1234,56,
{"test":"1234,56,7
{"test":"1234,56,78
{"test":"1234,56,78"
{"test":"1234,56,78"}
Is this what you expect?
Unless you modify it, Applesoft BASIC normally, and unfortunately, converts lower case that is entered to upper case:
`abcdefghijklmnopqrstuvwxyz{|}~
becomes:
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
Also, note that on my Apple II+ in TEXT mode:
`abcdefghijklmnopqrstuvwxyz{|}~
appears as:
!"#$%&'()*+,-./0123456789:;<=>?
> How do I accept the full string in BASIC?
That's a good question because there are lots of ways this can fail. Using
GET A$
, as your program does, is the way to go.I have an old Super Serial Card, but I haven't used it in quite a while. I do remember that absolutely all of the settings had to be correct on both sides: on the Apple II+ and on my iBook. Serial connections can be finicky.
PR_2, are you using a II+ or IIe or both? You've stated both in your posts.
He said (clone) in at least one spot... And that's relevant because a lot of clones came with Applesoft patched to take advantage of the upper and lower case they provided compared to a stock ][+.
For //e or a //e clone, it is relevant because the "Enhanced" //e changed Applesoft in similar ways compared to the original ROM.
Results for things like this could be different depending on what machine they are being run on.
Thanks softwarejanitor, I noticed his clone reference and the reason I raised my last question when a II+ and IIe had been mentioned, which lead you to your remark. Yes, it makes a difference which it is, clone et al.
Thank you all!
Here are some more details, I've tested on both II+ clone and IIe (not Enhanced) clone which I have, as well as in Virtual][ (where everything is as mmphosis observed on his machine). The clones are Bulgarian which add cyrillic letters (both lowercase and caps), so the codepages which they support are both 7bit (for the II+) and 8 bit + 7bit (for IIe). I'm attaching images from the original manuals for reference.
I've read the BASIC reference for these clones (for the GET operator in particular) and it seem to match the Applesoft Basic regarding the colon and comma restriction
So basically, as far as I can see it boils down to how BASIC reads the codepage of the incoming char codes though GET. In my case it seems lowercase letters are ignored, although it is supposed to be translated by the SCC before being sent to BASIC. They are translated if SCC is in Terminal mode though, or if I use INPUT operator in BASIC. It's just GET which can't get them right.
7bit.png
8bit.png
One thing to take into consideration when data is being sent over a serial connection from an Apple II to most other machines like PC clones is that usually Apple II doesn't really have a concept of a "code page". It is straight classic ASCII. And the Apple II normally sets the high bit on each byte, where most other machines expect it to be off. Foreign clones may have different CHARGEN EPROM imagines to contain those cyrillic characters, but usually that's just a display thing and the BASIC and SSC ROM images probably don't have significant customizations for the language.
Even before you set things, you need to make sure all the communication parameters are set correctly. It's often easiest to make sure the actual configurations are right using terminal software on the Apple II. You have to have the baud rate, number of data bits, number of stop bits, parity, etc., all correct or it won't communicate right at all, you'll get nothing or more likely just jibberish. I normally prefer 8N1 - 8 data bits, no parity, 1 stop bit.
And the physical wiring makes a difference too. Although minimally you only need 3 wires to move data (TX, RX & GND), in most cases you need a few other signals or the connections on either end may need to have some signals hard wired. This is especially important if the baud rate is set higher, as then you usually need hardware handshaking signals to prevent data loss. If you are moving relatively small amounts of data, troubleshooting may be simpler if you use a slow baud rate like 300 or 1200.
Anyway, I'd get the communications working first before I tried debugging my own code.
I've set up both appleII and the sending serial device to 9600bps, 8n1. The communications is ok, as I mentioned a bit earlier. If I just do in#4 (got SSC in slot 4) and send the data over serial, it appears correctly on apple2 (translated in capitals). This tells me there is no communication problem per se. I just can't capture this data in BASIC. I'll do some more experiments, it migh really be some weird BASIC rom changes on these clones.
Have you tried AppleWin instead of Virtual][. The latest version still cannot emulate Pravetz 8C (which I know you have), but it can do Pravetz 8A, which should be close enough. It can also do Pravetz 8M.
This is what I mean. Below is a phone picture of the real hardware screen. The vertical row is the output of the Basic program. At the bottom is just in#4 and serial data arriving at the prompt.
IMG_9106 Large.jpg
The problem is the program on the real hardware. On Virtual ][ works as expected.
It might be that BASIC is simply not fast enough and is dropping characters. Maybe try a lower baud rate. Try this program, and see if it doesn't lose as many characters:
0 GET A$: PRINT A$; : GOTO
1 TEXT : HOME : POKE 34,21 : VTAB 21 : print chr$(4);"IN#2" : GOTO
RUN 1
In the 1980s, I would connect to the college computer at 300 baud. I wrote a BASIC program to use as a dumb terminal but it was not fast enough! If I dropped the speed to 110 baud and only scrolled at most 4 lines of text it seemed to keep pace—if I remember correctly.
About twenty years ago, I transferred floppy disks to my iBook. I didn't know anything about ADTPro at the time. I wrote a custom assembly language program to read from disk and pipe the data over to the iBook. I had a program running on the iBook that would read the incoming data and save it as a .dsk file. Here's some notes:
# Serial Card in slot #2 of the APPLE ][
# Keyspan in the iBook
Communications between the APPLE ][+ and another computer.
9600 baud seems to be the fastest the APPLE ][+ can handle.
From the APPLE ][:
IN#2
From the command line:
tee > /dev/tty.KeyUSA28X21.1
From another command line:
stty -f /dev/tty.KeyUSA28X21.1 parenb opost onlcr
Misc. stuff, dunno if this works or not...
stty -f /dev/ttyp1 300 parity -icanon -echo nl -echoe -echoctl -echoke -echo onlcr
stty -f /dev/cu.KeyUSA28X21.1 parenb istrip
mmphosis has a point... 9600 is way faster than you need. I'd back it off to 300. It is more likely to work as he says because BASIC is sllllooooow. His command line examples should be close for MacOS but the device names (/dev/tty..) may be different. It's also fairly close for Linux. Windows I don't remember right off the top of my head, I haven't had to deal with that in years and I don't even have it myself to try.
You were right! BASIC is waaay too slow for 9600bps. I've reduced the speed to 300bps and the strings are being fully received by the Basic program. But even at that slow speed, if the string which has been sent is long, the chars at the end are radomlly missed by apple2. So if there's bigger string, it has to be chopped in smaller chunks and there has to be a small pause between sending each chunk.
Thank you all. It's valuable information which can't be found anywhere (I've looked around quite a bit) and it has to remain for others to benefit here.
Ok, I did it :)
Despite lowering the baud rate to the bare minimum which sending device supports - 1200 bps, there were still missing chars, so I reorganized my BASIC code and isolated the GET loop and var declarations in the beginning and the rest of the logic after that. Now at 1200bps, Basic seems to receive the string ok and parses it as anticipated.
The project was to get the weather data coming from my weatherstation via LoRa radio. Now I can get the json which is sent by the weatherstation directly on my Apple IIe clone without intermediary MCU. Lora module outputs serial string so I was able to get it via SSC. I'm still to find how stable this is though.
Here is the code if anyone wants to have a look: WEATHER.BAS_.txt
pravetz-lora.jpg
You are receiving weather data over radio? WX
I re-wrote your program but my program may not work because I don't know the json format it's sending. There are things one can do to speed up Applesoft BASIC: Do the processing at the top of the program. Use tight FOR loops. Inline code. Use variables in place of literal values. Use single letter variables and single number GOSUBs. Make the program short. Optimze where you can. For instance, my program draws the labels and units first, and only updates the changing values. If there is a carriage return between lines of json data, I think it might be possible to use the INPUT statement which is much faster than GET. And then there is assembly language.
0 GOSUB 9: FOR Q = 0 TO T STEP 0: VTAB K: PRINT W$;:J$ = "": FOR J = N TO M: GET A$:J$ = J$ + A$: IF A$ < > F$ THEN NEXT J: IF MID$ (J$,E,E) < > S$ THEN STOP
1 R$ = MID$ (J$,O,J):B = T:F = T: HTAB 1: CALL W: PRINT : PRINT J"- "R$: VTAB T: FOR I = T TO LEN (R$): IF MID$ (R$,I,T) = C$ THEN HTAB V: PRINT LEFT$ ( STR$ ( VAL ( MID$ (R$,B,I - B))) + P$,G):B = I + T
2 NEXT I: HTAB V: PRINT LEFT$ ( STR$ ( VAL ( MID$ (R$,B,I - B))) + P$,G): NEXT Q: STOP
9 PRINT CHR$ (4);"IN#4"
10 READ T,Z,E,G,L,O,K,V,N,M,W,C$,P$,W$
20 S$ = CHR$ ( ASC ("W") + 32) + CHR$ ( ASC ("T") + 32) + CHR$ ( ASC ("H") + 32): REMSTART
30 F$ = CHR$ ( ASC ("]") + 32): REMFINISH RIGHT CURLY QUOTE
40 HOME
50 FOR X = 0 TO L
60 READ L$,U$
70 PRINT L$": " TAB( 27)U$
80 NEXT
90 RETURN
100 DATA1,2,3,6,7,10,11,20,-10,255,-868,","," ","WAITING FOR DATA ... "
110 DATA"TEMPERATURE","C"
120 DATA"PRESSURE","HPA"
130 DATA"HUMIDITY","%" 140 DATA"WIND DIRECTION","-"
150 DATA"WIND SPEED","m/s"
160 DATA"WIND GUST","m/s"
170 DATA"RAINFALL","mm"
180 DATA"BATTERY","V"
REM TEST DATA - DON'T HAVE THE SPEC FOR THE JSON FORMAT
REM {"wth": "23.0,978.77,91.92,62.5,0.1,0,7,-12.3456"}
REM {"wth": "19.5,1006.1,50.65,90,25,30,5,12.3"}
REM {"wth": "29.98,980.97,44.63,170.3,2.5,0,0,14.528"}
REM TO ABORT WITH ?ILLEGAL QUANTITY ERROR
REM }
Doing code like that in assembler or maybe using a tool like cc65 to compile C code should be able to generate code that would be several times faster than Applesoft BASIC. Decent assembler code would probably be able to run reliably at 1200 baud for simple short strings like this.
Wow, thanks for the code refactoring and the tips!
I guess I need to try and learn some assembler or cc65, but the learning curve is quite high. My daily language is Python and Basic felt the right way to start with. I just didn't realize how slow it is. The weather station doesn't output <CR> at the end of the string, hence I didn't check for it and tried to match the closing curly brace as end of string. I could add the carriage return in the JSON source and use INPUT as you suggest, but it would probably mess up the other receiving devices and Homeassistant (or refactor their code).
The Einstein compiler is also something that might work out for you. It makes Basic code about 10 times faster in my experience. It doesn't support ProDOS though, only DOS 3.3, however lots of times the code just works fine in ProDOS as well.