Commit a7312849 authored by Juan David González Cobas's avatar Juan David González Cobas

Merge branch 'tom-rf-ertm14' into david-libertm-devel

Conflicts:
	libertm/libertm.c
parents a02ab8f1 3b273bc4
......@@ -125,6 +125,8 @@
/* power on flag */
#define ERTM_FLAGS_POWERED_ON (1<<0)
#define ERTM_FLAGS_DDS_POWER_VALID_MASK (0x80000000)
struct ertm14_dds_state
{
uint32_t ftw;
......@@ -240,7 +242,4 @@ struct ertm14_version_info {
firmware_metadata;
};
/* FIXME: this is not the best place for this declaration */
int wrc_diags_dump(struct wrc_diags *buf);
#endif /* __BOARD_STATE_ERTM14_H */
This diff is collapsed.
......@@ -107,6 +107,7 @@ extern unsigned char *BASE_EP;
#define ERTM14_RF_OUT_MIN_ID ERTM_COMMON_RF_OUT_MIN_ID
#define ERTM14_RF_OUT_MAX_ID ERTM_COMMON_RF_OUT_MAX_ID
#define ERTM14_ALL_RF_OUT_ID_MASK ERTM_COMMON_ALL_RF_OUT_ID_MASK
#define ERTM14_OUT_CLKA 0
#define ERTM14_OUT_CLKB 1
......
......@@ -23,6 +23,8 @@ extern "C" {
#define ERTM_COMMON_RF_OUT_MIN_ID 4
#define ERTM_COMMON_RF_OUT_MAX_ID 12
#define ERTM_COMMON_ALL_RF_OUT_ID_MASK (0x1ff0)
#define ERTM_COMMON_SYNC_SOURCE_NONE 0
#define ERTM_COMMON_SYNC_SOURCE_PPS 1
#define ERTM_COMMON_SYNC_SOURCE_RF_TRIGGER 2
......
......@@ -22,6 +22,7 @@
#include <stdint.h>
#include <math.h>
#include <limits.h>
#include <string.h>
#include <sys/errno.h>
......@@ -29,6 +30,7 @@
#include "dev/gpio.h"
#include "dev/74x595.h"
#include "dev/ad7888.h"
#include "util.h"
#include "ertm15_rf_distr.h"
#ifndef INT32_MAX
......@@ -141,6 +143,7 @@ static int rf_switch_set( int path, int channel, int state)
void ertm15_rf_distr_init( struct ertm15_rf_distribution_device *dev, struct ad7888_device *pwr_mon_adc )
{
memset(dev, 0, sizeof(struct ertm15_rf_distribution_device));
x595_gpio_create ( &gpio_rfsw_ref, 3, &pin_ref_ctrl_updtclk, &pin_ref_ctrl_shftclk, NULL, &pin_ref_ctrl_ser );
x595_gpio_create ( &gpio_rfsw_lo, 3, &pin_lo_ctrl_updtclk, &pin_lo_ctrl_shftclk, NULL, &pin_lo_ctrl_ser );
......@@ -243,6 +246,215 @@ static int convert_power( int adc_value )
#define ADC_CHANNEL_MASK 0xf
int ertm15_rf_distr_pwrmon_update( struct ertm15_rf_distribution_device *dev )
{
//pp_printf("ST %d\n", dev->pwr_meas_state);
switch(dev->pwr_meas_state)
{
case PWR_MEAS_STATE_IDLE:
return 0;
case PWR_MEAS_STATE_START:
tmo_init( &dev->pwr_meas_tmo, PWR_MEAS_STABILIZE_TMO_MS );
dev->pwr_meas_channel = ERTM14_RF_OUT_MIN_ID;
dev->pwr_meas_state = PWR_MEAS_STATE_PICK_CHANNEL;
dev->pwr_meas_start_tics = timer_get_tics();
if( dev->pwr_meas_force )
{
int i;
// all channels to OFF, so that they are terminated
for( i = ERTM14_RF_OUT_MIN_ID; i <= ERTM14_RF_OUT_MAX_ID; i ++ )
{
rf_switch_set( ERTM15_RF_REF, i, ERTM15_RF_OUT_OFF );
rf_switch_set( ERTM15_RF_LO, i, ERTM15_RF_OUT_OFF );
}
dev->pwr_ref_valid = 0;
dev->pwr_lo_valid = 0;
}
break;
case PWR_MEAS_STATE_PICK_CHANNEL:
{
if( ! tmo_expired( &dev->pwr_meas_tmo ) )
break;
tmo_restart( &dev->pwr_meas_tmo );
if( dev->pwr_meas_force || !(dev->ref_enabled & (1<<dev->pwr_meas_channel) ) )
rf_switch_set( ERTM15_RF_REF, dev->pwr_meas_channel, ERTM15_RF_OUT_MONITOR );
if( dev->pwr_meas_force || !(dev->lo_enabled & (1<<dev->pwr_meas_channel) ) )
rf_switch_set( ERTM15_RF_LO, dev->pwr_meas_channel, ERTM15_RF_OUT_MONITOR );
dev->pwr_meas_state = PWR_MEAS_STATE_START_ADC;
break;
}
case PWR_MEAS_STATE_START_ADC:
{
if( ! tmo_expired( &dev->pwr_meas_tmo ) )
break;
ad7888_start_conversion( dev->pwr_mon_adc, ADC_CHANNEL_MASK );
dev->pwr_meas_state = PWR_MEAS_STATE_READ_ADC;
break;
}
case PWR_MEAS_STATE_READ_ADC:
{
ad7888_poll( dev->pwr_mon_adc );
//pp_printf("CH %d V %x\n", dev->pwr_meas_channel, dev->pwr_mon_adc->channel_valid);
if( dev->pwr_mon_adc->channel_valid != ADC_CHANNEL_MASK )
break;
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 raw_pwr_ref = ad7888_meas_channel( dev->pwr_mon_adc, ADC_CH_REF_DDS_DISTR );
int raw_pwr_lo = ad7888_meas_channel( dev->pwr_mon_adc, ADC_CH_LO_DDS_DISTR );
if(dev->pwr_meas_force || !(dev->ref_enabled & (1<<dev->pwr_meas_channel) ) )
dev->pwr_ref_ch[ dev->pwr_meas_channel ] = convert_power( raw_pwr_ref );
if(dev->pwr_meas_force || !(dev->lo_enabled & (1<<dev->pwr_meas_channel) ) )
dev->pwr_lo_ch[ dev->pwr_meas_channel ] = convert_power( raw_pwr_lo );
//board_dbg("refin %d loin %d ref%d %d lo%d %d", dev->pwr_ref_in, dev->pwr_lo_in,
//dev->pwr_meas_channel, dev->pwr_ref_ch[dev->pwr_meas_channel],
//dev->pwr_meas_channel, dev->pwr_lo_ch[dev->pwr_meas_channel] );
if( dev->pwr_meas_force || !(dev->lo_enabled & (1<<dev->pwr_meas_channel) ) )
rf_switch_set( ERTM15_RF_LO, dev->pwr_meas_channel, ERTM15_RF_OUT_OFF );
if( dev->pwr_meas_force || !(dev->ref_enabled & (1<<dev->pwr_meas_channel) ) )
rf_switch_set( ERTM15_RF_REF, dev->pwr_meas_channel, ERTM15_RF_OUT_OFF );
if( dev->pwr_meas_channel >= ERTM14_RF_OUT_MAX_ID )
dev->pwr_meas_state = PWR_MEAS_STATE_FINISH;
else
{
dev->pwr_meas_channel++;
tmo_restart( &dev->pwr_meas_tmo );
dev->pwr_meas_state = PWR_MEAS_STATE_PICK_CHANNEL;
}
break;
}
case PWR_MEAS_STATE_FINISH:
{
if( dev->pwr_meas_force ) // restore state of channels that have been squelched during measurement
{
int i;
for( i = ERTM14_RF_OUT_MIN_ID; i <= ERTM14_RF_OUT_MAX_ID; i ++ )
{
rf_switch_set( ERTM15_RF_REF, i, dev->ref_enabled & (1<<i) ? ERTM15_RF_OUT_ON : ERTM15_RF_OUT_OFF );
rf_switch_set( ERTM15_RF_LO, i, dev->lo_enabled & (1<<i) ? ERTM15_RF_OUT_ON : ERTM15_RF_OUT_OFF );
}
dev->pwr_lo_valid = ERTM14_ALL_RF_OUT_ID_MASK;
dev->pwr_ref_valid = ERTM14_ALL_RF_OUT_ID_MASK;
}
else
{
dev->pwr_lo_valid = ERTM14_ALL_RF_OUT_ID_MASK & ~( dev->lo_enabled );
dev->pwr_ref_valid = ERTM14_ALL_RF_OUT_ID_MASK & ~( dev->ref_enabled );
}
uint32_t dt = timer_get_tics() - dev->pwr_meas_start_tics;
board_dbg("pwr_meas took %d ms, forced=%d\n", dt, dev->pwr_meas_force );
dev->pwr_meas_force = 0;
dev->pwr_meas_state = PWR_MEAS_STATE_DONE;
break;
}
default:
break;
}
return 0;
}
int ertm15_rf_distr_measure_power_restart( struct ertm15_rf_distribution_device *dev, int force )
{
if( force )
{
dev->pwr_meas_force = 1;
dev->pwr_lo_valid = 0;
dev->pwr_ref_valid = 0;
dev->pwr_meas_state = PWR_MEAS_STATE_START;
ertm15_rf_distr_pwrmon_update( dev );
}
else
{
dev->pwr_meas_state = PWR_MEAS_STATE_START;
}
return 0;
}
int ertm15_rf_distr_measure_power ( struct ertm15_rf_distribution_device *dev )
{
//pp_printf("Restart\n");
ertm15_rf_distr_measure_power_restart( dev, 0 );
while( dev->pwr_meas_state != PWR_MEAS_STATE_DONE )
ertm15_rf_distr_pwrmon_update( dev );
return 0;
}
#if 0
int i;
ad7888_start_conversion( dev->pwr_mon_adc, ADC_CHANNEL_MASK );
while( dev->pwr_mon_adc->channel_valid != ADC_CHANNEL_MASK )
{
ad7888_poll( dev->pwr_mon_adc );
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] );
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 );
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 );
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;
}
int ertm15_rf_distr_measure_power ( struct ertm15_rf_distribution_device *dev )
{
int i;
......@@ -286,6 +498,8 @@ int ertm15_rf_distr_measure_power ( struct ertm15_rf_distribution_device *dev )
return 0;
}
#endif
void ertm15_rf_distr_output_enable( struct ertm15_rf_distribution_device *dev, int path, int channel, int enabled )
{
......@@ -312,4 +526,7 @@ void ertm15_update_rf_switches( struct ertm15_rf_distribution_device *dev )
}
}
int ertm15_rf_distr_is_pwrmon_idle( struct ertm15_rf_distribution_device *dev )
{
return dev->pwr_meas_state == PWR_MEAS_STATE_DONE || dev->pwr_meas_state == PWR_MEAS_STATE_IDLE;
}
\ No newline at end of file
......@@ -23,6 +23,7 @@
#include <stdint.h>
#include "ertm-common.h"
#include "util.h"
#define ERTM15_RF_OUT_ON ERTM_COMMON_RF_OUT_ON
#define ERTM15_RF_OUT_MONITOR ERTM_COMMON_RF_OUT_MONITOR
......@@ -33,6 +34,15 @@
struct ad7888_device;
#define PWR_MEAS_STATE_IDLE 0
#define PWR_MEAS_STATE_PICK_CHANNEL 1
#define PWR_MEAS_STATE_READ_ADC 2
#define PWR_MEAS_STATE_DONE 3
#define PWR_MEAS_STATE_START 4
#define PWR_MEAS_STATE_START_ADC 5
#define PWR_MEAS_STATE_FINISH 6
#define PWR_MEAS_STABILIZE_TMO_MS 5
struct ertm15_rf_distribution_device {
uint16_t pwr_lo_valid;
......@@ -44,11 +54,21 @@ struct ertm15_rf_distribution_device {
int pwr_lo_in;
int pwr_ref_in;
struct ad7888_device *pwr_mon_adc;
int pwr_meas_state;
int pwr_meas_channel;
int pwr_meas_force;
uint32_t pwr_meas_lo_valid_next;
uint32_t pwr_meas_ref_valid_next;
timeout_t pwr_meas_tmo;
uint32_t pwr_meas_start_tics;
};
void ertm15_rf_distr_init( struct ertm15_rf_distribution_device *dev, struct ad7888_device *pwr_mon_adc );
int ertm15_rf_distr_measure_power ( struct ertm15_rf_distribution_device *dev );
int ertm15_rf_distr_pwrmon_update( struct ertm15_rf_distribution_device *dev );
int ertm15_rf_distr_measure_power_restart( struct ertm15_rf_distribution_device *dev, int force );
int ertm15_rf_distr_is_pwrmon_idle( struct ertm15_rf_distribution_device *dev );
void ertm15_rf_distr_output_enable( struct ertm15_rf_distribution_device *dev, int path, int channel, int enabled );
void ertm15_update_rf_switches( struct ertm15_rf_distribution_device *dev );
......
......@@ -19,6 +19,9 @@
#define ertm14_get_sensors 0x20
#define ertm14_get_version_info 0x21
#define ertm14_get_fpga_info 0x22
#define ertm14_get_streamers_diags 0x23
#define ertm14_reset_streamers_stats 0x24
#define ertm14_force_measure_channels_power 0x25
static struct ertm14_protocol_op {
int8_t opcode;
......@@ -82,6 +85,13 @@ static struct ertm14_protocol_op {
.length1 = 0,
.offset2 = 0,
.length2 = sizeof(struct wrc_diags),
},
{
.opcode = ertm14_get_streamers_diags,
.offset1 = 1,
.length1 = 0,
.offset2 = 0,
.length2 = sizeof(struct WR_STREAMERS_WB),
},
{
.opcode = ertm14_get_wrc_nco,
......@@ -104,7 +114,21 @@ static struct ertm14_protocol_op {
.offset2 = 1,
.length2 = 0,
},
{
{
.opcode = ertm14_reset_streamers_stats,
.offset1 = 1,
.length1 = 1,
.offset2 = 0,
.length2 = 0,
},
{
.opcode = ertm14_force_measure_channels_power,
.offset1 = 1,
.length1 = 1,
.offset2 = 0,
.length2 = 0,
},
{
.opcode = -1,
},
};
......
......@@ -60,6 +60,7 @@ int ad7888_create( struct ad7888_device *dev, struct spi_bus *bus )
dev->bus = bus;
dev->channel_valid = 0;
dev->current_ch = 0;
dev->conversion_pending = 0;
return 0;
}
......@@ -70,15 +71,17 @@ void ad7888_start_conversion( struct ad7888_device *dev, uint16_t channel_mask )
dev->channel_mask = channel_mask;
dev->channel_valid = 0;
dev->current_ch = -1;
dev->last_poll_tics = timer_get_tics();
tmo_init( &dev->poll_tmo, 1 );
dev->conversion_pending = 1;
int ch = first_bit_set_after( dev->channel_mask, dev->current_ch );
//pp_printf("sc %d %d %x\n", ch, dev->current_ch, dev->channel_mask );
if( ch < 0 )
return;
dev->current_ch = ch;
bb_spi_cs( dev->bus, 1 );
bb_spi_xfer( dev->bus, (ch << (3 + 8)), &dummy, 16);
bb_spi_cs( dev->bus, 0 );
......@@ -88,21 +91,29 @@ int ad7888_poll( struct ad7888_device *dev )
{
uint64_t rv;
if( !dev->conversion_pending )
return dev->channel_valid;
if( !dev->channel_mask )
return 0;
if( dev->last_poll_tics == timer_get_tics() )
if( !tmo_expired( &dev->poll_tmo ) )
return 0;
int next_ch = first_bit_set_after( dev->channel_mask, dev->current_ch );
bb_spi_cs( dev->bus, 1 );
bb_spi_xfer( dev->bus, (next_ch << (3 + 8)), &rv, 16);
bb_spi_cs( dev->bus, 0);
tmo_restart( &dev->poll_tmo );
dev->channel[ dev->current_ch ] = rv & 0xffff;
dev->channel_valid |= (1 << dev->current_ch);
dev->channel_valid |= (1 << dev->current_ch);
dev->current_ch = next_ch;
if( next_ch < 0 )
dev->conversion_pending = 0;
return dev->channel_valid;
}
......
......@@ -22,6 +22,7 @@
#define __AD7888_H
#include <stdint.h>
#include "util.h"
struct spi_bus;
......@@ -29,9 +30,10 @@ struct ad7888_device {
uint16_t channel[8];
uint16_t channel_valid;
uint16_t channel_mask;
uint8_t current_ch;
int8_t current_ch;
struct spi_bus* bus;
uint32_t last_poll_tics;
timeout_t poll_tmo;
uint8_t conversion_pending;
};
int ad7888_create( struct ad7888_device *dev, struct spi_bus *bus );
......
......@@ -2,11 +2,11 @@ ERTM_VERSION ?= $(shell git describe --always --dirty | sed 's;libertm-v;;' )
DEPLOY_TARGET ?= /acc/local/L867/drv/ertm/$(ERTM_VERSION)
TOOLS = ../tools/uart-bootloader/usb-bootloader.py ertm-cli udev-find
deploy: $(LIBS) libertm.h $(TOOLS) ../wrc.bin ertm-setup
deploy: $(LIBS) libertm.h $(TOOLS) ertm-setup
mkdir -p $(DEPLOY_TARGET)/lib $(DEPLOY_TARGET)/include/hw \
$(DEPLOY_TARGET)/tools $(DEPLOY_TARGET)/bin
ln -s ../pyenv $(DEPLOY_TARGET)
install -b ../wrc.bin $(LIBS) -C $(DEPLOY_TARGET)/lib
install -b $(LIBS) -C $(DEPLOY_TARGET)/lib
install -b libertm.h ../boards/ertm14/ertm-common.h -C $(DEPLOY_TARGET)/include
install -b ../include/hw/wrc_diags_regs.h -C $(DEPLOY_TARGET)/include/hw
install -b $(TOOLS) -C $(DEPLOY_TARGET)/tools
......
......@@ -19,10 +19,32 @@ static double ampl_factor_to_float(uint8_t ampl_factor)
{
return ampl_factor/256.0;
}
static int32_t signext32( uint32_t in, int bit )
{
uint32_t mask = ~ ((1<<bit)-1);
if( in & (1<<bit) )
return in | mask;
else
return in;
}
// fixme: I hate handling C strings. Can't we just rewrite this f***ing library in C++?
static void amp_power_to_string(uint32_t amp_power, char *str, int maxlen )
{
/* register values are in mBm, *not* mdBm;
* hence the *10/1000.0 factor */
if( ! (amp_power & ERTM_FLAGS_DDS_POWER_VALID_MASK ))
snprintf( str, maxlen, "invalid");
else
snprintf(str, maxlen, "%5.3f dBm", (signext32( amp_power & 0x7fffffff, 30 ) ) / 100.0 );
}
void display_dds_state(struct ertm14_dds_state *dds1,
struct ertm14_dds_state *dds2)
{
int i;
char tmp[1024];
printf("LO ftw: %08x (%7.3fMHz)%7c", dds1->ftw, (1000.0 * dds1->ftw) / (1L<<32), ' ');
printf(" | ");
......@@ -32,20 +54,24 @@ void display_dds_state(struct ertm14_dds_state *dds1,
printf(" | ");
printf("REF level adjust: %6.4f (%3d/256)%3c", ampl_factor_to_float(dds2->ampl_factor), dds2->ampl_factor, ' ');
printf("\n");
printf("LO pll_out_power: %5.3f dBm%9c", dds1->amp_power/100.0, ' '); /* register in mBm, not mdBm! */
amp_power_to_string( dds1->amp_power, tmp, sizeof(tmp) );
printf("LO pll_out_power: %s%9c", tmp, ' '); /* register in mBm, not mdBm! */
printf(" | ");
printf("REF pll_out_power: %5.3f dBm%9c", dds2->amp_power/100.0, ' '); /* ditto */
amp_power_to_string( dds2->amp_power, tmp, sizeof(tmp) );
printf("REF pll_out_power: %s%9c", tmp, ' '); /* ditto */
printf("\n");
printf("LO sync_state: %4s%17c", ertm_sync_states[dds1->sync_state].label, ' ');
printf(" | ");
printf("REF sync_state: %4s%17c", ertm_sync_states[dds2->sync_state].label, ' ');
printf("\n");
for (i = ERTM14_RF_OUT_MIN_ID; i <= ERTM14_RF_OUT_MAX_ID; i++) {
printf("LO%02d: pow: %5.3f dBm st:%-8s",
i, dds1->out_power[i]/100.0, state_literal[dds1->out_state[i]]);
amp_power_to_string( dds1->out_power[i], tmp, sizeof(tmp) );
printf("LO%02d: pow: %-15s st:%-8s",
i, tmp, state_literal[dds1->out_state[i]]);
printf(" | ");
printf("REF%02d: pow: %5.3f dBm st:%-8s",
i, dds2->out_power[i]/100.0, state_literal[dds2->out_state[i]]);
amp_power_to_string( dds2->out_power[i], tmp, sizeof(tmp) );
printf("REF%02d: pow: %-15s st:%-8s",
i, tmp, state_literal[dds2->out_state[i]]);
printf("\n");
}
}
......@@ -274,6 +300,71 @@ void display_wrc_diags_cooked(struct ertm_wr_status *diags)
printf(human, "SoftPLL Main DAC value [0-65535]", diags->WDIAG_SPLL_MY, diags->WDIAG_SPLL_MY);
}
void display_streamer_diags_cooked(struct ertm_streamer_status *diags)
{
char fmt[] = "%-20s\t0x%08x\n";
char human[] = "%-20s\t0x%08x (%7d)\n";
printf(fmt, "Version register", diags->VER);
printf(fmt, "SSCR1", diags->SSCR1);
printf(fmt, "SSCR2", diags->SSCR2);
printf(fmt, "SSCR3", diags->SSCR3);
printf(fmt, "TX_CFG0", diags->TX_CFG0);
printf(fmt, "TX_CFG1", diags->TX_CFG1);
printf(fmt, "TX_CFG2", diags->TX_CFG2);
printf(fmt, "TX_CFG3", diags->TX_CFG3);
printf(fmt, "TX_CFG4", diags->TX_CFG4);
printf(fmt, "TX_CFG5", diags->TX_CFG5);
printf(fmt, "RX_CFG0", diags->RX_CFG0);
printf(fmt, "RX_CFG1", diags->RX_CFG1);
printf(fmt, "RX_CFG2", diags->RX_CFG2);
printf(fmt, "RX_CFG3", diags->RX_CFG3);
printf(fmt, "RX_CFG4", diags->RX_CFG4);
printf(fmt, "RX_CFG5", diags->RX_CFG5);
printf(fmt, "RX_CFG6", diags->RX_CFG6);
double max_lat = WR_STREAMERS_RX_STAT0_RX_LATENCY_MAX_R(diags->RX_STAT0);
max_lat = (max_lat * 8) / 1000.0;
double min_lat = WR_STREAMERS_RX_STAT1_RX_LATENCY_MIN_R(diags->RX_STAT1);
min_lat = (min_lat * 8) / 1000.0;
int overflow = (WR_STREAMERS_SSCR1_RX_LATENCY_ACC_OVERFLOW & diags->SSCR1) ? 1 : 0;
// put it all together
uint64_t acc_lat = (((uint64_t)diags->RX_STAT11) << 32) | diags->RX_STAT10;
uint64_t cnt_lat = (((uint64_t)diags->RX_STAT13) << 32) | diags->RX_STAT12;
if (cnt_lat > 0)
{
double avg_lat = (((double)acc_lat) * 8 / 1000) / (double)cnt_lat;
printf("Latency [us] : min=%15g max=%15g avg =%15g "
"(overflow =%d)\n",
min_lat, max_lat, avg_lat, overflow);
}
else
printf("No frames received, so no latency stats...\n");
printf("Frames [number]:\n"
" - tx = %15" PRIu64 "\n"
" - rx = %15" PRIu64 "\n"
" - lost = %15" PRIu64 " (lost blocks =%" PRIu64 ")\n",
(((uint64_t)diags->TX_STAT3) << 32) | diags->TX_STAT2,
(((uint64_t)diags->RX_STAT5) << 32) | diags->RX_STAT4,
(((uint64_t)diags->RX_STAT7) << 32) | diags->RX_STAT6,
(((uint64_t)diags->RX_STAT9) << 32) | diags->RX_STAT8);
printf("Fixed latency frames [number]:\n"
" - match = %15"PRIu64"\n"
" - late = %15"PRIu64"\n"
" - timeout = %15"PRIu64"\n",
(((uint64_t)diags->RX_STAT20) << 32) | diags->RX_STAT20,
(((uint64_t)diags->RX_STAT16) << 32) | diags->RX_STAT16,
(((uint64_t)diags->RX_STAT18) << 32) | diags->RX_STAT18);
}
static const char *source_name(int sync_source)
{
switch (sync_source) {
......
......@@ -140,6 +140,53 @@ class ertm_wr_status(Structure):
("WDIAG_UCNT", c_uint),
("WDIAG_TEMP", c_uint),
]
class ertm_streamer_status(Structure):
_fields_ = [
("VER", c_uint),
("SSCR1", c_uint),
("SSCR2", c_uint),
("SSCR3", c_uint),
("RX_STAT0", c_uint),
("RX_STAT1", c_uint),
("TX_STAT2", c_uint),
("TX_STAT3", c_uint),
("RX_STAT4", c_uint),
("RX_STAT5", c_uint),
("RX_STAT6", c_uint),
("RX_STAT7", c_uint),
("RX_STAT8", c_uint),
("RX_STAT9", c_uint),
("RX_STAT10", c_uint),
("RX_STAT11", c_uint),
("RX_STAT12", c_uint),
("RX_STAT13", c_uint),
("TX_CFG0", c_uint),
("TX_CFG1", c_uint),
("TX_CFG2", c_uint),
("TX_CFG3", c_uint),
("TX_CFG4", c_uint),
("TX_CFG5", c_uint),
("RX_CFG0", c_uint),
("RX_CFG1", c_uint),
("RX_CFG2", c_uint),
("RX_CFG3", c_uint),
("RX_CFG4", c_uint),
("RX_CFG5", c_uint),
("CFG", c_uint),
("DBG_CTRL", c_uint),
("DBG_DATA", c_uint),
("DUMMY", c_uint),
("RSTR", c_uint),
("RX_STAT15", c_uint),
("RX_STAT16", c_uint),
("RX_STAT17", c_uint),
("RX_STAT18", c_uint),
("RX_STAT19", c_uint),
("RX_STAT20", c_uint),
("RX_CFG6", c_uint)
]
class ertm_nco_reset(Structure):
_fields_ = [
("enabled", c_uint),
......@@ -458,6 +505,12 @@ class ErtmTest(cmd.Cmd):
buf = ertm_wr_status()
self.lib.ertm_wr_diags(self.handle, byref(buf))
self.display.display_wrc_diags_cooked(byref(buf))
def do_streamer_diags(self, args):
"get WR Streamer (NCO) diagnostics."
buf = ertm_streamer_status()
self.lib.ertm_streamer_diags(self.handle, byref(buf))
self.display.display_streamer_diags_cooked(byref(buf))
def do_wr_status(self, args):
"get WRC link/lock status."
......@@ -483,6 +536,14 @@ class ErtmTest(cmd.Cmd):
return
self.lib.ertm_wr_enable(self.handle, mode)
def do_force_measure_channels_power(self, args ):
"forces an immediate measurement of REF/LO output power. WARNING, will squelch the signals for ~0.5 second!"
self.lib.ertm_force_measure_channels_power(self.handle)
def do_reset_streamer_diags(self, args):
"resets WR (NCO) streamer diagnostic counters."
self.lib.ertm_reset_streamer_diags(self.handle)
def do_wr_disable(self, args):
"""stop PTP daemon (synonymous to "wr_enable disable")."""
self.lib.ertm_wr_enable(self.handle, self.ERTM_WR_FREE_RUNNING)
......@@ -579,11 +640,14 @@ class ErtmTest(cmd.Cmd):
do_dc = do_disable_channel
do_gss = do_get_sync_state
do_wrd = do_wrc_diags
do_strd = do_streamer_diags
do_rstrd = do_reset_streamer_diags
do_temp = do_temperatures
do_volt = do_voltages
do_bi = do_board_info
do_nco = do_nco_status
do_snco = do_subscribe_nco_reset
do_fpm = do_force_measure_channels_power
do_gp = do_get_power
do_gcp = do_get_channel_power
......
......@@ -124,26 +124,26 @@ static struct ertm_voltages voltages_defaults = {
struct ertm_wr_status wr_status_default = {
/* FIXME: copied, not #include'd, from wrc_diags_regs.h */
/* eventually replace by struct wrc_diags */
.VER = 0xdeadbabe, /* [0x0]: REG Version register */
.CTRL = 0, /* [0x4]: REG Ctrl */
.WDIAG_SSTAT = 0, /* [0x8]: REG WRPC Diag: servo status */
.WDIAG_PSTAT = 1, /* [0xc]: REG WRPC Diag: Port status */
.WDIAG_PTPSTAT = 3, /* [0x10]: REG WRPC Diag: PTP state */
.WDIAG_ASTAT = 0xa5, /* [0x14]: REG WRPC Diag: AUX state */
.WDIAG_TXFCNT = 0xa5, /* [0x18]: REG WRPC Diag: Tx PTP Frame cnts */
.WDIAG_RXFCNT = 0xa5, /* [0x1c]: REG WRPC Diag: Rx PTP Frame cnts */
.WDIAG_SEC_MSB = 0xa5, /* [0x20]: REG WRPC Diag:local time [msb of s] */
.WDIAG_SEC_LSB = 0xa5, /* [0x24]: REG WRPC Diag: local time [lsb of s] */
.WDIAG_NS = 0xa5, /* [0x28]: REG WRPC Diag: local time [ns] */
.WDIAG_MU_MSB = 0xa5, /* [0x2c]: REG WRPC Diag: Round trip (mu) [msb of ps] */
.WDIAG_MU_LSB = 0xa5, /* [0x30]: REG WRPC Diag: Round trip (mu) [lsb of ps] */
.WDIAG_DMS_MSB = 0xa5, /* [0x34]: REG WRPC Diag: Master-slave delay (dms) [msb of ps] */
.WDIAG_DMS_LSB = 0xa5, /* [0x38]: REG WRPC Diag: Master-slave delay (dms) [lsb of ps] */
.WDIAG_ASYM = 0xa5, /* [0x3c]: REG WRPC Diag: Total link asymmetry [ps] */
.WDIAG_CKO = 0xa5, /* [0x40]: REG WRPC Diag: Clock offset (cko) [ps] */
.WDIAG_SETP = 0xa5, /* [0x44]: REG WRPC Diag: Phase setpoint (setp) [ps] */
.WDIAG_UCNT = 0xa5, /* [0x48]: REG WRPC Diag: Update counter (ucnt) */
.WDIAG_TEMP = 0xa5, /* [0x4c]: REG WRPC Diag: Board temperature [C degree] */
.VER = 0xdeadbabe, /* [0x0]: REG Version register */
.CTRL = 0, /* [0x4]: REG Ctrl */
.WDIAG_SSTAT = 0, /* [0x8]: REG WRPC Diag: servo status */
.WDIAG_PSTAT = 1, /* [0xc]: REG WRPC Diag: Port status */
.WDIAG_PTPSTAT = 3, /* [0x10]: REG WRPC Diag: PTP state */
.WDIAG_ASTAT = 0xa5, /* [0x14]: REG WRPC Diag: AUX state */
.WDIAG_TXFCNT = 0xa5, /* [0x18]: REG WRPC Diag: Tx PTP Frame cnts */
.WDIAG_RXFCNT = 0xa5, /* [0x1c]: REG WRPC Diag: Rx PTP Frame cnts */
.WDIAG_SEC_MSB = 0xa5, /* [0x20]: REG WRPC Diag:local time [msb of s] */
.WDIAG_SEC_LSB = 0xa5, /* [0x24]: REG WRPC Diag: local time [lsb of s] */
.WDIAG_NS = 0xa5, /* [0x28]: REG WRPC Diag: local time [ns] */
.WDIAG_MU_MSB = 0xa5, /* [0x2c]: REG WRPC Diag: Round trip (mu) [msb of ps] */
.WDIAG_MU_LSB = 0xa5, /* [0x30]: REG WRPC Diag: Round trip (mu) [lsb of ps] */
.WDIAG_DMS_MSB = 0xa5, /* [0x34]: REG WRPC Diag: Master-slave delay (dms) [msb of ps] */
.WDIAG_DMS_LSB = 0xa5, /* [0x38]: REG WRPC Diag: Master-slave delay (dms) [lsb of ps] */
.WDIAG_ASYM = 0xa5, /* [0x3c]: REG WRPC Diag: Total link asymmetry [ps] */
.WDIAG_CKO = 0xa5, /* [0x40]: REG WRPC Diag: Clock offset (cko) [ps] */
.WDIAG_SETP = 0xa5, /* [0x44]: REG WRPC Diag: Phase setpoint (setp) [ps] */
.WDIAG_UCNT = 0xa5, /* [0x48]: REG WRPC Diag: Update counter (ucnt) */
.WDIAG_TEMP = 0xa5, /* [0x4c]: REG WRPC Diag: Board temperature [C degree] */
.WDIAG_AUX0_DETAIL_STAT = 0xa5,
.WDIAG_AUX1_DETAIL_STAT = 0xa5,
.WDIAG_AUX2_DETAIL_STAT = 0xa5,
......@@ -483,6 +483,19 @@ static void diags_to_host(struct wrc_diags *diags, struct wrc_diags *host)
for (i = 0; i < ndiags; i++)
dst[i] = ntohl(src[i]);
}
static void streamer_diags_to_host(struct WR_STREAMERS_WB *diags, struct WR_STREAMERS_WB *host)
{
int i;
int ndiags = sizeof(*diags) / sizeof(uint32_t);
uint32_t *src = (uint32_t *)diags;
uint32_t *dst = (uint32_t *)host;
for (i = 0; i < ndiags; i++)
dst[i] = ntohl(src[i]);
}
/* here, bs **can** (and should) be st->state->board_state */
int ertm_get_board_config(struct ertm_status *st, struct ertm14_board_state *bs)
{
......@@ -500,6 +513,7 @@ int ertm_get_board_config(struct ertm_status *st, struct ertm14_board_state *bs)
int ertm_get_wr_diags(struct ertm_status *st, struct wrc_diags *wrc_diags)
{
int res;
struct wrc_diags d, *diags = &d;
res = ertm_proto_cycle(st, ertm14_get_wrc_diags, NULL, diags);
......@@ -510,6 +524,22 @@ int ertm_get_wr_diags(struct ertm_status *st, struct wrc_diags *wrc_diags)
return 0;
}
int ertm_get_streamer_diags(struct ertm_status *st, struct WR_STREAMERS_WB *streamer_diags)
{
int res;
struct WR_STREAMERS_WB d, *diags = &d;
res = ertm_proto_cycle(st, ertm14_get_streamers_diags, NULL, diags);
if (res < 0)
return res;
streamer_diags_to_host(diags, streamer_diags);
return 0;
}
void bytes_to_64_mac(uint64_t *mac, uint8_t src[])
{
uint64_t tmp = 0;
......@@ -933,11 +963,21 @@ struct ertm14_board_state *get_board_state(struct ertm_status *st)
return bs;
}
static int32_t signext32( uint32_t in, int bit )
{
uint32_t mask = ~ ((1<<bit)-1);
printf("MASK %x\n", mask);
if( in & (1<<bit) )
return in | mask;
else
return in;
}
static double amp_power_to_dBm(uint32_t amp_power)
{
/* register values are in mBm, *not* mdBm;
* hence the *10/1000.0 factor */
return amp_power / 100.0;
return (signext32( amp_power & 0x7fffffff, 30 ) ) / 100.0;
}
int ertm_get_power(struct ertm_status *handle,
......@@ -957,6 +997,10 @@ int ertm_get_power(struct ertm_status *handle,
}
update_board_config(handle, bs);
if( !( dds->amp_power & ERTM_FLAGS_DDS_POWER_VALID_MASK ) )
return -EBUSY;
*power = amp_power_to_dBm(dds->amp_power);
return 0;
}
......@@ -1000,8 +1044,12 @@ int ertm_get_channel_power_all(struct ertm_status *handle,
update_board_config(handle, bs);
for (i = ERTM_LOREF_MIN_CH; i <= ERTM_LOREF_MAX_CH; i++) {
if (valid_mask & (1<<i))
{
if( ! (dds->out_power[i] & ERTM_FLAGS_DDS_POWER_VALID_MASK) )
return -EBUSY;
power[i] = amp_power_to_dBm(dds->out_power[i]);
}
}
return 0;
}
......@@ -1122,7 +1170,7 @@ void nco_to_network_order(struct ertm_nco_reset *nco)
nco->connector = htonl(nco->connector);
};
int ertm_nco_reset_get_status(struct ertm_status *handle, struct ertm_nco_reset status[2])
int ertm_nco_reset_get_status(struct ertm_status *handle, struct ertm_nco_reset status[])
{
struct ertm14_board_state *bs = &handle->state->board_state;
int res;
......@@ -1195,6 +1243,23 @@ int ertm_wr_diags(struct ertm_status *handle, struct ertm_wr_status *status)
return ertm_get_wr_diags(handle, s);
}
int ertm_streamer_diags(struct ertm_status *handle, struct ertm_streamer_status *status)
{
struct WR_STREAMERS_WB *s = (struct WR_STREAMERS_WB *)status;
return ertm_get_streamer_diags(handle, s);
}
int ertm_reset_streamer_diags(struct ertm_status *handle )
{
if (bad_handle(handle))
return -ERTM_BAD_HANDLE;
/* do a call to ptp start/stop */
int dummy;
return ertm_proto_cycle(handle, ertm14_reset_streamers_stats, &dummy, NULL);
}
int ertm_wr_status(struct ertm_status *handle, int *link_up, int *is_locked)
{
struct ertm_wr_status status;
......@@ -1270,3 +1335,14 @@ int ertm_get_streamers_latency_timeout(struct ertm_status *handle,
*timeout_cycles = bs->streamers_timeout_cycles;
return 0;
}
int ertm_force_measure_channels_power( struct ertm_status *handle )
{
if (bad_handle(handle))
return -ERTM_BAD_HANDLE;
/* do a call to ptp start/stop */
int dummy;
return ertm_proto_cycle(handle, ertm14_force_measure_channels_power, &dummy, NULL);
}
......@@ -260,6 +260,99 @@ struct ertm_wr_status
uint32_t WDIAG_SPLL_MY; /* [0x88]: REG (ro) WRPC Diag: SoftPLL Main DAC value (MY) */
};
struct ertm_streamer_status
{
/* FIXME: copied, not #include'd, from wr_streamers.h
* This structure is read only. It does have the same format as the streamer's memory map but
* you can only use it to read the diagnostic values and nothing else. The xxxCFG and
* xxxCTRL register are just placeholders, they DO NOTHING */
/* [0x0]: REG Version register */
uint32_t VER;
/* [0x4]: REG Statistics status and ctrl register */
uint32_t SSCR1;
/* [0x8]: REG Statistics status and ctrl register */
uint32_t SSCR2;
/* [0xc]: REG Statistics status and ctrl register */
uint32_t SSCR3;
/* [0x10]: REG Rx statistics */
uint32_t RX_STAT0;
/* [0x14]: REG Rx statistics */
uint32_t RX_STAT1;
/* [0x18]: REG Tx statistics */
uint32_t TX_STAT2;
/* [0x1c]: REG Tx statistics */
uint32_t TX_STAT3;
/* [0x20]: REG Rx statistics */
uint32_t RX_STAT4;
/* [0x24]: REG Rx statistics */
uint32_t RX_STAT5;
/* [0x28]: REG Rx statistics */
uint32_t RX_STAT6;
/* [0x2c]: REG Rx statistics */
uint32_t RX_STAT7;
/* [0x30]: REG Rx statistics */
uint32_t RX_STAT8;
/* [0x34]: REG Rx statistics */
uint32_t RX_STAT9;
/* [0x38]: REG Rx statistics */
uint32_t RX_STAT10;
/* [0x3c]: REG Rx statistics */
uint32_t RX_STAT11;
/* [0x40]: REG Rx statistics */
uint32_t RX_STAT12;
/* [0x44]: REG Rx statistics */
uint32_t RX_STAT13;
/* [0x48]: REG Tx Config Reg 0 */
uint32_t TX_CFG0;
/* [0x4c]: REG Tx Config Reg 1 */
uint32_t TX_CFG1;
/* [0x50]: REG Tx Config Reg 2 */
uint32_t TX_CFG2;
/* [0x54]: REG Tx Config Reg 3 */
uint32_t TX_CFG3;
/* [0x58]: REG Tx Config Reg 4 */
uint32_t TX_CFG4;
/* [0x5c]: REG Tx Config Reg 4 */
uint32_t TX_CFG5;
/* [0x60]: REG Rx Config Reg 0 */
uint32_t RX_CFG0;
/* [0x64]: REG Rx Config Reg 1 */
uint32_t RX_CFG1;
/* [0x68]: REG Rx Config Reg 2 */
uint32_t RX_CFG2;
/* [0x6c]: REG Rx Config Reg 3 */
uint32_t RX_CFG3;
/* [0x70]: REG Rx Config Reg 4 */
uint32_t RX_CFG4;
/* [0x74]: REG Rx Config Reg 5 */
uint32_t RX_CFG5;
/* [0x78]: REG TxRx Config Override */
uint32_t CFG;
/* [0x7c]: REG DBG Control register */
uint32_t DBG_CTRL;
/* [0x80]: REG DBG Data */
uint32_t DBG_DATA;
/* [0x84]: REG Test value */
uint32_t DUMMY;
/* [0x88]: REG Reset Register */
uint32_t RSTR;
/* [0x8c]: REG Rx statistics */
uint32_t RX_STAT15;
/* [0x90]: REG Rx statistics */
uint32_t RX_STAT16;
/* [0x94]: REG Rx statistics */
uint32_t RX_STAT17;
/* [0x98]: REG Rx statistics */
uint32_t RX_STAT18;
/* [0x9c]: REG Rx statistics */
uint32_t RX_STAT19;
/* [0xa0]: REG Rx statistics */
uint32_t RX_STAT20;
/* [0xa4]: REG Rx Config Reg 6 */
uint32_t RX_CFG6;
};
/* as a general rule, all methods in libertm return an integer exit
* code 0 in case of success and < 0 in case of error, the type of error
* mapped to an errno value
......@@ -306,6 +399,7 @@ int ertm_get_channel_power(struct ertm_status *handle,
enum ertm_connector connector, int channel, double *power); /* power per channel in dBm */
int ertm_get_channel_power_all(struct ertm_status *handle,
enum ertm_connector connector, uint32_t valid_mask, double *power); /* powers in dBm */
int ertm_force_measure_channels_power( struct ertm_status *handle );
int ertm_dds_set_level_adjust(struct ertm_status *handle,
enum ertm_connector connector, double level); /* level in [0,1] */
int ertm_dds_get_level_adjust(struct ertm_status *handle,
......@@ -332,6 +426,9 @@ int ertm_wr_status(struct ertm_status *handle, int *link_up, int *is_locked);
int ertm_wr_diags(struct ertm_status *handle, struct ertm_wr_status *status);
/* streamer latency and timeout settings */
int ertm_reset_streamer_diags(struct ertm_status *handle);
int ertm_streamer_diags(struct ertm_status *handle, struct ertm_streamer_status *status);
int ertm_set_streamers_latency(struct ertm_status *handle, uint32_t cycles16n);
int ertm_set_streamers_timeout(struct ertm_status *handle, uint32_t cycles16n);
int ertm_get_streamers_latency_timeout(struct ertm_status *handle,
......
......@@ -12,6 +12,8 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include "libertm.h"
#include "private.h"
#include "display.h"
......@@ -19,11 +21,20 @@
/*
char *ertm_perror(int error)
*/
static uint64_t get_tics(void)
{
struct timezone tz = {0, 0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
int main(int argc, char *argv[])
{
static char usb[] = "/dev/ttyUSB2";
struct ertm_status *handle = ertm_init(NULL);
int attempt;
if (handle == NULL) {
fprintf(stderr, "could not open %s\n", usb);
......@@ -65,6 +76,39 @@ int main(int argc, char *argv[])
ertm_wr_diags(handle, &handle->state->wr_status);
display_wrc_diags_cooked(&handle->state->wr_status);
printf("---------: check force power measurement -------------------------\n");
for( attempt = 0; attempt < 5; attempt++ )
{
int ok = 0;
ertm_force_measure_channels_power( handle );
ertm_get_board_config(handle, &handle->state->board_state);
if( handle->state->board_state.lo.amp_power & ERTM_FLAGS_DDS_POWER_VALID_MASK )
{
fprintf(stderr,"Warning, power valid flag didn't get invalidated after force measure channels power call\n");
}
uint64_t tmo = get_tics();
while (tmo + 2000000ULL > get_tics() )
{
ertm_get_board_config(handle, &handle->state->board_state);
if( handle->state->board_state.lo.amp_power & ERTM_FLAGS_DDS_POWER_VALID_MASK )
{
ok = 1;
break;
}
}
if( ok )
printf("Power measurement received after %.0f ms\n", (double) (get_tics() - tmo) / 1000.0 );
else
printf("ERROR: Power measurement timeout expired.\n");
}
ertm_exit(handle);
return 0;
......
......@@ -16,6 +16,7 @@
#include "common-uart-link.h"
#include "hw/wrc_diags_regs.h"
#include "hw/wr_streamers.h"
struct ertm_state {
struct ertm_board_info board_info;
......
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