Updated with changes from the mBed version. The Emulator class now takes
a Stream as a constructor parameter and outputs onto that.
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
-    enum {Status_Stopped = 0x01,
-          Status_Heating = 0x10,
-          Status_Cooling = 0x20,
-          Status_HoldingLimit = 0x30,
-          Status_HoldingTime = 0x40,
-          Status_HoldingCurrent = 0x50};
+    enum {
+        Status_Stopped = 0x01,
+        Status_Heating = 0x10,
+        Status_Cooling = 0x20,
+        Status_HoldingLimit = 0x30,
+        Status_HoldingTime = 0x40,
+        Status_HoldingCurrent = 0x50
+    };
     enum {
         Error_CoolingRate = (1<<0),
         Error_OpenCircuit = (1<<1),
     enum {
         Error_CoolingRate = (1<<0),
         Error_OpenCircuit = (1<<1),
+    Emulator(Stream *stream)
         mIndex = 0;
         mStatus = Status_Stopped;
         mErrorCode = Error_NoError;
         mIndex = 0;
         mStatus = Status_Stopped;
         mErrorCode = Error_NoError;
     }
 
     void Command_R(const char *cmd)
     }
 
     void Command_R(const char *cmd)
-        char buffer[12];
-        Serial.write(mStatus);
-        Serial.write(mErrorCode);
-        sprintf(buffer, "++++%04x", mTemp);
-        Serial.write((const uint8_t *)buffer, 8);
-        Serial.write('\r');
+        uint8_t buffer[12];
+        buffer[0] = mStatus;
+        buffer[1] = mErrorCode;
+        sprintf((char *)&buffer[2], "++++%04x\r", mTemp);
+        mStream->write((const uint8_t *)buffer, 11);
     }
     void Command_S()
     {
         mStatus = (mTemp > mLimit) ? Status_Cooling : Status_Heating;
     }
     void Command_S()
     {
         mStatus = (mTemp > mLimit) ? Status_Cooling : Status_Heating;
     }
     void Command_E()
     {
         mStatus = Status_Stopped;
     }
     void Command_E()
     {
         mStatus = Status_Stopped;
             else
                 mStatus = Status_HoldingTime;
         }
             else
                 mStatus = Status_HoldingTime;
         }
     }
 
     // Tick is called once per second
     }
 
     // Tick is called once per second
     virtual void Error(uint8_t code, const char *message)
     {
         mErrorCode = code;
     virtual void Error(uint8_t code, const char *message)
     {
         mErrorCode = code;
+        mStream->print(code, HEX);
+        mStream->print(": ");
+        mStream->println(message);
-    virtual void Emit(const char *s) = 0;
+    bool IsHeating() const { return mStatus == Status_Heating; }
+    bool IsCooling() const { return mStatus == Status_Cooling; }
+    bool IsPumping() const { return false; }
     char mBuffer[10];
     uint8_t mIndex;
 
     char mBuffer[10];
     uint8_t mIndex;
 
 
 // Copyright (c) 2013 Pat Thoyts <patthoyts@users.sourceforge.net>
 //
 #include <Arduino.h>
 // Copyright (c) 2013 Pat Thoyts <patthoyts@users.sourceforge.net>
 //
 #include <Arduino.h>
 #include <avr/pgmspace.h>
 #include <avr/pgmspace.h>
+#include <MilliTimer.h>
+#include <LEDPulse.h>
-class Emulator2 : public Emulator
+const int LED_HEARTBEAT = 11; // R1: PB1 | OC1A  (green)
+const int LED_COOLING   = 10; // R2: PB2 | OC1B  (blue)
+const int LED_HEATING   = 9;  // R3: PB3 | OC2A  (red)
+const int LED_PUMPING   = 6;  // R4: PD6 | OC0A  (amber)
+
+static Emulator emulator(&Serial);
+static MilliTimer emulatorTimer;
+static MilliTimer heartbeatTimer;
+static LEDPulse heartbeatLed(LED_HEARTBEAT);
+
+inline void pinInit(int pin, int state)
-public:
-    void Emit(const char *s)
-    {
-        Serial.print(s);
-        Serial.print('\r');
-    }
-    void Error(uint8_t code, const char *msg)
-    {
-        Serial.println(msg);
-    }
-};
-static Emulator2 emulator;
-static MilliTimer timer1;
+    pinMode(pin, OUTPUT);
+    digitalWrite(pin, state);
+}
-    pinMode(13, OUTPUT);
-    digitalWrite(13, HIGH);
+    pinInit(LED_HEARTBEAT, LOW);
+    pinInit(LED_COOLING, LOW);
+    pinInit(LED_HEATING, LOW);
+    pinInit(LED_PUMPING, LOW);
     Serial.begin(19200, SERIAL_8N1);
 }
 
 void loop()
 {
     Serial.begin(19200, SERIAL_8N1);
 }
 
 void loop()
 {
+    if (heartbeatTimer.poll(10))
+    {
+        heartbeatLed.Next();
+    }
+
     int count = Serial.available();
     int count = Serial.available();
-    if (count > 0) {
-        for (int n = 0; n < count; ++n) {
+    if (count > 0)
+    {
+        for (int n = 0; n < count; ++n)
+        {
             char c = Serial.read();
             emulator.Add(c);
             char c = Serial.read();
             emulator.Add(c);
-            //Serial.print(c, HEX);
-    if (timer1.poll(1000)) {
+
+    if (emulatorTimer.poll(1000))
+    {
-        //Serial.println("tick");
-        PORTB ^= _BV(PINB5);
+        digitalWrite(LED_HEATING, emulator.IsHeating() ? HIGH : LOW);
+        digitalWrite(LED_COOLING, emulator.IsCooling() ? HIGH : LOW);
+        digitalWrite(LED_PUMPING, emulator.IsPumping() ? HIGH : LOW);