One part of the annoying thing in SMS is that you need to send the data in GSM septets (you may want to read it more in here and here).
There’s a lot of approach to encode your message to 7-bits GSM septets, but this is my approach to encode it without relying on java utils too much (which means that it’s quite portable for MCUs, like AVR).
First of all, let’s create two tables from the original data, like this:
Once the tables are created, the next step to get the encoding is easy.
- Shift the adder table 1-column to the left (the table, not the bytes inside the table)
- Add ’0′ (0×00) at the right-est column
- Sum the adder and base table row, except for the column where the shifter is 8 (on adder) or 7 (on base).
Here’s the illustration:

And here’s the java code for the thing:
/**
* brief Encode the message into GSM octets
* param data The user data in ASCII (ISO-8859-1 / Latin 1) charset
* return The GSM 03.40 compressed data
*/
public byte[] encode(String data) {
// rawData refers to 8-bit uncompressed byte
byte[] rawData = data.getBytes();
// compressedData refers to compressed septets list
ArrayList compressedData = new ArrayList();
byte shiftValue = 0;
int iRawData = 0;
while (iRawData > shiftValue) {
byte adderByte = 0;
if ((iRawData + 1) < rawData.length) {
adderByte = (byte) (rawData[iRawData + 1] << (7 - shiftValue));
} else {
// adderByte = 0; //< Not needed, since adderByte is initialized with 0
}
byte resultByte = (byte) (baseByte + adderByte);
if (shiftValue < 7) {
shiftValue++;
compressedData.add(new Byte(resultByte));
} else {
shiftValue = 0;
// Don't add the resultByte to the result.
}
iRawData++;
}
byte[] retVal =
translateToByte((Byte[]) compressedData.toArray(new Byte[0]));
return retVal;
}
/**
* brief Tranverse Bytes[] array into byte[] array
* param data Bytes[] array
* return byte[] array
*/
private byte[] translateToByte(Byte[] data) {
byte[] retVal = new byte[data.length];
for (int i = 0; i < data.length; i++) {
retVal[i] = data[i].byteValue();
}
return retVal;
}
Here’s some example of how to use it:
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java PduData ");
System.exit(1);
}
byte[] result = new PduData().encode(args[0]);
for (int i = 0; i < result.length; i++) {
System.out.print(Integer.toHexString(result[i] & 0xFF) + "");
}
System.out.println();
}
If you read the AVR323 application note, you’ll find out that the procedure to encode the septet is similar, except that the application sample has one-off bug in its while loop.

[...] 2008. Filed under: java, programming tips | Tags: java, java-sms | Once encoding is done (refer to this post), decoding is [...]
Pingback by Decoding GSM SMS Septets « Embedded Freaks.. — October 9, 2008 @ 5:18 pm
Errors in the code:
baseByte is not defined !
This condition is illogical and
will not work:
12 byte shiftValue = 0;
13 int iRawData = 0;
14 while (iRawData > shiftValue);
Parenthesis missing at some places
Comment by Mohsin — February 12, 2010 @ 9:00 pm
This code is not working. I have the working code on here. You can use site <a href="http://www.smartposition.nl/resources/sms_pdu.html” to verify the out put of my code. Also ask me if you need more explanationhere.
Comment by mlusincuba — December 2, 2011 @ 3:47 pm