Browse Source

initial commit

Keelan Lightfoot 1 year ago
commit
90b85dd184
3 changed files with 385 additions and 0 deletions
  1. 4
    0
      README.md
  2. 228
    0
      main.go
  3. 153
    0
      options.txt

+ 4
- 0
README.md View File

@@ -0,0 +1,4 @@
1
+# t4koptions
2
+
3
+This is a command line utility that can be used to generate option enable codes
4
+for a yellow box Trimble 4000 series receiver.

+ 228
- 0
main.go View File

@@ -0,0 +1,228 @@
1
+package main
2
+
3
+import (
4
+	"flag"
5
+	"fmt"
6
+	"os"
7
+)
8
+
9
+func main() {
10
+
11
+	var serial, option, value int
12
+	var valueStr string
13
+	var listOptions bool
14
+
15
+	flag.BoolVar(&listOptions, "l", false, "list options and exit")
16
+	flag.IntVar(&serial, "s", 0, "serial number of receiver")
17
+	flag.IntVar(&option, "o", 0, "option number (use -l to list)")
18
+	flag.StringVar(&valueStr, "v", "", "option value in hex (typically 00 = enable, FF = disable)")
19
+
20
+	flag.Parse()
21
+
22
+	if listOptions {
23
+		for i, name := range optionNames {
24
+			if name == "" {
25
+				continue
26
+			}
27
+			fmt.Printf("Option %2d = %s\n", i, name)
28
+		}
29
+		os.Exit(0)
30
+	}
31
+
32
+	if serial == 0 || option == 0 || valueStr == "" {
33
+		flag.PrintDefaults()
34
+		os.Exit(1)
35
+
36
+	}
37
+
38
+	if option < 0 || option > 59 {
39
+		fmt.Printf("Option number %d is out of range (allowed: 0-59)\n", option)
40
+		os.Exit(1)
41
+	}
42
+
43
+	n, err := fmt.Sscanf(valueStr, "%2x", &value)
44
+
45
+	if n == 0 || err != nil {
46
+		fmt.Println("Unable to parse option value.")
47
+		os.Exit(1)
48
+	}
49
+
50
+	e := encrypt(serial, option, value)
51
+
52
+	fmt.Printf("Receiver Serial Number: %d\n", serial)
53
+	if option < len(optionNames) {
54
+		fmt.Printf("Option Number: %d (%s)\n", option, optionNames[option])
55
+	} else {
56
+		fmt.Printf("Option Number: %d (out of range)\n", option)
57
+	}
58
+	fmt.Printf("Option Value: %02X\n", value)
59
+	fmt.Printf("Code: %s\n", e)
60
+
61
+	return
62
+
63
+}
64
+
65
+func encrypt(serialNumber, feature, value int) string {
66
+
67
+	passwordStr := fmt.Sprintf("%05d%02d%02X", serialNumber, feature, value)
68
+
69
+	password := []byte(passwordStr)
70
+
71
+	fromASCII(password)
72
+
73
+	sn := byte(serialNumber) & 0xF
74
+	secret := []byte{7, 7, 5, 5, 9, 8, 1, 4, 2}
75
+
76
+	encrypted := make([]byte, 10)
77
+
78
+	for x := 0; x < 9; x++ {
79
+		encrypted[8-x] = sn ^ secret[8-x] ^ reverseBits(password[x])
80
+	}
81
+
82
+	encrypted[9] = calculateCheck(encrypted)
83
+
84
+	toASCII(encrypted)
85
+
86
+	return string(encrypted)
87
+
88
+}
89
+
90
+func decrypt(serialNumber int, passwordStr string) (int, int, int, error) {
91
+
92
+	if len(passwordStr) != 10 {
93
+		return 0, 0, 0, fmt.Errorf("password must be 10 characters long")
94
+	}
95
+	password := []byte(passwordStr)
96
+
97
+	fromASCII(password)
98
+
99
+	sum := calculateCheck(password)
100
+	if password[9] != sum {
101
+		return 0, 0, 0, fmt.Errorf("bad checksum")
102
+	}
103
+
104
+	sn := byte(serialNumber) & 0xF
105
+	secret := []byte{7, 7, 5, 5, 9, 8, 1, 4, 2}
106
+
107
+	decrypted := make([]byte, 9)
108
+
109
+	for x := 0; x < 9; x++ {
110
+		decrypted[8-x] = reverseBits(sn ^ secret[x] ^ password[x])
111
+	}
112
+
113
+	toASCII(decrypted)
114
+
115
+	var serial, option, value int
116
+
117
+	_, err := fmt.Sscanf(string(decrypted), "%5d%2d%2X", &serial, &option, &value)
118
+	if err != nil {
119
+		return 0, 0, 0, err
120
+	}
121
+	return serial, option, value, nil
122
+
123
+}
124
+
125
+func calculateCheck(password []byte) byte {
126
+	sum := 0
127
+
128
+	for i := 8; i >= 0; i-- {
129
+		for j := 3; j >= 0; j-- {
130
+			sum += int(password[i]) >> j & 1
131
+		}
132
+	}
133
+
134
+	return byte(sum & 0xF)
135
+}
136
+
137
+func reverseBits(in byte) byte {
138
+	var out byte
139
+	for i := 0; i < 4; i++ {
140
+		if in&(1<<i) != 0 {
141
+			out |= 1 << (3 - i)
142
+		}
143
+	}
144
+	return out
145
+}
146
+
147
+func fromASCII(s []byte) {
148
+	for i, b := range s {
149
+		if b > '9' {
150
+			s[i] -= '7'
151
+		} else {
152
+			s[i] -= '0'
153
+		}
154
+	}
155
+}
156
+
157
+func toASCII(s []byte) {
158
+	for i, b := range s {
159
+		if b > 9 {
160
+			s[i] += '7'
161
+		} else {
162
+			s[i] += '0'
163
+		}
164
+	}
165
+}
166
+
167
+var optionNames = []string{
168
+	"POWER UP PORT SETTINGS",
169
+	"POWER UP OUTPUT MSGS",
170
+	"LOCATOR",
171
+	"POWER UP NV ERASE",
172
+	"RTCM ASCII",
173
+	"CYCLE PRINT",
174
+	"POSITION STATISTICS",
175
+	"TAILBOUY",
176
+	"PATHFINDER",
177
+	"LANDSEIS",
178
+	"RTCM NETWORK INPUT",
179
+	"CARRIER PHASE",
180
+	"HALF CYCLE L2",
181
+	"MAXWELL L1 ONLY",
182
+	"REMOTE DOWNLOAD",
183
+	"DEMO EQUIPMENT ONLY",
184
+	"",
185
+	"RT SURVEY DATA",
186
+	"LOCAL DATUMS",
187
+	"RSIM INTERFACE",
188
+	"DUAL FREQ / MULTI-BIT",
189
+	"RS-232 PORTS",
190
+	"MULTIPLE DATUMS",
191
+	"EXTERNAL TIMEBASE",
192
+	"EVENT MARKER",
193
+	"1 PPS",
194
+	"",
195
+	"FIRMWARE UPDATE",
196
+	"RTCM INPUTS",
197
+	"RTCM OUTPUTS",
198
+	"SYNC INTERVAL",
199
+	"NMEA-0183",
200
+	"SV SWAPPING",
201
+	"KEYBOARD TYPE",
202
+	"NAVIGATION",
203
+	"LctrCrPh",
204
+	"KINEMATIC",
205
+	"CONFIGURED",
206
+	"DATA LOGGING SIZE",
207
+	"SURVEY TYPE",
208
+	"RTK OTF CAPABILITIES",
209
+	"IONO-FREE POSITIONING",
210
+	"",
211
+	"I/O DRIVERS",
212
+	"",
213
+	"CMR TYPE2 RATE",
214
+	"RTK SPECIALS",
215
+	"",
216
+	"",
217
+	"",
218
+	"",
219
+	"",
220
+	"",
221
+	"",
222
+	"",
223
+	"",
224
+	"",
225
+	"",
226
+	"",
227
+	"",
228
+}

+ 153
- 0
options.txt View File

@@ -0,0 +1,153 @@
1
+These are the known option codes and their names. The names have been
2
+extracted from receiver firmware, and may not exist on your firmware
3
+version. The descriptions have been extracted from various sources,
4
+including Trimble marketing material.
5
+
6
+00: POWER UP PORT SETTINGS
7
+
8
+01: POWER UP OUTPUT MSGS
9
+
10
+02: LOCATOR OPERATION
11
+
12
+03: POWER UP NV ERASE
13
+
14
+04: RTCMAsci
15
+
16
+05: CyclPrnt
17
+
18
+06: POSITION STATISTICS
19
+
20
+	Enables a receiver to compute the probable error (“sigma”) in its
21
+	real- time position fixes.
22
+
23
+07: TAILBOUY
24
+
25
+	Elsewhere in the firmware this is parsed as 'LOW BATTERY OVERRIDE'.
26
+	I don't know what either of these mean.
27
+
28
+08: PATHFINDER
29
+
30
+09: LandSeis
31
+
32
+10: RTCM NETWORK INPUT
33
+
34
+11: CARRIER PHASE
35
+
36
+	Enables a receiver to measure satellite range by observing (among
37
+	other things) the phase difference between the L1 and L2 carriers.
38
+	This option is less precise than the L2 P-Code Option, but it is not
39
+	affected by Anti-Spoofing. It may be used as a less sophisticated
40
+	alternative to the L2 P-Code Option, or as a fallback when Anti-
41
+	Spoofing is active.
42
+
43
+12: HALF CYCLE L2
44
+
45
+	A technique for correcting ionospheric delay errors without the use of
46
+	P-code; replaced in recent dual-frequency receivers by the more
47
+	accurate Cross-Correlation Option.
48
+
49
+13: MAXWELL L1 ONLY
50
+
51
+14: REMOTE DOWNLOAD
52
+
53
+	Enables a computer equipped with a modem to download data files from
54
+	an unattended receiver.
55
+
56
+15: DEMO EQUIPMENT ONLY
57
+
58
+17: RT SURVEY DATA
59
+
60
+18: LOCAL DATUMS
61
+
62
+19: RSIM INTERFACE
63
+
64
+20: DUAL FREQ / MULTI-BIT
65
+
66
+21: RS-232 PORTS
67
+
68
+	The number of RS-232 ports installed in the
69
+	receiver. Two ports are built in, two additional ports can be
70
+	installed with additional hardware.
71
+
72
+22: MULTIPLE DATUMS
73
+
74
+23: EXTERNAL TIMEBASE
75
+
76
+	Enables a receiver to substitute a very precise external oscillator,
77
+	such as an atomic clock, for its internal quartz-crystal oscillator.
78
+	The EXT-REF BNC jack is only populated on CORS receivers, so enabling
79
+	this option without the appropriate jack is pointless.
80
+
81
+24: EVENT MARKER
82
+
83
+	Enables a receiver to log a time-stamped record whenever an event (an
84
+	electrical pulse) is detected on a special connector. You can record
85
+	alphanumeric messages associated with particular events; you can also
86
+	generate events from the receiver's keypad.
87
+
88
+25: 1 PPS
89
+
90
+	Provides a port through which the receiver can output a very precise
91
+	one pulse/second strobe, based on timing information in the satellite
92
+	signals. Other devices can use this strobe as a timing signal.
93
+
94
+27: FIRMWARE UPDATE
95
+
96
+28: RTCM INPUTS
97
+
98
+	Enables a receiver to serve as a DGPS differential station (a rover)
99
+	by inputting RTCM-104 corrections through a serial port from a digital
100
+	radio receiver.
101
+
102
+29: RTCM OUTPUTS
103
+
104
+	Enables a receiver to function as a DGPS reference station (a base
105
+	station) by outputting RTCM-104 corrections through a serial port to a
106
+	digital radio transmitter.
107
+
108
+30: SYNC INTERVAL
109
+
110
+	Interval between successive measurements in seconds.
111
+
112
+31: NMEA-01
113
+
114
+	Enables a receiver to output several types of NMEA-0183 messages
115
+	through a serial port. Other devices can use these messages for
116
+	navigation and similar functions. This option is used primarily in
117
+	marine applications.
118
+
119
+32: SV SWAPPING
120
+
121
+33: KEYBOARD TYPE
122
+
123
+34: NAVIGATION
124
+
125
+	Provides an extended set of navigation functions, including a cross-
126
+	track error display and the ability to define and use up to 99
127
+	waypoints.
128
+
129
+35: LOCATOR CAR. PHASE
130
+
131
+36: KINEMATIC
132
+
133
+	Enables a receiver to perform kinematic surveys.
134
+
135
+37: Config'd
136
+
137
+38: DATA LOGGING SIZE
138
+
139
+39: SURVEY TYPE
140
+
141
+40: RTK OTF CAPABILITIES
142
+
143
+41: IONO-FREE POSITIONING
144
+
145
+43: I/O DRIVERS
146
+
147
+	Described elsewhere in firmware as JX-1100A DRIVER, presumably the
148
+	Clarion JX-1100A, an early 2.4 GHz spread-spectrum radio modem. This
149
+	option seems to enable the radio config menu in the MODIFY menu.
150
+
151
+45: CMR TYPE2 RATE
152
+
153
+46: RTK SPECIALS