Amulet Communication Protocol
ASCII Protocol
Amulet uses an ASCII communication protocol between the Amulet LCD module and your embedded device (external processor). The external processor must be capable of RS-232 serial communications. Amulet master messages are initiated either by timer events or by user input from the touch panel. Amulet master messages are derived from compiled Amulet widgets stored in the data flash on the Amulet Controller Board. (See Widgets Document for more information.)
For more detail on the Amulet communication protocol, click on the following topics:
Physical interface Serial cable connections (standard RS-232):
| SIGNAL |
DB9 |
DB9 |
DESCRIPTION |
| DOUT |
Pin 2 |
Pin 2 |
Amulet output (your processor's input) |
| DIN |
Pin 3 |
Pin 3 |
Amulet input (your processor's output) |
| GND |
Pin 5 |
Pin 5 |
Signal Ground |
| Jumpered |
Pin 4 |
Pin 6 |
|
| Jumpered |
Pin 7 |
Pin8 |
Communications between the Amulet LCD module and an external processor are asynchronous serial transmissions, with the following format:
Baud Rate:
Parity
Data Bits
Stop Bits
: 1
The default baud rate is 115,200 bps. Other baud rates are set by using a META tag in the Page Properties (page functionality) or Project Properties (global functionality) by using the Amulet META attribute Baud.Project= xxxxx or Baud.Page=xxxxx, where xxxxxx is either 9600, 19200, 57600, or 115200.
Baud.Project should be used if the baud rate is going to be the same on all pages of the project. If using the Baud.Project META attribute, you only need to include that Amulet META on the home page.
Example:
<META NAME="Amulet" Content="Baud.Project=19200">
The default communication time-out period is 200ms. Other time-out periods are set by using a META tag in the Page Properties or Project Properties windows. Valid range is 0.02-2.55 seconds, in .01 increments. For example, to set the time-out rate at 20ms, use:
<META NAME="Amulet" Content="TimeOut.Page=0.02">
The default interbyte delay is dependent upon the activity on the display. Unless there is a large and fast animated .gif, the interbyte delay will usually be around 120us. If a longer interbyte delay is required, a 2-3ms delay can be added by using a META tag in the Page Properties or Project Properties windows. Example:
<META NAME="Amulet" Content="UARTDelay.Project">
By default, the protocol does not provide for a termination character, except when sending strings. The Amulet can be forced to null terminate every single response by using a META tag in the Page Properties or Project Properties windows. With this META attribute, all messages sent from the Amulet will be followed by a 0x00. This can be handy in the receive section of your serial protocol code if you don't have time to analyze each byte received as it is coming in. Example:
<META NAME="Amulet" Content="NullTerminate.Project">
If you are using a BASIC Stamp product, you should use the BASICStamp META tag attribute. You should also use 9600 baud. The BASICStamp attribute essentially sets both the UARTDelay and NullTerminate flags. The interbyte delay will be between 2-3ms and all messages from the Amulet will be null terminated. When using the SERIN command, use the following special string formatter SERIN 16, 84, [STR ByteArray \L {\E}] Where ByteArray is the name of an internal byte array in the BASIC Stamp, L is the size of the byte array, and E is the termination character. In the Amulet case, E would be 0. Make sure you do not put quotes around 0, otherwise the BASIC Stamp will be looking for a termination character of '0' or 0x30. Please see your BASIC Stamp documentation for full details regarding the SERIN command. Example of the BASICStamp META tag attribute:
<META NAME="Amulet" Content="BASICStamp.Project">
When the Amulet receives a "Set" or "Draw" command, by default, it responds back with the corresponding response byte followed by an echo of all the bytes sent to the Amulet. To cut back on unnecessary bytes, the SlaveAckRsp META tag attribute can be used. Instead of sending an echo of the entire message, it will only respond with an ACK (0xF0). If no response is desired, the SlaveNoRsp attribute can be used. Examples:
<META NAME="Amulet" Content="SlaveAckRsp.Project">
<META NAME="Amulet" Content="SlaveNoRsp.Project">
The Amulet system has two different ways of interfacing with an external processor. One method has the Amulet LCD module as the master and the external processor as the slave. The other method has the external processor as the master and the Amulet as the slave. Both methods can be run concurrently on the same HTML page.
To set the Amulet as the master, the HTML page to be compiled needs to have href commands that start with Amulet:UART(port) or Amulet:USB where port can be (comm) or (prog). If no (port) is specified, then it defaults to (comm). The Amulet will send out the href command at an interval based upon the updateRate specified in the HTML page. The Amulet expects a response from the external processor within 200ms, by default.
The Amulet does not need to be configured to be a slave. If the external processor chooses to be the master, it can send a valid Amulet message to the Amulet at any time or on any page and the Amulet will become the slave for that message. If the Amulet has any further master messages, it will once again become the master until the external processor chooses to be the master.
When the Amulet is the slave, the external processor can read and write to "virtual dual-port" RAM which resides on the Amulet side. The Amulet has 256 byte variables, 256 word variables, 199 19-character string variables and a 6 byte deep RPC buffer. Amulet Widgets can have href commands that start with Amulet:InternalRAM to access these "virtual dual-port" RAM variables.
The command characters are the same, regardless of who is the master or who is the slave. This means that a "Get byte variable" command sent to the Amulet looks exactly like a "Get byte variable" command sent to the external processor.
The Amulet communication protocol is half-duplex. The Amulet LCD module(master) can send ten different types of messages to the external processor (slave). You can substitute Amulet:UART(port) with Amulet:USB if you are using USB:
If the message is valid, the slave should either return the requested data (if a "Get" request) or confirm the message (if an "Invoke" or "Set" command). If the message is not valid, the slave should respond with an acknowledge (0xF0) to have the Amulet move to the next request, or the slave can respond with a negative acknowledgement (NAK) (0xF1) to have the Amulet resend the last message.
Table 1 defines thirteen messages that can be sent between the master and the slave, not counting the graphic primitive messages. The valid range of variables and Remote Procedure Calls is 0-0xFF. The valid range for byte variable values returned from the slave (in response to the "Get Byte variable" request) is also 0-0xFF. The valid range for word variable values returned from the slave (in response to the "Get Word variable" request) is 0-0xFFFF. String and label variable values returned from the slave (in response to the "Get String variable" request) can have a maximum of 252 ASCII (0x20-0x7E) characters plus a null termination character (0x00).
Since this is an ASCII protocol, two bytes must be sent out for every byte of data to be transmitted. All messages will start with a command character followed by the ASCII representation of all data. For example, if the page being compiled has a view widget with an href of Amulet:UART.byte(0x1A).value(), which will send out the "Get Byte Variable #0x1A" request, the message to be transmitted would consist of three bytes. The first byte is the command byte for "Get Byte Variable" 0xD0. The second byte is 0x31, which is the ASCII representation of the high nibble"1". The third and final byte is 0x41, which is the ASCII representation of the low nibble "A".
NOTE: The slave must respond to every valid Amulet command, even if it's only an acknowledge (0xF0). When commands are not responded to, a time-out will occur after 200ms, by default, and that message will be repeated until either a response is received or after a total of eleven attempts. After eleven attempts, all UART or USB variables are reset in an attempt to resync with the slave processor.
|
Message
|
Byte 1
|
Byte 2
|
Byte 3
|
Byte 4
|
Byte 5
|
Byte 6
|
Byte 7 .......... Byte N
|
|
|
Amulet Get Byte Variable
|
0xD0
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE0
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Value
Hi Nibble |
Value
Lo Nibble |
None
|
None
|
None
|
|
Amulet Get Word Variable
|
0xD1
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE1 |
Variable Hi Nibble |
Variable Lo Nibble |
|-----MS Byte-----|
Value Hi Value Hi Hi Nibble Lo Nibble |
|-----LS Byte-----|
Value Lo Value Lo Hi Nibble Lo Nibble |
None |
||
|
Amulet Get String Variable
|
0xD2
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE2
|
Variable
Hi Nibble |
Variable
Lo Nibble |
ASCII
char |
ASCII
char |
ASCII
char |
ASCII ............ 0x00
char |
|
|
Amulet Get Label Variable
|
0xD3
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE3
|
Variable
Hi Nibble |
Variable
Lo Nibble |
ASCII
char |
ASCII
char |
ASCII
char |
ASCII ............ 0x00
char |
|
|
Amulet Get Remote Procedure Calls (RPC)
|
0xD4**
|
RPC flag
Hi Nibble |
RPC flag
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE4
|
RPC flag
Hi Nibble |
RPC flag
Lo Nibble |
RPC #1
Hi Nibble |
RPC #1
Lo Nibble |
RPC #2
Hi Nibble |
RPC #2 ............ 0x00
Lo Nibble |
|
|
Amulet Set Byte Variable
|
0xD5
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Value
Hi Nibble |
Value
Lo Nibble |
None
|
None
|
None
|
| Server Response |
0xE5
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Value
Hi Nibble |
Value
Lo Nibble |
None
|
None
|
None
|
| Amulet Set Word Variable |
0xD6 |
Variable Hi Nibble |
Variable Lo Nibble |
|-----MS Byte-----|
Value Hi Value Hi Hi Nibble Lo Nibble |
|-----LS Byte-----|
Value Lo Value Lo Hi Nibble Lo Nibble |
None |
||
| Server Response |
0xE6 |
Variable Hi Nibble |
Variable Lo Nibble |
|-----MS Byte-----|
Value Hi Value Hi Hi Nibble Lo Nibble |
|-----LS Byte-----|
Value Lo Value Lo Hi Nibble Lo Nibble |
None |
||
| Amulet Set String Variable |
0xD7
|
Variable
Hi Nibble |
Variable
Lo Nibble |
ASCII
char |
ASCII
char |
ASCII
char |
ASCII .......... 0x00
char |
|
| Server Response |
0xE7
|
Variable
Hi Nibble |
Variable
Lo Nibble |
ASCII
char |
ASCII
char |
ASCII
char |
ASCII .......... 0x00
char |
|
|
Amulet Invoke Remote Procedure Call (RPC)
|
0xD8
|
RPC
Hi Nibble |
RPC
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xE8
|
RPC
Hi Nibble |
RPC
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
|
Amulet Get Byte
Variable Array |
0xDD
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xED
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Value
Hi Nibble |
Value .............. 0x00
Lo Nibble |
None
|
None
|
|
|
Amulet Get Word
Variable Array |
0xDE
|
Variable
Hi Nibble |
Variable
Lo Nibble |
None
|
None
|
None
|
None
|
None
|
| Server Response |
0xEE |
Variable Hi Nibble |
Variable Lo Nibble |
|-----MS Byte-----|
Value Hi Value Hi Hi Nibble Lo Nibble |
|-----LS Byte-----|
Value Lo Value Lo ....... 0x00 Hi Nibble Lo Nibble |
|||
| Amulet Set Byte Variable Array |
0xDF**
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Value
Hi Nibble |
Value .............. 0x00
Lo Nibble |
None
|
None
|
|
| Server Response |
0xEF
|
Variable
Hi Nibble |
Variable
Lo Nibble |
Array Cnt
Hi Nibble |
Array Cnt
Lo Nibble |
None
|
None
|
None
|
| Amulet Set Word Variable Array |
0xF2** |
Variable Hi Nibble |
Variable Lo Nibble |
|-----MS Byte-----|
Value Hi Value Hi Hi Nibble Lo Nibble |
|-----LS Byte-----|
Value Lo Value Lo ....... 0x00 Hi Nibble Lo Nibble |
|||
| Server Response |
0xF3 |
Variable
Hi Nibble |
Variable
Lo Nibble |
Array Cnt
Hi Nibble |
Array Cnt
Lo Nibble |
None
|
None
|
None
|
Table 1. Thirteen types of messages can be sent between the master and the slave, not counting the graphic primitives.
Synchronization--The master initiates all communications by sending a message to the slave. All valid messages from the Amulet to the external processor start with one of eight command bytes: [0xD0],[0xD1],[0xD2],[0xD3],[0xD5],[0xD6],[0xD7] or [0xD8] -- these are considered the Master Start Of Message (MSOM) characters. NOTE: These eight MSOM bytes ALWAYS signify the start of a message and they are not allowed in the body of any message. The only valid characters in the body of a message are: ASCII 0-9 (0x31-0x39), and A-F (0x41-0x46), except in the body of the "Get string" response, where all ASCII characters from ' ' -' ~' (0x20-0x7E) are valid, as well as the line feed character (0x0A)(See Widgets for more line feed info). If the slave receives any character other than those specified, the message should be considered errant, and the slave should start over hunting for a new MSOM character.
All slave responses must start with the counterpart of the MSOM character that began the message that is being responded to. The valid Slave Start Of Message (SSOM) bytes are: [0xE0],[0xE1],[0xE2],[0xE3],[0xE5],[0xE6],[0xE7] or [0xE8]. The body of the response message starts with a byte for byte echo of the command message. The echo is then followed by any optional response data (in ASCII format).
Upon receiving the last byte of a valid message from the master, the slave then has, by default, 200ms to respond to the message before the master times out. After 200ms, if there is no response, the master will continue to repeat the message until a response is received. After 10 unsuccessful attempts, the Amulet will flush its transmit buffer and reset all UART variables.
Other time out durations are set by using a META tag. Example:
<META NAME="Amulet" Content="timeOut.Project=0.5">
NOTE: The external processor slave must respond to every valid Amulet master command. It is okay to respond with a single byte of acknowledgement (0xF0) without transmitting data, but all Amulet commands should be responded to. When commands are not responded to, a time-out will occur, and that message will be repeated 10 more times before flushing the transmit buffer and resetting all UART variables.
The Amulet communication protocol is half-duplex, meaning the slave should not respond until the master is done sending its message. The external processor (master) can send fourteen different types of messages to the Amulet LCD module (slave). The external processor can read from and write to all the Amulet Internal RAM variables. The external processor can also force the Amulet to jump to a specific page. You can substitute Amulet:UART(port) with Amulet:USB if you are using USB:
If the message is valid, the Amulet LCD module slave will either return the requested data (if a "Get" request) or confirm the message (if a "Draw" or "Set" command). If the message is not a valid Amulet message, the Amulet will not respond.
The protocol is the same regardless of who is the master. So if an external processor is requesting the value of a byte variable on the Amulet (which would be an Internal RAM byte variable), the command opcode would be the same as if the Amulet was requesting the value of a byte variable that resides on the external processor.
If a setup where the Amulet is always the slave is needed or desired, then up to six RPCs can be buffered in the Amulet's Internal RAM. The external processor can request the contents of the RPC buffer by sending a "Get Internal RAM RPC buffer" request (0xD4), followed by the RPC buffer flag byte (which is ASCII-ized like all data within the Amulet protocol). The RPC buffer flag byte options are 0x00:send all RPCs from buffer, then flush. 0xFF:flush RPC buffer.
When the Amulet is the master and an RPC is invoked, the Amulet will immediately send out the RPC command. If the Amulet is setup to use the Internal RAM RPC buffer instead, then the Amulet will send the RPC to an RPC buffer. The RPC buffer can only be read by an external processor by sending a "Get Internal RAM RPC buffer" request (0xD4). The Amulet will respond with all the RPCs (up to six) stored in the RPC buffer, and then a null termination character, to signify the end of the buffer. After sending out the contents of the RPC buffer, the Amulet will flush the buffer.
In a dual-master system, it is possible that both masters will choose to send a message out at the same time. If the Amulet sees an incoming master message coming from the external processor while it is in the process of sending a master message of its own, it will finish sending its master message and then immediately respond to the incoming message, assuming it is a valid message with a valid CRC. After completely responding to the master message, the Amulet will then wait for a response to its own master message. If the host does not respond to the Amulet message, the Amulet will timeout and resend its own master message again.
In a system where the Amulet is the slave, it is possible to send a number of master messages in a row without waiting for a response from the Amulet. This becomes an important point when there are a large number of messages that need to be sent to the Amulet in a short period of time. If the Amulet is set to respond to every master message, like it will by default, or if you have setup the Amulet to respond with an ACK by using the Meta attribute SlaveAckRsp, only the last sent message will be responded to. So, if you send over 30 master messages packed together as a single stream of bytes, only one response message or ACK will be returned from the Amulet.
One of the problems of this technique is that the Amulet has a 256-byte receive buffer which can be filled to capacity if too many bytes are sent to the Amulet. The receive buffer is not circular, so when the Amulet is done parsing an incoming message, as long as there are no more bytes left in the receive buffer, the buffer counter is reset and the next message can be up to 256-bytes in length. Using the example above, if the master sends another 30 master messages before the Amulet is finished parsing the first batch of 30 master messages, the buffer counter will not get a chance to reset, thus filling up the buffer since 60 master messages, which on average are 5-bytes each, will not fit in a 256-byte receive buffer. If the buffer ever gets filled up, any further bytes that are sent will not be saved. Obviously, that is not acceptable in most applications.
To counter this problem, we've created a modified form of the XON/XOFF software handshaking protocol. In order to use the Amulet XON/XOFF protocol, you should probably use the Meta attribute SlaveNoRsp so that the Amulet will not respond to any master messages that do not require a response. Whenever the Amulet receives an XOFF command (0x13) it will respond with an XON command (0x11). So, to safely use the software handshaking, you should send a number of messages which will be less than 256 bytes in length, then terminate the stream of bytes with an XOFF command. Do not send any further commands until the Amulet has responded with the XON command. At that point, you can be assured that all the previous commands have been acted upon and the receive buffer is completely empty, thus allowing for another large string of bytes, up to 256.
This raises the question, why not just use SlaveAckRsp and wait for the ACK. In a perfect world, that would work perfectly fine. Unfortunately, when talking about serial communications, it is folly to believe that everything will be perfect. If there is a slight delay in between messages, it is possible for the Amulet to sneak an ACK out before the entire master stream of bytes is completely done. This could result in the master seeing the ACK, and depending on how/when the code decides to look at the incoming messages, incorrectly assuming that the ACK was in response to the last individual message of the stream. This could result in the master starting to send another large stream of bytes. That might or might not be a problem. If the Amulet was able to finish parsing the final message of the stream, then the receive buffer counters will be reset and the next stream will fit in the receive buffer, assuming the stream is less than 256 bytes. But, there could be a race condition where the Amulet doesn't quite finish parsing the final message of the stream before the master starts sending the new stream. This could result in entire streams being lost. Once again, that is not acceptable in most applications.
Therefore, if you are sending large streams to the Amulet, it is highly suggested that you use the SlaveNoRsp Meta attribute and also send an XOFF command at the conclusion of your stream. Do not send your next stream until the Amulet returns an XON command. This will close any race condition windows.
When the Amulet changes from one page to another, all UART or USB buffers are flushed, so if you are in the middle of sending the Amulet a Master Message while it is changing pages, it is possible that the Amulet will not fully receive your message. Another thing to keep in mind is that when first loading a page, the transmission of messages is halted until the page is fully rendered. The Amulet is capable of buffering incoming messages, but it will not process or respond to any incoming messages until the page is fully rendered. It can take up to 500ms for some complex pages to be fully rendered, so if you were to send a Master Message at the beginning of a page change, the Amulet might not respond back for up to 500ms later. If the Amulet does respond, it will have performed the request, albeit maybe not exactly when you thought it should.
With the above in mind, if your processor pounds Master Messages out at a rapid rate, you might want to have all your pages start out by sending an RPC, set byte or byteOut command that lets your processor know when it is okay to start transmitting again. You could also have an RPC, set byte or byteOut command go out prior to leaving any page, so your processor will know when to halt transmissions as well.
When it is desired to send a single byte out the UART or USB without regard to the Amulet protocol, then the href command to use is Amulet:UART.byteOut(x) or Amulet:USB.byteOut(x), where x is a raw byte to send out. By default, x is a decimal number, but if a hexadecimal number is desired, precede the byte with 0x to specify a hexadecimal number. For instance, to send out a single 0x3D, use the following: Amulet:UART.byteOut(0x3D) or Amulet:USB.byteOut(0x3D).
To send out a single ASCII character, use single quotes around the ASCII character. For instance, to send out an equals sign, use the following: Amulet:UART.byteOut('=') or Amulet:USB.byteOut('=').
Note that both Amulet:UART.byteOut(0x3D) or Amulet:USB.byteOut(0x3D) and Amulet:UART.byteOut('=') or Amulet:USB.byteOut('=') will send out the same 0x3D since the ASCII representation of the equals sign is 0x3D.
When the byteOut command is used, it is not part of the Amulet protocol, which means there are no header bytes and the data is not ASCII-ized for you. The byte you want to be sent out is what will be transmitted, nothing more and nothing less. This is a unidirectional message, meaning that the byte will be sent out, but it will not be expecting, nor accepting, any responses.
To send a stream of raw bytes out the UART or USB can be accomplished by calling multiple Amulet:UART.byteOut() or Amulet:USB.byteOut() functions separated by commas, but that is not the most efficient way. The href command Amulet:UART.streamOut(x1+x2+...xn) or Amulet:USB.streamOut(x1+x2+...xn) will send out the stream of bytes without any formatting. Notice that each byte is separated by a plus sign (+). Like the byteOut command, it is not part of the Amulet protocol, so the message will be sent out, but it will not be expecting, nor accepting, any responses. The bytes to be sent out are by default decimal. If hexadecimal numbers are desired, precede the numbers with 0x. For instance, to send out a stream consisting of 0x01, 0x11, 0x22, 0x33, use the following:
Amulet:UART.streamOut(0x01+0x11+0x22+0x33)
Amulet:USB.streamOut(0x01+0x11+0x22+0x33)
As is the case with the byteOut() function call, the GEM Graphical OS Chip is not expecting, nor accepting, any responses to the streamOut() function call.
To send a stream of raw bytes out the UART can be accomplished by calling multiple Amulet:UART.byteOut() or Amulet:USB.byteOut() functions separated by commas, but that is not the most efficient way. The href command Amulet:UART.stringOut('string') or Amulet:USB.stringOut('string') will send out the string of bytes without any formatting and it will not send out the null termination character. You can also use InternalRAM string variables as strings to be sent out. For instance, to send out the value of InternalRAM.string(0), use the following:
Amulet:UART.stringOut(InternalRAM.string(0))
Amulet:USB.stringOut(InternalRAM.string(0))
If it is desired to send out an ASCII string, that can be accomplished by entering a string that is enclosed by either single or double quotes. (Please see the section on entering strings for more information) For example, to send a string that says "123 ABC", use the following:
Amulet:UART.stringOut('123 ABC')
Amulet:USB.stringOut('123 ABC')
One thing to note is that the ASCII string that is sent out is not null terminated. If a null termination character is required, then you can enter an Amulet:UART.byteOut(0x00) or Amulet:USB.byteOut(0x00) immediately following the streamOut() function call, separated by a comma, such as:
Amulet:UART.stringOut('123 ABC'),Amulet:UART.byteOut(0x00)
Amulet:USB.stringOut('123 ABC'),Amulet:USB.byteOut(0x00)
As is the case with the byteOut() function call, the GEM Graphical OS Chip is not expecting, nor accepting, any responses to the stringOut() function call.
See Graphic Primitives for more information regarding the use of graphic primitives.
Table 2 defines the three types of messages regarding graphic primitives that can be sent between an external processor and the Amulet. If a graphics primitive is sent that does not fit within the bounds of the given LCD (i.e. a delta x of 380 pixels on a 320 x 240 LCD) the Amulet will not draw the graphic primitive.
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
"Draw" Line Primitive |
0xD9 |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Pnt 2 X |
Pnt 2 X |
Pnt 2 X |
Pnt 2 X |
Pnt 2 Y |
Pnt 2 Y |
Pnt 2 Y |
Pnt 2 Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|
||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
Amulet Response |
0xE9 |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Pnt 2 X |
Pnt 2 X |
Pnt 2 X |
Pnt 2 X |
Pnt 2 Y |
Pnt 2 Y |
Pnt 2 Y |
Pnt 2 Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|
||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
"Draw" Rectangle Primitive |
0xDA |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Delta X |
Delta X |
Delta X |
Delta X |
Delta Y |
Delta Y |
Delta Y |
Delta Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|
||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
Amulet Response |
0xEA |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Delta X |
Delta X |
Delta X |
Delta X |
Delta Y |
Delta Y |
Delta Y |
Delta Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|
||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
"Draw"Fill Rectangle Primitive |
0xDB |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Delta X |
Delta X |
Delta X |
Delta X |
Delta Y |
Delta Y |
Delta Y |
Delta Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|
||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
|
Message |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
Byte 5 |
Byte 6 |
Byte 7 |
Byte 8 |
Byte 9 |
|
Amulet Response |
0xEB |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 X |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
Pnt 1 Y |
|
Byte 10 |
Byte 11 |
Byte 12 |
Byte 13 |
Byte 14 |
Byte 15 |
Byte 16 |
Byte 17 |
Byte 18 |
Byte 19 |
|
Delta X |
Delta X |
Delta X |
Delta X |
Delta Y |
Delta Y |
Delta Y |
Delta Y |
Blue |
Blue |
|
Byte 20 |
Byte 21 |
Byte 22 |
Byte 23 |
Byte 24 |
|||||
|
Green |
Green |
Red |
Red |
Line Weight |
|||||
Table 2. Three types of messages to draw graphics primitives can be sent between an external processor (master)
and the Amulet LCD module (slave).
It is possible to send a Master Message to the Amulet which will force it to jump to a specific page within the project. The page number is an internal 16-bit number that the Amulet GEM Compiler generates. All pages and images are assigned an internal number which can be determined by looking at the Amulet link map. When this message is received by the Amulet, it will react as if the Amulet:fileNumber(x) was launched, meaning the Amulet will jump directly to the page specified by the 16-bit internal number. You must NOT jump directly to an image file number, it must be an html file number. If you do errantly jump to a non-valid page, the Amulet OS will respond with a soft reset. This will act exactly as if the reset button was pressed.
The message structure is different than all other Amulet commands. This message is NOT in ASCII. The first two bytes for jumping to a specific page are always 0xA0, 0x02. The next byte is the MSByte of the internal number and the following byte is the LSByte of the internal number. The final byte is the checksum byte, which when added to the first four bytes, should result with the LSByte of the sum being equal to 0x00.
Examples:
To jump to page 0x25:
0xA0,0x02,0x00,0x25,0x39
Notice that 0xA0+0x02+0x00+0x25+0x39 = 0x0100. LSByte of sum is 0x00.
To jump to page 0x103:
0xA0,0x02,0x01,0x03,0x5A
Notice that 0xA0+0x02+0x01+0x03+0x5A = 0x100. LSByte of sum is 0x00.
It is possible to send a Master Message to the Amulet which will force it to perform a soft reset. It will react exactly as if the reset button was pressed.
The message structure is similar to the Jump To Page command. This message is NOT in ASCII. The first four bytes are 0xA0, 0x02, 0xFF, 0xFF. The final byte is the checksum byte, which when added to the first four bytes, should result with the LSByte of the sum being equal to 0x00. Given that, the entire five byte string is 0xA0, 0x02, 0xFF, 0xFF, 0x60.
Example:
To cause a soft reset:
0xA0,0x02,0xFF,0xFF,0x60
Notice that 0xA0+0x02+0xFF+0xFF+0x60 = 0x0300. LSByte of sum is 0x00.
The Amulet protocol uses the UTF-8 standard to deal with string characters above the normal ASCII range of 0x20-0x7F. UTF-8 (8-bit UCS/Unicode Transformation Format) is a variable-length character encoding for Unicode. It is able to represent any character in the Unicode standard, yet is backwards compatible with ASCII. UTF-8 encodes each character (code point) in 1 to 4 octets (8-bit bytes), with the single octet encoding used only for the 128 US-ASCII characters from 0x20-0x7F.
The UTF-8 encoding is variable-width, ranging from 1–4 bytes. Each byte has 0–4 leading consecutive 1 bits followed by a zero bit to indicate its type. N 1 bits indicates the first byte in a N-byte sequence, with the exception that zero 1 bits indicates a one-byte sequence while one 1 bit indicates a continuation byte in a multi-byte sequence (this was done for ASCII compatibility). The scalar value of the Unicode code point is the concatenation of the non-control bits. In this table, zeroes and ones represent control bits, x's represent the lowest 8 bits of the Unicode value, y's represent the next higher 8 bits, and z's represent the bits higher than that.
| Unicode | Byte1 | Byte2 | Byte3 | Byte4 | example |
|---|---|---|---|---|---|
U+0000–U+007F |
0xxxxxxx |
'$' |
|||
U+0080–U+07FF |
110yyyxx |
10xxxxxx |
'¢' |
||
|
|
|
|
|
'€' |
|
|
|
|
|
|
|
'��' |
So the first 128 characters (US-ASCII) need one byte. The next 1,920 characters need two bytes to encode. This includes Latin letters with diacritics and characters from Greek, Cyrillic, Coptic, Armenian, Hebrew, Arabic, Syriac and Tāna alphabets. Three bytes are needed for the rest of the Basic Multilingual Plane (which contains virtually all characters in common use). Four bytes are needed for characters in the other planes of Unicode, which include less common CJK characters and various historic scripts.
| binary | hex | decimal | notes |
|---|---|---|---|
| 00000000-01111111 | 00-7F | 0-127 | US-ASCII (single byte) |
| 10000000-10111111 | 80-BF | 128-191 | Second, third, or fourth byte of a multi-byte sequence |
| 11000000-11000001 | C0-C1 | 192-193 | Overlong encoding: start of a 2-byte sequence, but code point ≤ 127 |
| 11000010-11011111 | C2-DF | 194-223 | Start of 2-byte sequence |
| 11100000-11101111 | E0-EF | 224-239 | Start of 3-byte sequence |
| 11110000-11110100 | F0-F4 | 240-244 | Start of 4-byte sequence |
| 11110101-11110111 | F5-F7 | 245-247 | Restricted by RFC 3629: start of 4-byte sequence for codepoint above 10FFFF |
| 11111000-11111011 | F8-FB | 248-251 | Restricted by RFC 3629: start of 5-byte sequence |
| 11111100-11111101 | FC-FD | 252-253 | Restricted by RFC 3629: start of 6-byte sequence |
| 11111110-11111111 | FE-FF | 254-255 | Invalid: not defined by original UTF-8 specification |
Amulet StringField Widgets can statically set the font style of the dynamic string at compile time. The font styles available are plain, bold, italic, underline and strikethrough. If it is desired to change the font style at runtime, that can be done by using the font style escape character (0x02). The byte following the font style escape character determines the font style of the characters that follow. It is not sent as an ASCII character, but rather a raw byte determined by the font style or styles chosen. Each font style is represented by a single bit within the font style byte. Multiple font styles can be specified at one time, except in the case of plain, which must stand alone.
|
Font Style |
Bit Location |
|
Bold |
0x01 |
|
Italic |
0x02 |
|
Strikethrough |
0x04 |
|
Underline |
0x08 |
|
Plain |
0x80 |
For example, to set InternalRAM string #1 to a string which looks like this:
Bold and italic and plain.
You would send the following message to the Amulet:
[0xD7][0x30][0x31][0x02][0x01][0x42][0x6F][0x6C][0x64][0x20][0x61][0x6E][0x64][0x20][0x02][0x03]
[0x69][0x74][0x61][0x6C][0x69][0x63][0x20][0x61][0x6E][0x64][0x20][0x02][0x80]
[0x70][0x6C][0x61][0x69][0x6E][0x2E][0x00]
Alternatively written with ASCII characters written out as ASCII characters, it would look like this:
[0xD7][0x30][0x31][0x02][0x01]Bold and [0x02][0x03]italic and [0x02][0x80]plain.[0x00]
The flow diagram of Table 3 depicts a sample communications session between the Amulet LCD module and an external processor. This sample is setup as a dual master system, with both the Amulet and the external processor sharing the responsibility of being the master. It is possible to have a system where only the Amulet is the master, only the external processor is the master, or as in this case, a dual master setup.
The variables used in this example have the following values:
External processor's byte variable 01 = 0x38
External processor's string variable 01 = "Abc"
External processor's word variable 03 = 0x10E8
Amulet Internal RAM byte variable 0xF4 = 0xA8
Amulet Internal RAM word variable 0x76 = 0x0000
Amulet Internal RAM RPC buffer = 0x52 only
Following the communication session, the following has occurred:
External processor's byte variable 01 = 0xFE
External processor performs user-defined RPC 02. (There are no reserved RPC #'s, so all 256 RPC's can perform any desired function on your processor.)
Amulet Internal RAM word variable 0x76 = 0x02c9
Amulet Internal RAM RPC buffer = empty
|
Amulet LCD Module
|
Dir.
|
External Processor
|
Description
|
| 0xD0 0x30 0x31 '0' '1' |
>>
|
|
Get byte variable 1
|
|
|
<<
|
0xE0 0x30 0x31 0x33 0x38
'0' '1' '3' '8' |
Return byte of byte var 1
|
| 0xD2 0x30 0x31 '0' '1' |
>>
|
|
Get string variable 1
|
|
|
<<
|
0xE2 0x30 0x31 0x41 0x62 0x63 0x00
'0' '1' 'A' 'b' 'c' |
Return string of string var 1
|
| 0xD5 0x30 0x31 0x46 0x45 '0' '1' 'F' 'E' |
>>
|
|
Set byte variable 1 to 0xFE
|
|
|
<<
|
0xE5 0x30 0x31 0x46 0x45
'0' '1' 'F' 'E' |
Confirm set byte variable 1
|
| 0xD8 0x30 0x32 '0' '2' |
>>
|
|
Invoke RPC2 (User-defined)
|
|
|
<<
|
0xE8 0x30 0x32
'0' '2' |
Confirm invoke RPC2
|
| 0xD1 0x30 0x33 '0' '3' |
>>
|
|
Get word variable 3
|
|
|
<<
|
0xE1 0x30 0x33 0x31 0x30 0x45 0x38
'0' '3' '1' '0' 'E' '8 |
Return word of word var 3
|
| 0xD0 0x30 0x34 '0' '4' |
>>
|
|
Get byte variable 4
(not on server)* |
|
|
<<
|
0xF0
|
Acknowledge (no data)
|
|
|
<<
|
0xD0 0x46 0x34
'F' '4' |
Get Internal RAM byte var 0xF4
|
| 0xE0 0x46 0x34 0x41 0x38 'F' '4' 'A' '8' |
>>
|
|
Return byte of IR byte var 0xF4
|
|
|
<<
|
0xD6 0x37 0x36 0x30 0x32 0x43 0x39
'7' '6' '0' '2' 'C' '9' |
Set IR word var 0x76
|
| 0xE6 0x37 0x36 0x30 0x32 0x43 0x39 '7' '6' '0' '2' 'C' '9' |
>>
|
|
Confrim setting of IR word
var 0x76 |
|
|
<<
|
0xD4 0x30 0x30
'0' '0' |
Get Internal RAM RPCs
|
| 0xE4 0x30 0x30 0x35 0x32 0x00 '0' '0' '5' '2' |
>>
|
|
Return IR RPC buffer
(null terminated) |
|
*NOTE: If master requests an invalid variable or RPC, the slave should respond with an acknowledgment (0xF0).
|
|||
Table 3. Data flow diagram depicting several messages transmitted between the Amulet and a fictitious external processor.
By default, the Amulet protocol uses the Command and Response Opcodes specified in this document. You can customize the Command and Response Opcodes at compile time by including a customization file in your HTML project. The customization file must have an "ini" extension and must reside in the same directory as your GUI project. You must include the customization file in a META tag in the home page of your HTML project. The syntax to include the file is:
<META NAME="initCommands" SRC="filename.ini">
The customization file, filename, must have a .ini extension and it must be located in the same directory as your main html page. Inside the customization file, any line preceded with // is treated as a comment. All customizations must be located in the far left column, so do not tab over. The GEM Compiler recognizes both decimal and hexadecimal numbers.
The default file, called defaultCommands.ini is located in the Amulet\Configurations\Init folder. If the above META tag is not specified, defaultCommands.ini is used as the opcode definition file. If you are going to make a customization file, you should copy the defaultCommands.ini and place it in the same directory as your main html page. The file can be renamed as long as it retains the .ini extension. The values of the opcodes can be changed to practically any single byte value between (1-254)*. All the names of the opcodes can be cross-referenced with the list below. The opcode names are self documenting.
*There are three opcodes that are off limits. They are 0x00, 0xA0 and 0xFF. These must not be used to customize any of the Command or Response Opcodes.
Note: For users who don't want to change the opcodes from an earlier version of Amulet software, we have included origCommands.ini in the Amulet\Configuration\Init folder. Copy origCommands.ini into your projects main directory and use the initCommands META with origCommands.ini as your SRC file.
|
Command Opcode |
Response Opcode |
Description |
Command Can Be Sent by Amulet |
Command Can Be Sent by External Processor |
|
0xD0 |
0xE0 |
Get byte variable |
X |
X |
|
0xD1 |
0xE1 |
Get word variable |
X |
X |
|
0xD2 |
0xE2 |
Get string variable |
X |
X |
|
0xD3 |
0xE3 |
Get label variable |
X |
|
|
0xD4 |
0xE4 |
Get RPC buffer |
X |
|
|
0xD5 |
0xE5 |
Set byte variable |
X |
X |
|
0xD6 |
0xE6 |
Set word variable |
X |
X |
|
0xD7 |
0xE7 |
Set string variable |
X |
X |
|
0xD8 |
0xE8 |
Invoke RPC |
X |
|
|
0xD9 |
0xE9 |
Draw Line |
X |
|
|
0xDA |
0xEA |
Draw Rectangle |
X |
|
|
0xDB |
0xEB |
Draw Filled Rectangle |
X |
|
|
0xDC |
0xEC |
Draw Pixel |
X |
|
|
0xDD |
0xED |
Get byte variable array |
X |
|
|
0xDE |
0xEE |
Get word variable array |
X |
|
|
0xDF |
0xEF |
Set byte variable array |
X |
|
|
0xF0 |
Acknowledgment (ACK) |
X |
X |
|
|
0xF1 |
Negative Acknowledgment (NAK) |
X |
||
|
0xF2 |
0xF3 |
Set word variable array |
X |
Table 4. Listing of all Amulet protocol command opcodes and response opcodes.

Start Here
Development Tools
| Site Use Terms | Terms of Sale | Privacy | Warranty | Site Map | |