Indigresso Wiki

Open Source Stuff for DASH7

User Tools

Site Tools


opentag:otlib:encode

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

opentag:otlib:encode [2012/03/09 17:09] (current)
jpnorair created
Line 1: Line 1:
 +====== Encode Module (OTlib) ======
 +[[opentag:​main|OpenTag]] uses the Encode Module to encode/​decode binary, byte-wise data to/from [[dash7_mode_2:​phy|DASH7 Mode 2 PHY]] data.  Functions from the Encode Module are typically called from within the [[opentag:​otlib:​radio_h|Radio Module]] implementation (i.e. the [[opentag:​radios:​main|radio driver]]) when data is being paged-in or paged-out from the radio core.  So, the [[opentag:​kernel:​main|kernel]] and [[opentag:​apps:​main|user applications]] never really need to interface with the Encode Module at all.
  
 +===== Module Design & Features =====
 +The Encode Module is designed to implement all of the features of the DASH7 Mode 2 PHY.  In summary, these are a method of PN9 encoding and a method of FEC encoding. ​ The Encode Module also manages CRC calculation transparently,​ via the [[opentag:​otlib:​crc|CRC Module]], so the kernel and user application never need to call the CRC module, either (unless they are using it for different purposes than radio communication).
 +
 +==== Software and Hardware Codecs ====
 +The Encode Module is implemented with a lot of preprocessor directives, so that only the parts that need to get compiled are actually compiled. ​ For example, if you are using a Radio core that has PN9 and FEC built in (such as [[opentag:​radios:​cc11xx|TI CC1101]]) the PN9 and FEC codecs will not get compiled, and the radio core will do these processes in hardware. ​ Thus, it is important to make sure that you configure your radio driver appropriately (all officially supported radio drivers already have optimized configuration files). ​ If your radio core does not have the ability to do the encoding in HW, then the Encode Module software codecs will get compiled, and they will be used.
 +
 +==== Data Elements ====
 +The Encode Module keeps a local struct called "​em2." ​ So far there is nothing outside OTlib/​encode_M2.c that uses it, but it is exposed anyway. ​ There are several functions available in the Encode Module, **em2_remaining_frames()**,​ **em2_remaining_bytes()**,​ and **em2_complete()**,​ which are intended to be convenient interfaces with the em2 struct. ​ The Radio Module uses these functions in place of accessing the actual struct. ​ The functions themselves are typically inlined by the compiler.
 +
 +==== Using the Encoder/​Decoder ====
 +One good reference is a radio driver C file, such as OTradio/​CC430/​radio_CC430.c. ​ The basic way the Encode Module is used is described below.
 +
 +=== 1. Prepare Encoder/​Decoder ===
 +The Encoder/​Decoder needs to be prepared, so that it initializes its em2 struct properly and selects the type of codec that needs to be used.  Basically, you will just call these two functions together to prepare the Encoder (same for decoder)
 +<​code>​
 +em2_encode_newpacket(); ​   //​em2_decode_newpacket() for decode
 +em2_encode_newframe(); ​    //​em2_decode_newframe() for decode
 +</​code>​
 +
 +=== 2. Encode/​Decode New Data ===
 +If you are encoding, you need to encode the data before TX'ing it on the radio. ​ If you are decoding, you need to RX it on the radio before there is any data to decode. ​ The methods for managing the data transfer from the radio core are not part of the Encode Module (they are part of the radio driver). ​ However, the Encode Module will access the radio core once the radio driver tells it that the radio core is ready to have encoded data paged-in or encoded data paged-out (which needs decoding). ​ The Encode Module uses the radio interface'​s **radio_rxopen()** and **radio_txopen()** functions to judge when the page is done.  Here is a typical implementation of encoding:
 +<​code>​
 +em2_encode_data();​
 +</​code>​
 +Note that the encoder must be initialized with step 1, before **em2_encode_data()** can be used.  **em2_encode_data()** is actually a function pointer that gets linked to the encode function it needs to use.  This design allows many different combinations of HW and SW encoding to be used, while the implementation on the radio driver stays simple. ​ **em2_encode_data()** will automatically fill the radio core FIFO and then stop.  Also note that some radio cores need to load the FIFO before starting TX, and others need to load the FIFO after starting TX.
 +
 +=== 3. Controlling Subsequent Paging ===
 +Every packet has at least one page of data.  The size of a page depends on the encoding type used and the size of the radio core's FIFO.  Sometimes, there needs to be more than one page.  The radio driver needs to manage the paging of data to/from the Encode Module and the radio core.  Below is an example from OTradio/​CC430/​radio_CC430.c that shows the TX data process using the Encode Module functions.
 +<​code>​
 +void rm2_txdata_isr() {
 +    /// Continues where rm2_txcsma() leaves off.
 +    switch ( (radio.state >> RADIO_STATE_TXSHIFT) & (RADIO_STATE_TXMASK >> RADIO_STATE_TXSHIFT) ) {
 +
 +        /// 4. Continuous TX'ing of a single packet data
 +        case (RADIO_STATE_TXDATA >> RADIO_STATE_TXSHIFT):​ {
 +        rm2_txpkt_TXDATA:​
 +            /// Buffer needs filling, frame is not done
 +            if (em2_remaining_bytes() != 0) {
 +                em2_encode_data();​
 +                break;
 +            }
 +
 +            /// Packet flooding. ​ Only needed on devices that can send M2AdvP
 +#           if (SYS_FLOOD == ENABLED)
 +            if (radio.flags & RADIO_FLAG_FLOOD) {
 +                radio.evtdone(2,​ 0);
 +                txq.getcursor = txq.front;
 +                em2_encode_newframe();​
 +                goto rm2_txpkt_TXDATA;​
 +            }
 +#           endif
 +
 +            /// If the frame is done (em2_remaining_bytes() == 0) and there are
 +            /// no more frames to transmit, then this interrupt is due to a low
 +            /// threshold, and we just need to turn-off the threshold interrupt
 +            /// and wait for the last bit of data to get sent.
 +            if (em2_remaining_frames() == 0) {
 +                radio.state = RADIO_STATE_TXDONE;​
 +                RFCONFIG_TXFIFOLOW_INTOFF();​
 +                break;
 +            }
 +
 +            /// If the frame is done, but more need to be sent (e.g. MFP's)
 +            /// queue it up.  The additional encode stage is there to fill up
 +            /// what's left of the buffer.
 +#           if (M2_FEATURE(MULTIFRAME) == ENABLED)
 +            if (radio.flags & RADIO_FLAG_FRCONT) {
 +                q_rebase(&​txq,​ txq.getcursor);​
 +                radio.evtdone(1,​ 0);        //callback action for next frame
 +                em2_encode_newframe();​
 +                txq.front[1] = phymac[0].tx_eirp;​
 +                em2_encode_data();​
 +                goto rm2_txpkt_TXDATA;​
 +            }
 +#           endif
 +        }
 +
 +        /// 5. Conclude the TX process, and wipe the radio state
 +        //     turn off any remaining TX interrupts
 +        case (RADIO_STATE_TXDONE >> RADIO_STATE_TXSHIFT):​
 +            sub_kill(0, 0);
 +            break;
 +
 +        /// Bug trap
 +        default:
 +            sub_kill(RM2_ERR_GENERIC,​ 0);
 +            break;
 +    }
 +}
 +</​code>​
 +
 +===== OTlib/​encode.h =====
 +The code from encode.h is pasted below, although you can also check the [[opentag:​doxygen|doxygen code documentation]].
 +<​code>​
 +#include "​OT_types.h"​
 +#include "​OT_config.h"​
 +
 +
 +typedef struct {
 +    ot_u8* ​ fr_info;
 +    ot_int ​ bytes;
 +    ot_int ​ state; ​             // could be changed to ot_s8
 +
 +#   if ( (RF_FEATURE(PN9) != ENABLED) || \
 +         ​((M2_FEATURE(FEC) == ENABLED) && (RF_FEATURE(FEC) != ENABLED)) )
 +        Twobytes PN9_lfsr;
 +#   endif
 +
 +#   if ((M2_FEATURE(FEC) == ENABLED) && (RF_FEATURE(FEC) != ENABLED))
 +        ot_int ​ databytes;
 +        ot_int ​ path_bits;
 +        ot_u8   ​last_buffer;​
 +        ot_u8   ​current_buffer;​
 +        ot_u8   ​cost_matrix[2][8];​
 +#   endif
 +
 +} em2_struct;
 +
 +extern em2_struct ​  em2;
 +
 +
 +
 +
 +/** @brief ​ Initializes the encoder for a new Mode 2 packet
 +  * @param ​ None
 +  * @retval None
 +  * @ingroup Encode
 +  */
 +void em2_encode_newpacket();​
 +
 +
 +/** @brief ​ Initializes the decoder for a new Mode 2 packet
 +  * @param ​ None
 +  * @retval None
 +  * @ingroup Encode
 +  *
 +  * The decoding engine needs to be initialized at the packet level. ​ It is
 +  * conceivable that a packet may consist of multiple frames.
 +  */
 +void em2_decode_newpacket();​
 +
 +
 +/** @brief ​ Initializes the encoder for encoding a Mode 2 Frame
 +  * @param ​ None
 +  * @retval None
 +  * @ingroup Encode
 +  */
 +void em2_encode_newframe();​
 +//ot_int em1_encode_newframe( );
 +
 +
 +/** @brief ​ Initialize the frame manager for decoding a Mode 2 Frame
 +  * @param ​ None
 +  * @retval None
 +  * @ingroup Encode
 +  *
 +  * The decoding engine is at the packet level, but the calculation of CRC and
 +  * management of the data queue are done at the frame level. ​ So to manage
 +  * the frame, this function needs to be run before a frame comes in.
 +  */
 +void em2_decode_newframe();​
 +//void em1_decode_newframe(ot_u32 header); ​
 +
 +
 +/** @brief ​ Returns the number of frames following the current one
 +  * @param none
 +  * @retval ot_int ​     value from em2.frames
 +  * @ingroup Encode
 +  */
 +ot_int em2_remaining_frames();​
 +
 +
 +/** @brief ​ Returns bytes remaining to encode or decode
 +  * @param none
 +  * @retval ot_int ​     value from em2.bytes
 +  * @ingroup Encode
 +  *
 +  * For encoding, the value returned is the number of unencoded bytes that are
 +  * remaining to be encoded. ​ For decoding, the value is the number of encoded
 +  * bytes that are remaining to be decoded.
 +  */
 +ot_int em2_remaining_bytes();​
 +
 +
 +/** @brief ​ Returns True when the encoding/​decoding is complete
 +  * @param none
 +  * @retval ot_bool ​    true on (em2.bytes == 0) && (em2.frames == 0)
 +  * @ingroup Encode
 +  */
 +ot_bool em2_complete();​
 +
 +
 +/** @par Mode 2 Encode Data function pointer
 +  * The function @c em2_encode_newframe() sets this function pointer to the 
 +  * appropriate encode function, based on the queue options field and compiled
 +  * in feature settings.
 +  * 
 +  * @fn     ​em2_encode_data
 +  * @brief ​ None
 +  * @param ​ q           ​(Queue*) queue to load data for encoding
 +  * @retval None
 +  * @ingroup Encode
 +  */
 +extern void (*em2_encode_data)();​
 +
 +
 +/** @par Decode function pointer
 +  * The function @c decode_newpacket sets this function pointer to the 
 +  * appropriate decode function, based on input to @c decode_newpacket
 +  *
 +  * @fn     ​decode_data
 +  * @brief ​ Decodes comm data into byte-wise data
 +  * @param ​ None
 +  * @retval None
 +  * @ingroup Encode
 +  */
 +extern void (*em2_decode_data)();​
 +
 +</​code>​
opentag/otlib/encode.txt ยท Last modified: 2012/03/09 17:09 by jpnorair