Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sfp): fix rx power conversion #479

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 17 additions & 50 deletions sonic_platform_base/sonic_sfp/sff8472.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
from __future__ import print_function

try:
import fcntl
import struct
import sys
import time
import os
import getopt
import types
from math import log10
from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods
from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods
from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods
Expand Down Expand Up @@ -828,49 +821,23 @@ def calc_rx_power(self, eeprom_data, offset, size):

# External Calibration

# RX_PWR(uW) = RX_PWR_4 * RX_PWR_AD +
# RX_PWR_3 * RX_PWR_AD +
# RX_PWR_2 * RX_PWR_AD +
# RX_PWR_1 * RX_PWR_AD +
# RX_PWR(0)
off = self.dom_ext_calibration_constants['RX_PWR_4']['offset']
rx_pwr_byte3 = int(eeprom_data[off], 16)
rx_pwr_byte2 = int(eeprom_data[off + 1], 16)
rx_pwr_byte1 = int(eeprom_data[off + 2], 16)
rx_pwr_byte0 = int(eeprom_data[off + 3], 16)
rx_pwr_4 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff)

off = self.dom_ext_calibration_constants['RX_PWR_3']['offset']
rx_pwr_byte3 = int(eeprom_data[off], 16)
rx_pwr_byte2 = int(eeprom_data[off + 1], 16)
rx_pwr_byte1 = int(eeprom_data[off + 2], 16)
rx_pwr_byte0 = int(eeprom_data[off + 3], 16)
rx_pwr_3 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff)

off = self.dom_ext_calibration_constants['RX_PWR_2']['offset']
rx_pwr_byte3 = int(eeprom_data[off], 16)
rx_pwr_byte2 = int(eeprom_data[off + 1], 16)
rx_pwr_byte1 = int(eeprom_data[off + 2], 16)
rx_pwr_byte0 = int(eeprom_data[off + 3], 16)
rx_pwr_2 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff)

off = self.dom_ext_calibration_constants['RX_PWR_1']['offset']
rx_pwr_byte3 = int(eeprom_data[off], 16)
rx_pwr_byte2 = int(eeprom_data[off + 1], 16)
rx_pwr_byte1 = int(eeprom_data[off + 2], 16)
rx_pwr_byte0 = int(eeprom_data[off + 3], 16)
rx_pwr_1 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff)

off = self.dom_ext_calibration_constants['RX_PWR_0']['offset']
rx_pwr_byte3 = int(eeprom_data[off], 16)
rx_pwr_byte2 = int(eeprom_data[off + 1], 16)
rx_pwr_byte1 = int(eeprom_data[off + 2], 16)
rx_pwr_byte0 = int(eeprom_data[off + 3], 16)
rx_pwr_0 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff)

rx_pwr = (rx_pwr_4 * result) + (rx_pwr_3 * result) + (rx_pwr_2 * result) + (rx_pwr_1 * result) + rx_pwr_0

result = float(result * 0.0001)
# SFF-8472 Rev 12.4 section 9.3 5)
# Rx_PWR (uW) = Rx_PWR(4) * Rx_PWR_ADe4 (16 bit unsigned integer) +
# Rx_PWR(3) * Rx_PWR_ADe3 (16 bit unsigned integer) +
# Rx_PWR(2) * Rx_PWR_ADe2 (16 bit unsigned integer) +
# Rx_PWR(1) * Rx_PWR_AD (16 bit unsigned integer) +
# Rx_PWR(0)
rx_pwr_ad = result
result = 0
for i in range(0, 5):
field_name = f'RX_PWR_{i}'
rx_pwr = self.dom_ext_calibration_constants[field_name]
off = rx_pwr['offset']
size = rx_pwr['size']
coeff = self.float_from_bytes(eeprom_data[off:off+size])
result += coeff * rx_pwr_ad ** i

result = result * 0.0001 # uW to mW

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the comment should make it clear that the result value is in 0.1 uW units, not uW (the formula in the documentation at section 9.3 is also misleading in that regards). Otherwise the conversion factor may be interpreted off by an order of magnitude by an unsuspecting reader.

#print(indent, name, " : ", power_in_dbm_str(result))
retval = self.power_in_dbm_str(result)
else:
Expand Down
4 changes: 4 additions & 0 deletions sonic_platform_base/sonic_sfp/sffbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def twos_comp(self, num, bits):
except Exception:
return 0

def float_from_bytes(b):
"""Convert IEEE 754 single precision float from bytes."""
return struct.unpack('!f', b)[0]

def mw_to_dbm(self, mW):
if mW == 0:
return float("-inf")
Expand Down
Loading