// *********************************************************************
// *                        E16-RANGE-TEST                             *
// *                        RF range test                              *
// *********************************************************************
// Intended for:
//   HW: - TR-72D, DK-EVAL-04A development kit (2 pcs.)
//
//   OS: - v4.06D
//
// Description:
//  - This program is designed for RF range testing in all RF modes.
//    It uses bidirectional (echoed) communication. Unlike the E09-LINK example,
//    the correct range is only indicated after the response is received.
//  - It consists of two units (TR modules): Master and Echo
//  - The Master unit periodically transmits a packet and attempts to receive the response
//    from the Echo unit. Each packet is indicated as follows: transmitted by the green LED
//    and received by the red LED and the piezo buzzer (if enabled).
//  - The Echo unit is constantly receiving. After each received packet it sends
//    the same packet back and flashes the red LED.
//  - The program with the same setting (see below) must be uploaded into two TR modules.
//    Do not make any changes in the code, just modify the User settings section accordingly.
//  - To activate this program as the Master unit, press and hold button SW1 on the DK-EVAL-04A
//    during TR module startup. The green LED immediatelly starts to indicate transmitted RF packets.
//  - To activate this program as the Echo unit, just switch on the TR module.
//    There is no LED indication until a packet is echoed.
//
//  - In case of piezo buzzer usage (at Master unit only) use simple directly driven piezo buzzer
//    and connect it to the side connector of the DK-EVAL-04A, pin 5 (C1) and pin 7 (GND).
//
//  - Practical information can be found in the RF Range Application Note AN014:
//    https://www.iqrf.org/download/d0af3084-af00-40ba-9d94-6d7613265f13
//
// ---------------------------------------------------------------------
// Online IQRF OS Reference Guide: https://doc.iqrf.org/IQRF-OS-Reference-guide
//
// Copyright (c) IQRF Tech s.r.o.
//
// File:    E16-RANGE-TEST.c
// Version: v1.00                                   Revision: 13/05/2022
//
// Revision history:
//   v1.00: 13/05/2022  First release for TR-72D and IQRF OS 4.06D.
//
// *********************************************************************
#include "IQRF.h"

// *********************************************************************
// User settings
#define STD                         // RF mode setting. Select from: STD, LP, XLP
#define RX_FILTER               5   // Select from 0 (no filter) to 64 (max. filter), default value: 5
#define TX_POWER                7   // Select from 0 (min.) to 7 (max.), default value: 7
#define BEEPER                      // Comment this if the piezo buzzer is not used
// Settings for advanced users
#define USER_BYTES              32  // DLEN setting
#define PREAMBLE_QUALITY_TEST

#ifdef BEEPER
    #define BEEPER_TRIS         TRISA.0 // C1 - pin connected to the piezo buzzer
    #define BEEPER_IO           LATA.0

    #define HIGH_TONE           25  // [5us] * 2 ~ cca 4kHz
    #define LOW_TONE            50  // [5us] * 2 ~ cca 2kHz
    #define TONE_LENGTH         20  // [ticks]
    
    void waitDelay_5us(uns8 val);
    void beep(void);
#endif

// *********************************************************************

void APPLICATION()
{
uns8 i;

#ifdef STD
    #message STD mode
    setRFmode(_WPE | _RX_STD | _TX_STD | _STDL);
    // Wait Packed End active so the toutRF can be set to minimum
    toutRF = 1;
  #ifdef PREAMBLE_QUALITY_TEST
      _checkRFcfg_PQT = 1;
  #endif      
    
#elif defined LP
    #message LP mode
    setRFmode(_WPE | _RX_LP  | _TX_LP);
    // To set internal filtering for LP receiving.
    checkRF(RX_FILTER);
    
#elif defined XLP
    #message XLP mode
    setRFmode(_WPE | _RX_XLP | _TX_XLP);
    // To set internal filtering for LP receiving.
    checkRF(RX_FILTER);
#else
    #error RF mode is not selected.
#endif

    setRFpower(TX_POWER);
     
    if (buttonPressed)
    {
// --- Master unit ---
// Button was pressed during TR module startup
        #ifdef BEEPER
            // Set pin as output in low level
            BEEPER_IO = 0;
            BEEPER_TRIS = 0;
        #endif
    
        while (1)
        {
            pulseLEDG();
            PIN = 0;
            DLEN = USER_BYTES;
            // Required min. delay before RFTXpacket
            waitMS(5);
            RFTXpacket();
 
#ifdef STD  // --------------------------------------------------
            // STD RF mode
            // Receiving time = i * cca 1ms
            i = 100;
            
            do
            {
                // RF signal detection (takes cca 1ms)
                if (checkRF(RX_FILTER))
                {
                    if (RFRXpacket())
                    {
                        pulseLEDR();
                        #ifdef BEEPER
                            beep();
                        #endif
                        break;
                    }
                }
            } while(--i);
#else       // --------------------------------------------------------
            // LP/XLP RF mode
            toutRF = 6;

            if (RFRXpacket())
            {
                pulseLEDR();
                #ifdef BEEPER
                    beep();
                #endif
            }
#endif      // -------------------------------------------------------    
        } 
    }
    else
    {
// --- Echo unit ---
// Button was not pressed during TR module startup
        while (1)
        {
#ifdef STD  // ---------------------------------------------------
            // STD RF mode
            // RF signal detection (takes cca 1ms)
            if (checkRF(RX_FILTER))
            {
                if (RFRXpacket())
                {
                    pulseLEDR();
                    PIN = 0;
                    DLEN = USER_BYTES;
                    // Required min. delay before RFTXpacket
                    waitMS(5);
                    RFTXpacket();
                }
            }
#else       // --------------------------------------------------------
            // LP/XLP RF mode
            toutRF = 255;
            
            if (RFRXpacket())
            {
                pulseLEDR();
                // Wait for end of LED flash
                waitDelay(5);

                PIN = 0;
                DLEN = USER_BYTES;
                RFTXpacket();
            }
#endif      // -------------------------------------------------------
        }
    }
}

#ifdef BEEPER
// *********************************************************************
void waitDelay_5us( uns8 val @ W ) // Absolutely precise timing but val != 0
// *********************************************************************
// 16 MHz MCU CLK
{ // + 0.75us ( W=val, Call )
  for ( ;; )
  {         // loop time
    nop2(); // 0.50us
    nop2(); // 1.00us
    nop2(); // 1.50us
    nop2(); // 2.00us
    nop2(); // 2.50us
    nop2(); // 3.00us
    nop();  // 3.25us
    if ( --val == 0 ) // + 0.75us (W--, BTFS ) 
      return;         // + 0.25us 
    nop2(); // 4.50us
  }         // 5.00us (Goto)
}

void beep(void)
{
    startDelay(TONE_LENGTH);

    while (isDelay())
    {
        BEEPER_IO ^= 1;
        waitDelay_5us(HIGH_TONE);
    }

    BEEPER_IO = 0;
}
#endif

// *********************************************************************

