2015-07-08 08:39:24 -07:00
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "max2837.hpp"
#include "hackrf_hal.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf :: one ;
#include "ch.h"
#include "hal.h"
#include <algorithm>
namespace max2837 {
2023-02-16 12:09:23 +00:00
using namespace max283x ;
2015-07-08 08:39:24 -07:00
namespace lna {
2023-02-16 12:09:23 +00:00
using namespace max283x :: lna ;
2023-05-19 08:16:05 +12:00
constexpr std :: array < uint8_t , 8 > lookup_8db_steps {
0b111 , 0b011 , 0b110 , 0b010 ,
0b100 , 0b000 , 0b000 , 0b000 };
2015-07-08 08:39:24 -07:00
static uint_fast8_t gain_ordinal ( const int8_t db ) {
2023-05-19 08:16:05 +12:00
const auto db_sat = gain_db_range . clip ( db );
return lna :: lookup_8db_steps [( db_sat >> 3 ) & 7 ];
2015-07-08 08:39:24 -07:00
}
} /* namespace lna */
namespace vga {
2023-02-16 12:09:23 +00:00
using namespace max283x :: vga ;
2015-07-08 08:39:24 -07:00
static uint_fast8_t gain_ordinal ( const int8_t db ) {
2023-05-19 08:16:05 +12:00
const auto db_sat = gain_db_range . clip ( db );
return (( db_sat >> 1 ) & 0b11111 ) ^ 0b11111 ;
2015-07-08 08:39:24 -07:00
}
} /* namespace vga */
2016-08-03 16:12:01 -07:00
namespace tx {
2023-02-16 12:09:23 +00:00
using namespace max283x :: tx ;
2016-08-03 16:12:01 -07:00
static uint_fast8_t gain_ordinal ( const int8_t db ) {
2023-05-19 08:16:05 +12:00
const auto db_sat = gain_db_range . clip ( db );
uint8_t value = db_sat & 0x0f ;
value = ( db_sat >= 16 ) ? ( value | 0x20 ) : value ;
value = ( db_sat >= 32 ) ? ( value | 0x10 ) : value ;
return ( value & 0b111111 ) ^ 0b111111 ;
2016-08-03 16:12:01 -07:00
}
} /* namespace tx */
2015-07-08 08:39:24 -07:00
namespace filter {
2023-02-16 12:09:23 +00:00
using namespace max283x :: filter ;
2015-07-08 08:39:24 -07:00
static uint_fast8_t bandwidth_ordinal ( const uint32_t bandwidth ) {
2023-05-19 08:16:05 +12:00
/* Determine filter setting that will provide bandwidth greater than or
* equal to requested bandwidth.
*/
return std :: lower_bound ( bandwidths . cbegin (), bandwidths . cend (), bandwidth ) - bandwidths . cbegin ();
2015-07-08 08:39:24 -07:00
}
} /* namespace filter */
/* Empirical testing indicates about 25us is necessary to get a valid
* temperature sense conversion from the ADC.
*/
constexpr float seconds_for_temperature_sense_adc_conversion = 30.0e-6 ;
constexpr halrtcnt_t ticks_for_temperature_sense_adc_conversion = ( base_m4_clk_f * seconds_for_temperature_sense_adc_conversion + 1 );
2023-02-16 12:09:23 +00:00
constexpr uint32_t reference_frequency = max283x_reference_f ;
2015-07-08 08:39:24 -07:00
constexpr uint32_t pll_factor = 1.0 / ( 4.0 / 3.0 / reference_frequency ) + 0.5 ;
void MAX2837 :: init () {
2023-05-19 08:16:05 +12:00
set_mode ( Mode :: Shutdown );
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
gpio_max283x_enable . output ();
gpio_max2837_rxenable . output ();
gpio_max2837_txenable . output ();
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . tx_gain . TXVGA_GAIN_SPI_EN = 1 ;
_map . r . tx_gain . TXVGA_GAIN_MSB_SPI_EN = 1 ;
_map . r . tx_gain . TXVGA_GAIN_SPI = 0x00 ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . lpf_3_vga_1 . VGAMUX_enable = 1 ;
_map . r . lpf_3_vga_1 . VGA_EN = 1 ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . hpfsm_3 . HPC_STOP = 1 ; /* 1kHz */
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . rx_top_rx_bias . LNAgain_SPI_EN = 1 ; /* control LNA gain from SPI */
_map . r . rxrf_2 . L = 0b000 ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . rx_top_rx_bias . VGAgain_SPI_EN = 1 ; /* control VGA gain from SPI */
_map . r . vga_2 . VGA = 0b01010 ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . lpf_3_vga_1 . BUFF_VCM = 0b00 ; /* TODO: Check values out of ADC */
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . lpf_1 . LPF_EN = 1 ; /* Enable low-pass filter */
_map . r . lpf_1 . ModeCtrl = 0b01 ; /* Rx LPF */
2023-10-08 17:50:31 +02:00
_map . r . lpf_1 . FT = 0b0000 ; /* 1,75MHz LPF */
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . spi_en . EN_SPI = 1 ; /* enable chip functions when ENABLE pin set */
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . lo_gen . LOGEN_2GM = 0 ;
2015-07-08 08:39:24 -07:00
#if 0
_map.r.rxrf_1.LNA_EN = 1;
_map.r.rxrf_1.Mixer_EN = 1;
_map.r.rxrf_1.RxLO_EN = 1;
_map.r.rx_top.DOUT_DRVH = 0; /* slow down DOUT edges */
_map.r.hpfsm_4.DOUT_CSB_SEL = 0; /* DOUT not tri-stated, is independent of CSB */
_map.r.xtal_cfg.XTAL_CLKOUT_EN = 0; /* CLKOUT pin disabled. (Seems to have no effect.) */
#endif
2023-05-19 08:16:05 +12:00
_map . r . vga_3_rx_top . RSSI_EN_SPIenables = 1 ;
_map . r . vga_3_rx_top . RSSI_MODE = 1 ; /* RSSI independent of RXHP */
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_dirty . set ();
flush ();
2015-12-17 20:59:21 -08:00
2023-05-19 08:16:05 +12:00
set_mode ( Mode :: Standby );
2015-07-08 08:39:24 -07:00
}
2024-02-04 00:57:45 +01:00
void MAX2837 :: set_tx_LO_iq_phase_calibration ( const size_t v ) {
2024-03-18 15:45:02 -05:00
Mode saved_mode = get_mode ();
2024-03-09 23:46:38 +01:00
/* TX IQ phase deg CAL adj (+4 ...-4) in 32 steps (5 bits), 00000 = +4deg (Q lags I by 94degs, default), 01111 = +0deg, 11111 = -4deg (Q lags I by 86degs) */
2024-02-04 00:57:45 +01:00
// TX calibration , Logic pins , ENABLE, RXENABLE, TXENABLE = 1,0,1 (5dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode ( Mode :: Tx_Calibration ); // write to ram 3 LOGIC Pins .
gpio_max283x_enable . output ();
gpio_max2837_rxenable . output ();
gpio_max2837_txenable . output ();
_map . r . spi_en . CAL_SPI = 1 ; // Register Settings reg address 16, D1 (CAL mode 1)
_map . r . spi_en . EN_SPI = 1 ; // Register Settings reg address 16, DO (CHIP ENABLE 1)
flush_one ( Register :: SPI_EN );
_map . r . tx_lo_iq . TXLO_IQ_SPI_EN = 1 ; // reg 30 D5, TX LO I/Q Phase SPI Adjust. Active when Address 30 D5 (TXLO_IQ_SPI_EN) = 1.
_map . r . tx_lo_iq . TXLO_IQ_SPI = v ; // reg 30 D4:D0, TX LO I/Q Phase SPI Adjust.
flush_one ( Register :: TX_LO_IQ );
// Exit Calibration mode, Go back to reg 16, D1:D0 , Out of CALIBRATION , back to default conditions, but keep CS activated.
_map . r . spi_en . CAL_SPI = 0 ; // Register Settings reg address 16, D1 (0 = Normal operation (default)
_map . r . spi_en . EN_SPI = 1 ; // Register Settings reg address 16, DO (1 = Chip select enable )
flush_one ( Register :: SPI_EN );
2024-03-18 15:45:02 -05:00
set_mode ( saved_mode ); // restore original mode
2024-02-04 00:57:45 +01:00
}
enum class Mask { // There are class Mask ,and class mode with same names, but they are not same.
2023-05-19 08:16:05 +12:00
Enable = 0b001 ,
RxEnable = 0b010 ,
TxEnable = 0b100 ,
Shutdown = 0b000 ,
Standby = Enable ,
Receive = Enable | RxEnable ,
Transmit = Enable | TxEnable ,
2024-02-04 00:57:45 +01:00
Rx_calibration = Enable | RxEnable , // sets the same 3 x logic pins to the Receive operating mode.
Tx_calibration = Enable | TxEnable , // sets the same 3 x logic pins to the Transmit operating mode.
2023-02-16 12:09:23 +00:00
};
2024-02-04 00:57:45 +01:00
Mask mode_mask ( const Mode mode ) { // based on enum Mode cases, we set up the correct 3 logic PINS .
2023-05-19 08:16:05 +12:00
switch ( mode ) {
case Mode :: Standby :
return Mask :: Standby ;
case Mode :: Receive :
return Mask :: Receive ;
case Mode :: Transmit :
return Mask :: Transmit ;
2024-02-04 00:57:45 +01:00
case Mode :: Rx_Calibration : // Let's add those two CAL logic pin settings- Rx and Tx calibration modes.
return Mask :: Rx_calibration ; // same logic pins as Receive mode = Enable | RxEnable, (the difference is in Reg add 16 D1:DO)
case Mode :: Tx_Calibration : // Let's add this CAL Tx calibration mode = Transmit.
return Mask :: Tx_calibration ; // same logic pins as Transmit = Enable | TxEnable,(the difference is in Reg add 16 D1:DO)
2023-05-19 08:16:05 +12:00
default :
return Mask :: Shutdown ;
}
2023-02-16 12:09:23 +00:00
}
2024-02-04 00:57:45 +01:00
void MAX2837 :: set_mode ( const Mode mode ) { // We set up the 3 Logic Pins ENABLE, RXENABLE, TXENABLE accordingly to the max2837 mode case, that we want to set up .
2024-03-18 15:45:02 -05:00
_mode = mode ;
2023-05-19 08:16:05 +12:00
Mask mask = mode_mask ( mode );
gpio_max283x_enable . write ( toUType ( mask ) & toUType ( Mask :: Enable ));
gpio_max2837_rxenable . write ( toUType ( mask ) & toUType ( Mask :: RxEnable ));
gpio_max2837_txenable . write ( toUType ( mask ) & toUType ( Mask :: TxEnable ));
2015-07-08 08:39:24 -07:00
}
2024-03-18 15:45:02 -05:00
Mode MAX2837 :: get_mode () {
return _mode ;
}
2015-07-08 08:39:24 -07:00
void MAX2837 :: flush () {
2023-05-19 08:16:05 +12:00
if ( _dirty ) {
for ( size_t n = 0 ; n < reg_count ; n ++ ) {
if ( _dirty [ n ]) {
write ( n , _map . w [ n ]);
}
}
_dirty . clear ();
}
2015-07-08 08:39:24 -07:00
}
void MAX2837 :: flush_one ( const Register reg ) {
2023-05-19 08:16:05 +12:00
const auto reg_num = toUType ( reg );
write ( reg_num , _map . w [ reg_num ]);
_dirty . clear ( reg_num );
2015-07-08 08:39:24 -07:00
}
2015-12-13 13:18:37 -08:00
void MAX2837 :: write ( const address_t reg_num , const reg_t value ) {
2023-05-19 08:16:05 +12:00
uint16_t t = ( 0U << 15 ) | ( reg_num << 10 ) | ( value & 0x3ffU );
_target . transfer ( & t , 1 );
2015-07-08 08:39:24 -07:00
}
2015-12-13 13:18:37 -08:00
reg_t MAX2837 :: read ( const address_t reg_num ) {
2023-05-19 08:16:05 +12:00
uint16_t t = ( 1U << 15 ) | ( reg_num << 10 );
_target . transfer ( & t , 1U );
return t & 0x3ffU ;
2015-07-08 08:39:24 -07:00
}
2015-12-13 13:18:37 -08:00
void MAX2837 :: write ( const Register reg , const reg_t value ) {
2023-05-19 08:16:05 +12:00
write ( toUType ( reg ), value );
2015-07-08 08:39:24 -07:00
}
2015-12-13 13:18:37 -08:00
reg_t MAX2837 :: read ( const Register reg ) {
2023-05-19 08:16:05 +12:00
return read ( toUType ( reg ));
2015-07-08 08:39:24 -07:00
}
2016-08-03 16:12:01 -07:00
void MAX2837 :: set_tx_vga_gain ( const int_fast8_t db ) {
2023-05-19 08:16:05 +12:00
_map . r . tx_gain . TXVGA_GAIN_SPI = tx :: gain_ordinal ( db );
_dirty [ Register :: TX_GAIN ] = 1 ;
flush ();
2015-07-08 08:39:24 -07:00
}
void MAX2837 :: set_lna_gain ( const int_fast8_t db ) {
2023-05-19 08:16:05 +12:00
_map . r . rxrf_2 . L = lna :: gain_ordinal ( db );
_dirty [ Register :: RXRF_2 ] = 1 ;
flush ();
2015-07-08 08:39:24 -07:00
}
void MAX2837 :: set_vga_gain ( const int_fast8_t db ) {
2023-05-19 08:16:05 +12:00
_map . r . vga_2 . VGA = vga :: gain_ordinal ( db );
_dirty [ Register :: VGA_2 ] = 1 ;
flush ();
2015-07-08 08:39:24 -07:00
}
2023-10-08 17:50:31 +02:00
void MAX2837 :: set_lpf_rf_bandwidth_rx ( const uint32_t bandwidth_minimum ) {
_map . r . lpf_1 . ModeCtrl = 0b01 ; /* Address reg 2, D3-D2, Set mode lowpass filter block to Rx LPF . Active when Address 6 D<9> = 1 */
2023-05-19 08:16:05 +12:00
_map . r . lpf_1 . FT = filter :: bandwidth_ordinal ( bandwidth_minimum );
2023-10-08 17:50:31 +02:00
flush_one ( Register :: LPF_1 );
_map . r . vga_3_rx_top . LPF_MODE_SEL = 1 ; /* Address 6 reg, D9 bit:LPF mode mux, LPF_MODE_SEL 0 = Normal operation, 1 = Operating mode is programmed Address 2 D3:D2*/
flush_one ( Register :: VGA_3_RX_TOP );
_map . r . vga_3_rx_top . LPF_MODE_SEL = 0 ; /* Leave LPF_MODE_SEL 0 = Normal operation */
flush_one ( Register :: VGA_3_RX_TOP );
}
void MAX2837 :: set_lpf_rf_bandwidth_tx ( const uint32_t bandwidth_minimum ) {
_map . r . lpf_1 . ModeCtrl = 0b10 ; /* Address 2 reg, D3-D2, Set mode lowpass filter block to Tx LPF . Active when Address 6 D<9> = 1 */
_map . r . lpf_1 . FT = filter :: bandwidth_ordinal ( bandwidth_minimum );
flush_one ( Register :: LPF_1 );
_map . r . vga_3_rx_top . LPF_MODE_SEL = 1 ; /* Address 6 reg, D9 bit:LPF mode mux, LPF_MODE_SEL 0 = Normal operation, 1 = Operating mode is programmed Address 2 D3:D2*/
flush_one ( Register :: VGA_3_RX_TOP );
_map . r . vga_3_rx_top . LPF_MODE_SEL = 0 ; /* Leave LPF_MODE_SEL 0 = Normal operation */
flush_one ( Register :: VGA_3_RX_TOP );
2015-07-08 08:39:24 -07:00
}
bool MAX2837 :: set_frequency ( const rf :: Frequency lo_frequency ) {
2023-05-19 08:16:05 +12:00
/* TODO: This is a sad implementation. Refactor. */
if ( lo :: band [ 0 ]. contains ( lo_frequency )) {
_map . r . syn_int_div . LOGEN_BSW = 0b00 ; /* 2300 - 2399.99MHz */
_map . r . rxrf_1 . LNAband = 0 ; /* 2.3 - 2.5GHz */
} else if ( lo :: band [ 1 ]. contains ( lo_frequency )) {
_map . r . syn_int_div . LOGEN_BSW = 0b01 ; /* 2400 - 2499.99MHz */
_map . r . rxrf_1 . LNAband = 0 ; /* 2.3 - 2.5GHz */
} else if ( lo :: band [ 2 ]. contains ( lo_frequency )) {
_map . r . syn_int_div . LOGEN_BSW = 0b10 ; /* 2500 - 2599.99MHz */
_map . r . rxrf_1 . LNAband = 1 ; /* 2.5 - 2.7GHz */
} else if ( lo :: band [ 3 ]. contains ( lo_frequency )) {
_map . r . syn_int_div . LOGEN_BSW = 0b11 ; /* 2600 - 2700Hz */
_map . r . rxrf_1 . LNAband = 1 ; /* 2.5 - 2.7GHz */
} else {
return false ;
}
_dirty [ Register :: SYN_INT_DIV ] = 1 ;
_dirty [ Register :: RXRF_1 ] = 1 ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
const uint64_t div_q20 = ( lo_frequency * ( 1 << 20 )) / pll_factor ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . syn_int_div . SYN_INTDIV = div_q20 >> 20 ;
_dirty [ Register :: SYN_INT_DIV ] = 1 ;
_map . r . syn_fr_div_2 . SYN_FRDIV_19_10 = ( div_q20 >> 10 ) & 0x3ff ;
_dirty [ Register :: SYN_FR_DIV_2 ] = 1 ;
/* flush to commit high FRDIV first, as low FRDIV commits the change */
flush ();
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . syn_fr_div_1 . SYN_FRDIV_9_0 = ( div_q20 & 0x3ff );
_dirty [ Register :: SYN_FR_DIV_1 ] = 1 ;
flush ();
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
return true ;
2015-07-08 08:39:24 -07:00
}
2024-03-09 23:46:38 +01:00
/*
void MAX2837::set_rx_lo_iq_calibration(const size_t v) { // Original code , rewritten below
2023-05-19 08:16:05 +12:00
_map.r.rx_top_rx_bias.RX_IQERR_SPI_EN = 1;
_dirty[Register::RX_TOP_RX_BIAS] = 1;
_map.r.rxrf_2.iqerr_trim = v;
_dirty[Register::RXRF_2] = 1;
flush();
2016-08-21 11:42:05 -07:00
}
2024-03-09 23:46:38 +01:00
*/
void MAX2837 :: set_rx_LO_iq_phase_calibration ( const size_t v ) {
/* RX IQ phase deg CAL adj (+4 ...-4) in 32 steps (5 bits), 00000 = +4deg (Q lags I by 94degs, default), 01111 = +0deg, 11111 = -4deg (Q lags I by 86degs) */
// RX calibration , Logic pins , ENABLE, RXENABLE, TXENABLE = 1,1,0 (3dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode ( Mode :: Rx_Calibration ); // write to ram 3 LOGIC Pins .
gpio_max283x_enable . output ();
gpio_max2837_rxenable . output ();
gpio_max2837_txenable . output ();
_map . r . spi_en . CAL_SPI = 1 ; // Register Settings reg address 16, D1 (CAL mode 1)
_map . r . spi_en . EN_SPI = 1 ; // Register Settings reg address 16, DO (CHIP ENABLE 1)
flush_one ( Register :: SPI_EN );
_map . r . rx_top_rx_bias . RX_IQERR_SPI_EN = 1 ; // reg 8 D9, RX LO IQ Phase calibration SPI control. Active when Address 8 D<9> = 1.
flush_one ( Register :: RX_TOP_RX_BIAS );
_map . r . rxrf_2 . iqerr_trim = v ; // reg 1 D9:D5, RX LO I/Q Phase SPI 5 bits Adjust
flush_one ( Register :: RXRF_2 );
// Exit Calibration mode, Go back to reg 16, D1:D0 , Out of CALIBRATION , back to default conditions, but keep CS activated.
_map . r . spi_en . CAL_SPI = 0 ; // Register Settings reg address 16, D1 (0 = Normal operation (default)
_map . r . spi_en . EN_SPI = 1 ; // Register Settings reg address 16, DO (1 = Chip select enable )
flush_one ( Register :: SPI_EN );
}
2016-08-21 11:42:05 -07:00
void MAX2837 :: set_rx_bias_trim ( const size_t v ) {
2023-05-19 08:16:05 +12:00
_map . r . rx_top_rx_bias . EN_Bias_Trim = 1 ;
_map . r . rx_top_rx_bias . BIAS_TRIM_SPI = v ;
_dirty [ Register :: RX_TOP_RX_BIAS ] = 1 ;
flush ();
2016-08-21 11:42:05 -07:00
}
void MAX2837 :: set_vco_bias ( const size_t v ) {
2023-05-19 08:16:05 +12:00
_map . r . vco_cfg . VCO_BIAS_SPI_EN = 1 ;
_map . r . vco_cfg . VCO_BIAS_SPI = v ;
_dirty [ Register :: VCO_CFG ] = 1 ;
flush ();
2016-08-21 11:42:05 -07:00
}
void MAX2837 :: set_rx_buff_vcm ( const size_t v ) {
2023-05-19 08:16:05 +12:00
_map . r . lpf_3_vga_1 . BUFF_VCM = v ;
_dirty [ Register :: LPF_3_VGA_1 ] = 1 ;
flush ();
2016-08-21 11:42:05 -07:00
}
2023-11-06 13:56:09 -06:00
int8_t MAX2837 :: temp_sense () {
2023-05-19 08:16:05 +12:00
if ( ! _map . r . rx_top . ts_en ) {
_map . r . rx_top . ts_en = 1 ;
flush_one ( Register :: RX_TOP );
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
chThdSleepMilliseconds ( 1 );
}
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . rx_top . ts_adc_trigger = 1 ;
flush_one ( Register :: RX_TOP );
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
halPolledDelay ( ticks_for_temperature_sense_adc_conversion );
2015-07-08 08:39:24 -07:00
2023-11-06 13:56:09 -06:00
/*
* Conversion to degrees C determined by testing - does not match data sheet.
*/
reg_t value = read ( Register :: TEMP_SENSE ) & 0x1F ;
2015-07-08 08:39:24 -07:00
2023-05-19 08:16:05 +12:00
_map . r . rx_top . ts_adc_trigger = 0 ;
flush_one ( Register :: RX_TOP );
2015-07-08 08:39:24 -07:00
2023-11-18 09:50:57 -06:00
return std :: min ( 127 , ( int )( value * 4.31 - 40 )); // reg value is 0 to 31; possible return range is -40 C to 127 C
2015-07-08 08:39:24 -07:00
}
2023-05-19 08:16:05 +12:00
} // namespace max2837