When updating the firmware while the OSTC is running in normal mode, the
V2 protocol should be used. However, the OSTC can also be rebooted from
the menu or reset using the magnetic switch, and then the V1 protocol
should be used. The only difference with the V2 protocol is the slower
baudrate (19200 vs 115200).
True autodetection of the protocol variant is difficult, because the
bootloader will abort the firmware update when not receiving a 0xC1
byte. But we can still take advantage of the fact that the normal
firmware does ignore any 0xC1 bytes sent at the wrong baudrate, and
probe with the V1 protocol first. If the bootloader is already running,
it will respond immediately and we're done. If the normal firmware is
still running, it won't respond and the probing with the V1 protocol
will fail. If we then switch to the V2 protocol, the firmware update
will continue as before.
The result is a firmware updater which supports both bootloader
protocols without requiring any manual configuration.
Currently, each backend has it's own function to verify whether the
object vtable pointer is the expected one. All these functions can be
removed in favor of a single isintance function in the base class,
which takes the expected vtable pointer as a parameter.
Functions which are called through the vtable, don't need to verify the
vtable pointer, and those checks are removed.
The term "backend" can be confusing because it can refer to both the
virtual function table and the device/parser backends. The use of the
term "vtable" avoids this.
The version function requires device specific knowledge to use it (at
least the required buffer size), it is already called internally when
necessary, and only a few backends support it. Thus there is no good
reason to keep it in the high-level public api.
The exact OSTC variant can be detected by means of the serial number.
Each of the three variants is now assigned an artifical model number,
and included explicitly in the list of supported models.
I forgot to update the device and parser initialization functions to
store the context pointer into the objects. As a result, the internal
context pointers were always NULL.
The public api is changed to require a context object for all
operations. Because other library objects store the context pointer
internally, only the constructor functions need an explicit context
object as a parameter.
Adding the "dc_" namespace prefix (which is of course an abbreviation
for libdivecomputer) should avoid conflicts with other libraries. For
the time being, only the high-level device and parser layers are
changed.
The public header files are moved to a new subdirectory, to separate
the definition of the public interface from the actual implementation.
Using an identical directory layout as the final installation has the
advantage that the example code can be build outside the project tree
without any modifications to the #include statements.
Sometimes there are a few garbages bytes received before the preamble
bytes. This typically happens when trying to download again after a
failed attempt. However trying to flush them immediately after opening
the serial port doesn't work.
When the OSTC receives the download dives command, it responds
immediately with the preamble bytes. But then it does a linear search
through its internal memory to locate the end-of-profile marker. As a
result the response time increases when the marker is located near the
end of the memory area. In the worst case scenario, the response time
can exceed the 3 second read timeout with a few milliseconds.
Since the required timeout depends on the total amount of profile
memory, this problem was indirectly introduced with firmware v1.91,
which doubled the amount of profile memory from 32K to 64K.