// *************************************************************************************************
//
//      Copyright (C) 2013 Aperture Labs Ltd. - http://aperturelabs.com/
//
//        Author: Adam Laurie <adam@aperturelabs.com>
//
//
//        Redistribution and use in source and binary forms, with or without
//        modification, are permitted provided that the following conditions
//        are met:
//
//          Redistributions of source code must retain the above copyright
//          notice, this list of conditions and the following disclaimer.
//
//          Redistributions in binary form must reproduce the above copyright
//          notice, this list of conditions and the following disclaimer in the
//          documentation and/or other materials provided with the
//          distribution.
//
//          Neither the name of Aperture Labs Ltd. nor the names of
//          its contributors may be used to endorse or promote products derived
//          from this software without specific prior written permission.
//
//        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//        "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//        A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
//        OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//        SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//        LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//        DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//        THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************
//
// portions copied from
// *************************************************************************************************
// cSLight
// Extension to drive the Conrad "Funk-Lichtschalter-mit-Sender"
// http://www.conrad.at/ce/de/product/620587/Funk-Lichtschalter-mit-Sender
// (c) Christian M. Schmid
// 1.1.2011


#include "chronic.h"

// system
#include "project.h"
#include "bm.h"

// driver
#include "display.h"
#include "radio.h"
#include "rf1a.h"
#include "ports.h"
#include "timer.h"

// chronic globals
unsigned char Button_Up_Data[3][BUTTON_DATA_SIZE];
unsigned char Up_Buttons= 1; // number of different up sequences to transmit
unsigned char Button_Down_Data[3][BUTTON_DATA_SIZE];
unsigned char Down_Buttons= 1;  // number of different down sequences to transmit
unsigned char Button_Delay= 75;
unsigned char Button_Repeat= 4;
unsigned char Emulation_Mode= EMULATION_MODE_NONE;

#ifdef ISM_LF // 433 MHz
	unsigned char Chronic_PA_Table[2]={0x00,0xC0}; //12 dBm
#endif
#ifdef ISM_EU // 868 MHz
	unsigned char Chronic_PA_Table[2]={0x00,0xC0}; //12 dBm
#endif

