This is an attempt to define a byte code language for an embedded interpreter with a special bias to IO processing. For example, a small PCB with a microcontroller could be connected to any sort of terminal and the byte codes loaded from there to cause the processor to make or measure electronic signals in other equipment. Byte codes could also be recorded in its EEPROM for playback with or without a terminal connected.
The ASCII vs Byte code can be confusing. I don't see any reason why the byte codes can't be ASCII... just pick ASCII characters that relate to the function of the byte code. E.g. A byte code that starts a conditional jump would be assigned "?". Bit oriented IO would be "P" as in P0AH for Pin 10 High.
If the ASCII byte codes selected relate to the function the perform, a human could use them to carry on a "conversation" with the processor just as easily as another computer. The advantages for debugging are enourmous. Being able to query the unit about what it is seeing on its ports and directly make adjustments to the signals it is sending replaces a bevy of external test equipment. Also, test equipment sees things from the outside and does not necessarily see what the processor itself sees.
Operation Source Dest Code Command Description ------- ------- --------------------------------------------------------- : ;C Switches between setting a dest and setting a source. Actually toggles the source/destination bit. ;When going from dest to source, also sets the operation to "copy" so that the first source found ; completes the set (dest operation and source) and causes the first source to be loaded to the dest ;When a set is complete and the operation has been executed, the operation and source are cleared. ;Sort of like := in pascal. e.g. R10:R09+R08 ;Not really necessary since the first item on the line is expected ; to be the dest and the remaining are sources, but this helps with ; confusion with e.g. R10=R09 (comparison) and ; makes the order correct. Eg:R10R09-R08 actually subtracts ; R09 from R10 and then doesn't know what to do with R08. ;It can be used to do multiple destinations on one line. When switching from source back to ;destination, it also finishs moving the source to the destination and clears the operation. # ;C Start of a single byte literal value in hex. e.g. R10:#21 For strings see " and ' "text" ;S Source "text" Sets source to this litteral string and sends each character to the dest until the closing ". 'hh' ;S Source Binary data. Convert each pair of hex digits into binary and send to the dest until closing '. + ;O add Source to Dest - ;O subtract Source from Dest * ;O multiply Dest times Source (Add Dest to Dest, Source times) / ;O divide Dest by Source ++ ;C increment Dest -- ;C decrement Dest. Set true/false to true if Dest is now zero | ;O Or Source to Dest & ;O And Source to Dest ^ ;O XOR Source to Dest ( ;C Save the value of the current dest and the operator to the stack and clear the dest value and operator ) ;C Restore the operator from the stack, exchange the dest and TOS values ; and apply the operation to the value from the stack placing the result in the destination. ;e.g. R08:R11+(R07*R01) ;"R08:R11"R08 is assigned the value of R11, "+"operator set to add, "("push R08, push +, set R08 to zero, operator set to null ;"R07"R08 is assigned the value of R07, "*"operator set to multiply, "R01"R08 is added to itself R01 times ;")"pop operator (now add), exchange the top of stack and R08, add top of stack to R08. @nnnnnn ;C At address. Set the Source/Dest buffer pointer (if possible) to a three byte address. @+ ;C At next. Move the Source/Dest buffer pointer forward @- ;C At previous. Move the Source/Dest buffer pointer backward (if possible) > ;O Greater. set true if Dest greater than Source. Dest is unaffected < ;O Less. set true if Dest less than Source. Dest in unaffected = ;O Equal. Set true if Source equal to Dest. NOT an assignement operator. See ":" Dest is unaffected. ~ ;O Not. Toggle true/false flag. Use with greater less and equal. ; >~ is less than or equal too. <~ is greater than or equal too. =~ is not equal ; e.g. R01<R02~ will set the true flag if R01 is greater than or equal to R02. :l ;C Define (l)able where l is [a-z]. Writes the current EEPROM address pointer into a ; table at the beginning of the EEPROM at the index l-'a' and sets dest to EEPROM l ;C Goto (l)able where l is [a-z]. Set the PC to the value of the label previously stored ; in the table at the start of the EEPROM. ;Note that these two different actions of label are chosen based on the source/dest bit. ;if label is the dest, the dest is called. If label is the source, lable is set. . ;C Return. Set the PC to the value previously stored on the Stack + 1. ^[ ;C Escape. Sets PC to zero stopping the operation of a stored program activated by a lable. ? ;C If the true/false flag is false, skip the rest of this line, otherwise continue. ;Eg: ?l Conditional branch to lable. if the Bit flag is true, set the PC to the value ; of the entry in the table previously stored at the start of the EEPROM at index l. ?(+|-)n ;C if the true/false flag is true, (+)increment or (-)decrement the PC by (n) lines [ ;C Repeat: Save the PC to the stack ] ;C Loop: If the true/false flag is true, reload the PC from the TOS else drop the TOS. A ;DS Show the value of the current Analog channel Ac ;DS set source then dest to (A)nalog A/D (c)hannel, where c=0-max_chan. And read a value to R0 AT ;C answer "OK" Used to autoset baud rate. B ;S show Bit Accumulator / Flag B(H|T) ;C set Bit Accumulator B(L|F|Z);C clear Bit Accumulator C ;DS show (C)ount and set dest then source to count register Cdd ;C set (C)ount. ie: C implys # ; eg. CZ set (C)ount to (Z)ero D ;S show (D)uty cycle / Timebase Ddd ;C set (D)uty cycle / sampleing Timebase to (dd)atabyte/256 See: PppDddG below Ddddd ;C set Timebase (S)ampling to the 16-bit multiple of 1 usec given by the 4 (dddd)igits; range 0001-FFFF hex (65535 dec). ; Eg D03E8 sets 03E8 hex (1000 dec) usec between samples E ;DS Set Dest then Source to the EEPROM. Show current address. ; Eg E:R00 saves value of register 0 into the current location in the EEPROM ; Eg :a"P01D80G." defines a subroutine "a" that sets up a 50% duty cycle on pin 1 and starts it running. ; Nothing happens until a is called. ; Eg E@000080:#2E puts a period at address 128. Address is now 129 F ;S Show the current frequency count FC ;C perform Frequency (C)ount on (p)in FD ;C (F)requency mode, measure (D)uration of pulse on (p)in, from 10 usec to 256 sec. FE ;C (F)requency mode, measure (E)lapsed time between 2 pulses on (p)in, from 10 usec to 256 sec. ; Eg FZ zero the (F)requency count. G ;C toggle (G)enerator On/off. See: PppDddG H ;C set last pin referenced (H)igh. If the pin is an analog input and can be reconfigured as digital, do so. I ;C set last pin referenced (I)n (without Pull up). Read value to bit accumulator and set true flag if 1 ;if the pin is an analog input, configure it for analog operation. J(+|-)l ;C unconditional jump to (l)ine or forward or back (l)ines if + or - used. K ;S set source to terminal (K)eyboard L ;C set last pin referenced (L)ow M ;C (M)ove data from source to destination for count while increaseing the source and destination addresses. O ;C set Dest to Terminal (O)utput P ;DS Show the current value of the source pin Pp(p) ;DS set Dest then Source to (P)ort or (P)ort (p)in. Q ;S (Q)uestion. read a byte from the Host. R ;C (R)ead a byte from the dest into the accumulator and increase the dest pointer ;allows the first item to be read. e.g. R08R rather then :R08 R ;DS Show the current register number and value. Rrr ;DS set Dest then Source to (R)egister(rr)egister S(C|I)d ;C (S)ample (Logic Analyzer) Binary (C)ount output mode ;- configure #bits specified by (d)igit as output, and output an incrementing binary count on the ;Logic Analyzer port during sampling, where (d)=0-8. (I)nvert means outputs are inverted. ;Eg, LC6 means configure port bits 0-5 as output, then count binary 0-63 and repeat during logic analyzer sampling. T(H|L) ;C (T)rigger on (H)igh/(L)ow "transition" T(A|B)dd;C (T)rigger when analog input goes (A)bove/(B)elow threshold where threshold=(dd)atabyte. TF ;C set (T)rigger to (F)reerun mode, ie, disable trigger. U ;C set pull (U)p on last pin referenced. Make it an input if not already. V ;O (V)iew source pin or A/D channel continuously. VA ;C (V)iew all (A)nalog A/D channels. VE ;C (V)iew EEPROM memory dump VP ;C (V)iew all (P)ort configurations/data, binary format ; - eg, 1:AiAAAA 2:OOUooOOi ; where A=analog, I=input, O=output, U=pull Up, uppercase=high and lowercase=low. VR ;C (V)iew all (R)egisters including CPU. Display RAM. Vvv ;C set programming (V)oltage to (v)olts W ;C write data to destination and increase the destination pointer, if there is one. Wdd ;C (W)ait dd mSecs Wdddd ;C (W)ait dddd uSecs X ;C Toggle last pin referenced Z ;C (Z)ero the current destination. ZZ ;C return chip to (Z)ero state, i.e. power-up configuration all inputs and send Version number to host.
Possible changes: (R)ead and (W)rite should be dis-ambiguated from (R)egister and (W)ait so that all capital letters can be executed immediatly and following values / modifiers can simply be acting on the destination. A more "stateless" operation is then possible. E.g. R08 Typeing the R immediatly causes the current register address and value to be displayed and the destination set to the register address pointer. An ' is implied. Then the 08 acts as a value to change the register pointer address to the eighth register and the destination is the eighth register. The disadvantage is that it requires several more possible destinations.
An example program segment in byte codes: ER ;input the next byte from the EEPROM into the accumulator R08W ;and save it in register 8 ;The R command just sets the FSR register to the hex value ;after the R (maybe plus some offset). Then the W just writes the accumulator to ;the IND register and increments FSR. R08E ;Set the destination to Register 8 then set the source to EEPROM. ;the default action is just to move. R08:E or R08:E! could be used for clarity l: ;define a label R0F#FF! ; set a count to 255 QR ;input a byte of hex data from the host PC0 ;set the destination to port 12 (the pin zero is not used here) ! ;write the last byte of data loaded out to port C ;strobe out a byte P0AL ;Pin 10 Low W64 ;Wait 100mS H ;Pin 10 High ;hold until pin 16 goes high P10I ;check pin 16 (make it an input and read ;the value to the bit accumulator also setting ;the true/false flag) ?-1 ;loop back 1 line ; Decrement the count and loop back to l if not zero R0F--?l ;Soem examples of how the codes can be combined. Ppp(L|H|I|U) ;Set (P)in (pp) to (L)ow, (H)igh, (I)n, or turn on pull (U)ps RrrR ;(R)egister, (R)ead (rr)egister - eg R40R reads register address 40h. Sets Zero flag etc... RrrW'dd';(R)egister, (W)rite (rr)egister with data (dd)igits - example syntax, R 21 W '0F, or R21W'0F ;Some examples related to other uses besides just programming. ;These may (will) also be very usefull in debugging the programmer RrrS ;set (L)ogic Analyzer to sample Port (r) - capture 128 samples up to 1 Mhz rate, then send to host. AcV ;(View) Oscilloscope display of analog data on A/D Channel (c) - 128 samples captured to buffer, at up to 50 Khz rate, and sent to host. PppFC ;perform Frequency (C)ount on (p)in ;FH ;perform (F)requency count on (H)igh-speed channel PppFD ;(F)requency mode, measure (D)uration of pulse on (p)in, from 10 usec to 256 sec. PppFE ;(F)requency mode, measure (E)lapsed time between 2 pulses on (p)in, from 10 usec to 256 sec. PppDddG ;(G)enerate Square-wave at (p)in with (d)uty cycle PppT(H|L);(T)rigger on (H)igh/(L)ow "transition" at (p)in. PppV ;(P)in (V)iew (p)in continuously.
Variables:
;Source and Destination. This is a single byte and clearning it sets Source and Destination to Unknown ; and sets the flag to load the destination next. SrcTyp ;3 bits to specify source (Unknown, Register, EEPROM, Terminal, Analog, Count, Port, Port/Pin) DstTyp ;3 bits to specify destination (Unknown, Register, EEPROM, Terminal, Analog, Duty, Port, Port/Pin) SnDBit ;bit that selects between source(set) and destination(clr) for the next byte code EEPtr ;pointer to the current address in the EEPROM RegPtr ;pointer to the current register PpPtr ;pointer to the current Port/Pin AioPtr ;pointer to the current Analog IO channel DstPtr ;pointer to the address of the destination. This may be an EEPROM, register, port, etc... PC ;Program Counter. Indexes EEPROM. When 0, accept or wait for tokens from the Terminal. SP ;Stack Pointer. Indexes a bank of ram (with overflow to EEPROM?) Acc ;Aka R00 TnFBit ;True / False Flag Cnt ;Count Dly ;Duty Cycle / Sample Timebase / Delay TrgPin TrgMax TrgMin TrgRun PgmVlt ;Programming Voltage
Also: