« Return to Documents & HOW-TOs
CPS Out of Band Modification HOW-TO
v2.0 03/17/2012
Introduction
This document details how to make modifications to currently available Customer Programming Software (CPS) for the Motorola Astro and Astro25 series tranceivers, to allow out of band programming. Modification methods discussed herein may be applicable to other CPS packages; the reader is encouraged to experiment on their own.
The Basics
Out of band (OOB) programming is the process of programming a frequency into a radio outside of its rated bandsplit. For example, Astro25 portables (such as the XTS5000) in the upper UHF split (which is called the UHF Range 2, or S split), have a rated bandsplit of 450-520. However, each physical RF component has slightly different tolerances, and may operate within specification (power output, frequency stability, etc) up to several MHz outside of the rated bandsplit. CPS will in some few cases (depending on band, model, etc) allow such programming without modification. In all other cases, it is necessary to modify CPS to allow such frequencies to be programmed without error.
Notice & Disclaimer
This guide is intended to allow Motorola enthusiasts to operate a radio tranceiver in a modified condition, on frequencies for which FCC type acceptance is not required (for example, on the amateur radio bands). A radio tranceiver modified thusly should not be used for commercial or public safety service, or in any situation where communications are critical or convey life and safety information.
The author(s) of this work hereby disclaim that the information given herein is suitable for any purpose whatsoever, and do not make any warranties or guaruntees, either implied or expressed, of the suitability of the information for any purpose. The author(s) of this work disclaim all liability in the event that the use of the information given herein results in harm to persons or property, to any extent.
Important: Please remember to make a backup of any executable file you modify before you begin. Make sure also to make backups of any codeplug on which you intend to use modified CPS. It would probably be a good idea to rigorously test any modified CPS on a test codeplug (to guard against inadvertent modification of non-bandsplit edge value data) prior to reading from or writing to any radios.
Section 1: History & Notes
This HOW-TO is based on the original WinCPS OOB document located at Batlabs.
Reference Band Edge Tables
For each CPS package (Portable and Mobile) there are generally two sets of band edges for each bandsplit, one for the bandsplit lower edge and one for the bandsplit upper edge. The table below shows the band tables for the Astro CPS packages, as presented on Batlabs. There is band info for various VHF, UHF, and 800 splits, which is generally represented in integer MHz values (except for the VHF value of 162.550):
Table 1: Astro Bandsplit Edge Table (Batlabs)
| Astro Mobile | Astro Portable |
| Lower Band Edge Tables | |
|
136 403 450 830 136 146 136 136 403 438 450 453 433 136 403 445 830 133 142 136 136 403 438 440 453 475 136 403 450 825 136 146 136 136 403 438 450 450 482 136 403 450 830 136 146 136 136 403 438 450 453 482 136 403 445 830 133 142 136 136 403 438 440 453 475 |
136 403 450 830 136 146 136 136 403 438 450 453 482 136 403 445 830 133 142 136 136 403 438 440 453 475 136 403 450 825 136 146 136 136 403 438 450 450 482 136 403 450 830 136 146 136 136 403 438 450 453 482 136 403 445 830 133 142 136 136 403 438 440 453 475 |
| Upper Band Edge Tables | |
|
178 470 520 915 162 174 174 174 433 470 482 490 512 179 477 521 915 171 175 174 174 441 470 491 490 515 |
178 470 520 915 162 174 174 174 433 470 482 490 512 179 477 521 915 171 175 174 174 441 470 491 490 515 |
Section 2: Current CPS Bandsplit Edge Discussion
Throughout this section, we will be using examples derived from Astro25 Portable CPS R09.01.02
Please Note: This document assumes that the reader has some basic knowledge of the tools mentioned, such as hex editors and debugging tools. Advanced topics, such as decompilation, are beyond the scope of this document.
In order to understand how bandsplit edge values are modified, it is first necessary to understand the basics of how the CPS executable functions. Astro and Astro25 CPS executables are what are known as Windows Portable Executable files. Such files are comprised of one or more sections of raw information, which can contain executable code, data, Win32 Resource objects, etc. The sections are defined by the section table, which immediately follows the PE header at the beginning of the file.
It is important to understand that these sections exist, because they in part define how we go about searching for bandsplit edge values (and collections of values in tables). Classically, bandsplit edge values were defined strictly in PE sections that contained only data (do not contain executable code). However, as time has progressed, it appears that some values that pertain to what frequency ranges the radio is allowed to operate in are being placed in sections of executable code. This seems to be especially prevalent for radios that operate on the 700 MHz band (more on this below). Thus, one might find a situation in which modifying bandsplit edge values in strictly data sections of the file do now allow certain OOB frequencies to be input, and in such situations additional values might need to be found and modified elsewhere within the CPS executable.
A useful tool to examine the contents of an executable file is a debugger. One of the better debuggers for Windows (and Windows executables) is OllyDbg. This kind of debugger will attempt to analyze the raw information in the executable file, determine which parts are executable code, and which are strictly data. A very useful and essential accompanyment to a debugger is the document that defines the the processor's instruction set. In the case of Astro and Astro25 CPS, this is the Intel x86 instruction set, reference material for which may be found on Intel's website.
To date, all Astro and Astro25 CPS executables examined have had four PE sections, as follows:
Table 2: Example CPS executable PE Section Table
| Section # | Name | Offset | Size |
| 01 | .text | 0x00001000 | 0x00D88000 |
| 02 | .rdata | 0x00D89000 | 0x0013A000 |
| 03 | .data | 0x00EC3000 | 0x00503000 |
| 04 | .rsrc | 0x013C600 | 0x001FA000 |
In this case the ".rdata" and ".data" sections contain raw data, and the ".rsrc" section contains Win32 Resource Objects (such as program icons, dialog boxes, etc). The ".text" section contains the executable code, and is the largest of the sections. If you load up the executable in OllyDbg, this should be the only section that shows up as executable module memory.
Section 2a: Bandsplit Edge Values in PE data-only sections
Before we look at where and how we find the actual bandsplit edge values, let's look at the layout of the tables.
Each table is comprised of a number of columns and rows. Astro CPS uses a table with 18 columns, and Astro25 CPS uses a table with 20 columns. Below is a meta-table showing a general description of each column and what that column is used for in the CPS packages of each platform.
Table 3: Overview of primary CPS Bandsplit Edge Tables
| Col # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| Band | 800 Gen |
900 Gen |
Not Used |
VHF Wide |
UHF R1 Wide |
UHF R2 Wide |
800 Unk |
VHF R1 Narrow |
VHF R2 Narrow |
VHF R3 Narrow |
VHF R4 Narrow |
UHF R1 Narrow |
UHF R2 Narrow |
UHF R3 Narrow |
UHF 3.5 Narrow |
UHF R4 Narrow |
Not Used |
Not Used |
7/800 Gen |
UHF R3.5 SP |
| Astro CPS |
800 Gen |
900 Gen |
Not Used |
Portable VHF K-Split |
Portable UHF R1 R-Split |
Portable UHF R2 S-Split |
Unk | Mobile VHF R1 J-Split |
Mobile VHF R2 K-Split |
Mobile VHF R3 Unused |
Mobile VHF R3 Unused |
Mobile UHF R1 Q-Split |
Mobile UHF R2 R-Split |
Mobile UHF R3 R-Split |
Mobile UHF R3.5 R-Split |
Mobile UHF R4 S-Split |
Not Used |
Not Used |
N/A | N/A |
| Astro25 CPS |
800 Gen |
900 Gen |
Not Used |
XTS/L VHF K-Split |
XTS/L UHF R1 Q-Split |
XTS/L UHF R2 S-Split |
Unk | AS+ VHF R1 J-Split |
AS+ VHF R2 K-Split |
AS+ VHF R3 Unused |
AS+ VHF R3 Unused |
AS+ UHF R1 Q-Split |
AS+ UHF R2 R-Split |
AS+ UHF R3 R-Split |
AS+ UHF R3.5 R-Split |
AS+ UHF R4 S-Split |
Not Used |
Not Used |
7/800 Gen |
AS+ UHF R3.5 R-Split |
Some notes on the columns:
- The "narrow" range columns typically apply to VHF & UHF Astro Spectra & Astro Spectra+ radios
- The "wide" range columns typically apply to VHF & UHF Astro Sabers and all XTS/XTL radios
- 700/800, 800, and 900 columns apply to both mobiles and portables in those bands
Now let's look at the rows. Each table is comprised of 5 rows which represent starting bandsplit edges, and 2 rows which represent ending bandsplit edges. Below are tables showing bandsplit edge values rounded to MHz (with annotations for values that are not represented in the table as integer MHz), for the CPS packages for each platform.
Table 4: Astro Bandsplit Edge Table
| Astro Mobile | |
| Start Edge |
806 896
000 136 403 450 830 136 146 136 136 403 438 450 453 482 000 000 806 896 000 136 403 445 830 133 142 136 136 403 438 440 453 475 000 000 851 935 000 136 403 450 825 136 146 136 136 403 438 450 450 482 000 000 851 935 000 136 403 450 830 136 146 136 136 403 438 450 453 482 000 000 851 935 000 136 403 445 830 133 142 136 136 403 438 440 453 475 000 000 |
| End Edge |
869 940
000 178 470 520 915 162 174 174 174 433 470 482 490 512 000 000 869 940 000 179 477 521 915 171 175 174 174 441 470 491 490 515 000 000 |
| Col # | 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 |
| Astro Portable | |
| Start Edge |
806 896
000 136 403 450 830 136 146 136 136 403 438 450 453 482 000 000 806 896 000 136 403 445 830 133 142 136 136 403 438 440 453 475 000 000 851 935 000 136 403 450 825 136 146 136 136 403 438 450 450 482 000 000 851 935 000 136 403 450 830 136 146 136 136 403 438 450 453 482 000 000 851 935 000 136 403 445 830 133 142 136 136 403 438 440 453 475 000 000 |
| End Edge |
869 940
000 178 470 520 915 162 174 174 174 433 470 482 490 512 000 000 869 940 000 179 477 521 915 171 175 174 174 441 470 491 490 515 000 000 |
Table 5: Astro25 Bandsplit Edge Table
| Astro25 Mobile | |
| Start Edge |
806 896
000 136 380 450 830 136 146 136 136 403 438 450 453 481 000 000
764 450 806 896 000 136 380 450 830 136 146 136 136 403 438 450 453 481 000 000 764 450 851 935 000 136 403 450 825 136 146 136 136 403 438 450 450 482 000 000 764 450 851 935 000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000 851 450 851 935 000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000 851 450 |
| End Edge |
869 940
000 174 470 520 915 162 174 174 174 433 470 482 490 512 000 000
869 488 869 940 000 174 470 520 915 162 174 174 174 433 470 482 490 512 000 000 869 488 |
| Col # | 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 |
| Astro25 Portable | |
| Start Edge |
806 896
000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000
764 450 806 896 000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000 764 450 851 935 000 136 403 450 825 136 146 136 136 403 438 450 450 482 000 000 764 450 851 935 000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000 851 450 851 935 000 136 380 450 830 136 146 136 136 403 438 450 453 482 000 000 851 450 |
| End Edge |
869 940
000 174 470 520 915 162 174 174 174 433 470 482 490 512 000 000
869 488 869 940 000 174 470 520 915 162 174 174 174 433 470 482 490 512 000 000 869 488 |
Now that we've seen how the tables are layed out, let's look at how to find them in the file.
Looking at Tables 4 & 5 from above, note that some rows share the same starting values. If we convert the first three frequency entry values in Hz into a little-endian longint (which is how the values are stored in the executable, this is discussed in more detail in Section 3 of this document), we get the following:
Table 6: Bandsplit Edge Table Row Finder
| Decimal Values: Frequencies in Hz | Hex Values: Frequencies in Little-Endian LongInt | |
| Start Rows 1-2 | 806012500 896012500 000000000 | 54C60A30 D4106835 00000000 |
| Start Rows 3-5 | 851012500 935012500 000000000 | 946BB932 9428BB37 00000000 |
| End Rows | 869987500 940987500 000000000 | ACF4DA33 6C541638 00000000 |
You should be able to use the resulting hexadecimal strings to search the executable file with your favorite hex editor (also discussed in further detail in Section 3) to find the offsets within the file. For reference, below is a list of the offsets for the current CPS as of this date:
Table 7: Bandsplit Edge Table Row in-file offsets by Platform & Version
| Astro Mobile R05.03.00 |
Astro Portable R05.03.00 |
Astro25 Portable R09.01.02 |
Astro25 Mobile R17.00.00 |
Astro25 Portable R17.00.00 |
|
| Start Row 1 | 0xCCA8B8 | 0xCA5B88 | 0x10462F8 | 0x13541C8 | 0x119FCD8 |
| Start Row 2 | 0xCCA900 | 0xCA5BD0 | 0x1046348 | 0x1354218 | 0x119FD28 |
| Start Row 3 | 0xCCA948 | 0xCA5C18 | 0x1046398 | 0x1354268 | 0x119FD78 |
| Start Row 4 | 0xCCAA20 | 0xCA5CF0 | 0x1046488 | 0x1354358 | 0x119FE68 |
| Start Row 5 | 0xCCAA68 | 0xCA5D38 | 0x10464D8 | 0x13543A8 | 0x119FEB8 |
| End Row 1 | 0xCCAAB0 | 0xCA5D80 | 0x1046528 | 0x13543F8 | 0x119FF08 |
| End Row 2 | 0xCCAAF8 | 0xCA5DC8 | 0x1046578 | 0x1354448 | 0x119FF58 |
If you find one of these hexadecimal strings in a part of the file far away from all the others, examine it carefully to make sure that it is in fact part of a bandsplit edge table, and that it doesn't appear in any part of the file identified as executable code by your debugger.
Please Note: There may be additional bandsplit edge values within the data-only sections of the executable, either individually or as small tables. If modifying the main bandsplit edge tables does not let you enter the desired frequency, you will probably need to search further for the necessary value to modify.
Section 2b: Bandsplit Edge Values in PE executable sections
As mentioned above, sometimes the bandsplit edge value you are looking for to allow a particular OOB frequency will not appear in data-only sections of the file. First let's look at one of the main reasons for this, the "700MHz Problem".
The 700MHz Problem
The extensive machinations surrounding the allocation of 700MHz frequencies vacated by TV broadcasters at the advent of digital TV broadcasts is outside of the scope of this document. Briefly, although the Astro25 700MHz capable radios are physically capable of and type accepted for continuous operation from 764MHz to 870MHz, the FCC rules governing use of the 700MHz spectrum allow LMR service on only portions of the spectrum from 764MHz to 806MHz. Because of this, CPS should only allow the programmer to input frequencies within these specified ranges. Additionally, between 2005 and 2008, the FCC realigned the public safety portion of 700MHz band from two 3MHz narrowband ranges (and a planned 6MHz wideband range), to two 5MHz narrowband ranges. Below is a visual synopsis of this change.
Figure 1: 700MHz Band Plan, 2005 vs 2008
Note the difference in subscriber frequency ranges. More importantly, note that the CPS still covers the pre-2008 ranges, and has been expanded to cover the post-2008 ranges only where they were not already covered. Below are the changes summarized numerically:
Table 8: 700MHz Bandsplit Edge Value changes, 2005 vs 2008
| 2005 Value | Changed? | 2008 Value |
| 766.993750 | No | 766.993750 |
| 773.006250 | Yes | 769.006250 |
| 775.993750 | No | 775.993750 |
| 794.006250 | No | 794.006250 |
| 796.993750 | No | 796.993750 |
| 803.006250 | Yes | 799.006250 |
Please Note: These values do not include the radio physical bandsplit edge values as those are defined by the hardware, not software.
Under normal circumstances you would not need to modify CPS to allow these additional frequencies to be used - you would have long ago upgraded your CPS accommodate the change. However, there are are circumstances in which you might be constrained to an older CPS version, say R09.01.02, which was built prior to this change. In that case, you can make these kinds of modifications.
Finding Bandsplit Edge Values in Executable Code
Values like the above 700MHz "sub" bandsplit edge values are pretty clearly not in the main bandsplit edge tables, and might reside in the executable sections of the CPS executable file. In fact, for 700MHz, this has been found to be true. Finding these values within executable code is more difficult than searching the data-only sections of the file if you are just using a hex editor, because it is hard to be sure if what you are seeing is code or data.
It's time to turn back to our handy debugger and x86 instruction set. Once you have identified the exact value to change, you can search through the analyzed code for the hex string representing the little-endian longint. What you're looking for is an instruction containing an opcode and the longint. Most commonly this is liable to be a PUSH (storing the value) or a CMP (compare). You might find something like this:
Table 9: Debugger analysis
| Address | Raw Code | Command Mnemonic | What it's doing |
| 0x004F9EA5 | 68 5665B72D | PUSH 2DB76556 | Storing the value in a stack |
| 0x007421DB | 817D E8 5665B72D | CMP DWORD PTR SS:[EBP-18],2DB76556 | Comparing the value of memory at an address in a register |
In this case we have searched for the frequency 766.993750 and found both a PUSH and a CMP. Note that the mnemonic will reverse the byte order of the longint.
Once you have verified that the hex string you found is indeed a data value, you can go ahead and modify it.
Section 3: Modifiying a Band Edge
The original document described the proceedure using the popular HexWorkshop hex editor. Another option is a freely available hex editor called XVI32. The proceedure is essentially the same in either application.
In the following example we will modify the CPS so that we can program 440 amateur radio frequencies into a S split (450-512) radio. The proceedure for any other band edge is the same.
Convert Values
As mentioned briefly above, the frequency values are stored in the executable file as little-endian longint (long integers), and are referenced in integer Hz.
For example:
Frequency: 450 MHz
Frequency in Hz: 450000000
Frequency in longint: 80 74 D2 1A
So, let's go convert us some numbers.
Open up XVI32, and open up the CPS exe file. (You made a backup... right?). Go to "Tools > Encode Number...". Set the encoding options, type the original frequency (in this case, 450MHz) as Hz into the input box, and press enter.
Figure 2: Encoding Frequency by Hz to LongInt (Little-Endian)
In Figure 1, we see that we have configured the encoder for LongInt, and chosen to display the output in the output box. Copy the hex string, we'll need that later.
Table 10: Converted Hex String for 450 MHz
| Original Value | Converted Value (Hex String) |
| 450000000 | 80 74 D2 1A |
We're almost ready. Use the encoder to encode the longint for 440 MHz, and copy the hex string:
Table 11: Converted Hex String for 440 MHz
| Original Value | Converted Value (Hex String) |
| 440000000 | 00 DE 39 1A |
Replace Values
Locate each instance of the original value you wish to change. Once you've located the string, go to "Edit > Overwrite String...". Paste in the 440 MHz hex string, and click on Overwrite. You've now replaced that instance of 450 MHz with 440 MHz.
Once you've replaced all the original values, save the modified file, and open CPS. You should now be able to program frequencies as low as 440.000 MHz into the CPS without it complaining.
Happy hacking!
| Copyright © 2000-2013 by Peter "Akardam" Acord | questions, comments, suggestions? contact me |