RADIO_REGS ChronicRF = {
	    0x29,  // IOCFG2           GDO2 Output Configuration
	    0x2E,  // IOCFG1           GDO1 Output Configuration
	    0x2E,  // IOCFG0           GDO0 Output Configuration
	    0x47,  // FIFOTHR          RX FIFO and TX FIFO Thresholds
	    0xD3,  // SYNC1            Sync Word, High Byte
	    0x91,  // SYNC0            Sync Word, Low Byte
	    0x0e,  // PKTLEN           Packet Length (set by transmit)
	    0x00,  // PKTCTRL1         Packet Automation Control (04)
	    0x00,  // PKTCTRL0         Packet Automation Control
	    0x00,  // ADDR             Device Address
	    0x00,  // CHANNR           Channel Number
	    0x0F,  // FSCTRL1          Frequency Synthesizer Control
	    0x00,  // FSCTRL0          Frequency Synthesizer Control
#ifdef ISM_LF // 433 MHz
	    0x10,  // FREQ2            Frequency Control Word, High Byte    868: 21		433: 10
	    0xb0,  // FREQ1            Frequency Control Word, Middle Byte  868: 6A     433: B0
	    0x71,  // FREQ0            Frequency Control Word, Low Byte     868: EE     433: 71
#endif
#ifdef ISM_EU // 868 MHz
	    0x21,  // FREQ2            Frequency Control Word, High Byte    868: 21		433: 10
	    0x6a,  // FREQ1            Frequency Control Word, Middle Byte  868: 6A     433: B0
	    0xee,  // FREQ0            Frequency Control Word, Low Byte     868: EE     433: 71
#endif
	    0xf6,  // MDMCFG4          Modem Configuration c6
	    0x93,  // MDMCFG3          Modem Configuration 78
	    0x34,  // MDMCFG2          Modem Configuration
	    0x03,  // MDMCFG1          Modem Configuration
	    0x11,  // MDMCFG0          Modem Configuration
	    0x36,  // DEVIATN          Modem Deviation Setting
	    0x07,  // MCSM2            Main Radio Control State Machine Configuration
	    0x30,  // MCSM1            Main Radio Control State Machine Configuration
	    0x10,  // MCSM0            Main Radio Control State Machine Configuration
	    0x76,  // FOCCFG           Frequency Offset Compensation Configuration
	    0x6C,  // BSCFG            Bit Synchronization Configuration
	    0x03,  // AGCCTRL2         AGC Control
	    0x40,  // AGCCTRL1         AGC Control
	    0x91,  // AGCCTRL0         AGC Control
	    0x87,  // WOREVT1          High Byte Event0 Timeout
	    0x6B,  // WOREVT0          Low Byte Event0 Timeout
	    0xF8,  // WORCTRL          Wake On Radio Control
	    0x56,  // FREND1           Front End RX Configuration
	    0x11,  // FREND0           Front End TX Configuration
	    0xEa,  // FSCAL3           Frequency Synthesizer Calibration
	    0x2A,  // FSCAL2           Frequency Synthesizer Calibration
	    0x00,  // FSCAL1           Frequency Synthesizer Calibration
	    0x1F,  // FSCAL0           Frequency Synthesizer Calibration
	    0x59,  // FSTEST           Frequency Synthesizer Calibration Control
	    0x7F,  // PTEST            Production Test
	    0x3F,  // AGCTEST          AGC Test
	    0x88,  // TEST2            Various Test Settings
	    0x31,  // TEST1            Various Test Settings
	    0x09,  // TEST0            Various Test Settings
	    0x00,  // PARTNUM          Chip ID
	    0x06,  // VERSION          Chip ID
	    0x00,  // FREQEST          Frequency Offset Estimate From Demodulator
	    0xFF,  // LQI              Demodulator Estimate for Link Quality
	    0x80,  // RSSI             Received Signal Strength Indication
	    0x01,  // MARCSTATE        Main Radio Control State Machine State
	    0x00,  // WORTIME1         High Byte of WOR Time
	    0x00,  // WORTIME0         Low Byte of WOR Time
	    0x80,  // PKTSTATUS        Current GDOx Status and Packet Status
	    0xFD,  // VCO_VC_DAC       Current Setting from PLL Calibration Module
	    0x00,  // TXBYTES          Underflow and Number of Bytes
	    0x00,  // RXBYTES          Overflow and Number of Bytes
	    0x00,  // RF1AIFCTL0       Radio interface control register 0
	    0x00,  // RF1AIFCTL1       Radio interface control register 1
	    0x00,  // RF1AIFCTL2       Reserved
	    0x00,  // RF1AIFERR        Radio interface error flag register
	    0x00,  // RF1AIFERRV       Radio interface error vector word register
	    0x00,  // RF1AIFIV         Radio interface interrupt vector word register
	    0x00,  // RF1AINSTRW       Radio instruction word register
	    0x00,  // RF1AINSTR1W      Radio instruction word register with 1-byte auto-read (low-byte ignored)
	    0x00,  // RF1AINSTR2W      Radio instruction word register with 2-byte auto-read (low-byte ignored)
	    0x00,  // RF1ADINW         Radio word data in register
	    0x00,  // RF1ASTAT0W       Radio status word register without auto-read
	    0x00,  // RF1ASTAT1W       Radio status word register with 1-byte auto-read
	    0x00,  // RF1ASTAT2W       Radio status word register with 2-byte auto-read
	    0x00,  // RF1ADOUT0W       Radio core word data out register without auto-read
	    0x00,  // RF1ADOUT1W       Radio core word data out register with 1-byte auto-read
	    0x00,  // RF1ADOUT2W       Radio core word data out register with 2-byte auto-read
	    0x00,  // RF1AIN           Radio core signal input register
	    0x00,  // RF1AIFG          Radio core interrupt flag register
	    0x00,  // RF1AIES          Radio core interrupt edge select register
	    0x00,  // RF1AIE           Radio core interrupt enable register
	    0x00,  // RF1AIV           Radio core interrupt vector word register
	    0x00,  // RF1ARXFIFO       Direct receive FIFO access register
	    0x00,  // RF1ATXFIFO       Direct transmit FIFO access register
};

