Amulet can use either an ASCII-based or a CRC-based communication protocol between the Amulet LCD module and your embedded device (external processor). New GEMstudio projects default to using the CRC protocol, which is very similar in structure to Modbus RTU. 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 GEMstudio code stored in the data flash on the Amulet module. (See Widgets Document for more information.)
For more detail on the Amulet CRC communication protocol, click on the following topics:
Physical interface Serial cable connections (standard RS-232):
Communications between the Amulet LCD module and an external processor are asynchronous serial transmissions, with the following format:
The default baud rate is 115,200 bps. Other baud rates are set in the Project Options > Communication tab.
The default communication time-out period is 200ms. Other time-out periods are set in the Project Options > Communication tab.
The default slave ID for the Amulet is 1 and for the Host it is 2. This is the first byte the master uses to address the slave, as per Modbus RTU specifications. If used on a peer to peer network, the slave ID numbers are not that important, as long as they are unique. If used in a multi-drop network where slave IDs are already defined, it might be necessary to give the Amulet and the Host new IDs to suit the existing network.
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 GEMstudio page.
To set the Amulet as the master, the GEMstudio page needs to have href commands that start with Amulet:UART. The Amulet will send out the href command at an interval based upon the updateRate specified within that particular object. 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, 256 26-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 opcodes 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 one difference is the slave ID, which is the first byte of every message. If the host is sending a master message to the Amulet processor, the message will start with the Amulet ID. If the Amulet is sending a master message to the host processor, the message will start with the Host ID.
Responses start with the same ID as the original message, so if the Amulet sends a master message to the host, the message from the Amulet processor will start with the Host ID and the response from the host will also start with the Host ID. Conversely, if the external processor sends a master message to the Amulet processor, the message will start with the Amulet ID and the response from the Amulet processor will also start with the Amulet ID.
The Amulet CRC communication protocol piggybacks on the Modbus RTU standard. That means if you already support Modbus RTU communication, you are almost done, you just need to add support for the Amulet specific function opcodes. For those not familiar with Modbus RTU, there is one oddity when it comes to numbers greater than 8-bit. When dealing with data within the payload, data is transmitted big-endian, meaning Most Significant Byte first. But, when dealing with the 16-bit CRC, the CRC is transmitted little-endian, meaning Least Significant Byte first.
When using the UART, the Amulet CRC protocol is full-duplex, meaning both the Amulet and the host processor can transmit at the same time. All master messages do require a response message, though. The Amulet LCD module(master) can send 13 different types of messages to the external processor (slave):
If the message is valid, the slave should either return the requested data (if a "Get" request) or confirm the message was received (if an "Invoke", "Set", or "Draw" command). If the message is not valid, the slave should respond with an acknowledge (ACK) to have the Amulet move to the next request, or the slave can respond with a negative acknowledgement (NAK) to have the Amulet resend the last message. If there is a CRC error, following the Modbus standard, the message should be ignored. If the message is not responded to, the Amulet will resend the message after a timeout period of 200ms.
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 250 characters plus a null termination character (0x00).
The first byte of all master messages is the ID of the slave processor. If the master is the Amulet processor, the first byte is the Host ID. If the slave is responding to a master message, it will also start with the ID of the slave processor. The second byte is always the opcode of the function. See Table 4 for the full list of available opcodes. The remaining payload bytes are opcode dependent. The final two bytes is the LSByte and MSByte of the CRC. See the CRC documentation on how to derive the 16-bit CRC. Essentially, all bytes prior to the two CRC bytes are run through the CRC algorithm. The result is the last two bytes of the message. If the CRC received is not the same as the CRC derived, then the message should be disregarded as the integrity of the message cannot be assured.
For example, if the GEMstudio file 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 five bytes. The first byte is the Host ID (0x02), the second byte is the "Get Byte Variable" opcode (0x20), third byte is the byte variable number (0x1A), fourth byte is the LSByte of the 16-bit CRC of the first three bytes (0x48), and the seventh and final byte is the MSbyte of the 16-bit CRC (0x0B). So the five byte message looks like: 0x02 0x20 0xA1 0x48 0x0B
NOTE: The slave must respond to every valid Amulet command. 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 variables are reset in an attempt to resync with the slave processor.
0x00 (Null Terminator)
Value Bits 31-24 (Alpha)
Value Bits 23-16 (Blue)
Value Bits 15-8 (Green)
Value Bits 7-0 (Red)
Variable Start Index
Count of Bytes in Array
Variable Start Index
Last Value in Array
Count of Words inArray
Last ValueLSByte in Array
Count of Colors inArray
Value Bits 15-8... (Green)
Last Value Bits 7-0 (Red) in Array
Count of RPCs in Buffer
Value Bits 23-16 (Blue)
Value Bits 15-8 (Green)
Value Bits 7-0 (Red)
Amulet Set Word Variable Array1
Amulet Set Color Variable Array1
Value Bits 15-8 (Green)...
1 Denotes command is only applicable when Amulet is the Slave.
Table 1. Seventeen 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 master to the slave start with the slave's ID (By default, the Amulet ID is 01 and the host processor's ID is 02). The payload is comprised of the Amulet message opcode (Byte 2) up to, but not including, the CRC bytes. The number of bytes following the opcode is dependent upon the opcode itself as each opcode has its own message structure.
When the Amulet is the master, 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 in the Project Properties menu from within GEMstudio.
By Modbus RTU standard, if a CRC error occurs, the slave should not respond at all. The master will timeout and resend the previous message.
NOTE: The external processor slave must respond to every valid Amulet master command. 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.
In the Amulet communications CRC protocol, the slave should not respond until the master is done sending its message. If the Amulet is going to be the slave in the protocol, the external processor (master) can send twenty-four 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 send graphic primitives (pixel, line, rectangle, and filled rectangle) to the Amulet. The external processor can also force the Amulet to jump to a specific page.
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 there is a CRC error, the Amulet will not respond at all. If the opcode is not a valid Amulet opcode, the Amulet will respond with a NAK and the "Illegal Function" error code #1.
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 (0x27).
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 (0x27). The Amulet will respond with a count byte and all the RPCs (up to six) stored in the RPC buffer. After sending out the contents of the RPC buffer, the Amulet will then flush the buffer.
For example, to request the contents of the InternalRAM RPC buffer, the following would be sent to the Amulet:0x01 0x27 0x40 0x3A
If the InternalRAM RPC buffer has the following RPCs in it, 0x01 0x05 0x05 0x06, the following would be returned by the Amulet:0x01 0x27 0x04 0x01 0x05 0x05 0x06 0x6E 0x78
If the same request is made before the InternalRAM RPC buffer is repopulated, the following would be returned by the Amulet:0x01 0x27 0x00 0x3B 0xF0
Where: is the slave ID (The Amulet ID in this case)is the Amulet message to sendis the two-byte CRC
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.
There are basically two types of communications errors that need to be handled by both the host and Amulet processors, CRC errors due to noise on the line and invalid requests. If the CRC check does not match, the slave should not respond at all. The master will timeout and resend its last message.
If an invalid request is received (i.e. requesting or setting a variable that does not exist), then the slave should respond with a NAK and an error code. The NAK is defined as the opcode with the Most Significant Bit set. Normally, the slave would respond back with the opcode sent to them, but in the case of an error, instead of the opcode, the slave would respond with the MSBit set plus the opcode sent to them. For instance, if the master was requesting a byte variable that did not exist, the opcode used to request a byte is 0x20. If an error existed, the slave would respond with 0xA0 (0x80 + 0x20) with the following byte being the error code.
List of error codes:
Amulet Action if Error Sent By Host
Will Amulet Send?
Opcode used was invalid
Illegal Data Address
Variable number used was invalid
Illegal Data Value
Implied length of array is incorrect (array overflow)
Slave Device Fail
Slave Device in failure mode
Slave currently too busy to process command
resend last message
Memory Parity Error
Not currently used
When the Amulet changes from one page to another, all UART 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.
See Graphic Primitives for more information regarding the use of graphic primitives.
Table 2 defines the four 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.
Set 8-bit Color for Primitive
8-bit color index
Set 32-bit Color for Primitive
Set InternalRAM Color Index for Primitive
IR color index
Set Line Weight for Primitive
"Draw" Pixel Primitive
Pnt X MSByte
Pnt Y MSByte
"Draw" Line Primitive
Pnt 1 X MSByte
Pnt 1 XLSByte
Pnt 1 Y MSByte
Pnt 1 YLSByte
Pnt 2 X MSByte
Pnt 2 XLSByte
Pnt 2 Y MSByte
Pnt 2 YLSByte
"Draw" Rectangle Primitive
Delta X MSByte
Delta Y MSByte
"Draw" Fill Rectangle Primitive
Table 2. Eight 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 HTMLCompiler 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. The Amulet will respond with a standard ACK message, complete with the 16-bit CRC.
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.
Jump To PageCommand
To jump to page 0x25, send the following sequence:0x01 0x50 0x00 0x25 0xC0 0x12
To jump to page 0x103, send the following sequence:0x01 0x50 0x01 0x03 0x40 0x58
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 essentially the Jump To Page command, but the page index is 0xFFFF.
To cause a soft reset, send the following sequence:0x01 0x50 0xFF 0xFF 0x00 0x79
To make the Amulet respond with the flash index of the current page, send the "Get Current Page Index" command. It will respond with a 16-bit value. See the Amulet Link Map for more information
To read the flash index of the current page, send the following sequence:0x01 0x51 0xC1 0xDC
The Amulet will respond with the following if the current page is index 0x20.
0x01 0x51 0x00 0x20 0x51 0xD1
When sending strings to the Amulet, all characters from 0x20-0x7F are valid. The Amulet protocol expects any characters above 0x7F to be in the UTF-8 format. See the documentation on UTF-8 below. In order for the Amulet to display characters over 0x7F, the font used to display these characters must have those characters explicitely defined in the .amf file. By default, only the characters 0x20-0x7F are saved in the .amf file, but in the Amulet GEM Font Converter, you can optionally save all the characters up to 0xFFFF.
UTF-8 (8-bit Unicode Transformation Format) is a variable-length character encoding for Unicode. Like UTF-16 and UTF-32, UTF-8 can represent every character in the Unicode character set, but unlike them it has the special property of being backwards-compatible with ASCII.
UTF-8 encodes each character (code point) in 1 to 4 octets (8-bit bytes). The first 128 characters of the Unicode character set (which correspond directly to the ASCII) use a single octet with the same binary value as in ASCII. The UTF-8 encoding is variable-width, with each character represented by 1 to 4 bytes. Each byte has 0–4 leading consecutive '1' bits followed by a '0' bit to indicate its type. 2 or more '1' bits indicates the first byte in a sequence of that many bytes. The scalar value of the Unicode code point is the concatenation of the non-control bits. In this table, zeros and ones in black represent control bits, each x represents one of the lowest 8 bits of the Unicode value, y represents the next higher 8 bits, and z represents the bits higher than that.
U+0000 to U+007F
00000000 to 01111111
'$' U+0024 = 00100100 → 00100100 → 0x24
U+0080 to U+07FF
00000000 10000000 to 00000111 11111111
'¢' U+00A2 = 00000000 10100010 → 11000010 10100010 → 0xC2 0xA2
U+0800 to U+FFFF
00001000 00000000 to 11111111 11111111
'€' U+20AC = 00100000 10101100 → 11100010 10000010 10101100 → 0xE2 0x82 0xAC
11100010 10000010 10101100
0xE2 0x82 0xAC
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 Tana 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.
With these restrictions, bytes in a UTF-8 sequence have the following meanings. The ones marked in red can never appear in a legal UTF-8 sequence. The ones in green are represented in a single byte. The ones in blue must only appear as the first byte in a multi-byte sequence, and the ones in orange can only appear as the second or later byte in a multi-byte sequence:
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. 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.
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:0x01 0x32 0x01 0x02 0x01 0x42 0x6F 0x6C 0x64 0x20 0x61 0x6E 0x64 0x20 0x02 0x030x69 0x74 0x61 0x6C 0x69 0x63 0x20 0x61 0x6E 0x64 0x20 0x02 0x80 0x70 0x6C 0x61 0x69 0x6E 0x2E 0x00 0xFC 0xEA
Alternatively written with ASCII characters written out as ASCII characters, it would look like this:[0x01][0x32][0x01][0x02][0x01]Bold and [0x02][0x03]italic and [0x02][0x80]plain.[0x00][0xFC][0xEA]
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 = 0x10E8Amulet Internal RAM byte variable 0xF4 = 0xA8Amulet Internal RAM word variable 0x76 = 0x0000Amulet 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
0x02 0x20 0x01 0x08 0x00
0x02 0x20 0x01 0x38 0x00 0x14
0x02 0x22 0x01 0x09 0x60
0x02 0x22 0x01 0x41 0x62 0x63 0x00 0x9E 0x90 'A' 'b' 'c'
0x02 0x30 0x01 0xFE 0x81 0x83
0x02 0x30 0x00 0xC4
0x02 0x37 0x02 0x47 0xF1
0x02 0x37 0x41 0x06
0x02 0x21 0x03 0x88 0x51
0x02 0x21 0x03 0x10 0xE8 0xAA 0x72
0x02 0x20 0x04 0xC8 0x03
0x02 0xA0 0x05 0x68 0x03
0x01 0x20 0xF4 0x38 0x47
0x01 0x20 0xF4 0xA8 0x47 0xC6
0x01 0x31 0x76 0x02 0xC9 0x37 0xD0
0x01 0x31 0xC1 0xF4
0x01 0x27 0x40 0x3A
0x01 0x27 0x01 0x52 0x31 0xBE
*NOTE: If master requests an invalid variable, the slave should at least respond with an ACK error code. It will allow the communications to continue on without displaying bogus data. This really should never happen since you have control of both the GEMstudio page and your processor's variables.
Table 3. Data flow diagram depicting several messages transmitted between the Amulet and a fictitious external processor.
Command Can Be Sent by Amulet
Command Can Be Sent by External Processor
Get byte variable
Get word variable
Get string variable
Get color variable
Get byte variable array
Get word variable array
Get color variable array
Get RPC buffer
Get label variable
Set byte variable
Set word variable
Set string variable
Set color variable
Set byte variable array
Set word variable array
Set color variable array
Set Graphic Primitive 8-bit color
Set Graphic Primitive 32-bit color
Set Graphic Primitive InternalRAM color index
Set Graphic Primitive Line Weight
Draw Filled Rectangle
Jump To Page
Table 4. Listing of all Amulet CRC protocol command opcodes and response opcodes.