- Posts: 3333
DSM Telemetry support
- vlad_vy
- Offline
Data type = 0x16 GPS Sensor (always second GPS packet)
0[00] 22(0x16)
1[01] 00
2[02] Altitude LSB (Decimal) //In 0.1m
3[03] Altitude MSB (Decimal) //Altitude = Altitude(0x17) * 10000 + Value (in 0.1m)
4[04] 1/10000 degree minutes latitude (Decimal) (DD MM.MMMM)
5[05] 1/100 degree minutes latitude (Decimal)
6[06] degree minutes latitude (Decimal)
7[07] degrees latitude (Decimal)
8[08] 1/10000 degree minutes longitude (Decimal) (DD MM.MMMM)
9[09] 1/100 degree minutes longitude (Decimal)
10[0A] degree minutes longitude (Decimal)
11[0B] degrees longitude (Decimal)
12[0C] Heading LSB (Decimal)
13[0D] Heading MSB (Decimal) Divide by 10 for Degrees
14[0E] Unknown (Decimal)
15[0F] First bit for latitude: 1=N(+), 0=S(-);
Second bit for longitude: 1=E(+), 0=W(-);
Third bit for longitude over 99 degrees: 1=+-100 degrees
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
It looks like wrong pointer in pkt32_to_coord(u16 *ptr). Is it possible?
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
3600000 (should have another zero)
36000000 = 60 x 60 x 1000 (edit: wrong)
edit: Ok, I made a mistake adding another zero. Anyway, lets see what number do you get now?
I have uploaded a new test build c3692a0
I have also added some checks to cyrf3936.c
Replacing:
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
//Set the post tx/rx state
CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x2C : 0x28);
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
// Wait for TXGO to self clear indicating transmit has completed.
while (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) { }
if ((mode != RX_EN) != (!(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80))) {
// if not RX_EN and still in receive mode
// OR providing TXGO and RXGO are not set, set end state.
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28); // force into Synth(TX) state.
}
The preceding while loop is not really required, that situation seems to only occur briefly after powering on tx. However, it does ensure that both TXGO and RXGO are not set, before forcing a mode change.
After forcing mode change, waiting for force to complete is not required.
Below is my original testing code:
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
unsigned i = 0;
// Wait for TXGO to self clear indicating transmit has completed.
while (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) { ++i; }
if (i) {
// this occurs briefly at startup (after POWER ON)
MUSIC_Play(MUSIC_DONE_BINDING);
i = 0;
}
if ((mode != RX_EN) != (!(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80))) {
// if not RX_EN and still in receive mode
// OR providing TXGO and RXGO are not set, set end state.
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28); // force into Synth(TX) state.
// Wait for the FRC_END_STATE bit in XACT_CFG register to clear indicating force has completed.
while ((CYRF_ReadRegister(CYRF_0F_XACT_CFG) & 0x20) && ++i < NUM_WAIT_LOOPS) { }
if (i >= NUM_WAIT_LOOPS) // If force does not complete within 100us,
MUSIC_Play(MUSIC_ALARM1); // we should probably reset, but for now just sound an alarm.
else if (i)
MUSIC_Play(MUSIC_TIMER_WARNING); // This won't sound if force completes immediately.
}
#if HAS_MULTIMOD_SUPPORT
...
void CYRF_StartReceive()
{
u8 reg = CYRF_ReadRegister(CYRF_05_RX_CTRL);
if (!(reg & 0x80)) {
// The RXGO bit must not be set until after it self clears.
CYRF_WriteRegister(CYRF_05_RX_CTRL, reg | 0x80); // Prepare to receive
CYRF_ReadRegister(CYRF_13_RSSI); // Clear RSSI
}
else // This happens before binding completes
MUSIC_Play(MUSIC_KEY_PRESSING);
}
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
if ( !(CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) && !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) {
// TXGO and RXGO are not set, set end state.
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28); //force into Synth(TX) end state
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x08); //set Synth(TX) as end state
}
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
What happens is it stays in receive mode waiting for receive to complete.
When required mode is not RX_EN, (eg. TX_EN) then we must force receive mode to end.
The while loop only executes breifly at startup. At other times it is always false (never loops).
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Please Log in or Create an account to join the conversation.
- PhracturedBlue
- Topic Author
- Offline
- Posts: 4402
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
//Set the post tx/rx state
if((mode == TX_EN) && !(CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
if((mode == RX_EN) && !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80) && !(CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
void CYRF_EndReceiveMode()
{
if (CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80) // If RXGO (receiving)
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28); // force into Synth(TX) state.
}
This seems to work, so no forcing is needed in:
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x08); // Set end state to Synth(TX).
New version 05041f3 uploaded to Test Builds.
Source
Latitude and Longitude ???? I don't know.
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Probably will be better combine buffer clean-up and reading into telemetry buffer at CYRF_RxPacketIsGood(length, *ptr) and force end state at the end of CYRF_RxPacketIsGood(length, *ptr).
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
Currently the Devo protocol calls CYRF_RxPacketIsGood() every 200us until receive is complete, so we can't combine with CYRF_EndReceiveMode(), unless we change Devo protocol to check only once, ie. as late as possible but allowing enough time for ParseTelemetryPacket() to complete.
So I'll keep CYRF_EndReceiveMode() and move the buffer clean-up to it; to end receive mode properly:
The recommended method to exit receive mode when an error has occurred is to force END STATE and then dummy read all RX_COUNT_ADR bytes from RX_BUFFER_ADR
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
void CYRF_SetTxRxMode(enum TXRX_State mode)
{
//Set the post tx/rx state
if((mode == TX_EN) && !(CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
#if HAS_MULTIMOD_SUPPORT
devo_cyrf6936
txState++;
if(txState == 16) { //2.3msec have passed
if (CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80) { //We're still in receive mode
//Disrupt any pending receive by enabling abort
//Force End State should not be used to abort a receive if a SOP has already happened
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20);
//Buffer clean-up
CYRF_RxPacketIsGood(0x00);
//Abort by writing the FRC_END_STATE bit in the XACT_CFG register
CYRF_SetTxRxMode(TX_EN); //Write mode
//Disable abort
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00);
}
else CYRF_SetTxRxMode(TX_EN); //Write mode
dsm2_cyrf6936
} else if(state == DSM2_CH2_READ_A || state == DSM2_CH2_READ_B) {
//Read telemetry if needed and parse if good
if (CYRF_RxPacketIsGood(0x10)) {
CYRF_ReadDataPacket(packet);
parse_telemetry_packet();
}
if (state == DSM2_CH2_READ_A && num_channels < 8) {
state = DSM2_CH2_READ_B;
CYRF_StartReceive(); //Prepare to receive
return 11000;
}
if (state == DSM2_CH2_READ_A)
state = DSM2_CH1_WRITE_B;
else
state = DSM2_CH1_WRITE_A;
if (CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80) { //We're still in receive mode
//Disrupt any pending receive by enabling abort
//Force End State should not be used to abort a receive if a SOP has already happened
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20);
//Buffer clean-up
CYRF_RxPacketIsGood(0x00);
//Abort by writing the FRC_END_STATE bit in the XACT_CFG register
CYRF_SetTxRxMode(TX_EN); //Write mode
//Disable abort
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00);
}
else CYRF_SetTxRxMode(TX_EN); //Write mode
set_sop_data_crc();
return READ_DELAY;
}
return 0;
}
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
If you find RX_ABORT is needed then your abort procedure should be added to CYRF_EndReceive().
IMHO. I think RX_ABORT is used for interrupting receive while a continuous data stream is being received.
In our case receive is just waiting for the rest of the expected data, so there is nothing really to interrupt.
I'm trying to keep code small, so I'll only include if really required. I've currently got DSM module size down to 3,908 bytes.
I've uploaded a new version bb10550 to Test Builds. This time Latitude and Longitude should work because I have pretty much restored original code (which I assume was working). Source code
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
}
txState = 0;
while(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80) {}
}
return delay;
}
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
Please try new version 55d20bd.
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Please Log in or Create an account to join the conversation.
- Indigo
- Offline
- Posts: 230
Is Devo telemetry working?
Please Log in or Create an account to join the conversation.
- vlad_vy
- Offline
- Posts: 3333
Please Log in or Create an account to join the conversation.
- Home
- Forum
- Development
- Protocol Development
- DSM Telemetry support