// device emulation routines

void display_doorbell(u8 line, u8 update)
{
	if (update == DISPLAY_LINE_UPDATE_FULL)
	{
		if(Emulation_Mode == EMULATION_MODE_DOORBELL)
			display_symbol(LCD_ICON_RECORD, SEG_ON);
		else
		    display_symbol(LCD_ICON_RECORD, SEG_OFF);
		display_chars(LCD_SEG_L1_3_0, (u8 *)"BELL", SEG_ON);
	}
}

// frequency specific items
#ifdef ISM_LF // 433MHz

// an example: my doorbell (A Byron SX30S)
// if you're in the neighbourhood, give it a ping! :)
void config_doorbell(u8 line)
{
	// gap between data pulses
	Button_Delay= 0;
	// how many times to send per button press
	Button_Repeat= 60;

	// set button content

	Up_Buttons= 1;
	// packet length
	Button_Up_Data[0][0]= 0x08;
	// payload
	memcpy(&Button_Up_Data[0][1],"\x2C\x92\x49\x6D\xB2\x00\x00\x00",Button_Up_Data[0][0]);

	Down_Buttons= 1;
	Button_Down_Data[0][0]= 0x08;
	memcpy(&Button_Down_Data[0][1],"\x2C\x92\x49\x6D\xB2\x00\x00\x00",Button_Down_Data[0][0]);

	// set frequency (433920000)
	ChronicRF.freq0= 0x71;
	ChronicRF.freq1= 0xB0;
	ChronicRF.freq2= 0x10;
	// set data rate (pulsewidth .000320, 3124.237061 Baud)
	// drate_m
	ChronicRF.mdmcfg3= 0xf8;
	// drate_e
	ChronicRF.mdmcfg4 &= 0xf0;
	ChronicRF.mdmcfg4 |= 0x06;
	// set modulation
	ChronicRF.mdmcfg2 &= ~MASK_MOD_FORMAT;
	ChronicRF.mdmcfg2 |= MOD_OOK;
	// set sync mode
	ChronicRF.mdmcfg2 &= ~MASK_SYNC_MODE;
	ChronicRF.mdmcfg2 |= SYNC_MODE_NONE;
	// set manchester false
	ChronicRF.mdmcfg2 &= ~MASK_MANCHESTER;
	display_symbol(LCD_ICON_RECORD, SEG_ON);
	Emulation_Mode= EMULATION_MODE_DOORBELL;
}

// another example - a simple garage door opener
void config_ruku(u8 line)
{
	// gap between data pulses
	Button_Delay= 0;
	// how many times to send per button press
	Button_Repeat= 6;

	// set button content

	Up_Buttons= 1;
	// packet length
	Button_Up_Data[0][0]= 0x07;
	// payload
	memcpy(&Button_Up_Data[0][1],"\x92\x4B\x2D\xB6\xC8\x00\x00",Button_Up_Data[0][0]);

	Down_Buttons= 1;
	Button_Down_Data[0][0]= 0x07;
	memcpy(&Button_Down_Data[0][1],"\x92\x4B\x2D\x96\xC8\x00\x00",Button_Down_Data[0][0]);

	// set frequency (393080000)
	ChronicRF.freq0= 0x53;
	ChronicRF.freq1= 0x1e;
	ChronicRF.freq2= 0x0f;
	// set data rate (pulsewidth .000100, 9992.599487 Baud)
	// drate_m
	ChronicRF.mdmcfg3= 0x93;
	// drate_e
	ChronicRF.mdmcfg4 &= 0xf0;
	ChronicRF.mdmcfg4 |= 0x08;
	// set modulation
	ChronicRF.mdmcfg2 &= ~MASK_MOD_FORMAT;
	ChronicRF.mdmcfg2 |= MOD_OOK;
	// set sync mode
	ChronicRF.mdmcfg2 &= ~MASK_SYNC_MODE;
	ChronicRF.mdmcfg2 |= SYNC_MODE_NONE;
	// set manchester false
	ChronicRF.mdmcfg2 &= ~MASK_MANCHESTER;
	display_symbol(LCD_ICON_RECORD, SEG_ON);
	Emulation_Mode= EMULATION_MODE_RUKU;
}

void display_ruku(u8 line, u8 update)
{
	if (update == DISPLAY_LINE_UPDATE_FULL)
	{
		if(Emulation_Mode == EMULATION_MODE_RUKU)
			display_symbol(LCD_ICON_RECORD, SEG_ON);
		else
		    display_symbol(LCD_ICON_RECORD, SEG_OFF);
		// 'K' displays as 't', so we use 'C' instead!
		display_chars(LCD_SEG_L1_3_0, (u8 *)"RUCU", SEG_ON);
	}
}

// end ISM_LF 433MHz
#endif

#ifdef ISM_EU // 868 MHz
// another doorbell...
// Friedland LIBRA+
void config_doorbell(u8 line)
{
	// gap between data pulses
	Button_Delay= 0;
	// how many times to send per button press
	Button_Repeat= 40;

	// set button content

	Up_Buttons= 1;
	// packet length
	Button_Up_Data[0][0]= 0x13;
	// payload
	memcpy(&Button_Up_Data[0][1],"\xE3\x69\x34\xD2\x49\x26\xDA\x49\xA4\x92\x4D\x24\x92\x49\x24\x92\x49\x24\x98",Button_Up_Data[0][0]);

	Down_Buttons= 1;
	Button_Down_Data[0][0]= 0x13;
	memcpy(&Button_Down_Data[0][1],"\xE3\x69\x34\xD2\x49\x26\xDA\x49\xA4\x92\x4D\x24\x92\x49\x24\x92\x49\x24\x98",Button_Down_Data[0][0]);

	// set frequency (868350000)
	ChronicRF.freq0= 0xE8;
	ChronicRF.freq1= 0x65;
	ChronicRF.freq2= 0x21;
	// set data rate (pulsewidth .000146, 9992.599487 Baud )
	// drate_m
	ChronicRF.mdmcfg3= 0x14;
	// drate_e
	ChronicRF.mdmcfg4 &= 0xf0;
	ChronicRF.mdmcfg4 |= 0x08;
	// set modulation
	ChronicRF.mdmcfg2 &= ~MASK_MOD_FORMAT;
	ChronicRF.mdmcfg2 |= MOD_OOK;
	// set sync mode
	ChronicRF.mdmcfg2 &= ~MASK_SYNC_MODE;
	ChronicRF.mdmcfg2 |= SYNC_MODE_NONE;
	// set manchester false
	ChronicRF.mdmcfg2 &= ~MASK_MANCHESTER;
	display_symbol(LCD_ICON_RECORD, SEG_ON);
	Emulation_Mode= EMULATION_MODE_DOORBELL;
}
// end ISM_EU 868 MHz
#endif

// do the actual transmission and maintain FIFO
void do_tx(unsigned char *data, unsigned char packet_length, unsigned long total_length)
{
	unsigned char *p= data, state;
	unsigned long remaining= total_length - (unsigned long) packet_length; // one packet already in FIFO

	if (total_length > 255L)
	{
		// we need infinite mode for long packets
		ChronicRF.pktctrl0 &= ~MASK_LENGTH_CONFIG;
		ChronicRF.pktctrl0 |= LENGTH_INFINITE;
		WriteSingleReg(PKTCTRL0, ChronicRF.pktctrl0);
	}
	else
	{
		// fixed length, one shot
		WriteSingleReg(PKTLEN, (unsigned char) total_length);
		ChronicRF.pktctrl0 &= ~MASK_LENGTH_CONFIG;
		ChronicRF.pktctrl0 |= LENGTH_FIXED;
		WriteSingleReg(PKTCTRL0, ChronicRF.pktctrl0);
	}

	// start TX
	Strobe(RF_STX);

	// wait for TX to end & fill FIFO if required
	// strictly speaking we should also check if we need to come out of infinite mode but
	// it's just extra logic (i.e. code space) and we'll stop when FIFO is empty anyway, so why bother?
	while(((state= ReadSingleReg(MARCSTATE) & MASK_MARCSTATE)) != MARCSTATE_TX_END && state != MARCSTATE_IDLE)
	{
		while(remaining && (ReadSingleReg(TXBYTES) & MASK_TXBYTES) < FIFO_CAPACITY)
		{
			if (p == data + packet_length)
				p= data;
			WriteSingleReg(RF_TXFIFOWR, *(p++));
			--remaining;
		}
        // Pat the dog
		// actually this is a bad idea! if it all goes horribly wrong, the watchdog will
		// reboot. if we keep the dog happy it won't and our only recourse is to remove
		// the battery!
        //WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL;
	}

	// and we're done
	Strobe(RF_SIDLE);
	// wait for RF to be in resting state
	while((ReadSingleReg(MARCSTATE) & 0x1F) != MARCSTATE_IDLE)
		;
}

