Skip to content
Snippets Groups Projects
Commit 98f01de5 authored by Ezekiel Dohmen's avatar Ezekiel Dohmen
Browse files

Adding sync code, to re-sync ADCs on startup

parent d38ea668
No related branches found
No related tags found
1 merge request!653Adding sync code, to re-sync ADCs on startup.
......@@ -81,6 +81,13 @@ sync2pps_signal( one_pps_sync_t* p1pps, adcInfo_t* padcinfo, uint64_t cpuClock[]
// Found a clock so now enable all cards
gscEnableAdcModule( &cdsPciModules, GSAI_ALL_CARDS, GSAI_DMA_MODE );
timer_start( &cpuClock[ CPU_TIME_CYCLE_START ] );
if (iop_adc_sync_cards( padcinfo ) != 0 ) {
RTSLOG_ERROR("Unsynchronized ADCs were detected, and we were unable to fix the issue within the time alloted.");
return -1;
}
// Now search for the 1PPS sync pulse
// on last channel of 1st ADC
timer_start( &start_tsc);
......
......@@ -14,6 +14,7 @@
#include "fm10Gen.h"//iir_filter_biquad()
#include "controller.h" //cdsPciModules, etc
#include "rts-logger.h"
#include <linux/delay.h>
#ifdef XMIT_DOLPHIN_TIME
#include "../fe/controllerIop.h" //pcieTimer
......@@ -29,6 +30,9 @@
static int first_adc_read = 1;
//Util functions
static int read_from_adc(adcInfo_t* adcinfo, unsigned adc_index);
// Routine for initializing ADC modules on startup
int
iop_adc_init( adcInfo_t* adcinfo )
......@@ -261,13 +265,13 @@ iop_adc_read( adcInfo_t* adcinfo, uint64_t cpuClock[] )
adcinfo->adcRdTimeMax[ card ] = adcinfo->adcRdTime[ card ];
if ( ( jj == 0 ) &&
( adcinfo->adcRdTimeMax[ card ] >
( MAX_ADC_WAIT_CARD_0 * UNDERSAMPLE ) ) )
adcinfo->adcRdTimeErr[ card ]++;
( adcinfo->adcRdTimeMax[ card ] >
( MAX_ADC_WAIT_CARD_0 * UNDERSAMPLE ) ) )
adcinfo->adcRdTimeErr[ card ]++;
if ( ( jj != 0 ) &&
( adcinfo->adcRdTimeMax[ card ] > MAX_ADC_WAIT_CARD_S ) )
adcinfo->adcRdTimeErr[ card ]++;
( adcinfo->adcRdTimeMax[ card ] > MAX_ADC_WAIT_CARD_S ) )
adcinfo->adcRdTimeErr[ card ]++;
/// - --------- If data not ready in time, abort.
/// Either the clock is missing or code is running too slow and ADC FIFO
......@@ -388,6 +392,7 @@ iop_adc_read( adcInfo_t* adcinfo, uint64_t cpuClock[] )
// dWord is the double representation of the ADC data
// This is the value used by the rest of the code calculations.
dWord[ card ][ chan ][ kk ] = adcinfo->adcData[ card ][ chan ];
// If running with fast ADC at 512K and gsc16ai64 at 64K, then:
// fill in the missing data by doing data copy
if ( cdsPciModules.adcType[ card ] == GSC_16AI64SSA &&
......@@ -414,6 +419,7 @@ iop_adc_read( adcInfo_t* adcinfo, uint64_t cpuClock[] )
ioMemData->inputData[ card ][ ioMemCntr ].data[ chan ] =
adcinfo->adcData[ card ][ chan ];
}
/// - ---- Check for ADC overflows
if ( ( adcinfo->adcData[ card ][ chan ] > limit ) ||
( adcinfo->adcData[ card ][ chan ] < -limit ) )
......@@ -424,8 +430,13 @@ iop_adc_read( adcInfo_t* adcinfo, uint64_t cpuClock[] )
adcinfo->adcOF[ card ] = 1;
odcStateWord |= ODC_ADC_OVF;
}
packedData++;
}
} //End of loop for each chan
// For normal IOP ADC undersampling ie not a mixed fast 512K adc and
// normal 64K adc
......@@ -500,3 +511,225 @@ iop_adc_read( adcInfo_t* adcinfo, uint64_t cpuClock[] )
first_adc_read = 0;
return 0;
}
int iop_adc_sync_cards( adcInfo_t* adcinfo )
{
//We need to read from ADC 0 and wait the expected time.
//If we have a fast read, we might just need to clear buffers
int card, jj, not_synced=1, attempts=0;
int slow_cards[MAX_ADC_MODULES] = {0}; //ADC 0 should be slow
volatile int* packedData;
int first_chan_marker = 0;
while( not_synced && attempts < 10 ) {
++attempts;
for ( jj = 0; jj < cdsPciModules.adcCount; jj++ )
{
card = adcinfo->adcRdOrder[ jj ];
packedData = cdsPciModules.pci_adc[ card ];
/// Where last channel is is dependent on adcDummyDatanumber of channels a
/// particular card type has.
switch ( cdsPciModules.adcType[ card ] )
{
case GSC_18AI32SSC1M:
if( first_adc_read && cdsPciModules.adcTimeShift[card] == UNDERSAMPLE )
{
// we'll re-use the first DMA result next IOP cycle.
continue;
}
if(first_adc_read)
{
packedData +=
( cdsPciModules.adcChannels[ card ] * (UNDERSAMPLE
- cdsPciModules.adcTimeShift[card]) - 1 );
}
else
{
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
}
first_chan_marker = GSAF_FIRST_SAMPLE_MARK;
break;
case GSC_18AI64SSC:
if( first_adc_read && cdsPciModules.adcTimeShift[card] == UNDERSAMPLE )
{
// we'll re-use the first DMA result next IOP cycle.
continue;
}
if(first_adc_read)
{
packedData +=
( cdsPciModules.adcChannels[ card ] *( UNDERSAMPLE
- cdsPciModules.adcTimeShift[card] )- 1 );
}
else
{
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
}
first_chan_marker = GSA7_FIRST_SAMPLE_MARK;
break;
default:
if(first_adc_read && cdsPciModules.adcTimeShift[card] == 1)
{
continue;
}
packedData += GSAI_64_OFFSET;
first_chan_marker = GSAI_FIRST_SAMPLE_MARK;
break;
}
uint64_t wait_start_tsc;
unsigned adc_wait_time_ns=0, adc_wait_limit_ns = MAX_ADC_WAIT_CARD_S * 1000;
if( jj == 0) {
adc_wait_limit_ns = MAX_ADC_WAIT_CARD_0*1000;
}
// Capture CPU clock cycle for timing diags
timer_start( &wait_start_tsc);
// Wait for ADC data to arrive via DMA
while ( ( *packedData == DUMMY_ADC_VAL ) &&
( adc_wait_time_ns < adc_wait_limit_ns ) );
{
udelay(1);
adc_wait_time_ns = timer_tock_ns( &wait_start_tsc );
}
RTSLOG_WARN("It took %d ns to read card %d\n", adc_wait_time_ns, card);
if( adc_wait_time_ns >= adc_wait_limit_ns) {
slow_cards[jj] = 1;
}
packedData = cdsPciModules.pci_adc[ card ];
*packedData = 0x0;
// Enable the ADC Demand DMA for next read
switch ( cdsPciModules.adcType[ card ] )
{
case GSC_18AI32SSC1M:
case GSC_18AI64SSC:
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
*packedData = DUMMY_ADC_VAL;
if ( first_adc_read )
{
plx9056_adc_dma_set_size(card,
cdsPciModules.adcChannels[ card ] * UNDERSAMPLE * 4 );
}
plx9056_adc_dma_start( card );
break;
default:
packedData += GSAI_64_OFFSET;
*packedData = DUMMY_ADC_VAL;
plx9056_adc_dma_start( card );
break;
}
} //End loop over ADCs
not_synced = 0;
for(jj=1; jj<cdsPciModules.adcCount; ++jj) {
if ( slow_cards[jj] == 1) {
not_synced = 1;
RTSLOG_WARN("Not synced detected!!!\n");
}
}
if ( not_synced ) { //Read from all fast ADCs
for(jj=0; jj<cdsPciModules.adcCount; ++jj) {
if( slow_cards[jj] == 0 )
read_from_adc(adcinfo, jj);
slow_cards[jj] = 0;//Reset for next loop
}
}
} //While not synced
if( attempts >= 10 ) return -1;
return 0;
}
static int read_from_adc(adcInfo_t* adcinfo, unsigned adc_index)
{
volatile int* packedData;
int card = adcinfo->adcRdOrder[ adc_index ];
int first_chan_marker;
packedData = cdsPciModules.pci_adc[ card ];
/// Where last channel is is dependent on adcDummyDatanumber of channels a
/// particular card type has.
switch ( cdsPciModules.adcType[ card ] )
{
case GSC_18AI32SSC1M:
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
first_chan_marker = GSAF_FIRST_SAMPLE_MARK;
break;
case GSC_18AI64SSC:
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
first_chan_marker = GSA7_FIRST_SAMPLE_MARK;
break;
default:
packedData += GSAI_64_OFFSET;
first_chan_marker = GSAI_FIRST_SAMPLE_MARK;
break;
}
uint64_t wait_start_tsc;
uint64_t adc_wait_time_ns=0, adc_wait_limit_ns = USEC_PER_CYCLE + 10;
// Capture CPU clock cycle for timing diags
timer_start( &wait_start_tsc);
// Wait for ADC data to arrive via DMA
while ( ( *packedData == DUMMY_ADC_VAL ) &&
( adc_wait_time_ns < adc_wait_limit_ns ) );
{
udelay(1);
adc_wait_time_ns = timer_tock_ns( &wait_start_tsc );
}
RTSLOG_WARN("It took %lu ns to read card %d in single ADC read\n", adc_wait_time_ns, card);
packedData = cdsPciModules.pci_adc[ card ];
*packedData = 0x0;
// Enable the ADC Demand DMA for next read
switch ( cdsPciModules.adcType[ card ] )
{
case GSC_18AI32SSC1M:
case GSC_18AI64SSC:
packedData +=
( cdsPciModules.adcChannels[ card ] * UNDERSAMPLE - 1 );
*packedData = DUMMY_ADC_VAL;
plx9056_adc_dma_start( card );
break;
default:
packedData += GSAI_64_OFFSET;
*packedData = DUMMY_ADC_VAL;
plx9056_adc_dma_start( card );
break;
}
return 0;
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ extern "C" {
int iop_adc_init( adcInfo_t* );
int iop_adc_read( adcInfo_t*, unsigned long long[] );
int iop_adc_sync_cards( adcInfo_t* adcinfo );
#ifdef __cplusplus
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment