Hacking GWTS

0x9? Packet Header

Many of the Glow with the Show commands are sent using this packet format. Each packet may contain multiple commands. Note that sending a new command does not completely reset previous commands. For example, if you have the had pulsing green, then you send a command to change the hat to red, the hat will change to red, but continue to pulse.

0x9? Packet Header

# +-+-+-+-+-+-+-+-+--------------------+-+-+-+-+-+-+-+-+

# | HDR | LEN | PAYLOAD | CRC |

# +-------+-+-+-+-+--------------------+-+-+-+-+-+-+-+-+

#HDR, 4-bits = 0b1001 = 9

#LEN, 4-bits, Number of bytes in payload-1

# 1-byte payload would have length 0b0000

# 2-byte payload would have length 0b0001

#PAYLOAD, variable length in bytes

# Contains command(s) for the GWTS ears.

#CRC, 1-byte, calculated across HDR, LEN, and PAYLOAD

# 8-bit CRC value as the last byte and uses a

# polynomial of X^8 + X^5 + X^4 + X^0

Simple Example: This GWTS command changes the color of the ears to green. 0x90 62 1A

HDR: 0x90 = 0b10010000. The first nibble (4-bits) 0b1001 = 9, it's always 9.

LEN: The 2nd nibble 0b0000 is the payload length -1. In this example the payload (0x62) length is 1 byte. So the payload length minus 1 is zero.

PAYLOAD: 0x62 : This command tells the ears to simply change color to green.

CRC: 0x1A : This is the result of an 8-bit CRC check using 0x82 as a Polynomial across 0x9062. You can see the math by entering 9062 here.

The following sections represent the commands that can be placed in the payload of the 0x9 command packets. You can can combine multiple commands into a single payload.

Setting Basic Colors using single byte command

Each color has an assigned code that will change both the ears to the specified color. To set just the right ear add 8 to the base code.

Setting Extended Colors using 0x0E command

Each of the following color codes follows 0x0E to specify one of the extended colors. This will change the color of both ears. To change the color of just the right ear add 128 (0x80) to the base code. Lots of pastel colors here. I described them the best I could you can explore the finer hues on your own :)

Format for both ears: 0x91 0E [00-1D] [CRC]

Format for right ears: 0x91 0E [(00-1D)+0x80] [CRC]

Reset

0x24: This command resets the ears back to black and clears effects.

Used by itself the command is: 0x90 24 81

Setting Effect Speed

0x58 ??: The 0x58 command is used with the 0x9 header to set the speed of the active effect where ?? is the specified speed.

0x58 01: Represents the fastest speed

0x58 FF : Represents the slowest speed

CRC Calculation:

CRC, 1-byte, calculated across HDR, LEN, and PAYLOAD. 8-bit CRC value as the last byte and uses a polynomial of X^8 + X^5 + X^4 + X^0

Used with the 0x9? command packets.

John's PERL source for generating GWTS CRC and Checksum: Link

Compatible online CRC calculator: Link

PERL CRC Calculator (binaries as strings)

# Test: "96 42 00 00 48 18 0C BE" Should give you "1B"

sub GWTS_crc8c_calc {

my($hex) = shift; # Space seperate Hex string to be converted

my($crc) = "00000000"; # Initialize CRC

my($poly) = "10001100"; # 0x8C

my(@bytes); (@bytes) = split(/ +/,$hex); # 1-byte per element


foreach my $byte (@bytes) { # Go byte by byte

my($binbyte) = lpad(hex2bin($byte),"0",8); # Hex2binary and left pad so string is 8 long.

my($i); for($i=0;$i<8;$i++) { # 8 times for 8 bits

if( substr($binbyte,7,1) eq substr($crc,7,1) ) { # Comparing right most bits

$binbyte = strbitwise_rshift($binbyte,1); # Right shift byte by 1 (advancing to next bit)

$crc = strbitwise_rshift($crc,1); # Right shift running CRC by 1

} else {

$binbyte = strbitwise_rshift($binbyte,1); # Right shift byte by 1 (advancing to next bit)

$crc = strbitwise_rshift($crc,1); # Right shift running CRC by 1

$crc = strbitwise_xor($poly,$crc); # XOR the current CRC with the shifted byte

} #endif

} #end for

} # end foreach

return(bin2hex($crc)); # Convert back to hex and return CRC

} # GWTS_crc8c_calc

Sample C Implementation

uint8_t gws_crc(uint8_t *d, unsigned len) {

crc = 0;

while(len--) {

crc ^= *d++;

unsigned n = 8; do crc = (crc & 1) ? (crc >> 1) ^ 0x8C : crc >> 1; while(--n);

}

return crc;

} /* C implementation of CRC calculator:

/* Kevin Timmerman (http://www.hifi-remote.com/forums/viewtopic.php?t=14541) */

Calculating Checksum for 0x55 AA System command

PERL Checksum for 0x55 AA Sys Command

# Calculates a checksum for a 0x55 AA system command

# 55 AA [19 04 01 02 0E 01 00 00 35] 64

sub GWTS_Checksum55AA {

my($hex) = shift;

$hex = uc($hex);

my(@bytes); (@bytes) = split(/ +/,$hex);

if( $bytes[0] eq "55" and $bytes[1] eq "AA" ) {

shift(@bytes); shift(@bytes);

} #endif

my($chksum) = 0;

foreach my $b (@bytes) {

$chksum += hex2dec($b);

} #endforeach

return(dec2hex($chksum));

} # GWTS_Checksum55AA