void chronic_tx(unsigned char button_data[BUTTON_SEQUENCES][BUTTON_DATA_SIZE], unsigned char sequences)
{
	unsigned char button, length, *data, i;

	//Display RF symbol
	display_symbol(LCD_ICON_BEEPER1, SEG_ON);
	display_symbol(LCD_ICON_BEEPER2, SEG_ON);
	display_symbol(LCD_ICON_BEEPER3, SEG_ON);

	//Reset radio
	ResetRadioCore();
	chronic_config_rf();

	RF1AIES |= BIT9;
	RF1AIFG &= ~BIT9;                         // Clear pending interrupts
	RF1AIE &= ~BIT9;                          // Disable TX end-of-packet interrupt

	//Transmit until button is released
	do
	{
		// TX button sequences
		for(button= 0 ; button < sequences ; ++button)
		{
			length= button_data[button][0];
			data= &button_data[button][1];

			// send using FIFO
			if (!Button_Delay)
			{
				WriteBurstReg(RF_TXFIFOWR, data,  length);
				do_tx(data, length, (unsigned long) length * (unsigned long) Button_Repeat);
			}
			else
				// no FIFO
				for(i= 0 ; i < Button_Repeat ; ++i)
				{
					WriteBurstReg(RF_TXFIFOWR, data, length);
					do_tx(data, length, (unsigned long) length);
					// pause between bursts
					Timer0_A4_Delay(CONV_MS_TO_TICKS(Button_Delay));
				}
		}
	}
	while(BUTTON_DOWN_IS_PRESSED||BUTTON_UP_IS_PRESSED)
		;

	// power down radio
	Strobe(RF_SPWD);

	//Clear RF symbol
	display_symbol(LCD_ICON_BEEPER1, SEG_OFF);
	display_symbol(LCD_ICON_BEEPER2, SEG_OFF);
	display_symbol(LCD_ICON_BEEPER3, SEG_OFF);
}

// up button transmit
void chronic_tx_up(u8 line)
{
	chronic_tx(Button_Up_Data, Up_Buttons);
}

// down button transmit
void chronic_tx_down(u8 line)
{
	chronic_tx(Button_Down_Data, Down_Buttons);
}

// config RF
void chronic_config_rf(void)
{
  PMMCTL0_H = 0xA5;
  PMMCTL0_L |= PMMHPMRE_L;
  PMMCTL0_H = 0x00;

  // set RF
  WriteRfSettings(&ChronicRF);
  // set output power
  WriteBurstPATable(&Chronic_PA_Table[0],2);
}

// *************************************************************************************************
// RF1A extensions
// *************************************************************************************************
// *************************************************************************************************
// @fn          WriteBurstPATable
// @brief       Write to multiple locations in power table
// @param       unsigned char *buffer	Pointer to the table of values to be written
// @param       unsigned char count	Number of values to be written
// @return      none
// *************************************************************************************************
void WriteBurstPATable(unsigned char *buffer, unsigned char count)
{
  volatile char i = 0;
  u16 int_state;

  ENTER_CRITICAL_SECTION(int_state);
  while( !(RF1AIFCTL1 & RFINSTRIFG));
  RF1AINSTRW = 0x7E00 + buffer[i];          // PA Table burst write

  for (i = 1; i < count; i++)
  {
    RF1ADINB = buffer[i];                   // Send data
    while (!(RFDINIFG & RF1AIFCTL1));       // Wait for TX to finish
  }
  i = RF1ADOUTB;                            // Reset RFDOUTIFG flag which contains status byte

  while( !(RF1AIFCTL1 & RFINSTRIFG));
  RF1AINSTRB = RF_SNOP;                     // reset PA Table pointer

  EXIT_CRITICAL_SECTION(int_state);
}

// *****************************************************************************
// @fn          WriteRfSettings
// @brief       Write the minimum set of RF configuration register settings
// @param       RADIO_REGS *pRfSettings  Pointer to the structure that holds the rf settings
// @return      none
// *****************************************************************************
void WriteRfSettings(RADIO_REGS *pRfSettings) {
	WriteSingleReg(IOCFG2,   pRfSettings->iocfg2);
    WriteSingleReg(IOCFG1,   pRfSettings->iocfg1);
    WriteSingleReg(IOCFG0,   pRfSettings->iocfg0);
    WriteSingleReg(FIFOTHR,  pRfSettings->fifothr);
    WriteSingleReg(SYNC1,    pRfSettings->sync1);
    WriteSingleReg(SYNC0,    pRfSettings->sync0);
    //WriteSingleReg(PKTLEN,   pRfSettings->pktlen); // packet length is set by transmit
    WriteSingleReg(PKTCTRL1, pRfSettings->pktctrl1);
    WriteSingleReg(PKTCTRL0, pRfSettings->pktctrl0);
    WriteSingleReg(ADDR,     pRfSettings->addr);
    WriteSingleReg(CHANNR,   pRfSettings->channr);
    WriteSingleReg(FREQ2,    pRfSettings->freq2);
    WriteSingleReg(FREQ1,    pRfSettings->freq1);
    WriteSingleReg(FREQ0,    pRfSettings->freq0);

    WriteSingleReg(MDMCFG4,  pRfSettings->mdmcfg4);
    WriteSingleReg(MDMCFG3,  pRfSettings->mdmcfg3);
    WriteSingleReg(MDMCFG2,  pRfSettings->mdmcfg2);
    WriteSingleReg(MDMCFG1,  pRfSettings->mdmcfg1);
    WriteSingleReg(MDMCFG0,  pRfSettings->mdmcfg0);
    WriteSingleReg(DEVIATN,  pRfSettings->deviatn);

    WriteSingleReg(MCSM0 ,   pRfSettings->mcsm0);
    WriteSingleReg(FOCCFG,   pRfSettings->foccfg);
    WriteSingleReg(BSCFG,    pRfSettings->bscfg);

    WriteSingleReg(FSCTRL1,  pRfSettings->fsctrl1);
    WriteSingleReg(FSCTRL0,  pRfSettings->fsctrl0);

    WriteSingleReg(FREND1,   pRfSettings->frend1);
    WriteSingleReg(FREND0,   pRfSettings->frend0);

    WriteSingleReg(FSCAL3,   pRfSettings->fscal3);
    WriteSingleReg(FSCAL2,   pRfSettings->fscal2);
    WriteSingleReg(FSCAL1,   pRfSettings->fscal1);
    WriteSingleReg(FSCAL0,   pRfSettings->fscal0);

    WriteSingleReg(AGCCTRL2, pRfSettings->agcctrl2);
    WriteSingleReg(AGCCTRL1, pRfSettings->agcctrl1);
    WriteSingleReg(AGCCTRL0, pRfSettings->agcctrl0);

    //WriteSingleReg(FSTEST,   pRfSettings->fstest);
    WriteSingleReg(TEST2,    pRfSettings->test2);
    WriteSingleReg(TEST1,    pRfSettings->test1);
    WriteSingleReg(TEST0,    pRfSettings->test0);
}

