The Teseo-LIV3 GPS module (as used in shabaz ' GPS / Galileo / BeiDou / GLONASS receiver) talks UART and I2C. I'm writing an OO driver for it, for embedded systems. In this blog, I configure the Teseo IC at runtime. And write some code guards (asserts) to validate that a (your?) project uses the library in the right way.
Initialisation
In the previous post, you had to pre-configure the Teseo-LIV3. This is advised in ST's application note for I2C communication. And if you're building a commercial device, that's the best option. A side effect is that it changes the out-of-box behaviour of the GPS. Not permanently, because it can be reverted.
I could do this configuration programmatically, at first run. But when you are designing, or when you want top try out my library, it may be unfunny when your GPS behaves differently, and you didn't expect that. A solution is to do the configuration for the current session only, at each startup. That's what I'm developing now.
Pre-configuring the IC
The ST application note proposes this one-time configuration (text copied from the previous post):
$PSTMCFGMSGL,3,1,0,0
$PSTMSETPAR,1227,1,2
$PSTMSAVEPAR
(from the appnote:) This set of commands will:
- Reset the i2c message list
- Disable the eco-ing message
- Save the configuration on flash
This will put the GPS in the right state for us at power on. If you don't mind reconfiguring the GPS (it's reversable), use this approach.
Run-time configuration
If you prefer to keep the device in its original configuration, you can use my init() functionality. Here's what it does:
- reset the IC
- stop the GPS engine
- do the same configuration as in the pre-configure scenario, but don't save the settings to persistent storage
- restart the GPS engine
Advantage:
- once you reset or power cycle the GPS, it's back to its original state
Disadvantage:
- it adds 4 seconds and a some ms to the startup time.
- an additional GPIO pin is needed to control the GPS reset.
To make dynamic configuration work reliable and repeatable, the IC needs to be reset. The i2C interface is available 4 seconds later. I made this configurable. I get reliable communication when waiting4 seconds before doing business. If the IC is preconfigured, there's no wait needed and we can get to business right away.
Init functionality
Again: no need to execute this if you pre-config the device. In that case, the project should not call init().
void teseo::init() { std::string s; resetter.call(); // stop the engine write("$PSTMGPSSUSPEND\n\r"); // reset the i2c message list write("$PSTMCFGMSGL,3,1,0,0\n\r"); // disable the eco-ing message write("$PSTMSETPAR,1227,1,2\n\r"); write("$PSTMGPSRESTART\n\r"); do { read(s); } while((s.find("$PSTMGPSRESTART") == std::string::npos)); // command successful }
The code follows the sequence described above. You can see that it requires a new callback: the resetter(). It's a simple function you'll have to provide that bumps the reset pin and waits as appropriately. I want to keep the library independent of the microcontroller that you use. So you 'll have to provide the reset function.
Here's my Pico implementation:
#define RESET_PIN (18) #define RESET_APPLY_MS (10) // recover must be more than 3 seconds #define RESET_RECOVER_MS (4000) // ... void init () { // ... gpio_init(RESET_PIN); gpio_put(RESET_PIN, 1); gpio_set_dir(RESET_PIN, GPIO_OUT); } void reset() { gpio_put(RESET_PIN, 0); sleep_ms(RESET_APPLY_MS); gpio_put(RESET_PIN, 1); sleep_ms(RESET_RECOVER_MS); return; } int main() { init(); // ... gps.getResetCallback().set([]() -> void { reset(); }); // ...
Hardware changes
- Connect Teseo RST Pico GP18.
Assist the developer with asserts
I'm trying to help users, by checking pre-conditions. Without increasing the final product's code size.
The library expects that you have your chickens in a row before you use the library. If I have to check that each time at runtime, it's going to increase the footprint of your production firmware.
That's why I use a debug-only function: asserts. Asserts are functions that will validate if something is true. At debug only. Once you build a release version of the firmware, these checks vaporise. They are ideal to catch if your code performs an action, when the object isn't properly set up. Or if you use parameters that are invalid.
I use them here to check, that you don't use functionality that needs a callback, before you registered the callback.
write:
#include <cassert> void teseo::write(const std::string& s) { assert(writer.armed()); writer.call(s); }
read:
void teseo::read(std::string& s) { assert(reader.armed()); reader.call(s); }
init:
void teseo::init() { assert(writer.armed()); assert(reader.armed()); assert(resetter.armed()); // ...
I had to adapt my callback code to support this. I could have just put the assert inside that class. But not having a callback may be a valid scenario.
That's why I added a checker method, and made it available for users. I think it may be useful in a program.
The price is low. It's an inline function. It 'll just resolve to the cheap C construct (poiner != null).
Why assertions? There is a hierarchy in the hurt caused by a bug:
Asserts fit in category 2. They add code to your project in the debug configuration. When you test the firmware, it can do additional (sometimes expensive) validations. And show where something invalid happens. As long as you test your code (you test it, don't you?) it 'll find logical errors that can't be found during compilation. The release build of your project will not include these checks. So they don't add to the firmware resource reqs. It doesn't make sense to add them to the release version, because your code doesn't know to handle them anyways. That's why you want to catch them at test. comments welcome |
Anything else?
Yes. This second post also brings joy to early adopters. To make this early project easier to grasp, I print the GPS reply to UART every time it's read. I use the Pico SDK stdio functions. So you can route it to a picoprobe or to the Pico's USB.
Enjoy. Project is attached. With uf2 firmware for drag&drop.
pico_gps_teseo_i2c_20240713_03.zip
next post: C++ library for ST Teseo GPS - pt. 3: Pico and UART support
visit the github repository (git clone https://github.com/jancumps/pico_gps_teseo.git --recursive)
view the online documentation
Link to all posts.
Top Comments