Provides a simple way to capture the wave form of a pin. For example it can be used to capture the digital state transitions of a pin connected to an IR receiver. These signals can later be played back using the Signal Generator library to control IR devices. The library supports two means of capturing the signal. The signal can be captured on any digital pin using polling while for higher resolution and more accurate timing the interrupt driven capture feature can be used.

Files at this revision

API Documentation at this revision

Comitter:
taylorza
Date:
Sat Sep 27 04:04:16 2014 +0000
Commit message:
Initial commit of the Signal Capture library

Changed in this revision

DigitalPinCapture.cpp Show annotated file Show diff for this revision Revisions of this file
DigitalPinCapture.h Show annotated file Show diff for this revision Revisions of this file
InterruptPinCapture.cpp Show annotated file Show diff for this revision Revisions of this file
InterruptPinCapture.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r c6f86d422a7e DigitalPinCapture.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DigitalPinCapture.cpp	Sat Sep 27 04:04:16 2014 +0000
@@ -0,0 +1,74 @@
+///////////////////////////////////////////////////////////////////////////////
+// Signal Capture Library
+// Author: Chris Taylor (taylorza)
+#include "mbed.h"
+#include "DigitalPinCapture.h"
+
+DigitalPinCapture::DigitalPinCapture(PinName pin, PinMode mode) :
+    _signalPin(pin, mode),
+    _readTimeout(10000000)
+{
+    
+}
+
+void DigitalPinCapture::setReadTimeout(uint32_t us)
+{
+    _readTimeout = us;
+}
+
+int DigitalPinCapture::read(bool triggerState, uint32_t *pReadings, int count)
+{
+    return readInternal(&triggerState, pReadings, count, true);
+}
+
+int DigitalPinCapture::read(bool *pInitialState, uint32_t *pReadings, int count)
+{
+    return readInternal(pInitialState, pReadings, count, false);
+}
+
+int DigitalPinCapture::readInternal(bool *pPinState, uint32_t *pReadings, int count, bool waitForTrigger)
+{
+    Timer timer;
+    
+    int lastPinState;
+    int lastTransitionTime;
+    
+    timer.start();    
+    if (waitForTrigger)
+    {
+        while (_signalPin == *pPinState)
+        {
+            if (timer.read_us() >= _readTimeout) return 0;
+        }
+        
+        while (_signalPin != *pPinState)
+        {
+            if (timer.read_us() >= _readTimeout) return 0;
+        }
+        lastTransitionTime = timer.read_us();        
+    }
+    else
+    {
+        *pPinState = _signalPin ? true : false;
+        lastTransitionTime = timer.read_us();
+    }
+    
+    lastPinState = *pPinState;
+    
+    int bufferIndex = 0;
+    while (bufferIndex < count && timer.read_us() < _readTimeout)
+    {
+        if (_signalPin != lastPinState)
+        {
+            uint32_t transitionTime = timer.read_us();
+            pReadings[bufferIndex++] = transitionTime - lastTransitionTime;
+            lastPinState = !lastPinState;
+            lastTransitionTime = transitionTime;            
+        }   
+    }
+    
+    timer.stop();        
+        
+    return bufferIndex;
+}
+
diff -r 000000000000 -r c6f86d422a7e DigitalPinCapture.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DigitalPinCapture.h	Sat Sep 27 04:04:16 2014 +0000
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+// Signal Capture Library
+// Author: Chris Taylor (taylorza)
+#ifndef __DIGITALPINCAPTURE_H__
+#define __DIGITALPINCAPTURE_H__
+
+/** Captures the digital wave form of a pin into a timing buffer. */
+class DigitalPinCapture
+{
+    public:
+        /** Create an instance of DigitalPinCapture connected to the specified pin 
+         * @note The DigitalPinCapture class polls the state of the pin and therefore might be less accurate than
+         * using InterruptPinCapture. However, it has the advantage that it does not require an interrupt capable pin.
+        */
+        DigitalPinCapture(PinName pin, PinMode mode);
+        
+        /** Maximum time to wait for waveform data to arrive or completely fill the timing buffer. 
+         * @param us Timeout specified in microseconds
+         */
+        void setReadTimeout(uint32_t us);
+        
+        /** Waits for the pin to transition to the trigger state and proceeds to capture the
+         * pins transition timing into the timing buffer.
+         * @param triggerState State that the pin must transistion to before the readings are captured
+         * @param pReadings Pointer to the timing buffer that will contain the readings in microseconds
+         * @param count The maximum number of readings that can be held in the buffer
+         * @returns The number of timings captured in the buffer.
+         */      
+        int read(bool triggerState, uint32_t *pReadings, int count);
+        
+        /** Immediately start capturing the pin transition timing into the timing buffer.
+         * @param pInitialState Pointer to a bool that will have the initial state of the pin at the time the capture started.
+         * @param pReadings Pointer to the timing buffer that will contain the readings in microseconds
+         * @param count The maximum number of readings that can be held in the buffer
+         * @returns The number of timings captured in the buffer.
+         */      
+        int read(bool *pInitialState, uint32_t *pReadings, int count);
+        
+    private:
+        int readInternal(bool *pPinState, uint32_t *pReadings, int count, bool waitForTrigger);
+        
+    private:        
+        DigitalIn _signalPin;            
+        uint32_t _readTimeout;        
+};
+#endif //__DIGITALPINCAPTURE_H__
diff -r 000000000000 -r c6f86d422a7e InterruptPinCapture.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InterruptPinCapture.cpp	Sat Sep 27 04:04:16 2014 +0000
@@ -0,0 +1,91 @@
+///////////////////////////////////////////////////////////////////////////////
+// Signal Capture Library
+// Author: Chris Taylor (taylorza)
+#include "mbed.h"
+#include "InterruptPinCapture.h"
+
+InterruptPinCapture::InterruptPinCapture(PinName pin, PinMode mode) :
+    _started(false),
+    _readTimeout(10000000),
+    _state(Stopped),
+    _signalPin(pin)
+{
+    _signalPin.mode(mode);        
+}
+
+void InterruptPinCapture::setReadTimeout(uint32_t us)
+{
+    _readTimeout = us;
+}
+
+int InterruptPinCapture::read(bool triggerState, uint32_t *pReadings, int count)
+{
+    return readInternal(&triggerState, pReadings, count, true);
+}
+
+int InterruptPinCapture::read(bool *pInitialState, uint32_t *pReadings, int count)
+{
+    return readInternal(pInitialState, pReadings, count, false);
+}
+
+int InterruptPinCapture::readInternal(bool *pPinState, uint32_t *pReadings, int count, bool waitForTrigger)
+{
+    _bufferIndex = 0;
+    _bufferMaxCount = count;
+    _pBuffer = pReadings;
+    _triggerState = *pPinState ? 1 : 0;   
+    
+    if (waitForTrigger)
+    {
+        _state = WaitForTrigger;
+    }
+    else
+    {
+        *pPinState = _signalPin.read() ? true : false;
+        _state = StartCapturing;
+    }
+    
+    _timer.reset();
+    _timer.start();     
+    
+    _signalPin.rise(this, &InterruptPinCapture::onPinTransition);
+    _signalPin.fall(this, &InterruptPinCapture::onPinTransition);
+    
+    while (_state != Stopped && _timer.read_us() < _readTimeout);
+    
+    _signalPin.rise(NULL);
+    _signalPin.fall(NULL);
+    _state = Stopped;        
+    _timer.stop();        
+        
+    return _bufferIndex;
+}
+
+void InterruptPinCapture::onPinTransition()
+{
+    uint32_t transitionTime = (uint32_t)_timer.read_us();
+    
+    switch(_state)
+    {
+        case WaitForTrigger:
+            if (_signalPin.read() == _triggerState)
+            {            
+                _state = StartCapturing;            
+            }
+            break;
+            
+        case StartCapturing:
+            _lastTransitionTime = transitionTime;
+            _state = Capturing;            
+            break;
+            
+        case Capturing:
+            _pBuffer[_bufferIndex++] = transitionTime - _lastTransitionTime;
+            _lastTransitionTime = transitionTime;
+            if (_bufferIndex >= _bufferMaxCount)
+            {
+                _state = Stopped;
+            }
+            break;        
+    }
+}
diff -r 000000000000 -r c6f86d422a7e InterruptPinCapture.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InterruptPinCapture.h	Sat Sep 27 04:04:16 2014 +0000
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////
+// Signal Capture Library
+// Author: Chris Taylor (taylorza)
+#ifndef __INTERRUPTPINCAPTURE_H__
+#define __INTERRUPTPINCAPTURE_H__
+
+/** Captures the digital wave form of an interrupt capable pin into a timing buffer. */
+class InterruptPinCapture
+{
+    public:
+        /** Create an instance of InterruptPinCapture connected to the specified pin */
+        InterruptPinCapture(PinName pin, PinMode mode);
+        
+        /** Maximum time to wait for waveform data to arrive or completely fill the timing buffer. 
+         * @param us Timeout specified in microseconds
+         */
+        void setReadTimeout(uint32_t us);
+        
+        /** Waits for the pin to transition to the trigger state and proceeds to capture the
+         * pins transition timing into the timing buffer.
+         * @param triggerState State that the pin must transistion to before the readings are captured
+         * @param pReadings Pointer to the timing buffer that will contain the readings in microseconds
+         * @param count The maximum number of readings that can be held in the buffer
+         * @returns The number of timings captured in the buffer.
+         */      
+        int read(bool triggerState, uint32_t *pReadings, int count);
+        
+        /** Immediately start capturing the pin transition timing into the timing buffer.
+         * @param pInitialState Pointer to a bool that will have the initial state of the pin at the time the capture started.
+         * @param pReadings Pointer to the timing buffer that will contain the readings in microseconds
+         * @param count The maximum number of readings that can be held in the buffer
+         * @returns The number of timings captured in the buffer.
+         */      
+        int read(bool *pInitialState, uint32_t *pReadings, int count);
+        
+    private:
+        int readInternal(bool *pPinState, uint32_t *pReadings, int count, bool waitForTrigger);
+        
+    private:
+        void onPinTransition();
+        
+        enum State
+        {
+            Stopped,
+            WaitForTrigger,
+            StartCapturing,
+            Capturing
+        };
+        
+    private:
+        bool _started;
+        uint32_t _readTimeout;        
+        volatile State _state;        
+        InterruptIn _signalPin;            
+        
+        uint32_t *_pBuffer;
+        int _bufferMaxCount;
+        int _bufferIndex;
+        int _startPinState;
+        
+        int _triggerState;
+        uint32_t _lastTransitionTime;
+        Timer _timer;
+};
+#endif //__INTERRUPTPINCAPTURE_H__
\ No newline at end of file