Beispiel #1
0
uint16 NodeEeprom::readEeprom(uint16 location)
{
    uint16 result;

    bool canCacheEeprom = NodeEepromMap::canUseCache_read(location);

    //if we want to pull from the cache
    if(m_useCache && canCacheEeprom)
    {
        //attempt to read the value from the cache
        if(readCache(location, result))
        {
            //the value was found in the cache, just return the result
            return result;
        }
    }

    //we didn't get a value from the cache

    //attempt to read the value from the device
    if(updateCacheFromDevice(location, canCacheEeprom))
    {
        //successfully read from the device, the cache has been updated so read from it
        readCache(location, result);

        return result;
    }

    //we failed to read the eeprom value from the cache or the device
    throw Error_NodeCommunication(m_nodeAddress, "Failed to read EEPROM " + Utils::toStr(location) + " from Node " + Utils::toStr(m_nodeAddress));
}
Beispiel #2
0
    AutoShuntCalResult WirelessNode_Impl::autoShuntCal(const ChannelMask& mask, const ShuntCalCmdInfo& commandInfo)
    {
        //verify the node supports this operation
        if(!features().supportsAutoShuntCal())
        {
            throw Error_NotSupported("AutoShuntCal is not supported by this Node.");
        }

        //verify the channel mask supports this operation
        if(!features().supportsChannelSetting(WirelessTypes::chSetting_autoShuntCal, mask))
        {
            throw Error_NotSupported("AutoShuntCal is not supported by the provided channel(s).");
        }

        uint8 channel = mask.lastChEnabled();
        WirelessTypes::ChannelType chType = features().channelType(channel);

        AutoShuntCalResult result;
        bool success = m_baseStation.node_autoShuntCal(m_address, commandInfo, channel, model(), chType, result);

        if(!success)
        {
            throw Error_NodeCommunication(m_address, "AutoShuntCal has failed.");
        }

        return result;
    }
Beispiel #3
0
    AutoCalResult_shmLink WirelessNode_Impl::autoCal_shmLink()
    {
        WirelessModels::NodeModel nodeModel = features().m_nodeInfo.model();

        //verify the node supports autocal
        if(!features().supportsAutoCal())
        {
            throw Error_NotSupported("AutoCal is not supported by this Node.");
        }

        //verify the node is the correct model
        if(nodeModel != WirelessModels::node_shmLink2 &&
           nodeModel != WirelessModels::node_shmLink2_cust1)
        {
            throw Error_NotSupported("autoCal_shmLink is not supported by this Node's model.");
        }

        //perform the autocal command by the base station
        AutoCalResult_shmLink result;
        bool success = m_baseStation.node_autocal_shm(m_address, result);

        if(!success)
        {
            throw Error_NodeCommunication(m_address, "AutoCal has failed.");
        }

        return result;
    }
Beispiel #4
0
void NodeEeprom::writeEeprom(uint16 location, uint16 value)
{
    //if we want to check the cache
    if(m_useCache && NodeEepromMap::canUseCache_write(location))
    {
        //attempt to read the value from the cache
        uint16 valInCache;
        if(readCache(location, valInCache))
        {
            //if the value in the cache is the same we are trying to write
            if(valInCache == value)
            {
                //do not need to write anything, just return
                return;
            }
        }
    }

    //if we made it here, we want to actually write to the device

    //if the read/write version is unknown
    if(m_readWriteVersion == 0)
    {
        //try to determine the version of the read/write eeprom cmd
        if(!determineReadWriteVersion())
        {
            //failed to get the read/write version
            throw Error_NodeCommunication(m_nodeAddress, "Failed to write EEPROM " + Utils::toStr(location) + " to Node " + Utils::toStr(m_nodeAddress));
        }
    }

    //attempt to write the value to the Node
    if(m_baseStation.node_writeEeprom(m_readWriteVersion, m_nodeAddress, location, value))
    {
        //successfully wrote to the Node, update the cache
        updateCache(location, value);

        return;
    }

    //we failed to write the value to the Node

    //clear the eeprom cache for this location if we have one, just to be safe
    clearCacheLocation(location);

    throw Error_NodeCommunication(m_nodeAddress, "Failed to write EEPROM " + Utils::toStr(location) + " to Node " + Utils::toStr(m_nodeAddress));
}
Beispiel #5
0
    void WirelessNode_Impl::erase()
    {
        //call the node_erase command from the parent BaseStation
        bool success = m_baseStation.node_erase(protocol(), m_address);

        //if the erase command failed
        if(!success)
        {
            throw Error_NodeCommunication(m_address, "Failed to erase the Node.");
        }
    }
Beispiel #6
0
    void WirelessNode_Impl::getDiagnosticInfo(ChannelData& result)
    {
        //verify the node supports this operation
        if(!features().supportsGetDiagnosticInfo())
        {
            throw Error_NotSupported("The Get Diagnostic Info command is not supported by this Node.");
        }

        bool success = m_baseStation.node_getDiagnosticInfo(m_address, result);

        if(!success)
        {
            throw Error_NodeCommunication(m_address, "Get Diagnostic Info has failed.");
        }
    }
    ByteStream* NodeMemory_v1::getByteStream(uint16 page)
    {
        //if the requested data is in the currently downloaded data buffer
        if(page == m_currentPageNumber && !m_currentData.empty())
        {
            //just return the address of m_currentPageData
            return &m_currentData;
        }

        //if the requested data is in the previously downloaded data buffer
        if(page == m_previousPageNumber && !m_previousData.empty())
        {
            //just return the address of m_previousPageData
            return &m_previousData;
        }

        //if we made it here, the page requested is data we don't already have

        //request the current page data
        ByteStream tempData;
        if(!m_node.getBaseStation().node_pageDownload(m_node.protocol(), m_node.nodeAddress(), page, tempData))
        {
            //the page download failed, throw an exception
            throw Error_NodeCommunication(m_node.nodeAddress(), "Failed to download data from the Node.");
        }

        //if there is current data that needs move to previous data
        if(!m_currentData.empty())
        {
            //copy the current data into the previous data buffer
            m_previousData.clear();
            m_previousData = m_currentData;
            m_previousPageNumber = m_currentPageNumber;
        }

        //copy the data that was just read into m_currentData
        m_currentData = tempData;
        m_currentPageNumber = page;

        //we successfully downloaded data that is in m_currentData
        return &m_currentData;
    }
Beispiel #8
0
    uint16 WirelessNode_Impl::getNumDatalogSessions()
    {
        if(features().datalogDownloadVersion() == 1)
        {
            return m_eepromHelper->read_numDatalogSessions();
        }
        else
        {
            //datalog v2+ doesn't support the num datalog sessions eeprom

            //use the getDatalogSessionInfo command to obtain this information
            DatalogSessionInfoResult info;
            if(!m_baseStation.node_getDatalogSessionInfo(protocol(), m_address, info))
            {
                throw Error_NodeCommunication(nodeAddress(), "Failed to get the Datalogging Session Info");
            }

            return info.sessionCount;
        }
    }
    DatalogDownloader::DatalogDownloader(const WirelessNode& node):
        m_node(node),
        m_foundFirstTrigger(false),
        m_outOfMemory(false),
        m_sweepCount(0)
    {
        //verify the node supports logged data
        if(!node.features().supportsLoggedData())
        {
            throw Error_NotSupported("Logging is not supported by this Node.");
        }

        m_datalogDownloadVersion = m_node.features().datalogDownloadVersion();

        if(m_datalogDownloadVersion == 1)
        {
            //get the datalogging information from the Node
            uint16 logPage = m_node.eepromHelper().read_logPage();
            uint16 pageOffset = m_node.eepromHelper().read_logPageOffset();

            //create the NodeMemory object (v1)
            m_nodeMemory.reset(new NodeMemory_v1(m_node, logPage, pageOffset));
        }
        else
        {
            //get the datalogging session info
            DatalogSessionInfoResult dlInfo;
            if(!m_node.getBaseStation().node_getDatalogSessionInfo(node.protocol(), node.nodeAddress(), dlInfo))
            {
                throw Error_NodeCommunication(m_node.nodeAddress(), "Failed to get the Datalog Session Info");
            }

            //get the FlashInfo
            FlashInfo flashInfo = m_node.eepromHelper().read_flashInfo();

            //create the Node Memory object (v2)
            m_nodeMemory.reset(new NodeMemory_v2(m_node, flashInfo, dlInfo.startAddress, dlInfo.maxLoggedBytes));
        }
    }
