Files
2014-04-10 12:20:24 +00:00

136 lines
3.4 KiB
C

/*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Aurelio Colosimo
* Based on ptp-noposix project (see AUTHORS for details)
*
* Released to the public domain
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int e = 0;
uint32_t delta;
if (ppi->is_new_state) {
wrp->wrPortState = WRS_CALIBRATION;
e = msg_issue_wrsig(ppi, CALIBRATE);
pp_timeout_set(ppi, PP_TO_EXT_0,
wrp->calPeriod);
if (wrp->calibrated)
wrp->wrPortState = WRS_CALIBRATION_2;
}
if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
if (wrp->wrMode == WR_MASTER)
ppi->next_state = PPS_MASTER;
else
ppi->next_state = PPS_LISTENING;
wrp->wrPortState = WRS_IDLE;
goto out;
}
switch (wrp->wrPortState) {
case WRS_CALIBRATION:
/* enable pattern sending */
if (wrp->ops->calib_pattern_enable(ppi, 0, 0, 0) ==
WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_1;
else
break;
case WRS_CALIBRATION_1:
/* enable Tx calibration */
if (wrp->ops->calib_enable(ppi, WR_HW_CALIB_TX)
== WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_2;
else
break;
case WRS_CALIBRATION_2:
/* wait until Tx calibration is finished */
if (wrp->ops->calib_poll(ppi, WR_HW_CALIB_TX, &delta) ==
WR_HW_CALIB_READY) {
wrp->deltaTx.scaledPicoseconds.msb =
0xFFFFFFFF & (((uint64_t)delta) >> 16);
wrp->deltaTx.scaledPicoseconds.lsb =
0xFFFFFFFF & (((uint64_t)delta) << 16);
pp_diag(ppi, ext, 1, "Tx=>>scaledPicoseconds.msb = 0x%x\n",
wrp->deltaTx.scaledPicoseconds.msb);
pp_diag(ppi, ext, 1, "Tx=>>scaledPicoseconds.lsb = 0x%x\n",
wrp->deltaTx.scaledPicoseconds.lsb);
wrp->wrPortState = WRS_CALIBRATION_3;
} else {
break; /* again */
}
case WRS_CALIBRATION_3:
/* disable Tx calibration */
if (wrp->ops->calib_disable(ppi, WR_HW_CALIB_TX)
== WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_4;
else
break;
case WRS_CALIBRATION_4:
/* disable pattern sending */
if (wrp->ops->calib_pattern_disable(ppi) == WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_5;
else
break;
case WRS_CALIBRATION_5:
/* enable Rx calibration using the pattern sent by other port */
if (wrp->ops->calib_enable(ppi, WR_HW_CALIB_RX) ==
WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_6;
else
break;
case WRS_CALIBRATION_6:
/* wait until Rx calibration is finished */
if (wrp->ops->calib_poll(ppi, WR_HW_CALIB_RX, &delta) ==
WR_HW_CALIB_READY) {
pp_diag(ppi, ext, 1, "Rx fixed delay = %d\n", (int)delta);
wrp->deltaRx.scaledPicoseconds.msb =
0xFFFFFFFF & (delta >> 16);
wrp->deltaRx.scaledPicoseconds.lsb =
0xFFFFFFFF & (delta << 16);
pp_diag(ppi, ext, 1, "Rx=>>scaledPicoseconds.msb = 0x%x\n",
wrp->deltaRx.scaledPicoseconds.msb);
pp_diag(ppi, ext, 1, "Rx=>>scaledPicoseconds.lsb = 0x%x\n",
wrp->deltaRx.scaledPicoseconds.lsb);
wrp->wrPortState = WRS_CALIBRATION_7;
} else {
break; /* again */
}
case WRS_CALIBRATION_7:
/* disable Rx calibration */
if (wrp->ops->calib_disable(ppi, WR_HW_CALIB_RX)
== WR_HW_CALIB_OK)
wrp->wrPortState = WRS_CALIBRATION_8;
else
break;
case WRS_CALIBRATION_8:
/* send deltas to the other port and go to the next state */
e = msg_issue_wrsig(ppi, CALIBRATED);
ppi->next_state = WRS_CALIBRATED;
wrp->calibrated = TRUE;
default:
break;
}
out:
ppi->next_delay = wrp->wrStateTimeout;
return e;
}