please dont rip this site

DECODING THE BASIC STAMP


By: Chuck McManis
Copyright (c) 1994 All Rights reserved.

Ever wonder what the actual "BASIC" program looked like that a Parallax BASIC Stamp runs? I did. My interest stemmed from two problems I was trying to solve, a "smart" robotics controller based on the PIC, and my inability to download programs into the stamp from my 486 based laptop. It was my belief that decoding the system used in the BASIC stamp would give me insight into how I might write a simiar system for a Robot Control language embedded in a PIC. I also believe that by knowing the program content I could decode a dump of the communication between a working PC and the stamp and derive the communications protocol.

For those of you reading this that are not familiar with the BASIC stamp I give you the following brief summary. A BASIC stamp is a preprogrammed Microchip 16C56 PIC controller and a serial EEPROM. The PIC is a loaded with a BASIC token interpreter, and the code to download BASIC tokens from the PC. BASIC programs are compiled into tokens on the PC and then serially downloaded into the EEPROM on the stamp board. The PIC then reads these tokens from the EEPROM and executes the program. The version of BASIC is "control oriented", meaning it doesn't support strings or complex I/O models, however it does have a fairly rich set of operations you can perform on the 8 I/O pins that are available for your use. For a complete description of what the stamp is and does I refer you to the reading at the end of the article.

Decoding the stamp tokens first required that I have a memory image of the contents of the EEPROM. There are three ways to get this information; Using a serial EEPROM programmer to read the contents of the EEPROM after it has been downloaded to, using the BASIC READ statement to read out the EEPROM, and finally using a little known command in the program, BSAVE, to store a copy of the EEPROM on disk. It was this latter command that made it straight forward to accomplish my mission.

GETTING DOWN TO BASICS

The BSAVE command is documented in the READ.ME file for the BSLOADR.EXE command. Essentially, the BSLOADR program will down load a precompiled BASIC program into the stamp. To create this precompiled program you put the statement BSAVE anywhere in your BASIC program, when you download it from the STAMP.EXE program, the STAMP.EXE program will create a companion file named "CODE.OBJ" in the current directory that contains the BASIC program. This works in the 1.3 Version of the stamp software (available from the Parallax BBS) but I've not tried this with the v1.2 software.

After trying this option I discovered that the code.obj file on my disk was exactly 256 bytes long. This corresponds exactly to the number of bytes that are stored in the serial EEPROM, so I guessed this was simply a copy of the EEPROMs memory image. I verified this using a simple basic program :

	FOR B0 = 0 to 255	' read all of memory
		READ B0, B1	' Read from (B0) -> B1
		DEBUG B0,B1,cr	' Display B0=xx B1=xx <cr>
		NAP 7		' time to copy it
	NEXT B0
	END

The contents were the same except for one important difference, the address of the bytes was reversed. Specifically byte 0 in the code.obj file matched byte 255 in the EEPROM, byte 1 in the code.obj file matched byte 254 in the EEPROM, etc. After decoding the data in the file I've come to the conclusion that the READ command in BASIC actually complements the address value before using it. This allows a user program to use "EEPROM locations" 0 - 10 for example which gets translated to addresses 255 - 245 in the EEPROM.

BASIC ANALYSIS

From this point analysis consisted of looking at the data in as many ways as possible and trying to re-construct the original basic program. My first step was to write a program to dump out the 'core' file in several different formats, (I started using the unix od(1) command but quickly exhausted its abilities) I called this program 'dumper' and the first version was simply:

	int	i, j, fd;
	unsigned char buffer[256];

	fd = open("core.obj", 0);
	read(fd, buffer, 256);
	for (i = 0; i < 256; i += 16) {
		printf("%02x: ");
		for (j = 0; j < 16; j++)
			printf("%02x ", buffer[i+j]);
		printf("\n");
	}

I then wrote a very simple BASIC program :

	BSAVE
	B0 = 1

And dumped it out and got:

	00: fa 05 95 98 85 f0 00 00 00 00 00 00 00 00 00 00 
	... and lots of zeros.

From this I noticed that the first two bytes were simply complements of each other and the second byte, 05 happened to correspond to the 'address' of the last byte of data.

Now the easiest way to analyze something like this code is to change one thing and analyze all of the dumps to see what changed, so I wrote three more programs:, B0 = 10, B0 = 100, b0 = 1000 and compared the results which were (including the first one):

