Helmut Schmücker / FtControlSet

Dependencies:   NeedfulThings

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FtControlSetReceiver.cpp Source File

FtControlSetReceiver.cpp

00001 #include "FtControlSetReceiver.h"
00002 
00003 #include "us_ticker_api.h"
00004 
00005 /// message timeout depends on selected sender frequency
00006 const uint32_t FtControlSetReceiver::c_messageTimeout[2] = {89000+20*c_maxPulseTime,118000+20*c_maxPulseTime};
00007 /// di-bit discrimination times
00008 const uint32_t FtControlSetReceiver::c_pulseWidthLimits[5] = {740,860,940,1055,1150};
00009 
00010 FtControlSetReceiver::FtControlSetReceiver(PinName in):
00011     m_pulseIRQ(in),
00012     m_rxBuffer(0),
00013     m_nPulses(0),
00014     m_timeOfLastEdge(0),
00015     m_nOnes(0),
00016     m_errorCount(0),
00017     m_nGracefullyIgnoredErrors(0),
00018     m_lastMessage(0)
00019 {
00020     m_pulseIRQ.mode(PullNone); // the CHQ0038 does't like the default pull down
00021     m_pulseIRQ.fall(this, &FtControlSetReceiver::pulseISR); // we are measuring the distances of falling edges
00022 
00023     //  attch the callbacks 
00024     m_messageTimeout.attach(this,&FtControlSetReceiver::messageTimeoutISR);
00025     m_receiveTimeout.attach(this,&FtControlSetReceiver::handleReceiveError);
00026     m_recoverTimeout.attach(this,&FtControlSetReceiver::recoverISR);
00027 }
00028 
00029 /// called on each falling edge on the IR receivers signal line
00030 void FtControlSetReceiver::pulseISR()
00031 {
00032     // takes 1µs-5µs, 4.1µs on average
00033     if(m_nPulses) {
00034         // received a messge pulse
00035         uint32_t now = us_ticker_read();
00036         m_receiveTimeout.remove();
00037         uint32_t width = now - m_timeOfLastEdge;
00038         m_timeOfLastEdge = now;
00039         if(width>=c_pulseWidthLimits[0] && width<c_pulseWidthLimits[4]) {
00040             if(width<c_pulseWidthLimits[1]){
00041                 // m_rxBuffer|=0x0;
00042             }else if(width<c_pulseWidthLimits[2]) {
00043                 m_rxBuffer|=0x1;
00044                 ++m_nOnes;
00045             } else if(width<c_pulseWidthLimits[3]) {
00046                 m_rxBuffer|=0x2;
00047                 ++m_nOnes;
00048             } else {
00049                 m_rxBuffer|=0x3;
00050             }
00051             m_rxBuffer<<=2;
00052             if(++m_nPulses<=15) {
00053                 // still receiving re-attach the pulse timeout
00054                 m_receiveTimeout.insert(m_timeOfLastEdge+c_maxPulseTime);
00055             } else {
00056                 // we have got a full message
00057                 FtControlSetMessage::Status status;
00058                 if(m_nOnes&1) { // message ones + parity one has to be even
00059                     status = FtControlSetMessage::ParityKO;
00060                 } else if(m_rxBuffer>>28!=8 || m_rxBuffer&4) { // check header=8 and tail=0
00061                     status = FtControlSetMessage::FrameKO;
00062                 } else { // happyhappyjoyjoy
00063                     status = FtControlSetMessage::OK;
00064                 }
00065                 // detach and reattach the message timeout
00066                 m_messageTimeout.remove();
00067                 m_messageTimeout.insert(m_timeOfLastEdge+c_messageTimeout[1]);//just take the longer timeout here, otherwise we run into problems
00068                 if(status == FtControlSetMessage::OK) {
00069                     m_nGracefullyIgnoredErrors = 0;
00070                     m_lastMessage = m_rxBuffer;
00071                 } else {
00072                     if(++m_nGracefullyIgnoredErrors <= c_errorsToBeGracefullyIgnored) {
00073                         m_lastMessage &= ~0x3; // just indicate the error but keep the old message
00074                         m_lastMessage |= status;
00075                     } else {
00076                         m_lastMessage = status; // reset the message and indicate the error
00077                     }
00078                     ++m_errorCount;
00079                 }
00080                 m_callback.call();
00081                 m_rxBuffer=0;
00082                 m_nPulses=0;
00083                 m_nOnes=0;
00084             }
00085         } else {
00086             handleReceiveError();
00087         }
00088     } else {
00089         // the very first edge of a potential message, just memorize time stamp
00090         m_timeOfLastEdge = us_ticker_read();
00091         m_receiveTimeout.insert(m_timeOfLastEdge+c_maxPulseTime);
00092         ++m_nPulses;
00093     }
00094 }
00095 
00096 void FtControlSetReceiver::messageTimeoutISR()
00097 {
00098     m_lastMessage = 0;
00099     m_callback.call();
00100 }
00101 
00102 // called on errors detected in pulseISR or on pulse timeouts
00103 void FtControlSetReceiver::handleReceiveError()
00104 {
00105     // receive errors are not reported via the status bits and the message is not reset here,
00106     // because it might have been just a disturbance between two messages.
00107     // On severe transmission problems the message timeout will bail us out
00108     ++m_errorCount;
00109     //m_errorCount+=10000;
00110     m_rxBuffer=0;
00111     m_nPulses=0;
00112     m_nOnes=0;
00113     // to be graceful in case of high frequency noise disconnect the ISR for some time
00114     m_pulseIRQ.fall(0);
00115     m_recoverTimeout.insert(us_ticker_read()+c_recoverTimeout);
00116 }
00117 
00118 void FtControlSetReceiver::recoverISR()
00119 {
00120     // reattach the pulse handler
00121     m_pulseIRQ.fall(this, &FtControlSetReceiver::pulseISR);
00122 }