Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Feature request: multi-valset #20

Closed
nseidle opened this issue Jun 21, 2019 · 5 comments
Closed

Feature request: multi-valset #20

nseidle opened this issue Jun 21, 2019 · 5 comments

Comments

@nseidle
Copy link
Member

nseidle commented Jun 21, 2019

From other issue:

Hi Nathan ( @nseidle ),
Sincere thanks for sharing this library! I'm using it to talk to the ZED-F9P.
Can I please raise a "feature request"?
setVal() is great - but can only set one value at a time. Could you add an elegant way to set multiple keys in a single packet?
My inelegant way is to define them as a ubxPacket and send them using .sendI2cCommand :

// setRAWXon: this is the message which enables all of the messages to be logged to SD card in one go
// It also sets the NMEA high precision mode for the GNGGA message
// It also sets the main talker ID to 'GN'
// UBX-CFG-VALSET message with key IDs of:
// 0x209102a5 (CFG-MSGOUT-UBX_RXM_RAWX_UART1)
// 0x20910232 (CFG-MSGOUT-UBX_RXM_SFRBX_UART1)
// 0x20910179 (CFG-MSGOUT-UBX_TIM_TM2_UART1)
// 0x2091002a (CFG-MSGOUT-UBX_NAV_POSLLH_UART1)
// 0x20910007 (CFG-MSGOUT-UBX_NAV_PVT_UART1)
// 0x2091001b (CFG-MSGOUT-UBX_NAV_STATUS_UART1)
// 0x10930006 (CFG-NMEA-HIGHPREC)
// 0x209100bb (CFG-MSGOUT-NMEA_ID_GGA_UART1)
// and values (rates) of 1
// 0x20930031 (CFG-NMEA-MAINTALKERID) has value 3 (GN)
static uint8_t setRAWXon_payload[] = {
0x00, 0x01, 0x00, 0x00,
0xa5, 0x02, 0x91, 0x20, 0x01,
0x32, 0x02, 0x91, 0x20, 0x01,
0x79, 0x01, 0x91, 0x20, 0x01,
0x2a, 0x00, 0x91, 0x20, 0x00, // Change the last byte from 0x01 to 0x00 to leave NAV_POSLLH disabled
0x07, 0x00, 0x91, 0x20, 0x01, // Change the last byte from 0x01 to 0x00 to leave NAV_PVT disabled
0x1b, 0x00, 0x91, 0x20, 0x01, // This line enables the NAV_STATUS message
0x31, 0x00, 0x93, 0x20, 0x03, // This line sets the main talker ID to GN
0x06, 0x00, 0x93, 0x10, 0x01, // This sets the NMEA high precision mode
0xbb, 0x00, 0x91, 0x20, 0x01 }; // This (re)enables the GGA mesage
ubxPacket setRAWXon = { 0x06, 0x8a, 49, 0, 0, setRAWXon_payload, 0, 0, false };

Sincere thanks,
Paul

@PaulZC
Copy link
Collaborator

PaulZC commented Jun 22, 2019

Hi Nathan,
Many thanks for opening this issue.
Let me know if you'd like me to run any tests on the new code. Very happy to be a beta tester.
The GPS-RTK2 board is awesome.
Thanks again,
Paul

@nseidle
Copy link
Member Author

nseidle commented Jun 25, 2019

Hi Paul - This is a good feature to have. Do you think it would be best implemented with a new setVal that takes in a pointer to a val array and a length? I'm thinking something like:

uint8_t SFE_UBLOX_GPS::setVal(uint32_t key, uint8_t value[], uint8_t valueLen, uint8_t layer, uint16_t maxWait)

Do you think users will need to pass more than 256 elements?

I'm not sure I have a good use case so if you have a real-world scenario that can be shown in an example, that would be helpful.

@PaulZC
Copy link
Collaborator

PaulZC commented Jun 26, 2019

