Commit fe37addf authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

boards/ertm14: correct LO/REF power measurements in mBm. BIST for flash.

parent 73199cb2
......@@ -169,6 +169,8 @@ spll_gain_schedule_t spll_main_ocxo_gain_sched;
#define ERTM14_BIST_CLKB 7
#define ERTM14_BIST_DDS_REF 8
#define ERTM14_BIST_DDS_LO 9
#define ERTM14_BIST_FLASH_PRESENCE 10
#define ERTM14_BIST_FLASH_FS_MOUNT 11
#define BIST_STATUS_DONE (1<<0)
#define BIST_STATUS_ERROR (1<<1)
......@@ -182,6 +184,8 @@ struct bist_stage
};
static struct bist_stage ertm_bist[] = {
{ERTM14_BIST_FLASH_PRESENCE, "Check flash presence", 1},
{ERTM14_BIST_FLASH_FS_MOUNT, "Mount flash FS", 1},
{ERTM14_BIST_LTC6950, "LTC6950", 1},
{ERTM14_BIST_MAC_EEPROM, "MAC EEPROM", 1},
{ERTM14_BIST_AD951X_EXT, "AD9510 (Ext)", 1},
......@@ -1215,7 +1219,6 @@ int ertm14_low_level_init(void)
&pin_ad9910_lo_sclk,
100 );
/* detect if the eRTM15 is present and decide how to configure the board */
int ertm15_present = check_ertm15_presence();
......@@ -1269,16 +1272,6 @@ int ertm14_low_level_init(void)
/* Read unique MAC addresses from storage chips (eRTM14 - IC7 and IC8) */
ertm14_init_mac_eeprom();
/* RF Power Monitor ADC (eRTM15 - IC43) */
bb_spi_create( &board.spi_ad7888,
&pin_pwrmon_adc_cs_n,
&pin_pwrmon_adc_din,
&pin_pwrmon_adc_dout,
&pin_pwrmon_adc_sclk,
100 );
ad7888_create( &board.pwrmon_adc, &board.spi_ad7888 );
board_dbg("Init Fine Pulse Generator\n");
/* Initialize the Fine Pulse Generator - it MUST be done
......@@ -1292,19 +1285,41 @@ int ertm14_low_level_init(void)
{
board_dbg("Initializing RF distribution\n");
/* RF Power Monitor ADC (eRTM15 - IC43) */
bb_spi_create( &board.spi_ad7888,
&pin_pwrmon_adc_cs_n,
&pin_pwrmon_adc_din,
&pin_pwrmon_adc_dout,
&pin_pwrmon_adc_sclk,
100 );
ad7888_create( &board.pwrmon_adc, &board.spi_ad7888 );
/* RF distribution switches and shift registers controlling these (eRTM15 - IC26..28) */
/* RF distribution switches and shift registers controlling these (eRTM15 - IC26..28) */
ertm15_rf_distr_init( &board.rf_distr, &board.pwrmon_adc );
/* Now that the PLL clocks are ready, init the DDS synthesizers */
/* Now that the PLL clocks are ready, init the DDS synthesizers */
board_dbg("Initializing DDSes\n");
ertm15_init_dds();
uint64_t ftw = ad9910_frequency_to_ftw( &board.dds_ad9910_ref, ERTM14_DEFAULT_DDS_FREQUENCY_HZ );
/* Program the DDSes to some meaninfgul settings, say, 205 MHz */
ad9910_program(&board.dds_ad9910_ref, ftw, 0, 0x0 );
ad9910_program(&board.dds_ad9910_lo, ftw, 0, 0x0 );
ad9910_program(&board.dds_ad9910_ref, ERTM14_DDS_DEFAULT_FTW, 0, ERTM14_DDS_DEFAULT_AMPLITUDE );
ad9910_program(&board.dds_ad9910_lo, ERTM14_DDS_DEFAULT_FTW, 0, ERTM14_DDS_DEFAULT_AMPLITUDE );
ertm15_rf_distr_measure_power ( &board.rf_distr );
int i;
board_dbg("PA PWR REF = %d mBm, LO = %d mBm\n", board.rf_distr.pwr_ref_in, board.rf_distr.pwr_lo_in );
for(i = ERTM14_RF_OUT_MIN_ID; i <= ERTM14_RF_OUT_MAX_ID; i++)
{
board_dbg("OUT[%d] PWR REF = %d mBm, LO = %d mBm\n", i, board.rf_distr.pwr_ref_ch[i], board.rf_distr.pwr_lo_ch[i] );
}
for(;;);
}
/* Setup the SoftPLL for the OCXO we have */
......@@ -1346,10 +1361,10 @@ void ertm14_config_init()
struct ertm14_board_state *cfg = &ertm14_configs[i];
cfg->valid = 1;
cfg->lo.ftw = 0x39374BC6;
cfg->ref.ftw = 0x39374BC6;
cfg->lo.ampl_factor = 50;
cfg->ref.ampl_factor = 50;
cfg->lo.ftw = ERTM14_DDS_DEFAULT_FTW;
cfg->ref.ftw = ERTM14_DDS_DEFAULT_FTW;
cfg->lo.ampl_factor = ERTM14_DDS_DEFAULT_AMPLITUDE;
cfg->ref.ampl_factor = ERTM14_DDS_DEFAULT_AMPLITUDE;
for( j = 0; j <= ERTM14_RF_OUT_MAX_ID; j++)
{
......@@ -1449,7 +1464,7 @@ static int evth_config_update_listener;
static void ertm14_config_update_init(void)
{
return 0;
}
static int ertm14_config_update_task(void)
......@@ -1509,6 +1524,9 @@ int ertm14_get_supported_clkab_freqs( int *freqs, int max_count )
return i;
}
#define ERTM14_EXPECTED_FLASH_ID 0x00016018
int wrc_board_early_init()
{
static int32_t flash_entry_points[64];
......@@ -1521,24 +1539,28 @@ int wrc_board_early_init()
&pin_sysc_spi_ncs,
&pin_sysc_spi_mosi,
&pin_sysc_spi_miso,
&pin_sysc_spi_sclk, 10 );
&pin_sysc_spi_sclk, 0 );
spi_flash_create( &wrc_flash_dev, &spi_wrc_flash, 16384, 0x600000 );
uint32_t id = spi_flash_read_id( &wrc_flash_dev );
bist_checkpoint( ertm_bist, ERTM14_BIST_FLASH_PRESENCE, 0, id == ERTM14_EXPECTED_FLASH_ID );
/* initialize I2C bus */
bb_i2c_init( &dev_i2c_fmc );
for(i = 0; i < 32 + 8; i++)
flash_entry_points[i] = 0x600000 + 0x40000 * i;
flash_entry_points[i] = -1;
/* init storage (we use the SPI flash on eRTM14) */
storage_spiflash_create( &wrc_storage_dev, &wrc_flash_dev );
wrc_storage_dev.entry_points = &flash_entry_points[0];
storage_mount( &wrc_storage_dev );
int rv = storage_mount( &wrc_storage_dev );
bist_checkpoint( ertm_bist, ERTM14_BIST_FLASH_FS_MOUNT, 0, rv == 0 );
/* reset the networking part of the WRCore and start the WR Endpoint */
net_rst();
......
......@@ -154,6 +154,9 @@ extern unsigned char *BASE_EP;
#define ERTM14_UART_PTYPE_SNMP_RESP 3
#define ERTM14_UART_PTYPE_MMC_STATUS_REQ 4
#define ERTM14_DDS_DEFAULT_FTW 0x39374BC6 /* 223.5 MHz @ 1 GHz refclk */
#define ERTM14_DDS_DEFAULT_AMPLITUDE 0x7f
struct ertm14_board
{
struct gpio_device gpio_aux;
......
......@@ -21,6 +21,9 @@
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <limits.h>
#include <sys/errno.h>
#include "board.h"
#include "dev/gpio.h"
......@@ -28,6 +31,14 @@
#include "dev/ad7888.h"
#include "ertm15_rf_distr.h"
#ifndef INT32_MAX
#define INT32_MAX INT_MAX
#endif
#ifndef INT32_MIN
#define INT32_MIN INT_MIN
#endif
static const struct gpio_pin pin_lo_ctrl_ser = { &board.gpio_aux, 39 };
static const struct gpio_pin pin_lo_ctrl_updtclk = { &board.gpio_aux, 40 };
static const struct gpio_pin pin_lo_ctrl_shftclk = { &board.gpio_aux, 41 };
......@@ -144,48 +155,128 @@ void ertm15_rf_distr_init( struct ertm15_rf_distribution_device *dev, struct ad7
ertm15_update_rf_switches( dev );
}
// fixed point logarithm code from: https://github.com/dmoulding/log2fix/blob/master/log2fix.c
#define INV_LOG2_E_Q1DOT31 (0x58b90bfcULL) // Inverse log base 2 of e
#define INV_LOG2_10_Q1DOT31 (0x268826a1ULL) // Inverse log base 2 of 10
int64_t log2fix (uint64_t x, size_t precision)
{
// This implementation is based on Clay. S. Turner's fast binary logarithm
// algorithm[1].
int64_t b = 1UL << (precision - 1);
int64_t y = 0;
if (precision < 1 || precision > 31) {
errno = -EINVAL;
return INT32_MAX; // indicates an error
}
if (x == 0) {
return INT32_MIN; // represents negative infinity
}
while (x < 1UL << precision) {
x <<= 1;
y -= 1UL << precision;
}
while (x >= 2UL << precision) {
x >>= 1;
y += 1UL << precision;
}
uint64_t z = x;
size_t i;
for (i = 0; i < precision; i++) {
z = z * z >> precision;
if (z >= 2UL << precision) {
z >>= 1;
y += b;
}
b >>= 1;
}
return y;
}
int32_t log10fix (uint64_t x, size_t precision)
{
uint64_t t;
t = log2fix(x, precision) * INV_LOG2_10_Q1DOT31;
return t >> 31;
}
// takes raw ADC readout (0..4095), returns normalized power value in mBm
static int convert_power( int adc_value )
{
pp_printf("ADCV %d\n", adc_value );
// pp_printf("ADCV %d\n", adc_value );
// ADC full scale: 0..4095 - 0..2.5 V
// LMH2120: 0 dBm = 2V (see datasheet Figure 17)
// LMH2120 pre-attenuator: 15 dB
float adc_voltage = (float) adc_value / 4096.0 * 2.5;
float rf_power = 10.0 * log( adc_voltage / 2.0 ) / log( 10.0 ) + 15.0; // 2V = 0 dBm, compensate for 15 dB attenuator
int precision_bits = 16;
return (int) (rf_power * 100.0);
int32_t f_adc_voltage = ( (int64_t)adc_value << precision_bits) * 25LL / 4096LL; // volts, fixed point
const int32_t f_2V = (20LL << precision_bits);
const int32_t f_log_2V_0dBm = log10fix( f_2V, precision_bits );
int32_t f_log_input = log10fix( f_adc_voltage, precision_bits );
int32_t pwr = ( ( 2000LL * (int64_t)(f_log_input - f_log_2V_0dBm) ) >> precision_bits ) + 1500;
return (int) (pwr);
}
#define ADC_CH_REF_DDS_PA 2
#define ADC_CH_LO_DDS_PA 0
#define ADC_CH_REF_DDS_DISTR 3
#define ADC_CH_LO_DDS_DISTR 1
#define ADC_CH_REF_DDS_PA 2
#define ADC_CH_REF_DDS_DISTR 3
int ertm15_rf_distr_measure_power ( struct ertm15_rf_distribution_device *dev )
{
int i;
ad7888_start_conversion( dev->pwr_mon_adc, 0x0f );
while( dev->pwr_mon_adc->channel_valid != 0x0f )
{
ad7888_poll( dev->pwr_mon_adc );
usleep(1000);
timer_delay_ms(1);
}
dev->pwr_ref_in = convert_power( dev->pwr_mon_adc->channel[ADC_CH_REF_DDS_PA] );
dev->pwr_lo_in = convert_power( dev->pwr_mon_adc->channel[ADC_CH_LO_DDS_PA] );
int i;
for( i = 4; i <= 12; i ++ )
timer_delay_ms(1);
for( i = ERTM14_RF_OUT_MIN_ID; i <= ERTM14_RF_OUT_MAX_ID; i ++ )
{
dev->pwr_ref_valid &= ~(1<<i);
if( ! (dev->ref_enabled & (1<<i) ) )
{
rf_switch_set( ERTM15_RF_REF, i, ERTM15_RF_OUT_MONITOR );
usleep(10000);
timer_delay_ms(10);
int raw_pwr = ad7888_meas_channel( dev->pwr_mon_adc, ADC_CH_REF_DDS_DISTR );
dev->pwr_ref_ch[ i ] = convert_power( raw_pwr );
pp_printf("Ch REF %d: pwr %d v %d\n", i, dev->pwr_ref_ch[i], dev->pwr_mon_adc->channel_valid );
dev->pwr_ref_valid |= (1<<i);
rf_switch_set( ERTM15_RF_REF, i, ERTM15_RF_OUT_OFF );
}
dev->pwr_lo_valid &= ~(1<<i);
if( ! (dev->lo_enabled & (1<<i) ) )
{
rf_switch_set( ERTM15_RF_LO, i, ERTM15_RF_OUT_MONITOR );
timer_delay_ms(10);
int raw_pwr = ad7888_meas_channel( dev->pwr_mon_adc, ADC_CH_LO_DDS_DISTR );
dev->pwr_lo_ch[ i ] = convert_power( raw_pwr );
dev->pwr_lo_valid |= (1<<i);
rf_switch_set( ERTM15_RF_LO, i, ERTM15_RF_OUT_OFF );
}
}
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment