Suggestion: PBASIC Enhancements for I/O processing
Phil Pilgrim (PhiPi)
Posts: 23,514
I'm working on a PBASIC program, using a BS2pe, for communicating with a PLC. The communication protocol relies heavily on hexadecimal formatting and linear redundancy checks (XOR-style "checksums"). I'm finding PBASIC to be very cumbersome for this in its present incarnation. But there are a few simple extensions to the language that would make things a lot easier.
1. PUT: How about an option for an argument list like those used with SEROUT? This would allow for creating and manipulating a buffer in memory before it's transmitted:
2. SEROUT: SERIN et al. have a SPSTR modifier for reading data into the scratchpad RAM. Why not also include it in output statements like SEROUT for sending data from this area? Continuing with the above example, here's how it could be used:
3. GET: After a string is read into scratchpad RAM using the SPSTR modifier, one might like to inspect it first to determine how to interpret it and to see if any checksum transmitted with it is correct. Then it should be possible to read the buffered data into variables, using the usual I/O modifiers:
4. GET: An alternate functional notation for GET would really be nice. It would eliminate having to waste a scratch variable (e.g. bufbyte in the above examples) every time GET is used. Two forms, GETBYTE and GETWORD, would be appropriate:
5. Word: In the same spirit of making memory access and I/O more alike, the Word modifier used with GET and PUT would also be useful in I/O operations, alleviating the ubiquitous and cumbersome MyVar.LOWBYTE, MyVar.HIGHBYTE two-step in argument lists:
Of course, whether these are feasible depends on whether PBASIC's tokenized code can support the requisite operations. My suspicion is that it can.
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 5/26/2007 8:12:57 PM GMT
1. PUT: How about an option for an argument list like those used with SEROUT? This would allow for creating and manipulating a buffer in memory before it's transmitted:
PUT 0, [noparse][[/noparse]SOH, HEX2 PLCAddr, "01", HEX4 vAddr, "00", HEX2 nWords << 1, "00", ETB] 'Write all but the checksum into the buffer. chksum = 0 'Compute the checksum from the buffer contents between the SOH and ETB. FOR i = 1 to 14 GET i, bufbyte chksum = chksum ^ bufbyte NEXT PUT 16, chksum 'Write the checksum into the buffer.
2. SEROUT: SERIN et al. have a SPSTR modifier for reading data into the scratchpad RAM. Why not also include it in output statements like SEROUT for sending data from this area? Continuing with the above example, here's how it could be used:
SEROUT 0, baud, [noparse][[/noparse]SPSTR 17] 'Transmit the contents of the buffer, including the checksum.
3. GET: After a string is read into scratchpad RAM using the SPSTR modifier, one might like to inspect it first to determine how to interpret it and to see if any checksum transmitted with it is correct. Then it should be possible to read the buffered data into variables, using the usual I/O modifiers:
SERIN 0, baud, [noparse][[/noparse]WAIT(SOH), SPSTR 16] 'Wait for the start-of-header, then read 16 bytes into scratchpad RAM. chksum = 0 'Compute the checksum. FOR i = 0 TO 15 GET i, bufbyte chksum = chksum + bufbyte NEXT IF (chksum = ETB) THEN 'If checksum is correct, GET 0, [noparse][[/noparse]HEX2 PLCAddr, SKIP 2, HEX4 vAddr] 'read the data in RAM into variables. ENDIF
4. GET: An alternate functional notation for GET would really be nice. It would eliminate having to waste a scratch variable (e.g. bufbyte in the above examples) every time GET is used. Two forms, GETBYTE and GETWORD, would be appropriate:
FOR i = 0 TO 15 chksum = chksum + GETBYTE(i) NEXT
5. Word: In the same spirit of making memory access and I/O more alike, the Word modifier used with GET and PUT would also be useful in I/O operations, alleviating the ubiquitous and cumbersome MyVar.LOWBYTE, MyVar.HIGHBYTE two-step in argument lists:
SEROUT 0, baud, [noparse][[/noparse]Word MyVar]
Of course, whether these are feasible depends on whether PBASIC's tokenized code can support the requisite operations. My suspicion is that it can.
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 5/26/2007 8:12:57 PM GMT
Comments
I don't see though how that could be done within the framework of existing tokens, just with tricks in the IDE. The GET and PUT tokens have no existing provision for modifies, so something like PUT 0, HEX2 x would have to be implemented in the IDE as something like
temp = x/16 << 4 + (x//16)
PUT 0,x
which would trash a RAM variable and also would take a bunch of calculations. The enhancement to PUT 0, Word x is simply tokenized as
PUT 0, x.Byte0
PUT 0, x.Byte1
I've wondered too why SPSTR does not have an function in SEROUT, I2COUT or OWOUT.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Seriously, I hadn't even looked at how the tokens work. I just assumed that each I/O modifier was handled by its own token or set of tokens and that their implementation was general enough to incorporate into any operation. For example, PUT 0, 123 + B0 * 2 is legal. So it's not a stretch to assume that PUT uses an internal stack for values that get stored to the scratchpad. It's also not a stretch to conjecture that there's a token for HEX2 that also returns a value on the stack and which could be used as an argument for PUT in place of a math expression.
But I suppose suggestions grounded in knowledge of the tokens would carry more weight than anything based on wild conjecture. I shall study the matter further...
-Phil
What I was thinking was this, that the instructions that involve lists are tokenized something like this:
P0 %0 P1 %0 P2 %0 OpCode %0 L0 %0 L1 %0 L2 %0 L3 %0 ... Ln %00
The parameters are pushed onto the expression stack, then the Opcode, then the list elements in sequence. Each element is separated by a %0 delimiter, and the command ends when the delimiter is %00. So the machine code that implements the opcode first takes the parameters and subsequently time and again passes control back to the interpreter to chop off the next necessary list element, each of which may involve computations and push pulll on the expression stack. I'm going on the basis of inferences from Brian Forbes' book.
PUT and GET opCodes do not AFAIK have provision for reading a list, which seems to involve special mechanisms. I could be wrong about that. Those commands are not in Brian's book, because it covers only the original BASIC Stamp. If that is the case, the IDE could still implement it, but it would have to be more like the commands that prestack the parameters, and then finish off with the opCode:
P0 %0 P1 %0 OpCode %0 P0 %0 P1 %0 OpCode %0 P0 %0 P1 %0 OpCode %0 , ...
Which is less efficient. Basically what you would get by doing it the way you are probably doing it now, as a sequence of separate PUTs and GETs.
I don't know why SPSTR was not impelemented for output. Maybe there was just not room. My understanding is that there is practically no room left in the SX48 -- full up. But then again, room was made for a couple of additional commands in the BS2px.
You can get SEROUT ... [noparse][[/noparse]Word myVar] with the expedient of [noparse][[/noparse]STR myVAR\2], so the IDE could possibly do that. But that send least significant byte first, and maybe that is not what you want, and it becomes a bug.
For math operations, I've always wished the carry/borrow status from math operations were available in a scratchpad location.
No problem to dream! But I think Jeff probably is swamped enough with projects and requests as it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Post Edited (Tracy Allen) : 5/27/2007 5:25:04 PM GMT