My real-world example is a little outdated now (I'll explain below) but here goes:

I need to log a continuous stream of RAWX, SFRBX and TIM_TM2 messages to SD card so I can post-process them (PPK) using RTKLIB.
If I'm only using UART and if I enable the messages one by one, I need to catch and ignore the UBX_ACK_ACK replies individually so they don't end up being logged. This gets messy if the first RAWX message arrives before I've received the ACK from the TIM_TM2...
The new F9 VALSET message means I can enable all three messages in one go, using a single message, and I only have one ACK to ignore which I can guarantee will arrive before the first RAWX message.
So, I'd very much like an elegant multi-setVal command to do just that.

The reason the above is outdated is that I've figured out that I can do the message enabling through the I2C port instead, leaving the UART port ACK-free! So, strictly, it doesn't matter if the messages are enabled one at a time. The ACKs come back via I2C and I don't need to worry about them.

You can find a UART-only example here plus here. It uses my own sendUBX routine.

The equivalent I2C example is here and here. This uses your sendCommand function.

VALSET can only support a maximum of 64 Key+value pairs:

image

Hopefully that's makes it (slightly) easier?

Perhaps the most elegant way would be to define an array of key and value pairs where each pair is defined as a struct of the 32-bit key plus 8, 16, or 32 bit values? Maybe with a union thrown in for good measure?

(But I have run into problems before when including 8-bit values in structs and unions. You end up with word alignment problems that can crash the M0 and you need to define everything as _ _ attribute _ _ ((packed)) !)

Thanks!
Paul

@nseidle
Copy link
Member Author

nseidle commented Jun 27, 2019

That makes sense. I suspect there will be plenty of users who will need to send a handful of configuration commands at startup. Better to pass a bulk of them than to do one at a time.

VALSET can only support a maximum of 64 Key+value pairs

For my own notes: each key is 4 bytes, and each config value can be 1 to 8 bytes. That's 12*64=768 bytes worst case.

I'm all for a struct with various byte sizes 1/2/4/8. Please have at it and let me know what you think is best.

@PaulZC
Copy link
Collaborator

PaulZC commented Jul 1, 2019

So... Like Issue #21 , I tried to do this with an overloaded function that would accept keyIDs plus 8, 16 or 32 bit values but ran into the same ambiguity problems.

Instead I have defined 8, 16 and 32 bit versions of three new functions: newCfgValset, addCfgValset and sendCfgValset.

You begin with a newCfgValset which initialises packetCfg with the class and ID etc and adds the first keyID and value to the payload. You can then add additional keyIDs with 8, 16 or 32 bit values using addCfgValset. Finally, you add one last keyID plus value using sendCfgValset and the 'multiValSet' packet is sent.

If you only want to set one value, use setVal8, setVal16 or setVal32 (Issue #21 ).
If you want to set two values, use newCfgValset followed by sendCfgValset.
For more values, use newCfgValset followed by (multiple) addCfgValset followed by sendCfgValset.

Usage example:

bool setValueSuccess = true;

//Begin with newCfgValset8/16/32
setValueSuccess &= myGPS.newCfgValset8(0x209102bd, 1); //Set output rate of msg 1005 over the I2C port to once per measurement (value is 8-bit (U1))
//Add extra keyIDs and values using addCfgValset8/16/32
setValueSuccess &= myGPS.addCfgValset8(0x209102cc, 1); //Set output rate of msg 1077 over the I2C port to once per measurement (value is 8-bit (U1))
setValueSuccess &= myGPS.addCfgValset8(0x209102d1, 1); //Set output rate of msg 1087 over the I2C port to once per measurement (value is 8-bit (U1))
setValueSuccess &= myGPS.addCfgValset8(0x209102d6, 1); //Set output rate of msg 1127 over the I2C port to once per measurement (value is 8-bit (U1))
setValueSuccess &= myGPS.addCfgValset8(0x20910318, 1); //Set output rate of msg 1097 over the I2C port to once per measurement (value is 8-bit (U1))
// Add the final value and send the packet using sendCfgValset8/16/32
setValueSuccess &= myGPS.sendCfgValset8(0x20910303, 10); //Set output rate of msg 1230 over the I2C port to once every 10 measurements (value is 8-bit (U1))

See PR #30 for the new code.

Thanks!
Paul

nseidle added a commit that referenced this issue Aug 7, 2019
#23)

Updated setVal, added 'multi' setVal and an Example (supersedes #28)
@nseidle nseidle closed this as completed Aug 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants