3D Low Frequency Wakeup Receiver
AS3933.cpp
- Committer:
- mcm
- Date:
- 2018-03-07
- Revision:
- 3:2de552c4ffbc
- Parent:
- 2:c3435a136e50
- Child:
- 4:10d482ca4eb1
File content as of revision 3:2de552c4ffbc:
/** * @brief AS3933.cpp * @details 3D Low Frequency Wakeup Receiver. * Function file. * * * @return N/A * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A * @pre This code belongs to Nimbus Centre ( http://unbarquero.blogspot.com ). */ #include "AS3933.h" AS3933::AS3933 ( PinName mosi, PinName miso, PinName sclk, PinName cs, uint32_t freq ) : _spi ( mosi, miso, sclk ) , _cs ( cs ) { _spi.frequency( freq ); _spi.format ( 8, 1 ); // 8-bits, mode1: CPOL = 0 | CPHA = 1 } AS3933::~AS3933() { } /** * @brief AS3933_SetLowPowerMode ( AS3933_channels_enable_t , AS3933_scanning_mode_t , AS3933_r4_t_off_value_t ) * * @details It configures the low power mode. * * @param[in] myEnabledChannels: Number of channels enabled. * @param[in] myLowPowerMode: Low power mode. * @param[in] myT_Off: Period only if ON/OFF mode is selected ( in myLowPowerMode ), it is ignored otherwise. * * @param[out] N/A. * * * @return Status of AS3933_SetLowPowerMode. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A * @warning Data-sheet p.14 8.1.1 Listening Mode. It is NOT clear which channels have to be enabled according to the * low power mode: '...If the three dimensional detection is not required, then it is possible to deactivate one * or more channels. In case only two channels are required, then the deactivated channel must be the number * three; while in case only one channel is needed, then the active channel must be the number one'. * * Data-sheet p.37 8.10 Channel Selection in Scanning Mode and ON/OFF Mode: 'In case only 2 channels are active and * one of the Low Power modes is enabled, then the channels 1 and 3 have to be active. If the chip works in On-Off * mode and only one channel is active then the active channel has to be the channel 1.'. * * This function follows the methodology in: Low Power Modes/Channels enabled: Data-sheet p.37 8.10 Channel * Selection in Scanning Mode and ON/OFF Mode. */ AS3933::AS3933_status_t AS3933::AS3933_SetLowPowerMode ( AS3933_channels_enable_t myEnabledChannels, AS3933_scanning_mode_t myLowPowerMode, AS3933_r4_t_off_value_t myT_Off ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R0 register cmd[0] = ( AS3933_READ | AS3933_R0 ); mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); // Mask Channels 1:3 cmd[1] &= ~( EN_A1_MASK | EN_A2_MASK | EN_A3_MASK ); // Mask Scanning Mode cmd[1] &= ~( MUX_123_MASK | ON_OFF_MASK ); // Set the channels enabled switch ( myEnabledChannels ) { case AS3933_CH1_OFF_CH2_OFF_CH3_OFF: cmd[1] &= ( EN_A1_DISABLED | EN_A2_DISABLED | EN_A3_DISABLED ); break; case AS3933_CH1_ON_CH2_OFF_CH3_OFF: cmd[1] |= ( EN_A1_ENABLED ); break; case AS3933_CH1_OFF_CH2_ON_CH3_OFF: cmd[1] |= ( EN_A2_ENABLED ); break; case AS3933_CH1_ON_CH2_ON_CH3_OFF: cmd[1] |= ( EN_A1_ENABLED | EN_A2_ENABLED ); break; case AS3933_CH1_OFF_CH2_OFF_CH3_ON: cmd[1] |= ( EN_A3_ENABLED ); break; case AS3933_CH1_ON_CH2_OFF_CH3_ON: cmd[1] |= ( EN_A1_ENABLED | EN_A3_ENABLED ); break; case AS3933_CH1_OFF_CH2_ON_CH3_ON: cmd[1] |= ( EN_A2_ENABLED | EN_A3_ENABLED ); break; default: case AS3933_CH1_ON_CH2_ON_CH3_ON: cmd[1] |= ( EN_A1_ENABLED | EN_A2_ENABLED | EN_A3_ENABLED ); break; } // Set Scanning mode switch ( myLowPowerMode ) { default: case AS3933_STANDARD_LISTENING_MODE: break; case AS3933_SCANNING_MODE: if ( ( myEnabledChannels == AS3933_CH1_ON_CH2_OFF_CH3_ON ) || ( myEnabledChannels == AS3933_CH1_ON_CH2_ON_CH3_ON ) || ( myEnabledChannels == AS3933_CH1_ON_CH2_OFF_CH3_OFF ) || ( myEnabledChannels == AS3933_CH1_OFF_CH2_ON_CH3_OFF ) || ( myEnabledChannels == AS3933_CH1_OFF_CH2_OFF_CH3_ON ) ) cmd[1] |= ( MUX_123_ENABLED ); else return AS3933_FAILURE; break; case AS3933_ON_OFF_MODE: if ( ( myEnabledChannels == AS3933_CH1_ON_CH2_OFF_CH3_ON ) || ( myEnabledChannels == AS3933_CH1_ON_CH2_ON_CH3_ON ) || ( myEnabledChannels == AS3933_CH1_ON_CH2_OFF_CH3_OFF ) ) cmd[1] |= ( ON_OFF_ENABLED ); else return AS3933_FAILURE; break; } // Update power mode and active channels cmd[0] = ( AS3933_WRITE | AS3933_R0 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( myLowPowerMode == AS3933_ON_OFF_MODE ) { // Read R4 register cmd[0] = ( AS3933_READ | AS3933_R4 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask T_OFF cmd[1] &= ~( T_OFF_MASK ); // Update Off time in ON/OFF operation mode cmd[1] |= ( myT_Off ); cmd[0] = ( AS3933_WRITE | AS3933_R4 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; } if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetArtificialWakeUp ( AS3933_r8_t_auto_value_t ) * * @details It configures the artificial wakeup. * * @param[in] myArtificialWakeUp: Period only if ON/OFF mode is selected ( in myLowPowerMode ), it is ignored otherwise. * * @param[out] N/A. * * * @return Status of AS3933_SetArtificialWakeUp. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetArtificialWakeUp ( AS3933_r8_t_auto_value_t myArtificialWakeUp ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R8 register cmd[0] = ( AS3933_READ | AS3933_R8 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Artificial wakeup cmd[1] &= ~( T_AUTO_MASK ); // Update the value cmd[1] |= myArtificialWakeUp; // Update artificial wakeup cmd[0] = ( AS3933_WRITE | AS3933_R8 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_ReadFalseWakeUpRegister ( AS3933_data_t* ) * * @details It gets feedback on the surrounding environment reading the false wakeup register. * * @param[in] N/A * * @param[out] myF_WAKE: F_WAKE register. * * * @return Status of AS3933_ReadFalseWakeUpRegister. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_ReadFalseWakeUpRegister ( AS3933_data_t* myF_WAKE ) { char cmd[] = { ( AS3933_READ | AS3933_R13 ), 0 }; int mySPI_status; // Read R13 register _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; myF_WAKE->f_wake = cmd[1]; if ( mySPI_status == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetClockGenerator ( AS3933_r1_en_xtal_value_t, AS3933_r16_clock_gen_dis_value_t ) * * @details It configures the clock generator. * * @param[in] myClockGenerator: Enable/Disable external crystal oscillator. * @param[in] myClockGeneratorOutputMode: Enable/Disable the clock generator output signal displayed on CL_DAT pin. * * @param[out] N/A. * * * @return Status of AS3933_SetClockGenerator. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetClockGenerator ( AS3933_r1_en_xtal_value_t myClockGenerator, AS3933_r16_clock_gen_dis_value_t myClockGeneratorOutputMode ) { char cmd[] = { 0, 0 }; int mySPI_status; // Configure the Crystal oscillator // Read R1 register cmd[0] = ( AS3933_READ | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Crystal oscillator cmd[1] &= ~( EN_XTAL_MASK ); // Update the value cmd[1] |= myClockGenerator; // Update Crystal oscillator cmd[0] = ( AS3933_WRITE | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; // Configure the Clock Generator Output // Read R16 register cmd[0] = ( AS3933_READ | AS3933_R16 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Clock Generator output signal cmd[1] &= ~( CLOCK_GEN_DIS_MASK ); // Update the value cmd[1] |= myClockGeneratorOutputMode; // Update Clock Generator output signal cmd[0] = ( AS3933_WRITE | AS3933_R16 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_CalibrateRC_Oscillator ( AS3933_r1_en_xtal_value_t, AS3933_r16_clock_gen_dis_value_t ) * * @details It calibrates RC oscillator. * * @param[in] N/A * * @param[out] N/A. * * * @return Status of AS3933_CalibrateRC_Oscillator. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre RC-Oscillator: Self Calibration is ONLY available. * @warning In case the pattern detection and the Manchester decoder are not enabled ( R1<1>=0 and R1<3>=1 ) the calibration on the RC-oscillator * is not needed. Should this not be the case, the RC-oscillator has to be calibrated. */ AS3933::AS3933_status_t AS3933::AS3933_CalibrateRC_Oscillator ( void ) { char cmd[] = { 0, 0 }; uint32_t myTimeout = 0; int mySPI_status; // Start the calibration cmd[0] = ( AS3933_DIRECT_COMMAND | CALIB_RCO_LC ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 0 ); _cs = 0; // RC oscillator will be calibrated when RC_CAL_OK = '1' ( R14<6> ) myTimeout = 23232323; do{ cmd[0] = ( AS3933_READ | AS3933_R14 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; myTimeout--; } while ( ( ( cmd[1] & RC_CAL_OK_MASK ) != RC_CAL_OK_HIGH ) && ( myTimeout > 0 ) ); if ( ( mySPI_status == SPI_SUCCESS ) && ( myTimeout > 0 ) ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetAntennaDamper ( AS3933_r1_att_on_value_t, AS3933_r4_d_res_value_t ) * * @details It configures the antenna damper and its shunt resistor. * * @param[in] myAntennaDamperMode: Enable/Disable antenna dumper. * @param[in] myShuntResistor: Configure antenna dumping resistor. * * @param[out] N/A. * * * @return Status of AS3933_SetAntennaDamper. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetAntennaDamper ( AS3933_r1_att_on_value_t myAntennaDamperMode, AS3933_r4_d_res_value_t myShuntResistor ) { char cmd[] = { 0, 0 }; int mySPI_status; // Configure Antenna dumper // Read R1 register cmd[0] = ( AS3933_READ | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Antenna dumper cmd[1] &= ~( ATT_ON_MASK ); // Update Antenna dumper cmd[0] = ( AS3933_WRITE | AS3933_R1 ); cmd[1] |= ( myAntennaDamperMode ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; // Configure Antenna dumper resistor // Read R4 register cmd[0] = ( AS3933_READ | AS3933_R4 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Antenna dumper resistor cmd[1] &= ~( D_RES_MASK ); // Update Antenna dumper resistor cmd[0] = ( AS3933_WRITE | AS3933_R4 ); cmd[1] |= ( myShuntResistor ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetEnvelopDetector ( AS3933_r3_fs_env_value_t ) * * @details It configures the envelop detector for different symbol rates. * * @param[in] mySymbolRates: Envelop detector time constant. * * @param[out] N/A. * * * @return Status of AS3933_SetEnvelopDetector. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetEnvelopDetector ( AS3933_r3_fs_env_value_t mySymbolRates ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R3 register cmd[0] = ( AS3933_READ | AS3933_R3 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Symbol rate cmd[1] &= ~( FS_ENV_MASK ); // Update symbol rate cmd[0] = ( AS3933_WRITE | AS3933_R3 ); cmd[1] |= ( mySymbolRates ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetDataSlicer ( AS3933_r1_abs_hy_value_t , AS3933_r3_fs_scl_value_t ) * * @details It configures the data slicer for different preamble length. * * @param[in] myAbsoluteThresholdMode: Enable Data slicer absolute reference. * @param[in] myMinimumPreambleLength: Data slices time constant. * * @param[out] N/A. * * * @return Status of AS3933_SetDataSlicer. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetDataSlicer ( AS3933_r1_abs_hy_value_t myAbsoluteThresholdMode, AS3933_r3_fs_scl_value_t myMinimumPreambleLength ) { char cmd[] = { 0, 0 }; int mySPI_status; // Configure Data slicer absolute reference // Read R1 register cmd[0] = ( AS3933_READ | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Data slicer absolute reference cmd[1] &= ~( ABS_HY_MASK ); // Update symbol rate cmd[0] = ( AS3933_WRITE | AS3933_R1 ); cmd[1] |= ( myAbsoluteThresholdMode ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; // Configure Data slices time constant // Read R3 register cmd[0] = ( AS3933_READ | AS3933_R3 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Data slices time constant cmd[1] &= ~( FS_SCL_MASK ); // Update Data slices time constant cmd[0] = ( AS3933_WRITE | AS3933_R3 ); cmd[1] |= ( myMinimumPreambleLength ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetComparatorHysteresis ( AS3933_r3_hy_pos_value_t , AS3933_r3_hy_20m_value_t ) * * @details It configures the hysteresis on the data slicer comparator. * * @param[in] myHysteresisMode: Data slicer hysteresis, edge. * @param[in] myHysteresisRange: Data slicer hysteresis, comparator. * * @param[out] N/A. * * * @return Status of AS3933_SetComparatorHysteresis. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetComparatorHysteresis ( AS3933_r3_hy_pos_value_t myHysteresisMode, AS3933_r3_hy_20m_value_t myHysteresisRange ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R3 register cmd[0] = ( AS3933_READ | AS3933_R3 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask both hysteresis edge and comparator cmd[1] &= ~( HY_POS_MASK | HY_20M_MASK ); // Update hysteresis on the data slicer comparator cmd[0] = ( AS3933_WRITE | AS3933_R3 ); cmd[1] |= ( myHysteresisMode | myHysteresisRange ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetGainReduction ( AS3933_r4_gr_value_t ) * * @details It configures the gain reduction. * * @param[in] myGainReductionValue: Gain reduction. * * @param[out] N/A. * * * @return Status of AS3933_SetGainReduction. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetGainReduction ( AS3933_r4_gr_value_t myGainReductionValue ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R4 register cmd[0] = ( AS3933_READ | AS3933_R4 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Gain reduction cmd[1] &= ~( GR_MASK ); // Update Gain reduction cmd[0] = ( AS3933_WRITE | AS3933_R4 ); cmd[1] |= ( myGainReductionValue ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetOperatingFrequencyRange ( AS3933_r8_band_sel_value_t ) * * @details It configures the operating frequency range. * * @param[in] myOperatingFrequencyRange: Band selection. * * @param[out] N/A. * * * @return Status of AS3933_SetOperatingFrequencyRange. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetOperatingFrequencyRange ( AS3933_r8_band_sel_value_t myOperatingFrequencyRange ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R8 register cmd[0] = ( AS3933_READ | AS3933_R8 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Band selection cmd[1] &= ~( BAND_SEL_MASK ); // Update Band selection cmd[0] = ( AS3933_WRITE | AS3933_R8 ); cmd[1] |= ( myOperatingFrequencyRange ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetFrequencyDetectionTolerance ( AS3933_tolerance_settings_t ) * * @details It configures the frequency detection tolerance. * * @param[in] myTolerance: Tolerance band. * * @param[out] N/A. * * * @return Status of AS3933_SetFrequencyDetectionTolerance. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetFrequencyDetectionTolerance ( AS3933_tolerance_settings_t myTolerance ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R2 register cmd[0] = ( AS3933_READ | AS3933_R2 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Tolerance band cmd[1] &= ~( AS3933_TOLERANCE_MASK ); // Update Tolerance band cmd[0] = ( AS3933_WRITE | AS3933_R2 ); cmd[1] |= ( myTolerance ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetGainBoost ( AS3933_r2_g_boost_value_t ) * * @details It configures the +3dB gain boost. * * @param[in] myGainBoostMode: Enable/Disable +3dB Amplifier Gain Boost. * * @param[out] N/A. * * * @return Status of AS3933_SetGainBoost. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetGainBoost ( AS3933_r2_g_boost_value_t myGainBoostMode ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R2 register cmd[0] = ( AS3933_READ | AS3933_R2 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Gain boost cmd[1] &= ~( G_BOOST_MASK ); // Update Gain boost cmd[0] = ( AS3933_WRITE | AS3933_R2 ); cmd[1] |= ( myGainBoostMode ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetAGC ( AS3933_r1_agc_tlim_value_t , AS3933_r1_agc_ud_value_t ) * * @details It configures the Automatic Gain Control ( AGC ). * * @param[in] myAGC_CarrierBurstMode: Enable/Disable AGC acting only on the first carrier burst. * @param[in] myAGC_OperatingDirection: Configure AGC direction operating. * * @param[out] N/A. * * * @return Status of AS3933_SetAGC. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetAGC ( AS3933_r1_agc_tlim_value_t myAGC_CarrierBurstMode, AS3933_r1_agc_ud_value_t myAGC_OperatingDirection ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R1 register cmd[0] = ( AS3933_READ | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask both AGC acting only on the first carrier burst and AGC direction operating cmd[1] &= ~( AGC_TLIM_MASK | AGC_UD_MASK ); // Update both AGC acting only on the first carrier burst and AGC direction operating cmd[0] = ( AS3933_WRITE | AS3933_R1 ); cmd[1] |= ( myAGC_CarrierBurstMode | myAGC_OperatingDirection ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetDataMask ( AS3933_r0_dat_mask_value_t ) * * @details It configures the mask data before wakeup. * * @param[in] myDataMaskMode: Mask data on DAT pin before wakeup happens. * * @param[out] N/A. * * * @return Status of AS3933_SetDataMask. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetDataMask ( AS3933_r0_dat_mask_value_t myDataMaskMode ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R0 register cmd[0] = ( AS3933_READ | AS3933_R0 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Mask data on DAT pin before wakeup happens cmd[1] &= ~( DAT_MASK_MASK ); // Update Mask data on DAT pin before wakeup happens cmd[0] = ( AS3933_WRITE | AS3933_R0 ); cmd[1] |= ( myDataMaskMode ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetCorrelator ( AS3933_r1_en_wpat_value_t , AS3933_r0_patt32_value_t , AS3933_r7_t_hbit_value_t , AS3933_r1_en_manch_value_t ) * * @details It configures the correlator and the Manchester Decoder. * * @param[in] myCorrelatorMode: Enable/Disable Correlator. * @param[in] mySymbolPattern: Pattern extended. * @param[in] myRate: Bit rate definition. * @param[in] myManchesterDecoderMode: Enable/Disable Manchester decoder. * * @param[out] N/A. * * * @return Status of AS3933_SetCorrelator. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetCorrelator ( AS3933_r1_en_wpat_value_t myCorrelatorMode, AS3933_r0_patt32_value_t mySymbolPattern, AS3933_r7_t_hbit_value_t myRate, AS3933_r1_en_manch_value_t myManchesterDecoderMode ) { char cmd[] = { 0, 0 }; int mySPI_status; // Configure Correlator mode and Manchester decoder mode // Read R1 register cmd[0] = ( AS3933_READ | AS3933_R1 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask both Correlator mode and Manchester decoder mode cmd[1] &= ~( EN_WPAT_MASK | EN_MANCH_MASK ); // Update both Correlator mode and Manchester decoder mode cmd[0] = ( AS3933_WRITE | AS3933_R1 ); cmd[1] |= ( myCorrelatorMode | myManchesterDecoderMode ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; // Configure Pattern extended // Read R0 register cmd[0] = ( AS3933_READ | AS3933_R0 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[1], 1 ); _cs = 0; // Mask Pattern extended cmd[1] &= ~( PATT32_MASK ); // Update Pattern extended cmd[0] = ( AS3933_WRITE | AS3933_R0 ); cmd[1] |= ( mySymbolPattern ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; // Configure Bit rate definition // Read R7 register cmd[0] = ( AS3933_READ | AS3933_R7 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Bit rate definition cmd[1] &= ~( T_HBIT_MASK ); // Update Bit rate definition cmd[0] = ( AS3933_WRITE | AS3933_R7 ); cmd[1] |= ( myRate ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetWakeUpPattern ( AS3933_data_t ) * * @details It sets the wakeup pattern ( Manchester ). * * @param[in] myWakeUpPattern: PATT1B and PATT2B ( Manchester ). * * @param[out] N/A. * * * @return Status of AS3933_SetWakeUpPattern. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetWakeUpPattern ( AS3933_data_t myWakeUpPattern ) { char cmd[] = { 0, 0 }; int mySPI_status; // Update PATT2B cmd[0] = ( AS3933_WRITE | AS3933_R5 ); cmd[1] = ( myWakeUpPattern.patt2b ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 1 ); _cs = 0; // Update PATT1B cmd[0] = ( AS3933_WRITE | AS3933_R6 ); cmd[1] = ( myWakeUpPattern.patt1b ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 1 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_GetWakeUpPattern ( AS3933_data_t* ) * * @details It gets the wakeup pattern ( Manchester ). * * @param[in] N/A * * @param[out] myWakeUpPattern: PATT1B and PATT2B ( Manchester ). * * * @return Status of AS3933_GetWakeUpPattern. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_GetWakeUpPattern ( AS3933_data_t* myWakeUpPattern ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R5 register cmd[0] = ( AS3933_READ | AS3933_R5 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; myWakeUpPattern->patt2b = cmd[1]; // Read R6 register cmd[0] = ( AS3933_READ | AS3933_R6 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; myWakeUpPattern->patt1b = cmd[1]; if ( mySPI_status == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetAutomaticTimeOut ( AS3933_r7_t_out_value_t ) * * @details It sets the automatic time-out setup. * * @param[in] myAutomaticTimeOut: Automatic time-out. * * @param[out] N/A. * * * @return Status of AS3933_SetAutomaticTimeOut. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetAutomaticTimeOut ( AS3933_r7_t_out_value_t myAutomaticTimeOut ) { char cmd[] = { 0, 0 }; int mySPI_status; // Read R7 register cmd[0] = ( AS3933_READ | AS3933_R7 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Automatic time-out cmd[1] &= ~( T_OUT_MASK ); // Update Automatic time-out cmd[0] = ( AS3933_WRITE | AS3933_R7 ); cmd[1] |= ( myAutomaticTimeOut ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_SetParallelTuningCapacitance ( AS3933_parallel_tuning_channels_t , AS3933_parallel_tuning_capacitance_t ) * * @details It sets the parallel tuning capacitance on the chosen channel. * * @param[in] myChannel: Channel for Parallel Tuning Capacitance. * @param[in] myAddedCapacitance: Parallel Tuning Capacitance. * * @param[out] N/A. * * * @return Status of AS3933_SetParallelTuningCapacitance. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_SetParallelTuningCapacitance ( AS3933_parallel_tuning_channels_t myChannel, AS3933_parallel_tuning_capacitance_t myAddedCapacitance ) { char cmd[] = { 0, 0 }; int mySPI_status; AS3933_spi_command_structure_registers_t myAuxRegister; // Select the channel switch ( myChannel ){ default: case AS3933_CHANNEL_LF1P: myAuxRegister = AS3933_R17; break; case AS3933_CHANNEL_LF2P: myAuxRegister = AS3933_R18; break; case AS3933_CHANNEL_LF3P: myAuxRegister = AS3933_R19; break; } // Read register cmd[0] = ( AS3933_READ | myAuxRegister ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], 2 ); _cs = 0; // Mask Parallel Tuning Capacitance cmd[1] &= ~( AS3933_CAPACITANCE_MASK ); // Update Parallel Tuning Capacitance cmd[0] = ( AS3933_WRITE | myAuxRegister ); cmd[1] |= ( myAddedCapacitance ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), &cmd[0], 0 ); _cs = 0; if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_GetRSSI ( AS3933_data_t* ) * * @details It gets the RSSI for all channels. * * @param[in] mySPI_parameters: N/A * * @param[out] myChannelRSSI: RSSI. * * * @return Status of AS3933_GetRSSI. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_GetRSSI ( AS3933_data_t* myChannelRSSI ) { char cmd[] = { 0, 0, 0 }; int mySPI_status; // Get All RSSIs // Read R10 register ( auto-increment ) cmd[0] = ( AS3933_READ | AS3933_R10 ); _cs = 1; mySPI_status = _spi.write ( &cmd[0], 1, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); _cs = 0; // Parse the data myChannelRSSI->rssi1 = ( cmd[0] & RSSI1_MASK ); // Channel1: RSSI1 myChannelRSSI->rssi3 = ( cmd[1] & RSSI3_MASK ); // Channel3: RSSI3 myChannelRSSI->rssi2 = ( cmd[2] & RSSI2_MASK ); // Channel2: RSSI2 if ( ( mySPI_status / ( sizeof( cmd )/sizeof( cmd[0] ) ) ) == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; } /** * @brief AS3933_Send_DirectCommand ( AS3933_spi_direct_commands_t ) * * @details It sends a direct command. * * @param[in] myDirectCommand: Direct command to be sent. * * @param[out] N/A. * * * @return Status of AS3933_Send_DirectCommand. * * * @author Manuel Caballero * @date 7/March/2018 * @version 7/March/2018 The ORIGIN * @pre N/A. * @warning N/A. */ AS3933::AS3933_status_t AS3933::AS3933_Send_DirectCommand ( AS3933_spi_direct_commands_t myDirectCommand ) { char cmd = 0; int mySPI_status; // Send a direct command cmd = ( AS3933_DIRECT_COMMAND | myDirectCommand ); _cs = 1; mySPI_status = _spi.write ( &cmd, 1, &cmd, 0 ); _cs = 0; if ( mySPI_status == SPI_SUCCESS ) return AS3933_SUCCESS; else return AS3933_FAILURE; }