RSeries astromech firmware
I2CReceiver.h
Go to the documentation of this file.
1 #ifndef I2CReceiver_h
2 #define I2CReceiver_h
3 
4 #include "ReelTwo.h"
5 #include "core/AnimatedEvent.h"
6 #include "core/CommandEvent.h"
7 #include <Wire.h>
8 
33 template<int bufferSize = 32>
35 {
36 public:
43  I2CReceiverBase(void (*callback)(char*) = nullptr) :
44  fCallback(callback)
45  {
46  *myself() = this;
47  #if !defined(ESP32) || (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 2)
48  Wire.onReceive(i2cEvent); // Register event so when we receive something we jump to i2cEvent();
49  #else
50  #warning NOTE: I2C receiver will not work. Upgrade to version 2.0.4
51  #endif
52  }
53 
60  I2CReceiverBase(byte i2caddress, void (*callback)(char*) = nullptr) :
61  fCallback(callback)
62  {
63  *myself() = this;
64  #if !defined(ESP32) || (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 2)
65  Wire.onReceive(i2cEvent); // Register event so when we receive something we jump to i2cEvent();
66  #else
67  #warning NOTE: I2C receiver will not work. Upgrade to version 2.0.4
68  #endif
69  begin(i2caddress);
70  }
71 
72  void begin(byte i2caddress = 0x19)
73  {
74  Wire.begin(i2caddress); // Connects to I2C Bus and establishes address.
75  }
76 
80  virtual void animate() override
81  {
82  if (fCmdReady && *fCmdString != 0)
83  {
84  if (fCmdString[1] == 0 && fCmdString[0] >= 0 && fCmdString[0] <= 9)
85  {
86  fCmdString[0] += '0';
87  }
88  if (fCallback != nullptr)
89  {
90  fCallback(fCmdString);
91  }
92  else
93  {
94  CommandEvent::process(fCmdString);
95  }
96  }
97  fCmdReady = false;
98  }
99 
100 private:
101  char fCmdString[bufferSize];
102  volatile bool fCmdReady = false;
103  void (*fCallback)(char*) = nullptr;
104 
105  void handleEvent(int howMany)
106  {
107  UNUSED_ARG(howMany)
108  /* ignore any new i2c event until previous one has been processed */
109  if (fCmdReady)
110  return;
111  for (byte i = 0; Wire.available();)
112  {
113  char ch = (char)Wire.read();
114  // Dont add leading whitespace
115  if (i < sizeof(fCmdString) - 1 && (i != 0 || !isspace(ch)))
116  {
117  fCmdString[i++] = (ch != '\r') ? ch : '\n';
118  fCmdString[i] = 0;
119  }
120  }
121  // DEBUG_PRINTLN(fCmdString);
122  fCmdReady = true;
123  }
124 
125  static void i2cEvent(int howMany)
126  {
127  (*myself())->handleEvent(howMany);
128  }
129 
130  static I2CReceiverBase<bufferSize>** myself()
131  {
132  static I2CReceiverBase<bufferSize>* self;
133  return &self;
134  }
135 
136  static constexpr bool sCreated = false;
137 };
138 
156 #endif
CommandEvent::process
static void process(char *cmd)
Calls handleCommand() for each created CommandEvent subclass.
Definition: CommandEvent.h:33
I2CReceiverBase::I2CReceiverBase
I2CReceiverBase(void(*callback)(char *)=nullptr)
Constructor.
Definition: I2CReceiver.h:43
ReelTwo.h
AnimatedEvent
Base class for all animated devices. AnimatedEvent::animate() is called for each device once through ...
Definition: AnimatedEvent.h:18
AnimatedEvent.h
I2CReceiverBase::begin
void begin(byte i2caddress=0x19)
Definition: I2CReceiver.h:72
I2CReceiverBase::I2CReceiverBase
I2CReceiverBase(byte i2caddress, void(*callback)(char *)=nullptr)
Constructor.
Definition: I2CReceiver.h:60
I2CReceiverBase::animate
virtual void animate() override
Dispatch any received i2c event to CommandEvent.
Definition: I2CReceiver.h:80
I2CReceiverBase
Base template of automatic forwarder from i2c to CommandEvent.
Definition: I2CReceiver.h:34
I2CReceiver
I2CReceiverBase I2CReceiver
Definition: I2CReceiver.h:155
UNUSED_ARG
#define UNUSED_ARG(arg)
Definition: ReelTwo.h:25
CommandEvent.h