Provides a simple way to generate complex square wave signals on any available pin. In addition the SignalGenerator can generate a carrier wave which is useful when generating IR signals to control electronic devices like a TV etc. The signal generation can be carried out either synchronously or asynchronously. In the case of synchronous signal generation all interrupts can optionally be disabled to improve timing accuracy.

Revision:
3:f30dcc6e8e70
Parent:
2:b2a449bd787f
Child:
4:64d2d834341b
--- a/SignalGenerator.cpp	Fri Sep 12 05:20:08 2014 +0000
+++ b/SignalGenerator.cpp	Sat Sep 13 21:40:16 2014 +0000
@@ -4,56 +4,9 @@
 #include "mbed.h"
 #include "SignalGenerator.h"
 
-int32_t SignalGenerator::_latency = -1;
-
 SignalGenerator::SignalGenerator(PinName pin) : _pin(pin)
 {
-    if (_latency == -1)
-    {
-        Timer t;
-        
-        t.start();
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;
-        _pin = 0;            
-        t.stop();
-        int pinLatency = (t.read_us() + 0.5) / 10;
-        
-        t.reset();
-        t.start();
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        wait_us(100);
-        t.stop();
-        int waitLatency = (t.read_us() + 0.5) / 1000;
-        
-        t.reset();
-        t.start();
-        for (int i = 0; i < 20; i += 2)
-        {
-            wait_us(100);
-        }
-        t.stop();
-        
-        int loopLatency = ((t.read_us() - (1000 + (10 * waitLatency))) + 0.5) / 10;
-        
-        _latency = pinLatency + waitLatency + loopLatency;
-    }
+    
 }
           
 void SignalGenerator::set(bool pinState)
@@ -68,69 +21,81 @@
     uint32_t lastStateHoldTime, 
     int32_t carrierFrequency)
 {
-    uint32_t carrierHalfPeriod = 0;
-    
     if (timingBuffer == NULL || bufferCount == 0)
     {
         return;
     }
 
+    uint16_t lastTiming = bufferCount - 1;
+    
+    Timer transitionTimer;
     if (carrierFrequency > 0)
-    {
-        carrierHalfPeriod = (uint32_t)(500000 / carrierFrequency);
+    {        
+        int timingIndex = 0;                     
+        bool pinState = initialState;
+        bool carrierState = true;        
+        uint32_t carrierHalfPeriod = (500000 / carrierFrequency);
+        uint32_t compare = timingBuffer[timingIndex++];
+        uint32_t carrierCompare = carrierHalfPeriod;       
         
-        bool state = initialState;
-        for(uint16_t i = 0; i < bufferCount; i++)
-        {
-            int c = (int)(timingBuffer[i] / (carrierHalfPeriod + _latency));
-            if (!state)
-            {
-                wait_us(timingBuffer[i]);
+        transitionTimer.start();
+        while(true)
+        {    
+            bool stateChange = false;
+            if (transitionTimer.read_us() >= compare)
+            {                
+                pinState = !pinState;                  
+                stateChange = true;                                              
+                if (timingIndex == lastTiming) break;
+                compare += timingBuffer[timingIndex++];                
             }
-            else
+            
+            if (transitionTimer.read_us() >= carrierCompare)
             {
-                for(int j = 0; j < c; j += 2)
-                {
-                    _pin = 1;
-                    wait_us(carrierHalfPeriod);
-                    _pin = 0;
-                    wait_us(carrierHalfPeriod);
-                }
+                carrierState = !carrierState;                
+                carrierCompare += carrierHalfPeriod;                
+                stateChange = true;
             }
-            state = !state;          
+            
+            if (stateChange) _pin = pinState & carrierState ? 1 : 0;
         }
-         
+
         if (lastStateHoldTime > 0)
         {
-            int c = (int)((double)lastStateHoldTime / carrierHalfPeriod);
-            if (!state)
-            {
-                wait_us(lastStateHoldTime);
-            }
-            else
+            compare += lastStateHoldTime;
+            while (transitionTimer.read_us() < compare)
             {
-                for(int j = 0; j < c; j += 2)
+                if (transitionTimer.read_us() >= carrierCompare)
                 {
-                    _pin = 1;
-                    wait_us(carrierHalfPeriod);
-                    _pin = 0;
-                    wait_us(carrierHalfPeriod);
-                }
+                    carrierState = !carrierState;
+                    carrierCompare += carrierHalfPeriod;
+                    _pin = pinState & carrierState ? 1 : 0;
+                }                    
             }
-        }                
+        }                            
     }
     else
-    {
-        set(initialState);
-        for(uint16_t i = 0; i < bufferCount; ++i)
-        {
-            wait_us(timingBuffer[i]);
-            _pin = !_pin;
+    {   
+        int timingIndex = 0;                     
+        uint32_t compare = timingBuffer[timingIndex++];
+        transitionTimer.start();        
+        set(initialState);                
+        while(true)
+        {                     
+            if (transitionTimer.read_us() >= compare)
+            {   
+                _pin = !_pin;                                                             
+                if (timingIndex == lastTiming) break;
+                compare += timingBuffer[timingIndex++];
+            }
         }
-        
         if (lastStateHoldTime > 0)
         {
-            wait_us(lastStateHoldTime);
-        }
+            compare += lastStateHoldTime;
+            while (transitionTimer.read_us() < compare)
+            {
+                ;
+            }
+        }        
     }  
 }
\ No newline at end of file