From 3a7e62b8edddcba911569cb16830bd3b618cba23 Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Sun, 14 Feb 2021 23:16:37 +0100 Subject: [PATCH 1/6] V1.06 02/14/2021 enhance interface / implementation for priorized sensor send capabilities --- README.adoc | 3 +++ src/JetiExProtocol.cpp | 27 ++++++++++++++++++--------- src/JetiExProtocol.h | 18 ++++++++++++++---- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/README.adoc b/README.adoc index 6fe603a..516b203 100644 --- a/README.adoc +++ b/README.adoc @@ -43,6 +43,9 @@ Serial interface to transmit telemetry data to Jeti Duplex receivers. For Arduin in order to improve behaviour on telemetry reset 1.04 07/18/2017 dynamic sensor de-/activation 1.05 11/12/2017 send 3 textframes before start of EX transmission to get transmitter ready + 1.06 02/14/2021 enhance interface / implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) + to avoid deffered transmission of high prio data (vario). + == License == diff --git a/src/JetiExProtocol.cpp b/src/JetiExProtocol.cpp index 4e08d58..419ff6d 100644 --- a/src/JetiExProtocol.cpp +++ b/src/JetiExProtocol.cpp @@ -35,6 +35,8 @@ in order to improve behaviour on telemetry reset 1.04 07/18/2017 dynamic sensor de-/activation 1.05 11/12/2017 send 3 textframes before start of EX transmission to get transmitter ready + 1.06 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) + to avoid deffered transmission of high prio data (vario). Todo: - better check for ex buffer overruns @@ -67,7 +69,7 @@ // JetiSensor work data /////////////////////// JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) - : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) + : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_prio(1), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) { // sensor state m_bActive = (pProtocol->m_activeSensors[arrIdx >> 3] & (1 << (arrIdx & 7))) ? true : false; @@ -83,6 +85,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) // value m_value = pProtocol->m_pValues[ arrIdx ].m_value; + m_prio = pProtocol->m_pValues[ arrIdx ].m_prio; // copy to combined sensor/value buffer copyLabel( (const uint8_t*)constData.text, (const uint8_t*)constData.unit, m_label, sizeof( m_label ), &m_textLen, &m_unitLen ); @@ -205,13 +208,19 @@ uint8_t JetiExProtocol::DoJetiSend() return 0; } -void JetiExProtocol::SetSensorValue( uint8_t id, int32_t value ) +/** + * @id: id of the sensor + * @value: value of the sensor to be transferred + * @prio: transmission prioity: 1=send with every frame, 2=send with every second frame, .... + */ +void JetiExProtocol::SetSensorValue( uint8_t id, int32_t value , uint8_t prio) { if( m_pValues && id < sizeof( m_sensorMapper ) ) m_pValues[ m_sensorMapper[ id ] ].m_value = value; + m_pValues[ m_sensorMapper[ id ] ].m_prio = prio; } -void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value ) +void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value, uint8_t prio ) { // Jeti doc: If the lowest bit of a decimal point (Bit 5) equals log. 1, the data represents longitude. According to the highest bit (30) of a decimal point it is either West (1) or East (0). // Jeti doc: If the lowest bit of a decimal point (Bit 5) equals log. 0, the data represents latitude. According to the highest bit (30) of a decimal point it is either South (1) or North (0). @@ -236,10 +245,10 @@ void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value gps.vBytes[3] |= bLongitude ? 0x20 : 0; gps.vBytes[3] |= (value < 0) ? 0x40 : 0; - SetSensorValue( id, gps.vInt ); + SetSensorValue( id, gps.vInt, prio ); } -void JetiExProtocol::SetSensorValueDate( uint8_t id, uint8_t day, uint8_t month, uint16_t year ) +void JetiExProtocol::SetSensorValueDate( uint8_t id, uint8_t day, uint8_t month, uint16_t year, uint8_t prio ) { // Jeti doc: If the lowest bit of a decimal point equals log. 1, the data represents date // Jeti doc: (decimal representation: b0-7 day, b8-15 month, b16-20 year - 2 decimals, number 2000 to be added). @@ -259,10 +268,10 @@ void JetiExProtocol::SetSensorValueDate( uint8_t id, uint8_t day, uint8_t month, date.vBytes[2] = day & 0x1F; date.vBytes[2] |= 0x20; - SetSensorValue( id, date.vInt ); + SetSensorValue( id, date.vInt, prio ); } -void JetiExProtocol::SetSensorValueTime( uint8_t id, uint8_t hour, uint8_t minute, uint8_t second ) +void JetiExProtocol::SetSensorValueTime( uint8_t id, uint8_t hour, uint8_t minute, uint8_t second, uint8_t prio ) { // If the lowest bit of a decimal point equals log. 0, the data represents time // (decimal representation: b0-7 seconds, b8-15 minutes, b16-20 hours). @@ -277,7 +286,7 @@ void JetiExProtocol::SetSensorValueTime( uint8_t id, uint8_t hour, uint8_t minut date.vBytes[1] = minute; date.vBytes[2] = hour & 0x1F; - SetSensorValue( id, date.vInt ); + SetSensorValue( id, date.vInt, prio ); } void JetiExProtocol::SetSensorActive( uint8_t id, bool bEnable, JETISENSOR_CONST * pSensorArray ) @@ -436,7 +445,7 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) if( ++m_sensorIdx >= m_nSensors ) // wrap index when array is at the end m_sensorIdx = 0; - if( sensor.m_bActive && sensor.m_value != -1 ) // -1 is "invalid" + if( sensor.m_bActive && sensor.m_value != -1 && (frameCnt % sensor.m_prio) == 0) // -1 is "invalid" { if( sensor.m_id > 15 ) { diff --git a/src/JetiExProtocol.h b/src/JetiExProtocol.h index f5e198b..f0e29f4 100644 --- a/src/JetiExProtocol.h +++ b/src/JetiExProtocol.h @@ -24,6 +24,8 @@ - JETI_DEBUG and BLOCKING_MODE removed (cleanup) 1.02 03/28/2017 New sensor memory management. Sensor data can be located in PROGMEM 1.04 07/18/2017 dynamic sensor de-/activation + 1.05 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) + to avoid deffered transmission of high prio data (vario). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -85,6 +87,10 @@ class JetiValue protected: // value int32_t m_value; + + // send priority / incidence + uint8_t m_prio; + }; // complete data for a sensor to fill ex frame buffer @@ -116,6 +122,10 @@ class JetiSensor // value uint8_t m_bActive; + // send priority / incidence + uint8_t m_prio; + + // label/description of value uint8_t m_label[ 20 ]; uint8_t m_textLen; @@ -166,10 +176,10 @@ class JetiExProtocol uint8_t DoJetiSend(); // call periodically in loop() void SetDeviceId( uint8_t idLo, uint8_t idHi ) { m_devIdLow = idLo; m_devIdHi = idHi; } // adapt it, when you have multiple sensor devices connected to your REX - void SetSensorValue( uint8_t id, int32_t value ); - void SetSensorValueGPS( uint8_t id, bool bLongitude, float value ); - void SetSensorValueDate( uint8_t id, uint8_t day, uint8_t month, uint16_t year ); - void SetSensorValueTime( uint8_t id, uint8_t hour, uint8_t minute, uint8_t second ); + void SetSensorValue( uint8_t id, int32_t value, uint8_t prio=1 ); + void SetSensorValueGPS( uint8_t id, bool bLongitude, float value, uint8_t prio=1 ); + void SetSensorValueDate( uint8_t id, uint8_t day, uint8_t month, uint16_t year , uint8_t prio=1 ); + void SetSensorValueTime( uint8_t id, uint8_t hour, uint8_t minute, uint8_t second , uint8_t prio=1 ); void SetSensorActive( uint8_t id, bool bEnable, JETISENSOR_CONST * pSensorArray ); void SetJetiboxText( enLineNo lineNo, const char* text ); void SetJetiboxExit() { m_bExitNav = true; }; From 82dbbacee8bbd481d1bfb618584a773b7f2e4010 Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Thu, 18 Feb 2021 23:28:39 +0100 Subject: [PATCH 2/6] V1.07: fixed priorized sensor implementation and added interface to speed up frame send cycle --- src/JetiExProtocol.cpp | 68 ++++++++++++++++++++++++++++-------------- src/JetiExProtocol.h | 8 +++-- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/JetiExProtocol.cpp b/src/JetiExProtocol.cpp index 419ff6d..1cab6a7 100644 --- a/src/JetiExProtocol.cpp +++ b/src/JetiExProtocol.cpp @@ -37,6 +37,8 @@ 1.05 11/12/2017 send 3 textframes before start of EX transmission to get transmitter ready 1.06 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). + 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle + SetJetiSendCycle(aTime); Todo: - better check for ex buffer overruns @@ -69,7 +71,7 @@ // JetiSensor work data /////////////////////// JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) - : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_prio(1), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) + : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) { // sensor state m_bActive = (pProtocol->m_activeSensors[arrIdx >> 3] & (1 << (arrIdx & 7))) ? true : false; @@ -85,7 +87,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) // value m_value = pProtocol->m_pValues[ arrIdx ].m_value; - m_prio = pProtocol->m_pValues[ arrIdx ].m_prio; + mp_prio = &pProtocol->m_pValues[ arrIdx ].m_prio; // copy to combined sensor/value buffer copyLabel( (const uint8_t*)constData.text, (const uint8_t*)constData.unit, m_label, sizeof( m_label ), &m_textLen, &m_unitLen ); @@ -114,7 +116,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) JetiExProtocol::JetiExProtocol() : m_tiLastSend( 0 ), m_frameCnt( 0 ), m_nameLen( 0 ), m_pSensorsConst( 0 ), m_pValues( 0 ), m_nSensors( 0 ), m_sensorIdx( 0 ), m_dictIdx( 0 ), m_pSerial( 0 ), m_alarmChar( 0 ), m_bExitNav( 0 ), - m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ) + m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ), m_ExFrameSendCycle ( 150 ) { m_name[0] = '\0'; memset( m_activeSensors, 255, sizeof(m_activeSensors) ); // default: all sensors active @@ -176,10 +178,15 @@ uint8_t JetiExProtocol::GetJetiboxKey() return m_pSerial->Getchar(); } +/// set the send cycle to the given value in ms (min = 75) +void JetiExProtocol::SetJetiSendCycle(uint8_t aTime) { + m_ExFrameSendCycle = max (75, aTime); +} + uint8_t JetiExProtocol::DoJetiSend() { // send every 150 ms only - if( ( m_tiLastSend + 150 ) <= millis() ) + if( ( m_tiLastSend + m_ExFrameSendCycle ) <= millis() ) { m_tiLastSend = millis(); @@ -217,7 +224,12 @@ void JetiExProtocol::SetSensorValue( uint8_t id, int32_t value , uint8_t prio) { if( m_pValues && id < sizeof( m_sensorMapper ) ) m_pValues[ m_sensorMapper[ id ] ].m_value = value; - m_pValues[ m_sensorMapper[ id ] ].m_prio = prio; + uint8_t p = min(15, max( 1, prio)); // normalize prio to 1-15 + + // m_prio first four bits = requested prio for sending the value each n.th frame + // m_prio last four bits = counter to check when the value shall be send + m_pValues[ m_sensorMapper[ id ] ].m_prio &= ~(0x0F); // clear the first four bits + m_pValues[ m_sensorMapper[ id ] ].m_prio |= p; // now set the given 4 prio bits } void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value, uint8_t prio ) @@ -405,7 +417,7 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) // sensor name in frame 0 if( frameCnt == 0 ) { // sensor name - m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text + m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text m_exBuffer[8] = 0x00; // 8Bit id m_exBuffer[9] = m_nameLen<<3; // 5Bit description, 3Bit unit length (use one space character) memcpy( m_exBuffer + 10, m_name, m_nameLen ); // copy label plus unit to ex buffer starting from pos 10 @@ -423,8 +435,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) if( sensor.m_bActive ) { m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text - m_exBuffer[8] = sensor.m_id; // 8Bit id - m_exBuffer[9] = (sensor.m_textLen<<3) | sensor.m_unitLen; // 5Bit description, 3Bit unit length + m_exBuffer[8] = sensor.m_id; // 8Bit id + m_exBuffer[9] = (sensor.m_textLen<<3) | sensor.m_unitLen; // 5Bit description, 3Bit unit length n = sensor.jetiCopyLabel( m_exBuffer, 10 ) + 10; // copy label plus unit to ex buffer starting from pos 10 break; } @@ -435,8 +447,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) { int bufLen; int nVal = 0; // count values - m_exBuffer[ 2 ] = 0x40; // 2Bit Type(0-3) 0x40=Data, 0x00=Text - n=8; // start at nineth byte in buffer + m_exBuffer[ 2 ] = 0x40; // 2Bit Type(0-3) 0x40=Data, 0x00=Text + n=8; // start at nineth byte in buffer do { @@ -445,16 +457,27 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) if( ++m_sensorIdx >= m_nSensors ) // wrap index when array is at the end m_sensorIdx = 0; - if( sensor.m_bActive && sensor.m_value != -1 && (frameCnt % sensor.m_prio) == 0) // -1 is "invalid" + + uint8_t prio = *sensor.mp_prio & 0x0F; // first four bits are prio (1-15) + uint8_t cnt = *sensor.mp_prio >> 4; // last four bits are the send counter (0-15) + if (cnt%prio == 0) { + cnt = 1; + } else { + cnt++; + } + *sensor.mp_prio &= ~(0xF0); // clear the last four bits + *sensor.mp_prio |= (cnt << 4) ; // now set the counter to the last four bits + + if( sensor.m_bActive && sensor.m_value != -1 && cnt == 1) // -1 is "invalid" { - if( sensor.m_id > 15 ) - { - m_exBuffer[n++] = 0x0 | (sensor.m_dataType & 0x0F); // sensor id > 15 --> put id to next byte - m_exBuffer[n++] = sensor.m_id; - } - else - m_exBuffer[n++] = (sensor.m_id<<4) | (sensor.m_dataType & 0x0F); // 4Bit id, 4 bit data type (i.e. int14_t) - + if( sensor.m_id > 15 ) + { + m_exBuffer[n++] = 0x0 | (sensor.m_dataType & 0x0F); // sensor id > 15 --> put id to next byte + m_exBuffer[n++] = sensor.m_id; + } + else + m_exBuffer[n++] = (sensor.m_id<<4) | (sensor.m_dataType & 0x0F); // 4Bit id, 4 bit data type (i.e. int14_t) + bufLen = sensor.m_bufLen; n += sensor.jetiEncodeValue( m_exBuffer, n ); } @@ -465,8 +488,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) } // complete some more EX frame data - m_exBuffer[0] = 0x7E; m_exBuffer[1] = 0x2F; // EX-Frame Separator - m_exBuffer[2] |= n-2; // frame length to Byte 2 + m_exBuffer[0] = 0x7E; m_exBuffer[1] = 0x2F; // EX-Frame Separator + m_exBuffer[2] |= n-2; // frame length to Byte 2 m_exBuffer[3] = MANUFACTURER_ID_LOW; m_exBuffer[4] = MANUFACTURER_ID_HI; // sensor ID m_exBuffer[5] = m_devIdLow; m_exBuffer[6] = m_devIdHi; m_exBuffer[7] = 0x00; // reserved (key for encryption) @@ -511,7 +534,7 @@ uint8_t JetiSensor::jetiEncodeValue( uint8_t * exbuf, uint8_t n ) exbuf[n] = ( m_value & 0x1F) | ((m_value < 0) ? 0x80 :0x00 ); // 5 bit value and sign exbuf[n] |= m_precision; // precision in bit 5/6 (0, 20, 40) return 1; - + case TYPE_14b: exbuf[n] = m_value & 0xFF; // lo byte exbuf[n + 1] = ( (m_value >> 8) & 0x1F) | ((m_value < 0) ? 0x80 :0x00 ); // 5 bit hi byte and sign @@ -588,3 +611,4 @@ uint8_t JetiExProtocol::jeti_crc8 (uint8_t *exbuf, unsigned char framelen) crc = update_crc (exbuf[c], crc); return (crc); } + diff --git a/src/JetiExProtocol.h b/src/JetiExProtocol.h index f0e29f4..13ef17a 100644 --- a/src/JetiExProtocol.h +++ b/src/JetiExProtocol.h @@ -26,6 +26,8 @@ 1.04 07/18/2017 dynamic sensor de-/activation 1.05 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). + 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle + SetJetiSendCycle(aTime); Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -82,7 +84,7 @@ class JetiValue friend class JetiExProtocol; public: - JetiValue() : m_value( -1 ) {} + JetiValue() : m_value( -1 ), m_prio( 0 ) {} protected: // value @@ -123,7 +125,7 @@ class JetiSensor uint8_t m_bActive; // send priority / incidence - uint8_t m_prio; + uint8_t* mp_prio; // label/description of value @@ -174,6 +176,7 @@ class JetiExProtocol void Start( const char * name, JETISENSOR_CONST * pSensorArray, enComPort comPort = DEFAULTPORT ); // call once in setup(), comPort: 0=Default, Teensy: 1..3 uint8_t DoJetiSend(); // call periodically in loop() + void SetJetiSendCycle(uint8_t aTime); void SetDeviceId( uint8_t idLo, uint8_t idHi ) { m_devIdLow = idLo; m_devIdHi = idHi; } // adapt it, when you have multiple sensor devices connected to your REX void SetSensorValue( uint8_t id, int32_t value, uint8_t prio=1 ); @@ -205,6 +208,7 @@ class JetiExProtocol // EX frame control unsigned long m_tiLastSend; // last send time uint8_t m_frameCnt; + uint8_t m_ExFrameSendCycle; // sensor name char m_name[ 20 ]; From d106c5f918f226287029fe01e3140cc36490bf0e Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Thu, 18 Feb 2021 23:28:39 +0100 Subject: [PATCH 3/6] V1.07: fixed priorized sensor implementation and added interface to speed up frame send cycle --- README.adoc | 1 + src/JetiExProtocol.cpp | 68 ++++++++++++++++++++++++++++-------------- src/JetiExProtocol.h | 8 +++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/README.adoc b/README.adoc index 516b203..f199b86 100644 --- a/README.adoc +++ b/README.adoc @@ -45,6 +45,7 @@ Serial interface to transmit telemetry data to Jeti Duplex receivers. For Arduin 1.05 11/12/2017 send 3 textframes before start of EX transmission to get transmitter ready 1.06 02/14/2021 enhance interface / implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). + 1.07 02/18/2021 fixed priorized sensor implementation and added interface to speed up frame send cycle (SetJetiSendCycle(aTime)) == License == diff --git a/src/JetiExProtocol.cpp b/src/JetiExProtocol.cpp index 419ff6d..1cab6a7 100644 --- a/src/JetiExProtocol.cpp +++ b/src/JetiExProtocol.cpp @@ -37,6 +37,8 @@ 1.05 11/12/2017 send 3 textframes before start of EX transmission to get transmitter ready 1.06 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). + 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle + SetJetiSendCycle(aTime); Todo: - better check for ex buffer overruns @@ -69,7 +71,7 @@ // JetiSensor work data /////////////////////// JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) - : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_prio(1), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) + : m_id( 0 ), m_value( -1 ), m_bActive( true ), m_textLen( 0 ), m_unitLen( 0 ), m_dataType( 0 ), m_precision( 0 ), m_bufLen( 0 ) { // sensor state m_bActive = (pProtocol->m_activeSensors[arrIdx >> 3] & (1 << (arrIdx & 7))) ? true : false; @@ -85,7 +87,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) // value m_value = pProtocol->m_pValues[ arrIdx ].m_value; - m_prio = pProtocol->m_pValues[ arrIdx ].m_prio; + mp_prio = &pProtocol->m_pValues[ arrIdx ].m_prio; // copy to combined sensor/value buffer copyLabel( (const uint8_t*)constData.text, (const uint8_t*)constData.unit, m_label, sizeof( m_label ), &m_textLen, &m_unitLen ); @@ -114,7 +116,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) JetiExProtocol::JetiExProtocol() : m_tiLastSend( 0 ), m_frameCnt( 0 ), m_nameLen( 0 ), m_pSensorsConst( 0 ), m_pValues( 0 ), m_nSensors( 0 ), m_sensorIdx( 0 ), m_dictIdx( 0 ), m_pSerial( 0 ), m_alarmChar( 0 ), m_bExitNav( 0 ), - m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ) + m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ), m_ExFrameSendCycle ( 150 ) { m_name[0] = '\0'; memset( m_activeSensors, 255, sizeof(m_activeSensors) ); // default: all sensors active @@ -176,10 +178,15 @@ uint8_t JetiExProtocol::GetJetiboxKey() return m_pSerial->Getchar(); } +/// set the send cycle to the given value in ms (min = 75) +void JetiExProtocol::SetJetiSendCycle(uint8_t aTime) { + m_ExFrameSendCycle = max (75, aTime); +} + uint8_t JetiExProtocol::DoJetiSend() { // send every 150 ms only - if( ( m_tiLastSend + 150 ) <= millis() ) + if( ( m_tiLastSend + m_ExFrameSendCycle ) <= millis() ) { m_tiLastSend = millis(); @@ -217,7 +224,12 @@ void JetiExProtocol::SetSensorValue( uint8_t id, int32_t value , uint8_t prio) { if( m_pValues && id < sizeof( m_sensorMapper ) ) m_pValues[ m_sensorMapper[ id ] ].m_value = value; - m_pValues[ m_sensorMapper[ id ] ].m_prio = prio; + uint8_t p = min(15, max( 1, prio)); // normalize prio to 1-15 + + // m_prio first four bits = requested prio for sending the value each n.th frame + // m_prio last four bits = counter to check when the value shall be send + m_pValues[ m_sensorMapper[ id ] ].m_prio &= ~(0x0F); // clear the first four bits + m_pValues[ m_sensorMapper[ id ] ].m_prio |= p; // now set the given 4 prio bits } void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value, uint8_t prio ) @@ -405,7 +417,7 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) // sensor name in frame 0 if( frameCnt == 0 ) { // sensor name - m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text + m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text m_exBuffer[8] = 0x00; // 8Bit id m_exBuffer[9] = m_nameLen<<3; // 5Bit description, 3Bit unit length (use one space character) memcpy( m_exBuffer + 10, m_name, m_nameLen ); // copy label plus unit to ex buffer starting from pos 10 @@ -423,8 +435,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) if( sensor.m_bActive ) { m_exBuffer[2] = 0x00; // 2Bit packet type(0-3) 0x40=Data, 0x00=Text - m_exBuffer[8] = sensor.m_id; // 8Bit id - m_exBuffer[9] = (sensor.m_textLen<<3) | sensor.m_unitLen; // 5Bit description, 3Bit unit length + m_exBuffer[8] = sensor.m_id; // 8Bit id + m_exBuffer[9] = (sensor.m_textLen<<3) | sensor.m_unitLen; // 5Bit description, 3Bit unit length n = sensor.jetiCopyLabel( m_exBuffer, 10 ) + 10; // copy label plus unit to ex buffer starting from pos 10 break; } @@ -435,8 +447,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) { int bufLen; int nVal = 0; // count values - m_exBuffer[ 2 ] = 0x40; // 2Bit Type(0-3) 0x40=Data, 0x00=Text - n=8; // start at nineth byte in buffer + m_exBuffer[ 2 ] = 0x40; // 2Bit Type(0-3) 0x40=Data, 0x00=Text + n=8; // start at nineth byte in buffer do { @@ -445,16 +457,27 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) if( ++m_sensorIdx >= m_nSensors ) // wrap index when array is at the end m_sensorIdx = 0; - if( sensor.m_bActive && sensor.m_value != -1 && (frameCnt % sensor.m_prio) == 0) // -1 is "invalid" + + uint8_t prio = *sensor.mp_prio & 0x0F; // first four bits are prio (1-15) + uint8_t cnt = *sensor.mp_prio >> 4; // last four bits are the send counter (0-15) + if (cnt%prio == 0) { + cnt = 1; + } else { + cnt++; + } + *sensor.mp_prio &= ~(0xF0); // clear the last four bits + *sensor.mp_prio |= (cnt << 4) ; // now set the counter to the last four bits + + if( sensor.m_bActive && sensor.m_value != -1 && cnt == 1) // -1 is "invalid" { - if( sensor.m_id > 15 ) - { - m_exBuffer[n++] = 0x0 | (sensor.m_dataType & 0x0F); // sensor id > 15 --> put id to next byte - m_exBuffer[n++] = sensor.m_id; - } - else - m_exBuffer[n++] = (sensor.m_id<<4) | (sensor.m_dataType & 0x0F); // 4Bit id, 4 bit data type (i.e. int14_t) - + if( sensor.m_id > 15 ) + { + m_exBuffer[n++] = 0x0 | (sensor.m_dataType & 0x0F); // sensor id > 15 --> put id to next byte + m_exBuffer[n++] = sensor.m_id; + } + else + m_exBuffer[n++] = (sensor.m_id<<4) | (sensor.m_dataType & 0x0F); // 4Bit id, 4 bit data type (i.e. int14_t) + bufLen = sensor.m_bufLen; n += sensor.jetiEncodeValue( m_exBuffer, n ); } @@ -465,8 +488,8 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) } // complete some more EX frame data - m_exBuffer[0] = 0x7E; m_exBuffer[1] = 0x2F; // EX-Frame Separator - m_exBuffer[2] |= n-2; // frame length to Byte 2 + m_exBuffer[0] = 0x7E; m_exBuffer[1] = 0x2F; // EX-Frame Separator + m_exBuffer[2] |= n-2; // frame length to Byte 2 m_exBuffer[3] = MANUFACTURER_ID_LOW; m_exBuffer[4] = MANUFACTURER_ID_HI; // sensor ID m_exBuffer[5] = m_devIdLow; m_exBuffer[6] = m_devIdHi; m_exBuffer[7] = 0x00; // reserved (key for encryption) @@ -511,7 +534,7 @@ uint8_t JetiSensor::jetiEncodeValue( uint8_t * exbuf, uint8_t n ) exbuf[n] = ( m_value & 0x1F) | ((m_value < 0) ? 0x80 :0x00 ); // 5 bit value and sign exbuf[n] |= m_precision; // precision in bit 5/6 (0, 20, 40) return 1; - + case TYPE_14b: exbuf[n] = m_value & 0xFF; // lo byte exbuf[n + 1] = ( (m_value >> 8) & 0x1F) | ((m_value < 0) ? 0x80 :0x00 ); // 5 bit hi byte and sign @@ -588,3 +611,4 @@ uint8_t JetiExProtocol::jeti_crc8 (uint8_t *exbuf, unsigned char framelen) crc = update_crc (exbuf[c], crc); return (crc); } + diff --git a/src/JetiExProtocol.h b/src/JetiExProtocol.h index f0e29f4..13ef17a 100644 --- a/src/JetiExProtocol.h +++ b/src/JetiExProtocol.h @@ -26,6 +26,8 @@ 1.04 07/18/2017 dynamic sensor de-/activation 1.05 02/14/2021 Rainer Stransky: added implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). + 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle + SetJetiSendCycle(aTime); Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -82,7 +84,7 @@ class JetiValue friend class JetiExProtocol; public: - JetiValue() : m_value( -1 ) {} + JetiValue() : m_value( -1 ), m_prio( 0 ) {} protected: // value @@ -123,7 +125,7 @@ class JetiSensor uint8_t m_bActive; // send priority / incidence - uint8_t m_prio; + uint8_t* mp_prio; // label/description of value @@ -174,6 +176,7 @@ class JetiExProtocol void Start( const char * name, JETISENSOR_CONST * pSensorArray, enComPort comPort = DEFAULTPORT ); // call once in setup(), comPort: 0=Default, Teensy: 1..3 uint8_t DoJetiSend(); // call periodically in loop() + void SetJetiSendCycle(uint8_t aTime); void SetDeviceId( uint8_t idLo, uint8_t idHi ) { m_devIdLow = idLo; m_devIdHi = idHi; } // adapt it, when you have multiple sensor devices connected to your REX void SetSensorValue( uint8_t id, int32_t value, uint8_t prio=1 ); @@ -205,6 +208,7 @@ class JetiExProtocol // EX frame control unsigned long m_tiLastSend; // last send time uint8_t m_frameCnt; + uint8_t m_ExFrameSendCycle; // sensor name char m_name[ 20 ]; From 9027587de867d7d6ac141f3eadf0bb83399a0450 Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Mon, 1 Mar 2021 01:50:09 +0100 Subject: [PATCH 4/6] 1.08 02/28/2021 - bug fix: ex buffer overrun + some refactoring --- src/JetiExProtocol.cpp | 93 ++++++++++++++++++++++++------------------ src/JetiExProtocol.h | 20 +++++++-- 2 files changed, 69 insertions(+), 44 deletions(-) diff --git a/src/JetiExProtocol.cpp b/src/JetiExProtocol.cpp index 1cab6a7..305d03d 100644 --- a/src/JetiExProtocol.cpp +++ b/src/JetiExProtocol.cpp @@ -39,6 +39,11 @@ to avoid deffered transmission of high prio data (vario). 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle SetJetiSendCycle(aTime); + 1.08 02/28/2021 - bug fix: ex buffer overrun for sensor ids >15 fixed (forced strange behaviour in prio handling) + - some more index size checks + - simplified code for prio data handling + - handling of -1 as invalid data removed, due to dynamic prio (SetSensorValue(..., prio) and SetSensorActive() + interface Todo: - better check for ex buffer overruns @@ -87,7 +92,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) // value m_value = pProtocol->m_pValues[ arrIdx ].m_value; - mp_prio = &pProtocol->m_pValues[ arrIdx ].m_prio; + m_prio = pProtocol->m_pValues[ arrIdx ].m_prio; // copy to combined sensor/value buffer copyLabel( (const uint8_t*)constData.text, (const uint8_t*)constData.unit, m_label, sizeof( m_label ), &m_textLen, &m_unitLen ); @@ -116,7 +121,7 @@ JetiSensor::JetiSensor( int arrIdx, JetiExProtocol * pProtocol ) JetiExProtocol::JetiExProtocol() : m_tiLastSend( 0 ), m_frameCnt( 0 ), m_nameLen( 0 ), m_pSensorsConst( 0 ), m_pValues( 0 ), m_nSensors( 0 ), m_sensorIdx( 0 ), m_dictIdx( 0 ), m_pSerial( 0 ), m_alarmChar( 0 ), m_bExitNav( 0 ), - m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ), m_ExFrameSendCycle ( 150 ) + m_devIdLow( DEVICE_ID_LOW ), m_devIdHi( DEVICE_ID_HI ), m_ExFrameSendCycle ( 150 ) , m_ValueCycleCnt ( 1 ) { m_name[0] = '\0'; memset( m_activeSensors, 255, sizeof(m_activeSensors) ); // default: all sensors active @@ -218,18 +223,22 @@ uint8_t JetiExProtocol::DoJetiSend() /** * @id: id of the sensor * @value: value of the sensor to be transferred - * @prio: transmission prioity: 1=send with every frame, 2=send with every second frame, .... + * @prio: transmission prioity: 1=send with every frame, 2=send with every second frame, ...., + * #defines avaiable + * JEP_PRIO_ULTRA_HIGH 1 + * JEP_PRIO_HIGH 3 + * JEP_PRIO_STANDARD 5 + * JEP_PRIO_LOW 10 + * JEP_PRIO_ULTRA_LOW 15 */ void JetiExProtocol::SetSensorValue( uint8_t id, int32_t value , uint8_t prio) { - if( m_pValues && id < sizeof( m_sensorMapper ) ) - m_pValues[ m_sensorMapper[ id ] ].m_value = value; - uint8_t p = min(15, max( 1, prio)); // normalize prio to 1-15 - - // m_prio first four bits = requested prio for sending the value each n.th frame - // m_prio last four bits = counter to check when the value shall be send - m_pValues[ m_sensorMapper[ id ] ].m_prio &= ~(0x0F); // clear the first four bits - m_pValues[ m_sensorMapper[ id ] ].m_prio |= p; // now set the given 4 prio bits + if( m_pValues && id < sizeof( m_sensorMapper ) ) { + if (m_sensorMapper[ id ] < m_nSensors) { + m_pValues[ m_sensorMapper[ id ] ].m_value = value; + m_pValues[ m_sensorMapper[ id ] ].m_prio = prio; + } + } } void JetiExProtocol::SetSensorValueGPS( uint8_t id, bool bLongitude, float value, uint8_t prio ) @@ -306,13 +315,14 @@ void JetiExProtocol::SetSensorActive( uint8_t id, bool bEnable, JETISENSOR_CONST if( m_nSensors == 0 && pSensorArray ) // dont do it more than once InitSensorMapper( pSensorArray ); - if( id < sizeof( m_sensorMapper ) ) - { + if( id < sizeof( m_sensorMapper ) ) { int idx = m_sensorMapper[ id ]; - if( bEnable ) - m_activeSensors[ idx >>3 ] |= 1 << (idx & 7); - else - m_activeSensors[ idx >>3 ] &= ~(1 << (idx & 7)); + if (idx < m_nSensors) { + if( bEnable ) + m_activeSensors[ idx >>3 ] |= 1 << (idx & 7); + else + m_activeSensors[ idx >>3 ] &= ~(1 << (idx & 7)); + } } // restart sending dictionary @@ -452,42 +462,44 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) do { - bufLen = 0; // last value buffer length JetiSensor sensor( m_sensorIdx, this ); - if( ++m_sensorIdx >= m_nSensors ) // wrap index when array is at the end - m_sensorIdx = 0; - - uint8_t prio = *sensor.mp_prio & 0x0F; // first four bits are prio (1-15) - uint8_t cnt = *sensor.mp_prio >> 4; // last four bits are the send counter (0-15) - if (cnt%prio == 0) { - cnt = 1; - } else { - cnt++; - } - *sensor.mp_prio &= ~(0xF0); // clear the last four bits - *sensor.mp_prio |= (cnt << 4) ; // now set the counter to the last four bits - - if( sensor.m_bActive && sensor.m_value != -1 && cnt == 1) // -1 is "invalid" - { - if( sensor.m_id > 15 ) - { + if( sensor.m_bActive && ((m_ValueCycleCnt%sensor.m_prio) == 0)) { + // id+type+value+precision + CRC + bufLen = sensor.m_bufLen + 1 ; + if( sensor.m_id > 15 ) { + // next byte for id > 15 + bufLen++; + if (n + bufLen > JEP_MAX_BYTE_PER_BUF) { + // not enough bytes free + break; + } m_exBuffer[n++] = 0x0 | (sensor.m_dataType & 0x0F); // sensor id > 15 --> put id to next byte m_exBuffer[n++] = sensor.m_id; - } - else + } else { + if (n + bufLen > JEP_MAX_BYTE_PER_BUF) { + // not enough bytes free + break; + } m_exBuffer[n++] = (sensor.m_id<<4) | (sensor.m_dataType & 0x0F); // 4Bit id, 4 bit data type (i.e. int14_t) + } - bufLen = sensor.m_bufLen; n += sensor.jetiEncodeValue( m_exBuffer, n ); } - if( ++nVal >= m_nSensors ) // dont send twice in a frame + + if( ++m_sensorIdx >= m_nSensors ) { // wrap index when array is at the end + m_sensorIdx = 0; + m_ValueCycleCnt++; + } + if( ++nVal >= m_nSensors ) { // dont send twice in a frame break; + } } - while( n < ( 26 - bufLen ) ); // jeti spec says max 29 Bytes per buffer + while( true ); // jeti spec says max 29 Bytes per buffer } // complete some more EX frame data + // 8 Byte Header m_exBuffer[0] = 0x7E; m_exBuffer[1] = 0x2F; // EX-Frame Separator m_exBuffer[2] |= n-2; // frame length to Byte 2 m_exBuffer[3] = MANUFACTURER_ID_LOW; m_exBuffer[4] = MANUFACTURER_ID_HI; // sensor ID @@ -495,6 +507,7 @@ void JetiExProtocol::SendExFrame( uint8_t frameCnt ) m_exBuffer[7] = 0x00; // reserved (key for encryption) // calculate crc + // 1 Byte CRC m_exBuffer[n] = jeti_crc8( m_exBuffer, n ); // serial transmission diff --git a/src/JetiExProtocol.h b/src/JetiExProtocol.h index 13ef17a..5aa872a 100644 --- a/src/JetiExProtocol.h +++ b/src/JetiExProtocol.h @@ -28,6 +28,11 @@ to avoid deffered transmission of high prio data (vario). 1.07 02/18/2021 Rainer Stransky: fixed priorized sensor implementation and added interface to speed up frame send cycle SetJetiSendCycle(aTime); + 1.08 02/28/2021 - bug fix: ex buffer overrun for sensor ids >15 fixed (forced strange behaviour in prio handling) + - some more index size checks + - simplified code for prio data handling + - handling of -1 as invalid data removed, due to dynamic prio (SetSensorValue(..., prio) and SetSensorActive() + interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -51,12 +56,20 @@ #ifndef JETIEXPROTOCOL_H #define JETIEXPROTOCOL_H +#define JEP_PRIO_ULTRA_HIGH 1 +#define JEP_PRIO_HIGH 3 +#define JEP_PRIO_STANDARD 5 +#define JEP_PRIO_LOW 10 +#define JEP_PRIO_ULTRA_LOW 15 + #if ARDUINO >= 100 #include #else #include #endif +#define JEP_MAX_BYTE_PER_BUF 29 + #include "JetiExSerial.h" #include @@ -90,9 +103,8 @@ class JetiValue // value int32_t m_value; - // send priority / incidence + // send priority uint8_t m_prio; - }; // complete data for a sensor to fill ex frame buffer @@ -125,8 +137,7 @@ class JetiSensor uint8_t m_bActive; // send priority / incidence - uint8_t* mp_prio; - + uint8_t m_prio; // label/description of value uint8_t m_label[ 20 ]; @@ -219,6 +230,7 @@ class JetiExProtocol JetiValue * m_pValues; // sensor value array, same order as constant data array int m_nSensors; // number of sensors uint8_t m_sensorIdx; // current index to sensor array to send value + uint8_t m_ValueCycleCnt; // current index to sensor array to send value uint8_t m_dictIdx; // current index to sensor array to send sensor dictionary uint8_t m_sensorMapper[ MAX_SENSORS ]; // id to idx lookup table to accelerate SetSensorValue() uint8_t m_activeSensors[ MAX_SENSORBYTES ]; // bit array for active sensor bit field From 787d525d7dc844dce438874e3f3480f5c675af8a Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Mon, 1 Mar 2021 01:55:41 +0100 Subject: [PATCH 5/6] 1.08 02/28/2021 - bug fix: ex buffer overrun + some refactoring --- README.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.adoc b/README.adoc index f199b86..03786b7 100644 --- a/README.adoc +++ b/README.adoc @@ -46,6 +46,11 @@ Serial interface to transmit telemetry data to Jeti Duplex receivers. For Arduin 1.06 02/14/2021 enhance interface / implementation for priorized sensor send capabilities (SetSensorValue(id, value, prio)) to avoid deffered transmission of high prio data (vario). 1.07 02/18/2021 fixed priorized sensor implementation and added interface to speed up frame send cycle (SetJetiSendCycle(aTime)) + 1.08 02/28/2021 - bug fix: ex buffer overrun for sensor ids >15 fixed (forced strange behaviour in prio handling) + - some more index size checks + - simplified code for prio data handling + - handling of -1 as invalid data removed, due to dynamic prio (SetSensorValue(..., prio) and SetSensorActive() + interface == License == From bac5ee4d2084186418595370773406d5037e05be Mon Sep 17 00:00:00 2001 From: Rainer Stransky Date: Thu, 24 Nov 2022 01:20:40 +0100 Subject: [PATCH 6/6] version info updated --- library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index e919575..7a8bfcf 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=JetiExSensor -version=1.0.5 -author=Bernd Wokoeck +version=1.1.0 +author=Bernd Wokoeck/Rainer Stransky maintainer= sentence=Serial interface to transmit telemetry data to Jeti Duplex receivers. For Arduino Mini Pro 328, Nano, Leonardo/Pro Micro and Teensy 3.x paragraph=Connect your Arduino mini to a Jeti duplex receiver and see telemetry values on your transmitter display. category=Communication -url=https://sourceforge.net/projects/jetiexsensorcpplib/JetiExSensor_V1.0.5.zip +url= architectures=avr