B0=1	00: fa 05 95 98 85 f0 00 00 00 00 00 00 00 00 00 00 
B0=10	00: fa 05 f5 b5 10 be 00 00 00 00 00 00 00 00 00 00 
B0=100	00: f9 06 75 cc 91 0b e0 00 00 00 00 00 00 00 00 00 
B0=1000	00: f8 07 75 e0 7d 11 0b e0 00 00 00 00 00 00 00 00 

Which were clearly different, but how were they different? The one reasurring fact was that byte 1 continued to contain the address of the last real byte of data and byte 0 continued to hold the ones complement of that value.

I stared at this for quite a bit with no luck and decided to check to see just what _bits_ were different. Back to the dumper program and now modified to print out the data in binary. This resulted in these values...

02: 10010101 10011000 10000101 11110000 00000000 00000000 
02: 11110101 10110101 00010000 10111110 00000000 00000000 
02: 01110101 11001100 10010001 00001011 11100000 00000000 
02: 01110101 11100000 01111101 00010001 00001011 11100000 

Now we were getting somewhere (I started at byte 2 since 0 and 1 seemed to be the complement of the length, and the length) So there were some obvious similarities, but some differences too, but what really lept out at me was they they were definitely NOT byte aligned. This meant that every bit was significant!

So removing the artificial byte alignments and lining up like bits, I got this:

1: 100 10101 1001                1000100001011111000000000000 00000000 
2: 111 10101 1011010             1000100001011111000000000 00000000 
3: 011 10101 11001100100         100010000101111100000 00000000 
4: 011 10101 1110000001111101000 100010000101111100000 

I did the alignment by starting at like bits at the end and moving forward, putting a space, and then doing the same from the front.

Well the 1001 in line 1 doesn't look all that much like '1' but the 1011010 has at least '1010' as its last four bits and this is 10. So what is 100 in binary? 0110 0100 (64h). And where does that appear in line 3? After the 110 sequence. This suggested the first three bits somehow described the constant and the rest were the constant. Note that splitting 1001 into three bits of prefix and the rest data is "100 1." So on line four the first three bits were 111 and then the binary code for 1000, in 4 nybbles, even though it could have been represented in three. After some head scratching I came to the conclusion that constants were represented as: 1 nn ddddd where '1' indicates it is a constant, 'nn' is the number of nybbles in the constant except 00 means only one bit (boolean) and 11 means 4 nybbles (word), and ddddd is the constant itself. I verified this by running a few more constants through this analysis and they all held up. Modifying the program slightly to be;

B0 = B0, then
	 B0 = B1, then 
	 B0 = B2 etc.

And looking in the same bit positions that the constant showed up in, I was able to determine that a variable was represented as '0 vvvvvv' where 0 means, this is a variable, and vvvvvv is a 6 bit quantity representing the variable in question.

So what about the rest of the bits? Well by changing the program to B1= B0, B2=B0, B3=B0, etc I was able to figure out where the variable on the left half of the equals is in the bitstream, turns out it is the 6 bits following the variable/constant, and it doesn't have a leading '0' bit because it can only be a variable (LET 10 = B0 doesn't parse), determining the bitfields for the operators (+, -, *, //, etc) was simply a matter of cranking through the bits.

With that complete I needed to discover how a complete LET statment was constructed. To do that I put together several variations using variable names and operators that I knew the bit patterns for, except for one problem, the operator values were different. By analyzing this statement:

B0 = 1 + 1

I had separated the bits as follows:

101 10101 1001 100010 00011 1001 00110 11111000
 |    |     |     |     |     |     |    |
 |    |     |     |     |     |     |    +-- trailer (unknown meaning)
 |    |     |     |     |     |     +------- Addition operator
 |    |     |     |     |     +------------- Constant '1'
 |    |     |     |     +------------------- Equals operator
 |    |     |     +------------------------- B0 identifier
 |    |     +------------------------------- Constant '1'
 |    +------------------------------------- "LET" statment
 +------------------------------------------ prefix (unknown meaning)

But compiling and verifying B0 = 1 + 1 + 1 gave this (prefix and suffix removed for clarity):

10101 1001 100010 00011 1001 00111 1001 00110 
  |    |     |     |     |     |     |    |
  |    |     |     |     |     |     |    +-- Addition operator
  |    |     |     |     |     |     +------- Constant '1'
  |    |     |     |     |     +------------- Addition oerator + 1?
  |    |     |     |     +------------------- Constant '1'
  |    |     |     +------------------------- Equals operator
  |    |     +------------------------------- B0 identifier
  |    +------------------------------------- constant 1
  +------------------------------------------ "LET" statement

Then it dawned on me that the operators were really "oooo F" where oooo was the operator identifier (4 bits) and "F" was 1 if there was more operators to follow, and 0 if this was the last operator.

That completed, I could now decode any LET statement from the bits back into the original program text. This was used for the final breakthrough...

DEEPER ANALYSIS

I had to move from decoding LET statments to decoding any statement. Given that any statement could start on any boundary, how could I tell where the statements started? I could put in a LET statement, and its end would be where the next statement started, but where did that statement end?

This was my dilemma until a solution suggested itself from the basic operation of the interpreter. How did *it* know where a statement started? Well parsing along it knew how to get around but what about jumps? The GOTO statement had to encode that address of the statement that the interpreter should jump to, so if I could figure out GOTO statements I could ask it where the next statement was, this will become clear in a moment, but first how to figure out a GOTO? The answer was, take what you know and wrap it around something you don't know, remove what you know and you are left with what is new. I took the program:

BSAVE
	B0 = 1
	goto test
	b0 = 2
test:	END

And dumped it out for analysis, the results were instructive to say the least. What I got was this (separated by bits I understood at the time.):

101 <- this strange prefix
	10101 1001 100010 00010 <= let B0 = 1
	11001 00001001011
	10101 1001 100010 00010 <= let b0 = 1
	11111 11111000 <- now a double dose of 1 bits at the end

Given the LET statements I postulated, what if the "statement" token was 5 bits? That would allow us to have 32 different statements. A quick tally of all the statements in the BASIC manual also came up, 32. Coincidence? I didn't think so. Ok so lets take the first 5 bits and call that the statement token, as you can see I already put a space in between them above. What does that imply? For one thing the last statement in our program was "END" and that would appear to be token 11111 (31 decimal) Hmmm, maybe the compiler always sticks an END statement into our code, that would explain why now we have two and we used to have 1. But for our GOTO, what does that give us? It means that 11001 is the GOTO token and 00001001011 is the address. Eleven bits? There are only 256 bytes in the EEPROM. But then it hit me, statements are not aligned on BYTE boundaries, they are aligned on BIT boundaries, how many bits are there in this EEPROM? 2048? Hmmm, 11 bits of address could address 2048 bits. So now back to our END statement (the target of the Goto) as it turns out it occurs in byte 9 of the dump (shown below with byte separations and bit numbers above the bytes.)

of: 01234567 01234567 01234567 01234567 01234567 01234567
--- -------- -------- -------- -------- -------- -------- 
02: 10110101 10011000 10000101 10010000 10010111 01011001 
08: 10001000 01011111 11111000 00000000 00000000 00000000 
                ^
		|
	Start of the END statement.

The END statement starts in byte 9 at bit 3, now going back to our address:

00001001 011

Split this way it shows an 8 bit BYTE address and a 3 bit BIT address. I've chosen to represent these addresses as xx:n where xx is the hex byte address and n is the decimal bit number (could be hex it never goes above 7 :-)) Further, given this bit centricity of the interpreter the strange 3 bit prefix suggested itself to be a bit representation. And sure enough, the 11 bits that start at byte 1 in the dump define the address (in bit notation) of the first available bit in the EEPROM. The value 2048 - (byte[1] * 8) + prefix)) == total number of bits used in the EEPROM.

I had the key and the tools. To use them I rewrote my analyzer/dumper program to look for GOTO statements in the data first and save the addresses they pointed to, then when a non-goto was detected, print out all of the bits between the target and the next target. Then I could feed the analyzer programs of the form:

BSAVE
	GOTO	label1
	GOTO	label2
	GOTO	label3
	GOTO	label4
label1:	FOR B0 = 1 to 10
label2:	PAUSE B0
label3:	NEXT B0
label4:	END

And it could track the GOTO targets to statements and then print out, as a bitstring, all of the bits in each statement. Running it on the above program yielded:

4 GOTOs found, statement dump is as follows:
1	0a:3 (010 bits) = 01010 1001100010
2	0c:2 (007 bits) = 01111 0100010
3	0d:6 (033 bits) = 10111 100110001011011010100100001100010
4	12:4 (005 bits) = 11111 11111

So now Line 1 is the FOR loop statment, line 2 is the PAUSE statement, line 3 the NEXT statement and line 4 the END statement. I separate the first 5 bits from the rest because I know that is the token for that statement. Knowing how to pick out variables and constants, and keeping in mind that a bit here or there is used as a flag to indicate something (like more parameters in a SOUND statement) I was able to completely decode the entire set of PIC BASIC tokens.

CONCLUSIONS

Well at this point I've put in a lot of work and what do I have to show for it? One benefit is that I can now write a STAMP compiler that can compile STAMP programs into correctly formatted memory images for the EEPROM. This brings me one large step closer to being able to use the BASIC stamp from my UNIX workstation. This also gives me the ability to decode the PIC protocol, because now that I know what part of the data being sent to the PIC is data to be stored in EEPROM, and I know the 11 bit address format, I can filter that out of the bits I see going back and forth which leaves me with just the protocol bits. Figuring those out so that I can write my own downloader has to wait for another couple of spare weekends.

APPENDIX A: Suggested Reading

APPENDIX B: The Complete BASIC Stamp Token List.

Variables 				Operators
   Token	     Value		  Token 	 Value
-------------	---------------		 -------	-------
PIN0 - PIN7	000000 - 000111		    =		  0001
DIR0 - DIR7	001000 - 001111		    -		  0010
BIT0 - BIT15	010000 - 011111		    +		  0011
PINS		100000			    *		  0100
DIRS		100001			    **		  0101
B0-B13		100010 - 101111		    //		  0110
PORT		110000			    /		  0111
?		110001			    &/		  1000
W0 		110010			    &		  1001
?		110011			    |/		  1010
W1		110100			    |		  1011
?		110101			    ^/		  1100
W2		110110			    ^		  1101
?		110111			    MIN		  1110
W3		111000			    MAX		  1111
?		111001
W4		111010
?		111011
W5		111100
?		111101
W6		111110

In the notation for statements variables are shown as VVVVVV

Constants coded with a two bit 'size' and some number of databits they are as follows (M = MSB, L = LSB):

00	M			Single bit (boolean)
	01	MxxL			One Nybble (short byte)
	10	MxxxxxxL		Two Nybbles (byte)
	11	MxxxxxxxxxxxxxxL	Four Nybbles (word)

In the notation below a constant is identified as:

CCCCCC

When either a constant or a variable can be used, the notation CCCVVV is used, this is represented in the bitstream as:

1 CCCCCC	1 followed by constant value
		0 VVVVVV	0 followed by variable identifier

Addresses consist of 11 binary digits, the upper 8 are the byte address and the lower 3 are the bit offset in that byte. Bit 0 is the MSB of the byte. In the statement notation and address is represented as:

AAAAAAAAAAA	11 bit address of the form Byte:bit

Individual flag bits are represented in the statement notation as:

F		 Flag bit

Numbers that must be one or zero are represented as 1 or 0.

Braces, { and } enclose bit patterns that may or may not be present based on the state of a flag bit in the statement.

LET statement encoding

10101 CCCVVV VVVVVV 0001 F  { CCCVVV OOOO F }
  |     |      |      |  |      |     |   |
  |     |      |      |  |      |     |   +-- More Operators Flag
  |     |      |      |  |      |     +------ Operator
  |     |      |      |  |      +------------ Constant/Variable
  |     |      |      |  |
  |     |      |      |  +------------------- More operators Flag
  |     |      |      +----------------------- "=" operator value
  |     |      +------------------------------ Destination variable
  |     +------------------------------------- Source Variable
  +------------------------------------------- LET token

GOTO token encoding:

11001 AAAAAAAAAAA
  |      |      
  |      +------ Address to jump to.
  +------------- GOTO token.

NEXT token encoding:

Note: All of the "smarts" in a FOR/NEXT loop are done by the NEXT token. The address it points to is the address of the statement just AFTER the FOR statement.

Note: The step constant is always a positive number, however if the Positive step flag is false, this number is subtracted from the counter variable.

10111 CCCVVV VVVVVV F CCCVVV CCCVVV AAAAAAAAAAA
  |      |     |    |   |       |       |  
  |      |     |    |   |       |       +-------- Statement Address
  |      |     |    |   |       +---------------- starting const/variable
  |      |     |    |   +------------------------ ending const/variable
  |      |     |    +---------------------------- Positive Step value flag
  |      |     +--------------------------------- Counter variable
  |      +--------------------------------------- Step increment (decrement)
  +---------------------------------------------- NEXT token

FOR token encoding:

01010 CCCVVV VVVVVV
  |      |     |
  |      |     +- counter variable for the LOOP
  |      +------- Constant/Variable initial value (assigned to variable)
  +-------------- FOR token

BRANCH token encoding:

11010 CCCVVV AAAAAAAAAAA F { AAAAAAAAAAA F }
   |     |         |      |        |      |
   |     |         |      |        |      +-- Another Address Flag
   |     |         |      |        +--------- Branch address
   |     |         |      +------------------ Another Address Flag
   |     |         +------------------------- Branch address (always present)
   |     +----------------------------------- Constant/Variable Index
   +----------------------------------------- BRANCH token

BUTTON token encoding:

10001 CCCVVV CCCVVV CCCVVV CCCVVV VVVVVV CCCVVV AAAAAAAAAAA
   |      |      |      |      |      |      |       |
   |      |      |      |      |      |      |       +-- GOTO Address
   |      |      |      |      |      |      +---------- C/V Target State
   |      |      |      |      |      +----------------- Var Workspace
   |      |      |      |      +------------------------ C/V Repeat Rate
   |      |      |      +------------------------------- C/V Delay Value
   |      |      +-------------------------------------- C/V Down state
   |      +--------------------------------------------- C/V Pin to use
   +---------------------------------------------------- BUTTON token

EEPROM encoding:

Note: There is no bytecode encoding for EEPROM since this is taken care of by the STAMP.EXE program.

END token encoding:

11111
   |
   +---- END token

HIGH token encoding:

00000 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- HIGH token

LOW token encoding:

00001 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- LOW token

INPUT token encoding:

00010 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- INPUT token

OUTPUT token encoding:

00011 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- OUTPUT token

TOGGLE token encoding:

00100 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- TOGGLE token

REVERSE token encoding:

00101 CCCVVV
  |     |
  |     +--- Constant/variable containing pin number
  +--------- REVERSE token

IF token encoding:

Table of logical operator values.

Token	Value
	-----	-----
	 ???	 000
	  <	 001
	  >	 010
	 <>	 011
	  =	 100
	 <=	 101
	 >=	 110
	 ???	 111
11000 CCCVVV VVVVVV F F OOO {CCCVVV VVVVVV F F OOO} AAAAAAAAAAA
  |     |       |   | |  |     |       |   | |  |      | 
  |     |       |   | |  |     |       |   | |  |      +- Address of GOTO
  |     |       |   | |  |     |       |   | |  +-------- Logical Operator
  |     |       |   | |  |     |       |   | +----------- OR/AND (1/0)
  |     |       |   | |  |     |       |   +------------- Another Clause Flag
  |     |       |   | |  |     |       +----------------- Comparison Variable
  |     |       |   | |  |     +------------------------- C/V compared value.
  |     |       |   | |  +------------------------------- Logical Operator
  |     |       |   | +---------------------------------- OR/AND (1/0)
  |     |       |   +------------------------------------ Another Clause Flag
  |     |       +---------------------------------------- Comparison Variable
  |     +------------------------------------------------ Value to compare to
  +------------------------------------------------------ IF token

GOSUB token encoding:

01110 0000 AAAAAAAAAAA
  |    |       |
  |    |       +-- Address of the GOSUB
  |    +---------- GOSUB "#" max of 16 (0 - 15)
  +--------------- GOSUB token

RETURN token encoding:

11011 
  |
  +------- RETURN token

DEBUG token encoding:

Note that all of the string stuff is done in the STAMP.EXE program. When a debug statement is hit, it sends its address to the downloader and the stamp program uses that to figure out what to print.

11110 AAAAAAAAAAA
  |      |
  |      +-- Address of this debug token (identifies it)
  +--------- DEBUG token

LOOKUP token encoding:

10110  CCCVVV VVVVVV CCCVVV F {CCCVVV F}
  |      |      |      |    |    |    |
  |      |      |      |    |    |    +--- Another Constant Flag
  |      |      |      |    |    +-------- constant/variable in list
  |      |      |      |    +------------- Another Constant Flag
  |      |      |      +------------------ constant/variable in list
  |      |      +------------------------- destination variable
  |      +-------------------------------- const/variable index into list
  +--------------------------------------- LOOKUP token

LOOKDOWN token encoding:

01101  CCCVVV VVVVVV CCCVVV F {CCCVVV F}
  |      |      |      |    |    |    |
  |      |      |      |    |    |    +--- Another Constant Flag
  |      |      |      |    |    +-------- constant/variable in list
  |      |      |      |    +------------- Another Constant Flag
  |      |      |      +------------------ constant/variable in list
  |      |      +------------------------- destination variable
  |      +-------------------------------- const/variable index into list
  +--------------------------------------- LOOKDOWN token

POT token encoding:

00111 CCCVVV CCCVVV VVVVVV
  |      |      |      |
  |      |      |      +-- variable to receive input
  |      |      +--------- desired state
  |      +---------------- pin # to monitor
  +----------------------- POT token

PULSOUT token encoding:

01000 CCCVVV CCCVVV
  |     |      |
  |     |      +--------- variable/constant length of pulse
  |     +---------------- variable/constant identifying pin to pulse
  +---------------------- PULSOUT token

PULSIN token encoding:

01001 CCCVVV CCCVVV VVVVVV
  |     |      |      |
  |     |      |      +-- Variable to get pulse width
  |     |      +--------- variable/constant identifying edge (1/0)
  |     +---------------- variable/constant identifying pin to monitor
  +---------------------- PULSIN token

NAP token encoding:

11100 AAAAAAAAAAA CCCVVV
  |        |        |
  |        |        +--- constant/variable nap 'units' (0-7 legal)
  |        +------------ address of next statement to execute
  +--------------------- NAP token

PWM token encoding:

00110 CCCVVV CCCVVV CCCVVV
  |     |      |      |
  |     |      |      +-- variable/constant holding number of cycles
  |     |      +--------- variable/constant analog level (0 - 255)
  |     +---------------- variable/constant identifying pin (0 - 7)
  +---------------------- PWM token

RANDOM token encoding:

10000 VVVVVV
  |     |
  |     +---- Word variable to store random number in
  +---------- RANDOM token

READ token encoding:

Note: I believe this command complements the value in the constant/variable so that low addresses in the EEPROM appear as high addresses.

01011 AAAAAAAAAAA CCCVVV VVVVVV
  |        |         |     |
  |        |         |     +-- Variable to read into (byte variable)
  |        |         +-------- variable/constant EEPROM Address to read from 
  |        +------------------ Address of next statement 
  +--------------------------- READ token

WRITE token encoding:

Note: I believe this command complements the value in the constant/variable so that low addresses in the EEPROM appear as high addresses.

01100 AAAAAAAAAAA CCCVVV VVVVVV
  |        |         |     |
  |        |         |     +-- Variable to read from (byte variable)
  |        |         +-------- variable/constant EEPROM Address to write to 
  |        +------------------ Address of next statement 
  +--------------------------- WRITE token

SLEEP token encoding:

Note: Several statements encode the next statement to execute in their bits. I believe these are ones that use the Watchdog timer to wake them up. When woken up, the timer looks at the address that the interpreter has stored somewhere (probably in a register) and continues execution from there.

11101 AAAAAAAAAAA CCCVVV
  |        |        |
  |        |        +--- constant/variable time in seconds
  |        +------------ address of next statement to execute
  +--------------------- SLEEP token

SOUND token encoding:

10010 CCCVVV CCCVVV CCCVVV F {CCCVVV CCCVVV F}
  |     |      |      |    |    |       |   |
  |     |      |      |    |    |       |   +-- Another Note Flag
  |     |      |      |    |    |       +------ Note duration
  |     |      |      |    |    +-------------- Note number
  |     |      |      |    +------------------- Another Note Flag
  |     |      |      +------------------------ Variable/constant note duration
  |     |      +------------------------------- Variable/constant note number
  |     +-------------------------------------- Variable/constant pin number
  +-------------------------------------------- SOUND token

SEROUT token encoding:

10011 CCCVVV CCCVVV {CCCVVV <F> <C>}
  |     |      |      |     |   |
  |     |      |      |     |   +-- Continuation flag (another const/var)
  |     |      |      |     +------ Format flag (1 = convert to number)
  |     |      |      +------------ Constant/variable to send.
  |     |      +------------------- Constant/variable Serial mode to use.
  |     +-------------------------- Constant/variable Pin number to use
  +-------------------------------- SEROUT token

SERIN token encoding:

This one is really weird, I've done it in three parts to make it more clear.

version 1 = Variables but No Qualifiers

10100 CCCVVV CCCVVV 0 {F vvvvvv V}
  |     |      |    |  |   |    |
  |     |      |    |  |   |    +---- More Variables flag (1 = More)
  |     |      |    |  |   +--------- Variable
  |     |      |    |  +------------- Format flag, 1 = Number (#) input
  |     |      |    +---------------- Qualifiers flag, 0 = No Qualifiers
  |     |      +--------------------- Constant/Variable Baud rate information
  |     +---------------------------- Constant/Variable Pin to use
  +---------------------------------- SERIN token

version 2 = Qualifiers but No Variables

10100 CCCVVV CCCVVV 1 CCCVVV AAAAAAAAAAA Q {CCCVVV Q} 0
  |     |      |    |   |         |      |    |    |  |
  |     |      |    |   |         |      |    |    |  +- Variables Present Flag
  |     |      |    |   |         |      |    |    +- More Qualifiers flag
  |     |      |    |   |         |      |    +------ Const/Variable Qualifier
  |     |      |    |   |         |      +--- More Qualifiers Flag 
  |     |      |    |   |         +-------- Address of the following Flag ?!?!
  |     |      |    |   +------------------ Const/Variable First Qualifier
  |     |      |    +---------------------- Qualifiers flag, 1 = Qualifiers
  |     |      +--------------------------- Const/Variable Baud Rate
  |     +---------------------------------- Constant/Variable Pin to use
  +---------------------------------------- SERIN token

version 3 = Qualifiers and Variables

10100 CCCVVV CCCVVV 1 CCCVVV AAAAAAAAAAA Q {CCCVVV Q} 1 {F vvvvvv V}
  |     |      |    |   |         |      |    |    |  |  |   |    |
  |     |      |    |   |         |      |    |    |  |  |   |    +- More Vars
  |     |      |    |   |         |      |    |    |  |  |   +------ Variable
  |     |      |    |   |         |      |    |    |  |  +---------- Var Format
  |     |      |    |   |         |      |    |    |  +- Variables Present Flag
  |     |      |    |   |         |      |    |    +- More Qualifiers flag
  |     |      |    |   |         |      |    +------ Const/Variable Qualifier
  |     |      |    |   |         |      +--- More Qualifiers Flag 
  |     |      |    |   |         +-------- Address of the following Flag ?!?!
  |     |      |    |   +------------------ Const/Variable First Qualifier
  |     |      |    +---------------------- Qualifiers flag, 1 = Qualifiers
  |     |      +--------------------------- Const/Variable Baud Rate
  |     +---------------------------------- Constant/Variable Pin to use
  +---------------------------------------- SERIN token

Appendix C: Complete token/keyword list (in token order)

Token	Keyword
=====	=========
00000	HIGH
00001	LOW
00010	INPUT
00011	OUTPUT
00100	TOGGLE
00101	REVERSE
00110	PWM
00111	POT
01000	PULSOUT
01001	PULSIN
01010	FOR
01011	READ
01100	WRITE
01101	LOOKDOWN
01110	GOSUB
01111	PAUSE
10000	RANDOM
10001	BUTTON
10010	SOUND
10011	SEROUT
10100	SERIN
10101	LET
10110   LOOKUP
10111	NEXT
11000	IF/THEN
11001	GOTO
11010	BRANCH
11011	RETURN
11100	NAP
11101	SLEEP
11110	DEBUG
11111	END

See also:


file: /Techref/microchip/language/basic/stamp-decode.htm, 34KB, , updated: 2012/7/12 07:35, local time: 2014/9/2 21:30,
TOP NEW HELP FIND: 
54.91.69.181:LOG IN

 ©2014 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF="http://www.piclist.org/techref/microchip/language/basic/stamp-decode.htm"> Decoding the BASIC Stamp</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2014 contributors:
o List host: MIT, Site host massmind.org, Top posters @20140902 RussellMc, Richard R. Pope, IVP, John Gardner, alan.b.pearce, David C Brown, James Cameron, Josh Koffman, Bob Blick, Isaac Marino Bavaresco,
* Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.
 

Welcome to www.piclist.org!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .