Programming a GPS watch

Introduction

A while ago, I built a reverse geocache box from a broken GPS wristwatch (Keymaze 700 trail) found in an electronics recycle bin. For that, I had to upload a custom firmware in the STM32F103 microcontroller through JTAG (with a buspirate and OpenOCD).

The GPS wristwatch "CW Kalenji 700 gps", is very similar to the "Keymaze 700 trail", it has the same microcontroller and thus can be easily reprogrammed. Rather than having to open it in order to program it by JTAG, it would be much more convenient to use the built-in firmware upgrade mechanism of the watch.

The information needed for this project were gathered by reverse engineering the watch in two different ways :

Hardware : by studying the pcb of the watch to find out the connections between the microcontroller and the various peripheral. Mainly on another watch ("W Kalenji 300 gps") which has the same pcb.

Software : By disassembling the original firmware and bootloader.

Upgrade process

firmware upgrade mode of the watch

The watch can be taken into its "firmware upgrade mode" by two different means :

There is an option in the menu of the original firmware

By switching the watch on while pressing ledt and right buttons

The upgrade is normaly taken care of by the Geonaute Software, by recording a firmware upgrade session, I was able to write a small program to upload a firmware into the watch from outside the Geonaute Software. The watch is detected by the pc as a virtual COM port. The firmware upgrade protocol is the following :

Baudrate : 19200; WordLength=8; StopBits=1; Parity=No parity

Sending 0x11 0x02 0x00 0x00 0x00 0x02 initialize the memory erasing, when it is finished, the watch sends back 0x88

initialize the memory erasing, when it is finished, the watch sends back Uploading of the firmware (of exactly 500k) by packets of 1k (0x400 bytes)

Preamble of each "packet" : 0x11 0x02 0x04 nn mm ( nn mm packet number, nn=LSB )

( packet number, ) At the end of each packet, 1 checksum byte = XOR of each byte appart from the first one ( 0x11 )

) After each packet, the watch sends back 0x88

The python program used to upload a firmware is available here

Direct download of original geonaute firmware :

The bootloader

The bootloader starts at address 0x08000000 and has a size of 12kB (0x3000 = 0x400*12 bytes)

The firmware starts at address 0x08003000 and has a size of 500kB.

In order to study the bootloader code, I extracted it from a watch with the help of a buspirate and the pirate-swd program which implements the Serial Wire Debug protocol.

The disassembly of the bootloader allowed to work out the software method to put the watch in its "firmware upgrade mode" : restart it with the value "fu" stored in the BKP_DR10 register.

Piece of the bootloader which checks if it should jump to "firmware upgrade mode"

The binary file of the bootloader (including the begining of the firmware) is available here.

The LCD screen

LCD of the GPS watch

Driving the LCD was probably the most tricky part of this project, even after quite a bit of time, I was unable to find any documentation about this particular display. It was impossible to find the correct commands (SPI communication) to drive it.

Features

Controled by SPI

100 lines x 128 columns

4 grayscales

The closest I found was ST7571 (datasheet ), but some of the ST7571 commands still don't work with this display. I was able to find the initialization sequence of the display in the disassembly of the original firmware. Looking for SPI communication parts in the disassembly, one can find this part :

Part of the firmware which initialize the LCD

The initialization sequence deduced from this code is E2 24 C2 A0 D2 EB 81 1E F1 63 F2 00 F3 63 AF .

One data byte data corresponds to 4 pixels, the bits of data being grouped by pairs to code the gray levelof the corresponding pixel. The leftmost pixel is coded in the LSB pair of bits anf the rightmost in the MSB pair.

The PCB

Here is the PCB of a "W Kalenji 300 gps" annotated with various peripherals

PCB of a Kalenji 300 GPS (click to enlarge)

Composants :

Processor : STM32F103RET6

Memory : MX25L1006

GPS : GSC3f (datasheet)

Power circuit : AAT7601, clone LCT3455 (datasheet)

LCD : similar to ST7571 (datasheet )

Custom firmware

Time displayed by the custom firmware

The main objective of all this was to make this GPS watch programmable, and write a custom firmware. It is currently only a very basic program which shows how to control the main functions of the watch (buttons, GPS, LCD). There are still a large amount of work needed to make it truely usable with a custom firmware but I think that the current state is a good starting point.

In order to print text on screen, I used the excellent u8glib library which includes many fonts and code to render them. For now it is only used to display some text but it can do much more.

The firmware source code can be downloaded here

Demonstration video

Showing the custom firmware upgrade process.