Beispiel #10
0
    AutoBalanceResult WirelessNode_Impl::autoBalance(const ChannelMask& mask, float targetPercent)
    {
        Utils::checkBounds_min(targetPercent, 0.0f);
        Utils::checkBounds_max(targetPercent, 100.0f);

        //attempt a few pings first 
        //(legacy (v1) autobalance doesn't have a response packet, so need to check communication)
        uint8 retryCounter = 0;
        bool pingSuccess = false;
        while(!pingSuccess && retryCounter < 3)
        {
            pingSuccess = ping().success();
            retryCounter++;
        }

        if(!pingSuccess)
        {
            throw Error_NodeCommunication(nodeAddress());
        }

        //find the eeprom location that the autobalance will adjust
        //Note: this also verifies that it is supported for this mask
        const EepromLocation& eepromLoc = features().findEeprom(WirelessTypes::chSetting_autoBalance, mask);

        //currently, autobalance is always per channel, so get the channel from the mask
        uint8 channelNumber = mask.lastChEnabled();

        AutoBalanceResult result;

        //perform the autobalance command with the parent base station
        m_baseStation.node_autoBalance(protocol(), m_address, channelNumber, targetPercent, result);

        //clear the cache of the hardware offset eeprom location we adjusted
        eeprom().clearCacheLocation(eepromLoc.location());

        Utils::threadSleep(200);

        //if we used the legacy command, we don't get result info, need to do more work to get it
        if(result.m_errorCode == WirelessTypes::autobalance_legacyNone)
        {
            result.m_errorCode = WirelessTypes::autobalance_maybeInvalid;

            //force the read eeprom retries to a minimum of 3
            uint8 startRetries = m_eepromSettings.numRetries;

            //when this goes out of scope, it will change back the original retries value
            ScopeHelper writebackRetries(std::bind(&WirelessNode_Impl::setReadWriteRetries, this, startRetries));

            //if there are less than 10 retries
            if(startRetries < 10)
            {
                //we want to retry at least a few times
                setReadWriteRetries(10);
            }
            else
            {
                //don't need to write back the retries since we didn't make a change
                writebackRetries.cancel();
            }

            //read the updated hardware offset from the node
            result.m_hardwareOffset = readEeprom(eepromLoc).as_uint16();

            bool readSensorSuccess = false;

            uint8 readSensorTry = 0;
            do
            {
                //perform the read single sensor command
                uint16 sensorVal = 0;
                readSensorSuccess = m_baseStation.node_readSingleSensor(m_address, channelNumber, sensorVal);

                if(readSensorSuccess)
                {
                    //find the max bits value of the node
                    uint32 maxBitsVal = 0;
                    switch(model())
                    {
                        case WirelessModels::node_vLink:
                        case WirelessModels::node_sgLink_rgd:
                        case WirelessModels::node_shmLink:
                            maxBitsVal = 65536;
                            break;

                        default:
                            maxBitsVal = 4096;
                            break;
                    }

                    //calculate and store the percent achieved
                    result.m_percentAchieved = static_cast<float>(sensorVal) / static_cast<float>(maxBitsVal) * 100.0f;
                }

                readSensorTry++;
            }
            while(!readSensorSuccess && readSensorTry <= 3);

            if(readSensorSuccess)
            {
                //mark as questionable if not close enough to the target percentage
                if(std::abs(result.m_percentAchieved - targetPercent) > 5.0)
                {
                    result.m_errorCode = WirelessTypes::autobalance_maybeInvalid;
                }
                else
                {
                    result.m_errorCode = WirelessTypes::autobalance_success;
                }
            }
        }

        return result;
    }