Changeset 17636 for trunk


Ignore:
Timestamp:
03/27/14 16:11:06 (11 years ago)
Author:
tbretz
Message:
Simplified the code to read from the socket; some more cosmitcs and simplifications; increased precision of voltage calculation; added counter to track the broken messages
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/fscctrl.cc

    r17623 r17636  
    2828class ConnectionFSC : public Connection
    2929{
    30     boost::array<unsigned char, 4096> fArray;
    31     vector<unsigned char> input_buffer;
    32     boost::array<unsigned char, sizeof(FSC::BinaryOutput_t)> one_message;
     30    FSC::BinaryOutput_t fMsg;       // A single message
    3331
    3432    bool fIsVerbose;
    35     bool fDump;
    36 
    37     ofstream fDumpStream;
     33
     34    size_t fNumConsecutiveErrors;   // Number of consecutive messages with errors
     35    size_t fNumConsecutiveMessages; // Number of consecutive message which are ok
    3836
    3937
     
    5654    virtual void UpdateCur(float, const vector<float>&)
    5755    {
    58     }
    59 
    60     /*
    61     virtual void UpdateError()
    62     {
    63         if (!fIsVerbose)
    64             return;
    65 
    66         Out() << endl << kRed << "Error received:" << endl;
    67         Out() << fError;
    68         if (fIsHexOutput)
    69             Out() << Converter::GetHex<uint16_t>(fError, 16) << endl;
    70     }
    71 */
    72 
    73     void Dump(const string &str)
    74     {
    75         if (!fDumpStream.is_open())
    76         {
    77             fDumpStream.open("socket_dump-fsc.txt", ios::app);
    78             if (!fDumpStream)
    79             {
    80                 //ostringstream str;
    81                 //str << "Open file " << name << ": " << strerror(errno) << " (errno=" << errno << ")";
    82                 //Error(str);
    83 
    84                 return;
    85             }
    86         }
    87 
    88         fDumpStream << str << endl;
    8956    }
    9057
     
    10774    }
    10875
    109     uint16_t fletcher16( uint8_t const *data, size_t bytes )
    110     {
    111         uint16_t sum1 = 0xff, sum2 = 0xff;
     76    template<typename T>
     77    uint16_t fletcher16(const T *t, size_t cnt)
     78    {
     79        const uint8_t *data = reinterpret_cast<const uint8_t*>(t);
     80
     81        size_t bytes = cnt*sizeof(T);
     82
     83        uint16_t sum1 = 0xff;
     84        uint16_t sum2 = 0xff;
    11285
    11386        while (bytes)
     
    11588            size_t tlen = bytes > 20 ? 20 : bytes;
    11689            bytes -= tlen;
     90
    11791            do {
    118                     sum2 += sum1 += *data++;
     92                sum2 += sum1 += *data++;
    11993            } while (--tlen);
     94
    12095            sum1 = (sum1 & 0xff) + (sum1 >> 8);
    12196            sum2 = (sum2 & 0xff) + (sum2 >> 8);
    12297        }
    123         /* Second reduction step to reduce sums to 8 bits */
     98
     99        // Second reduction step to reduce sums to 8 bits
    124100        sum1 = (sum1 & 0xff) + (sum1 >> 8);
    125101        sum2 = (sum2 & 0xff) + (sum2 >> 8);
     102
    126103        return sum2 << 8 | sum1;
    127104    }
    128    
    129     /* ProcessMessage is only called from HandleRead, when enough bytes were received from the FSC
    130      * The bytes of one message were already stored in *one_message*.
    131      * We convert it to an instance of FSC::BinaryOutput_t
    132      * then we check the two checksums
    133      * and then update the DimServices or not depending on the checksums
    134      */
    135     void ProcessMessage() {
    136 
    137         FSC::BinaryOutput_t* bin_out;
    138         bin_out = (FSC::BinaryOutput_t*)one_message.data();
    139        
    140         if (fIsVerbose) {
     105
     106    bool CheckChecksum()
     107    {
     108        const uint16_t volt_checksum = fletcher16(fMsg.adc_values,    kNumVoltageChannels);
     109        const uint16_t resi_checksum = fletcher16(fMsg.ad7719_values, kNumResistanceChannels);
     110
     111        const bool volt_ok = volt_checksum == fMsg.adc_values_checksum;
     112        const bool resi_ok = resi_checksum == fMsg.ad7719_values_checksum;
     113
     114        if (volt_ok && resi_ok)
     115            return true;
     116
     117        fNumConsecutiveErrors++;
     118
     119        ostringstream out;
     120        out << "Checksum error (V:";
     121        out << hex << setfill('0');
     122
     123        if (volt_ok)
     124            out << "----|----";
     125        else
     126        {
     127            out << setw(4) << volt_checksum;
     128            out << "|";
     129            out << setw(4) << fMsg.adc_values_checksum;
     130        }
     131
     132        out << ", R:";
     133
     134        if (resi_ok)
     135            out << "----|----";
     136        else
     137        {
     138            out << setw(4) << resi_checksum;
     139            out << "|";
     140            out << setw(4) << fMsg.ad7719_values_checksum;
     141        }
     142
     143        out << ",  " << dec;
     144        out << "Nok=" << fNumConsecutiveMessages << ", ";
     145        out << "Nerr=" << fNumConsecutiveErrors << ")";
     146
     147        Warn(out);
     148
     149        fNumConsecutiveMessages = 0;
     150
     151        return false;
     152    }
     153
     154    void ProcessMessage()
     155    {
     156        if (fIsVerbose)
    141157           Out() << "Received one_message of FSC::BinaryOutput_t ... will now process it" << endl;
    142         }
    143        
    144        
    145         uint16_t volt_checksum = fletcher16( (uint8_t const *)&one_message[offsetof(FSC::BinaryOutput_t,adc_values)],
    146                                                 sizeof(bin_out->adc_values) );
    147         if (volt_checksum != bin_out->adc_values_checksum ){
    148             ostringstream out;
    149             out << "volt checksums are different. We calculated " << volt_checksum << " transmitted was: ";
    150             out << bin_out->adc_values_checksum << ".";
    151             Warn(out);
    152             StartRead();
     158
     159        if (!CheckChecksum())
    153160            return;
    154         }
    155        
    156         uint16_t resist_checksum = fletcher16( (uint8_t const *)&one_message[offsetof(FSC::BinaryOutput_t,ad7719_values)],
    157                                                 sizeof(bin_out->ad7719_values) );
    158         if (resist_checksum != bin_out->ad7719_values_checksum ){
    159             ostringstream out;
    160             out << "resist checksums are different. We calculated " << resist_checksum << " transmitted was: ";
    161             out << bin_out->ad7719_values_checksum << ".";
    162             Warn(out);
    163             StartRead();
    164             return;
    165         }
    166 
    167         vector<int> volt (bin_out->adc_values,
    168                             bin_out->adc_values + sizeof(bin_out->adc_values) / sizeof(uint16_t)
    169                           );
    170                          
    171         vector<float> resist(bin_out->ad7719_values,
    172                             bin_out->ad7719_values + sizeof(bin_out->ad7719_values) / sizeof(uint32_t)
    173                           );
    174         float time= float(bin_out->time_sec) + float(bin_out->time_ms)/1000.;
    175 
    176         if (volt.size()!=84 || resist.size()!=64) {
    177             ostringstream out;
    178 
    179             out << "Something went wrong in vector constructors " << volt.size() << " voltages and ";
    180             out << resist.size() << " resistances received; 84 and 64 expected)";
    181             Warn(out);
    182             StartRead();
    183             return;
    184         }
    185        
     161
     162        // That looks a bit odd because it copies the values twice for no reason.
     163        // This is historical and keeps the following code consistent with the
     164        // previous code which was reading ascii data from the fsc
     165        vector<float> volt(  fMsg.adc_values,    fMsg.adc_values    + kNumVoltageChannels);
     166        vector<float> resist(fMsg.ad7719_values, fMsg.ad7719_values + kNumResistanceChannels);
     167
     168        const float time = fMsg.time_sec + fMsg.time_ms/1000.;
     169
    186170        // We want to convert the pure ADC values from the FSC board to mV and kOhm respectively
    187171        // So we do:
    188         for (unsigned int i=0; i<volt.size(); i++){
     172        for (unsigned int i=0; i<volt.size(); i++)
    189173            volt[i] /= 10;
    190         }
    191         for (unsigned int i=0; i<resist.size(); i++){
     174
     175        for (unsigned int i=0; i<resist.size(); i++)
    192176            resist[i] *= (6.25 * 1024) / (1 << 25);
    193         }
    194        
    195177
    196178        int mapv[] =
     
    208190            -1
    209191        };
    210 
    211192
    212193        int mapc[] =
     
    487468        UpdateCur( time, currents);
    488469        UpdateHum( time, humidities);
    489        
    490     }
    491 
    492     void StartRead() {
    493         // DN: 20140318
    494         async_read_some(ba::buffer(fArray),
    495                             boost::bind(&ConnectionFSC::HandleRead, this,     
    496                             dummy::error,
    497                             dummy::bytes_transferred)
    498                         );
    499        
    500         // FIXME: Add timeout here
    501     }
    502    
    503     void HandleRead(const boost::system::error_code& err, size_t bytes_received) {
     470
     471        fNumConsecutiveErrors = 0;
     472        fNumConsecutiveMessages++;
     473    }
     474
     475    void StartRead()
     476    {
     477        ba::async_read(*this, ba::buffer(&fMsg, sizeof(FSC::BinaryOutput_t)),
     478                       boost::bind(&ConnectionFSC::HandleRead, this,
     479                                   dummy::error, dummy::bytes_transferred));
     480
     481        AsyncWait(fInTimeout, 35000, &Connection::HandleReadTimeout); // 30s
     482    }
     483
     484    void HandleRead(const boost::system::error_code& err, size_t bytes_received)
     485    {
    504486        // Do not schedule a new read if the connection failed.
    505487        if (bytes_received==0 || err)
    506488        {
    507489            if (err==ba::error::eof)
    508             {
    509490                return;
    510             }
    511491
    512492            // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
     
    523503            return;
    524504        }
    525        
    526         input_buffer.insert(input_buffer.end(), fArray.data(), fArray.data()+bytes_received);
    527         if (input_buffer.size() >= sizeof(FSC::BinaryOutput_t)){
    528             for (unsigned int i=0; i<sizeof(FSC::BinaryOutput_t); i++){
    529                 one_message[i] = input_buffer[i];
    530             }
    531             input_buffer.erase(input_buffer.begin(),input_buffer.begin()+sizeof(FSC::BinaryOutput_t));
    532             ProcessMessage();
    533         }
    534 
     505
     506        ProcessMessage();
    535507        StartRead();
    536508    }
    537509
    538     void ConnectionEstablished() {
     510    void ConnectionEstablished()
     511    {
     512        fNumConsecutiveErrors   = 0;
     513        fNumConsecutiveMessages = 0;
     514
    539515        StartRead();
    540516    }
    541517
    542 /*
    543518    void HandleReadTimeout(const bs::error_code &error)
    544519    {
     
    575550        PostClose();
    576551    }
    577 */
    578552
    579553public:
    580554    ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
    581         fIsVerbose(false), fDump(false)
     555        fIsVerbose(false)
    582556    {
    583557        SetLogStream(&imp);
     
    587561    {
    588562        fIsVerbose = b;
    589     }
    590 
    591     void SetDumpStream(bool b)
    592     {
    593         fDump = b;
    594563    }
    595564
     
    837806    }
    838807
    839     int SetDumpStream(const EventImp &evt)
    840     {
    841         if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
    842             return T::kSM_FatalError;
    843 
    844         fFSC.SetDumpStream(evt.GetBool());
    845 
    846         return T::GetCurrentState();
    847     }
    848 
    849808public:
    850809    StateMachineFSC(ostream &out=cout) :
     
    863822            ("set verbosity state"
    864823             "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
    865 
    866         T::AddEvent("DUMP_STREAM", "B:1")
    867             (bind(&StateMachineFSC::SetDumpStream, this, placeholders::_1))
    868             (""
    869              "");
    870824
    871825        // Conenction commands
Note: See TracChangeset for help on using the changeset viewer.