JeeLib
An easy interface to the port headers, the RF12 driver library, timers, low-power code, and more.
 All Classes Files Functions Variables Enumerations Macros Pages
Ports.h
Go to the documentation of this file.
1 // 2009-02-13 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
2 
3 #ifndef Ports_h
4 #define Ports_h
5 
6 /// @file
7 /// Ports library definitions.
8 
9 #if ARDUINO >= 100
10 #include <Arduino.h> // Arduino 1.0
11 #else
12 #include <WProgram.h> // Arduino 0022
13 #endif
14 #include <stdint.h>
15 #include <avr/pgmspace.h>
16 //#include <util/delay.h>
17 
18 // tweak this to switch ATtiny84 etc to new Arduino 1.0+ conventions
19 // see http://arduino.cc/forum/index.php/topic,51984.msg371307.html#msg371307
20 // and http://forum.jeelabs.net/node/1567
21 #if ARDUINO >= 100
22 #define WRITE_RESULT size_t
23 #else
24 #define WRITE_RESULT void
25 #endif
26 
27 /// Interface for JeeNode Ports - see the wiki docs for
28 /// [JeeNodes](https://jeelabs.net/projects/hardware/wiki/JeeNode) and
29 /// [pinouts](https://jeelabs.net/projects/hardware/wiki/Pinouts).
30 /// The Ports class is a thin wrapper around the Arduino's digitalRead(),
31 /// digitalWrite(), analogRead(), etc. functions. It was designed to simplify
32 /// the use of the four standard port headers on JeeNodes.
33 class Port {
34 protected:
35  /// The port number is a small integer mathing the hardware port used.
36  /// Port 0 is special, it designates the I2C hardware pins on a JeeNode.
37  uint8_t portNum;
38 
39 #if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__)
40  /// @return Arduino digital pin number of a Port's D pin (uint8_t).
41  inline uint8_t digiPin() const
42  { return 0; }
43  /// @return Arduino digital pin number of a Port's A pin (uint8_t).
44  inline uint8_t digiPin2() const
45  { return 2; }
46  /// @return Arduino digital pin number of the I pin on all Ports (uint8_t).
47  static uint8_t digiPin3()
48  { return 1; }
49  /// @return Arduino analog pin number of a Port's A pin (uint8_t).
50  inline uint8_t anaPin() const
51  { return 0; }
52 #elif defined(__AVR_ATtiny84__)
53  /// @return Arduino digital pin number of a Port's D pin (uint8_t).
54  inline uint8_t digiPin() const
55  { return 12 - 2 * portNum; }
56  /// @return Arduino digital pin number of a Port's A pin (uint8_t).
57  inline uint8_t digiPin2() const
58  { return 11 - 2 * portNum; }
59  /// @return Arduino digital pin number of the I pin on all Ports (uint8_t).
60  static uint8_t digiPin3()
61  { return 3; }
62  /// @return Arduino analog pin number of a Port's A pin (uint8_t).
63  inline uint8_t anaPin() const
64  { return 11 - 2 * portNum; }
65 #else
66  /// @return Arduino digital pin number of a Port's D pin (uint8_t).
67  inline uint8_t digiPin() const
68  { return portNum ? portNum + 3 : 18; }
69  /// @return Arduino digital pin number of a Port's A pin (uint8_t).
70  inline uint8_t digiPin2() const
71  { return portNum ? portNum + 13 : 19; }
72  /// @return Arduino digital pin number of the I pin on all Ports (uint8_t).
73  static uint8_t digiPin3()
74  { return 3; }
75  /// @return Arduino analog pin number of a Port's A pin (uint8_t).
76  inline uint8_t anaPin() const
77  { return portNum - 1; }
78 #endif
79 
80 public:
81  ///Contructor for a Port.
82  inline Port (uint8_t num) : portNum (num) {}
83 
84  // DIO pin
85 
86  /// Set the pin mode of a Port's D pin. The mode() function member sets the
87  /// I/O data direction of the DIO pin associated with a specific port.
88  /// @param value INPUT or OUTPUT.
89  inline void mode(uint8_t value) const
90  { pinMode(digiPin(), value); }
91  /// Reads the value of a Port's D pin.
92  /// @return High or Low.
93  inline uint8_t digiRead() const
94  { return digitalRead(digiPin()); }
95  /// Write High or Low to a Port's D pin.
96  /// @param value High or Low.
97  inline void digiWrite(uint8_t value) const
98  { return digitalWrite(digiPin(), value); }
99  /// Writes a PWM value to a Port's D pin.
100  inline void anaWrite(uint8_t val) const
101  { analogWrite(digiPin(), val); }
102  /// Applies the Arduino pulseIn() function on a Port's D pin.
103  inline uint32_t pulse(uint8_t state, uint32_t timeout =1000000L) const
104  { return pulseIn(digiPin(), state, timeout); }
105 
106  // AIO pin
107 
108  /// Set the pin mode of a Port's A pin. The mode2() function member sets
109  /// the I/O data direction of the AIO pin associated with a specific port.
110  /// @param value INPUT or OUTPUT.
111  inline void mode2(uint8_t value) const
112  { pinMode(digiPin2(), value); }
113  /// Reads an analog value from a Port's A pin.
114  /// @return int [0..1023]
115  inline uint16_t anaRead() const
116  { return analogRead(anaPin()); }
117  /// Reads the value of a Port's A pin.
118  /// @return High or Low.
119  inline uint8_t digiRead2() const
120  { return digitalRead(digiPin2()); }
121  /// Write High or Low to a Port's A pin.
122  /// @param value High or Low.
123  inline void digiWrite2(uint8_t value) const
124  { return digitalWrite(digiPin2(), value); }
125  /// Applies the Arduino pulseIn() function on a Port's A pin.
126  /// @see http://arduino.cc/en/Reference/pulseIn for more details.
127  inline uint32_t pulse2(uint8_t state, uint32_t timeout =1000000L) const
128  { return pulseIn(digiPin2(), state, timeout); }
129 
130  // IRQ pin (INT1, shared across all ports)
131 
132  /// Set the pin mode of the I pin on all Ports. The mode3() function member
133  /// sets the I/O direction of the IRQ pin associated with a specific port.
134  /// Note that this is the same pin on all ports.
135  /// @param value INPUT or OUTPUT.
136  static void mode3(uint8_t value)
137  { pinMode(digiPin3(), value); }
138  /// Reads the value of the I pin on all Ports.
139  /// @return High or Low.
140  static uint8_t digiRead3()
141  { return digitalRead(digiPin3()); }
142  /// Writes the value of the I pin on all Ports.
143  /// @param value High or Low.
144  static void digiWrite3(uint8_t value)
145  { return digitalWrite(digiPin3(), value); }
146  /// Writes a PWM value to the I pin of all Ports.
147  static void anaWrite3(uint8_t val)
148  { analogWrite(digiPin3(), val); }
149 
150  // both pins: data on DIO, clock on AIO
151 
152  /// Does Arduino shiftOut() with data on D and clock on A pin of the Port.
153  inline void shift(uint8_t bitOrder, uint8_t value) const
154  { shiftOut(digiPin(), digiPin2(), bitOrder, value); }
155  uint16_t shiftRead(uint8_t bitOrder, uint8_t count =8) const;
156  void shiftWrite(uint8_t bitOrder, uint16_t value, uint8_t count =8) const;
157 };
158 
159 /// These objects represent remote nodes connected via wireless.
160 /// Requires the RemotePort and RemoteHandler classes.
161 class RemoteNode {
162 public:
163  /// @struct Data
164  /// %Data structure exchanged to implement RemoteNode functionality.
165  typedef struct {
166  uint8_t flags, modes, digiIO, anaOut[2];
167  uint16_t anaIn[4]; // only bits 0..11 used
168  } Data;
169 
170  RemoteNode (char id, uint8_t band, uint8_t group =0);
171 
172  void poll(uint16_t msecs);
173 
174  friend class RemoteHandler;
175  friend class RemotePort;
176 private:
177  uint8_t nid;
178  uint32_t lastPoll;
179  Data data;
180 };
181 
182 /// A remote handler is able to deal with information from remote nodes.
184 public:
185  static void setup(uint8_t id, uint8_t band, uint8_t group =0);
186  static uint8_t poll(RemoteNode& node, uint8_t send);
187 };
188 
189 /// A remote port is like a local port, bot connected to a remote node.
190 class RemotePort : protected Port {
191  RemoteNode& node;
192 
193  inline uint8_t pinBit() const
194  { return portNum - 1; }
195  inline uint8_t pinBit2() const
196  { return portNum + 3; }
197 public:
198  RemotePort (RemoteNode& remote, uint8_t num) : Port (num), node (remote) {}
199 
200  void mode(uint8_t value) const;
201  uint8_t digiRead() const;
202  void digiWrite(uint8_t value) const;
203  void anaWrite(uint8_t val) const;
204 
205  void mode2(uint8_t value) const;
206  uint16_t anaRead() const;
207  uint8_t digiRead2() const;
208  void digiWrite2(uint8_t value) const;
209 };
210 
211 /// Can be used to drive a software (bit-banged) I2C bus via a Port interface.
212 /// @todo Speed up the I2C bit I/O, it's far too slow right now.
213 class PortI2C : public Port {
214  uint8_t uswait;
215 #if 0
216 // speed test with fast hard-coded version for Port 1:
217  inline void hold() const
218  { _delay_us(1); }
219  inline void sdaOut(uint8_t value) const
220  { bitWrite(DDRD, 4, !value); bitWrite(PORTD, 4, value); }
221  inline uint8_t sdaIn() const
222  { return bitRead(PORTD, 4); }
223  inline void sclHi() const
224  { hold(); bitWrite(PORTC, 0, 1); }
225  inline void sclLo() const
226  { hold(); bitWrite(PORTC, 0, 0); }
227 public:
228  enum { KHZMAX, KHZ400, KHZ100, KHZ_SLOW };
229 #else
230  inline void hold() const
231  { delayMicroseconds(uswait); }
232  inline void sdaOut(uint8_t value) const
233  { mode(!value); digiWrite(value); }
234  inline uint8_t sdaIn() const
235  { return digiRead(); }
236  inline void sclHi() const
237  { hold(); digiWrite2(1); }
238  inline void sclLo() const
239  { hold(); digiWrite2(0); }
240 public:
241  enum { KHZMAX = 1, KHZ400 = 2, KHZ100 = 9 };
242 #endif
243 
244  /// Creates an instance of class PortI2C
245  /// @param num port number corresponding to physical JeeNode port number.
246  /// @param rate in microseconds - time delay between bits? (not quite!)
247  PortI2C (uint8_t num, uint8_t rate =KHZMAX);
248 
249  /// Initalize I2C communication on a JeeNode port.
250  /// @param addr I2C address of device with which to communicate
251  /// @returns 1 if communication succeeded, 0 otherwise
252  uint8_t start(uint8_t addr) const;
253  /// Terminate transmission on an I2C connection.
254  void stop() const;
255  /// Send one byte of data to the currently address I2C device.
256  /// @param data the data byte to send out
257  /// @returns 1 if device acknowledged write, 0 if device did not respond
258  uint8_t write(uint8_t data) const;
259  /// Read a byte using I2C protocol on a JeeNode port.
260  /// @param last pass 1 to signal the last byte read in this bus transaction
261  /// @returns data (byte) read from the I2C device
262  uint8_t read(uint8_t last) const;
263 };
264 
265 /// Each device on the I2C bus needs to be defined using a DeviceI2C instance.
266 class DeviceI2C {
267  const PortI2C& port;
268  uint8_t addr;
269 
270 public:
271  DeviceI2C(const PortI2C& p, uint8_t me) : port (p), addr (me << 1) {}
272 
273  /// see if a device answers at an I2C address
274  bool isPresent() const;
275 
276  /// Create a start condition on the I2C bus, and set things up for sending
277  /// data to this device.
278  /// @returns true if acknowledged by the slave device.
279  uint8_t send() const
280  { return port.start(addr); }
281  /// Create a start condition on the I2C bus, and set things up for receiving
282  /// data from this device.
283  /// @returns true if acknowledged.
284  uint8_t receive() const
285  { return port.start(addr | 1); }
286  /// Create a stop condition on the I2C bus, ending the current transfer.
287  void stop() const
288  { port.stop(); }
289  /// Write a byte to the currently addressed device. Must be preceded by a
290  /// proper PortI2C start() call.
291  /// @param data Data byte to be sent.
292  /// @returns true if the device acknowledged the byte (accepts more data).
293  uint8_t write(uint8_t data) const
294  { return port.write(data); }
295  /// Read a byte from the currently addressed device. Must be preceded by a
296  /// proper PortI2C start() call.
297  /// @param last Indicates whether this is the last byte to read. Used to
298  /// respond to the write with a positive or negative ack.
299  /// Pass 1 if reading the last byte, otherwise pass 0.
300  uint8_t read(uint8_t last) const
301  { return port.read(last); }
302 
303  void setAddress(uint8_t me)
304  { addr = me << 1; }
305 };
306 
307 /// The millisecond timer can be used for timeouts up to 60000 milliseconds.
308 /// Setting the timeout to zero disables the timer.
309 ///
310 /// * for periodic use, poll the timer object with "if (timer.poll(123)) ..."
311 /// * for one-shot use, call "timer.set(123)" and poll as "if (timer.poll())"
312 
313 class MilliTimer {
314  word next;
315  byte armed;
316 public:
317  MilliTimer () : armed (0) {}
318 
319  /// poll until the timer fires
320  /// @param ms Periodic repeat rate of the time, omit for a one-shot timer.
321  byte poll(word ms =0);
322  /// Return the number of milliseconds before the timer will fire
323  word remaining() const;
324  /// Returns true if the timer is not armed
325  byte idle() const { return !armed; }
326  /// set the one-shot timeout value
327  /// @param ms Timeout value. Timer stops once the timer has fired.
328  void set(word ms);
329 };
330 
331 /// Low-power utility code using the Watchdog Timer (WDT). Requires a WDT
332 /// interrupt handler, e.g. EMPTY_INTERRUPT(WDT_vect);
333 class Sleepy {
334 public:
335  /// start the watchdog timer (or disable it if mode < 0)
336  /// @param mode Enable watchdog trigger after "16 << mode" milliseconds
337  /// (mode 0..9), or disable it (mode < 0).
338  /// @note If you use this function, you MUST included a definition of a WDT
339  /// interrupt handler in your code. The simplest is to include this line:
340  ///
341  /// ISR(WDT_vect) { Sleepy::watchdogEvent(); }
342  ///
343  /// This will get called when the watchdog fires.
344  static void watchdogInterrupts (char mode);
345 
346  /// enter low-power mode, wake up with watchdog, INT0/1, or pin-change
347  static void powerDown ();
348 
349  /// Spend some time in low-power mode, the timing is only approximate.
350  /// @param msecs Number of milliseconds to sleep, in range 0..65535.
351  /// @returns 1 if all went normally, or 0 if some other interrupt occurred
352  /// @note If you use this function, you MUST included a definition of a WDT
353  /// interrupt handler in your code. The simplest is to include this line:
354  ///
355  /// ISR(WDT_vect) { Sleepy::watchdogEvent(); }
356  ///
357  /// This will get called when the watchdog fires.
358  static byte loseSomeTime (word msecs);
359 
360  /// This must be called from your watchdog interrupt code.
361  static void watchdogEvent();
362 };
363 
364 /// simple task scheduler for times up to 6000 seconds
365 class Scheduler {
366  word* tasks;
367  word remaining;
368  byte maxTasks;
369  MilliTimer ms100;
370 public:
371  /// initialize for a specified maximum number of tasks
372  Scheduler (byte max);
373  Scheduler (word* buf, byte max);
374 
375  /// Return next task to run, -1 if there are none ready to run, but there
376  /// are tasks waiting, or -2 if there are no tasks waiting (i.e. all idle)
377  char poll();
378  /// same as poll, but wait for event in power-down mode.
379  /// Uses Sleepy::loseSomeTime() - see comments there re requiring the
380  /// watchdog timer.
381  char pollWaiting();
382 
383  /// set a task timer, in tenths of seconds
384  void timer(byte task, word tenths);
385  /// cancel a task timer
386  void cancel(byte task);
387 
388  /// return true if a task timer is not running
389  byte idle(byte task) { return tasks[task] == ~0U; }
390 };
391 
392 /// Interface for the Blink Plug - see https://jeelabs.org/bp
393 class BlinkPlug : public Port {
394  MilliTimer debounce;
395  byte leds, lastState, checkFlags;
396 public:
397  /// Enum containing shorthands for BlinkPlug button states.
398  enum { ALL_OFF, ON1, OFF1, ON2, OFF2, SOME_ON, ALL_ON }; // for buttonCheck
399 
400  /// Constructor for the BlinkPlug class.
401  /// @param port Portnumber the blinkplug is connected to.
402  BlinkPlug (byte port)
403  : Port (port), leds (0), lastState (0), checkFlags (0) {}
404 
405  void ledOn(byte mask);
406  void ledOff(byte mask);
407  /// @return One byte containing the state of both leds.
408  byte ledState() const { return leds; }
409 
410  byte state();
411  byte pushed(); // deprecated, don't use in combination with buttonCheck
412  byte buttonCheck();
413 };
414 
415 /// Interface for the Memory Plug - see https://jeelabs.org/mp
416 class MemoryPlug : public DeviceI2C {
417  uint32_t nextSave;
418 public:
419  MemoryPlug (PortI2C& port)
420  : DeviceI2C (port, 0x50), nextSave (0) {}
421 
422  void load(word page, byte offset, void* buf, int count);
423  void save(word page, byte offset, const void* buf, int count);
424 };
425 
426 /// A memory stream can save and reload a stream of bytes on a MemoryPlug.
428  MemoryPlug& dev;
429  word start, curr;
430  char step;
431  byte buffer[256], pos;
432 public:
433  MemoryStream (MemoryPlug& plug, word page =0, char dir =1)
434  : dev (plug), start (page), curr (page), step (dir), pos (0) {}
435 
436  long position(byte writing) const;
437  byte get();
438  void put(byte data);
439  word flush();
440  void reset();
441 };
442 
443 /// Interface for the UART Plug - see https://jeelabs.org/up
444 class UartPlug : public Print {
445  DeviceI2C dev;
446  // avoid per-byte access, fill entire buffer instead to reduce I2C overhead
447  byte rxbuf[20], in, out;
448 
449  void regSet (byte reg, byte value);
450  void regRead (byte reg);
451 
452 public:
453  UartPlug (PortI2C& port, byte addr)
454  : dev (port, addr), in (0), out (0) {}
455 
456  void begin(long);
457  byte available();
458  int read();
459  void flush();
460  virtual WRITE_RESULT write(byte);
461 };
462 
463 /// Interface for the Dimmer Plug - see https://jeelabs.org/dp
464 class DimmerPlug : public DeviceI2C {
465 public:
466  enum {
467  MODE1, MODE2,
468  PWM0, PWM1, PWM2, PWM3, PWM4, PWM5, PWM6, PWM7,
469  PWM8, PWM9, PWM10, PWM11, PWM12, PWM13, PWM14, PWM15,
470  GRPPWM, GRPFREQ,
471  LEDOUT0, LEDOUT1, LEDOUT2, LEDOUT3,
472  SUBADR1, SUBADR2, SUBADR3, ALLCALLADR,
473  };
474 
475  DimmerPlug (PortI2C& port, byte addr)
476  : DeviceI2C (port, addr) {}
477 
478  void begin ();
479  byte getReg(byte reg) const;
480  void setReg(byte reg, byte value) const;
481  void setMulti(byte reg, ...) const;
482 };
483 
484 /// Interface for the Lux Plug - see https://jeelabs.org/xp
485 class LuxPlug : public DeviceI2C {
486  union { byte b[4]; word w[2]; } data;
487 public:
488  enum {
489  CONTROL, TIMING,
490  THRESHLOWLOW, THRESHLOWHIGH, THRESHHIGHLOW, THRESHHIGHHIGH, INTERRUPT,
491  LUXID = 0xA,
492  DATA0LOW = 0xC, DATA0HIGH, DATA1LOW, DATA1HIGH,
493  };
494 
495  LuxPlug (PortI2C& port, byte addr) : DeviceI2C (port, addr) {}
496 
497  /// Initialize the LuxPlug. Wait at least 1000 ms after calling this!
498  void begin() {
499  send();
500  write(0xC0 | CONTROL);
501  write(3); // power up
502  stop();
503  }
504 
505  ///Power down the lux plug for low power usage.
506  void poweroff() {
507  send();
508  write(0xC0 | CONTROL);
509  write(0); // power down
510  stop();
511  }
512 
513  void setGain(byte high);
514 
515  const word* getData();
516 
517  word calcLux(byte iGain =0, byte tInt =2) const;
518 };
519 
520 // Interface for the HYT131 thermometer/hygrometer - see https://jeelabs.org/2012/06/30/new-hyt131-sensor/
521 class HYT131 : public DeviceI2C {
522 public:
523  // Constructor for the HYT131 sensor.
524  HYT131 (PortI2C& port) : DeviceI2C (port, 0x28) {}
525 
526  // Execute a reading; results are in tenths of degrees and percent, respectively
527  // @param temp in which to store the temperature (int, tenths of degrees C)
528  // @param humi in which to store the humidity (int, tenths of percent)
529  // @param delayFun (optional) supply delayFun that takes ms delay as argument, for low-power waiting during reading (e.g. Sleepy::loseSomeTime()). By default, delay() is used
530  void reading (int& temp, int& humi, byte (*delayFun)(word ms) =0);
531 };
532 
533 /// Interface for the Gravity Plug - see https://jeelabs.org/gp
534 class GravityPlug : public DeviceI2C {
535  /// Data storage for getAxes() and sensitivity()
536  union { byte b[6]; int w[3]; } data;
537 public:
538  /// Constructor for Gravity Plug.
539  GravityPlug (PortI2C& port) : DeviceI2C (port, 0x38) {}
540 
541  /// Setup GravityPlug. Call during setup()
542  void begin() {}
543  /// Set GravityPlug sensitivity.
544  /// @param range 2,4,8
545  /// @param bw (optional) bandwidth.
546  void sensitivity(byte range, word bw =0);
547 
548  /// Get accelleration data from GravityPlug.
549  /// @return An array with 3 integers. (x,y,z) respectively.
550  const int* getAxes();
551  /// Read out the temperature (only for BMA150, not the older BMA020)
552  /// @return temp, in half deg C steps, from -30C to +50C (i.e. times 2)
553  char temperature();
554 };
555 
556 /// Interface for the Input Plug - see https://jeelabs.org/ip
557 class InputPlug : public Port {
558  uint8_t slow;
559 public:
560  InputPlug (uint8_t num, uint8_t fix =0) : Port (num), slow (fix) {}
561 
562  void select(uint8_t channel);
563 };
564 
565 /// Interface for the Infrared Plug - see https://jeelabs.org/ir
566 class InfraredPlug : public Port {
567  uint8_t slot, gap, buf [40];
568  char fill;
569  uint32_t prev;
570 public:
571  /// Initialize with default values for NEC protocol
572  InfraredPlug (uint8_t num);
573 
574  /// Set slot size (us*4) and end-of-data gap (us*256)
575  void configure(uint8_t slot4, uint8_t gap256 =80);
576 
577  /// Call this continuously or at least right after a pin change
578  void poll();
579 
580  /// Returns number of nibbles read, or 0 if not yet ready
581  uint8_t done();
582 
583  enum { UNKNOWN, NEC, NEC_REP };
584  /// Try to decode a received packet, return type of packet
585  /// if recognized, the receive buffer will be overwritten with the results
586  uint8_t decoder(uint8_t nibbles);
587 
588  /// Access to the receive buffer
589  const uint8_t* buffer() { return buf; }
590 
591  /// Send out a bit pattern, cycle time is the "slot4" config value
592  void send(const uint8_t* data, uint16_t bits);
593 };
594 
595 /// Interface for the Heading Board - see https://jeelabs.org/hb
596 class HeadingBoard : public PortI2C {
597  DeviceI2C eeprom, adc, compass;
598  Port aux;
599  // keep following fields in order:
600  word C1, C2, C3, C4, C5, C6, C7;
601  byte A, B, C, D, setReset;
602 
603  byte eepromByte(byte reg) const;
604  void getConstants();
605  word adcValue(byte press) const;
606 
607 public:
608  HeadingBoard (int num)
609  : PortI2C (num), eeprom (*this, 0x50), adc (*this, 0x77),
610  compass (*this, 0x30), aux (5-num), setReset (0x02) {}
611 
612  void begin();
613  void pressure(int& temp, int& pres) const;
614  void heading(int& xaxis, int& yaxis);
615 };
616 
617 /// Interface for the Modern Device 3-axis Compass board.
618 /// See http://shop.moderndevice.com/products/3-axis-compass
619 class CompassBoard : public DeviceI2C {
620  int read2 (byte last);
621 public:
622  CompassBoard (PortI2C& port) : DeviceI2C (port, 0x1E) {}
623 
624  float heading();
625 };
626 
627 /// Interface for the Proximity Plug - see https://jeelabs.org/yp
628 class ProximityPlug : public DeviceI2C {
629 public:
630  enum {
631  FIFO, FAULT, TPSTATUS, TPCONFIG,
632  STR1, STR2, STR3, STR4, STR5, STR6, STR7, STR8,
633  ECEMR, MNTPR, MTPR, TASPR, SCR, LPCR, SKTR,
634  CONFIG, SINFO,
635  };
636 
637  ProximityPlug (PortI2C& port, byte num =0)
638  : DeviceI2C (port, 0x5C + num) {}
639 
640  void begin();
641 
642  void setReg(byte reg, byte value) const;
643  byte getReg(byte reg) const;
644 };
645 
646 /// Interface for the Analog Plug - see https://jeelabs.org/ap
647 class AnalogPlug : public DeviceI2C {
648  byte config;
649 public:
650  AnalogPlug (const PortI2C& port, byte addr =0x69)
651  : DeviceI2C (port, addr), config (0x1C) {}
652 
653  /// Default mode is channel 1, continuous, 18-bit, gain x1
654  void begin (byte mode =0x1C);
655  /// Select channel (1..4), must wait to read it out (up to 270 ms for 18-bit)
656  void select (byte channel);
657  /// Read out 4 bytes, caller will need to shift out the irrelevant lower bits
658  long reading ();
659 };
660 
661 /// Interface for the DHT11 and DHT22 sensors, does not use floating point
662 class DHTxx {
663  byte pin;
664 public:
665  DHTxx (byte pinNum);
666  /// Results are returned in tenths of a degree and percent, respectively.
667  /// Set "precise" to true for the more accurate DHT21 and DHT22 sensors.
668  bool reading (int& temp, int &humi, bool precise =false);
669 };
670 
671 /// Interface for the Color Plug - see https://jeelabs.org/cp
672 class ColorPlug : public DeviceI2C {
673  union { byte b[8]; word w[4]; } data;
674  word chromacct[3];
675 public:
676  enum {
677  CONTROL, TIMING, INTERRUPT, INTERRUPTSOURCE, CPID, GAIN = 0x7,
678  THRESHLOWLOW, THRESHLOWHIGH, THRESHHIGHLOW, THRESHHIGHHIGH,
679  DATA0LOW = 0x10, DATA0HIGH, DATA1LOW, DATA1HIGH,
680  DATA2LOW, DATA2HIGH, DATA3LOW, DATA3HIGH,
681  BLOCKREAD = 0x4F
682  };
683 
684  ColorPlug (PortI2C& port, byte addr) : DeviceI2C (port, addr) {}
685 
686  void begin() {
687  send();
688  write(0x80 | CONTROL);
689  write(3); // power up
690  stop();
691  }
692 
693  void setGain(byte gain, byte prescaler);
694 
695  // returns four 16-bit values: red, green, blue, and clear intensities
696  const word* getData();
697 
698  const word* chromaCCT();
699 };
700 
701 #ifdef Stream_h // only available in recent Arduino IDE versions
702 
703 /// Simple parser for input data and one-letter commands
704 class InputParser {
705 public:
706  typedef struct {
707  char code; // one-letter command code
708  byte bytes; // number of bytes required as input
709  void (*fun)(); // code to call for this command
710  } Commands;
711 
712  /// Set up with a buffer of specified size
713  InputParser (byte size, Commands*, Stream& =Serial);
714  InputParser (byte* buf, byte size, Commands*, Stream& =Serial);
715 
716  /// Number of data bytes
717  byte count() { return fill; }
718 
719  /// Call this frequently to check for incoming data
720  void poll();
721 
722  InputParser& operator >> (char& v) { return get(&v, 1); }
723  InputParser& operator >> (byte& v) { return get(&v, 1); }
724  InputParser& operator >> (int& v) { return get(&v, 2); }
725  InputParser& operator >> (word& v) { return get(&v, 2); }
726  InputParser& operator >> (long& v) { return get(&v, 4); }
727  InputParser& operator >> (uint32_t& v) { return get(&v, 4); }
728  InputParser& operator >> (const char*& v);
729 
730 private:
731  InputParser& get(void*, byte);
732  void reset();
733 
734  byte *buffer, limit, fill, top, next;
735  byte instring, hexmode, hasvalue;
736  uint32_t value;
737  Commands* cmds;
738  Stream& io;
739 };
740 
741 #endif // Stream_h
742 
743 #endif
byte buttonCheck()
Check the state of the buttons.
Definition: Ports.cpp:331
Data structure exchanged to implement RemoteNode functionality.
Definition: Ports.h:165
Interface for the Color Plug - see https://jeelabs.org/cp.
Definition: Ports.h:672
Interface for JeeNode Ports - see the wiki docs for JeeNodes and pinouts.
Definition: Ports.h:33
uint8_t decoder(uint8_t nibbles)
Try to decode a received packet, return type of packet if recognized, the receive buffer will be over...
Definition: Ports.cpp:873
const word * getData()
Read the raw data from the photodiodes.
Definition: Ports.cpp:560
The millisecond timer can be used for timeouts up to 60000 milliseconds.
Definition: Ports.h:313
PortI2C(uint8_t num, uint8_t rate=KHZMAX)
Creates an instance of class PortI2C.
Definition: Ports.cpp:182
uint16_t shiftRead(uint8_t bitOrder, uint8_t count=8) const
Shift a number of bites in to read them.
Definition: Ports.cpp:87
uint8_t write(uint8_t data) const
Send one byte of data to the currently address I2C device.
Definition: Ports.cpp:203
Interface for the Dimmer Plug - see https://jeelabs.org/dp.
Definition: Ports.h:464
simple task scheduler for times up to 6000 seconds
Definition: Ports.h:365
void cancel(byte task)
cancel a task timer
Definition: Ports.cpp:1248
static void digiWrite3(uint8_t value)
Writes the value of the I pin on all Ports.
Definition: Ports.h:144
void begin(byte mode=0x1C)
Default mode is channel 1, continuous, 18-bit, gain x1.
Definition: Ports.cpp:934
void mode2(uint8_t value) const
Set the pin mode of a Port's A pin.
Definition: Ports.h:111
uint8_t start(uint8_t addr) const
Initalize I2C communication on a JeeNode port.
Definition: Ports.cpp:190
Low-power utility code using the Watchdog Timer (WDT).
Definition: Ports.h:333
void set(word ms)
set the one-shot timeout value
Definition: Ports.cpp:263
static void mode3(uint8_t value)
Set the pin mode of the I pin on all Ports.
Definition: Ports.h:136
A remote handler is able to deal with information from remote nodes.
Definition: Ports.h:183
bool reading(int &temp, int &humi, bool precise=false)
Results are returned in tenths of a degree and percent, respectively.
Definition: Ports.cpp:985
word calcLux(byte iGain=0, byte tInt=2) const
Calculate Lux value from the raw data retreived.
Definition: Ports.cpp:581
void send(const uint8_t *data, uint16_t bits)
Send out a bit pattern, cycle time is the "slot4" config value.
Definition: Ports.cpp:899
void select(uint8_t channel)
Select the channel on the multiplexer.
Definition: Ports.cpp:656
void setGain(byte high)
Set the gain mode of the 16x multiplier in the LuxPlug.
Definition: Ports.cpp:550
char pollWaiting()
same as poll, but wait for event in power-down mode.
Definition: Ports.cpp:1219
Interface for the Gravity Plug - see https://jeelabs.org/gp.
Definition: Ports.h:534
uint8_t digiRead2() const
Reads the value of a Port's A pin.
Definition: Ports.h:119
static void watchdogEvent()
This must be called from your watchdog interrupt code.
Definition: Ports.cpp:1172
void begin()
Initialize the LuxPlug. Wait at least 1000 ms after calling this!
Definition: Ports.h:498
Interface for the Modern Device 3-axis Compass board.
Definition: Ports.h:619
void poweroff()
Power down the lux plug for low power usage.
Definition: Ports.h:506
void anaWrite(uint8_t val) const
Writes a PWM value to a Port's D pin.
Definition: Ports.h:100
uint8_t receive() const
Create a start condition on the I2C bus, and set things up for receiving data from this device...
Definition: Ports.h:284
Interface for the Lux Plug - see https://jeelabs.org/xp.
Definition: Ports.h:485
bool isPresent() const
see if a device answers at an I2C address
Definition: Ports.cpp:234
static void powerDown()
enter low-power mode, wake up with watchdog, INT0/1, or pin-change
Definition: Ports.cpp:1120
Interface for the Proximity Plug - see https://jeelabs.org/yp.
Definition: Ports.h:628
void poll()
Call this continuously or at least right after a pin change.
Definition: Ports.cpp:831
void digiWrite(uint8_t value) const
Write High or Low to a Port's D pin.
Definition: Ports.h:97
Scheduler(byte max)
initialize for a specified maximum number of tasks
Definition: Ports.cpp:1176
void shiftWrite(uint8_t bitOrder, uint16_t value, uint8_t count=8) const
The shiftWrite() call is similar but more general than the shift() call in that it allows an adjustab...
Definition: Ports.cpp:115
void ledOff(byte mask)
Turn off the corresponding leds.
Definition: Ports.cpp:289
Can be used to drive a software (bit-banged) I2C bus via a Port interface.
Definition: Ports.h:213
GravityPlug(PortI2C &port)
Constructor for Gravity Plug.
Definition: Ports.h:539
void shift(uint8_t bitOrder, uint8_t value) const
Does Arduino shiftOut() with data on D and clock on A pin of the Port.
Definition: Ports.h:153
void stop() const
Terminate transmission on an I2C connection.
Definition: Ports.cpp:197
byte idle(byte task)
return true if a task timer is not running
Definition: Ports.h:389
These objects represent remote nodes connected via wireless.
Definition: Ports.h:161
static byte loseSomeTime(word msecs)
Spend some time in low-power mode, the timing is only approximate.
Definition: Ports.cpp:1138
long reading()
Read out 4 bytes, caller will need to shift out the irrelevant lower bits.
Definition: Ports.cpp:946
static void anaWrite3(uint8_t val)
Writes a PWM value to the I pin of all Ports.
Definition: Ports.h:147
uint8_t write(uint8_t data) const
Write a byte to the currently addressed device.
Definition: Ports.h:293
A remote port is like a local port, bot connected to a remote node.
Definition: Ports.h:190
static void watchdogInterrupts(char mode)
start the watchdog timer (or disable it if mode < 0)
Definition: Ports.cpp:1102
uint8_t done()
Returns number of nibbles read, or 0 if not yet ready.
Definition: Ports.cpp:859
byte ledState() const
Definition: Ports.h:408
Interface for the Infrared Plug - see https://jeelabs.org/ir.
Definition: Ports.h:566
byte poll(word ms=0)
poll until the timer fires
Definition: Ports.cpp:240
uint8_t anaPin() const
Definition: Ports.h:76
void sensitivity(byte range, word bw=0)
Set GravityPlug sensitivity.
Definition: Ports.cpp:614
const uint8_t * buffer()
Access to the receive buffer.
Definition: Ports.h:589
void configure(uint8_t slot4, uint8_t gap256=80)
Set slot size (us*4) and end-of-data gap (us*256)
Definition: Ports.cpp:825
uint16_t anaRead() const
Reads an analog value from a Port's A pin.
Definition: Ports.h:115
const int * getAxes()
Get accelleration data from GravityPlug.
Definition: Ports.cpp:628
Each device on the I2C bus needs to be defined using a DeviceI2C instance.
Definition: Ports.h:266
static uint8_t digiRead3()
Reads the value of the I pin on all Ports.
Definition: Ports.h:140
A memory stream can save and reload a stream of bytes on a MemoryPlug.
Definition: Ports.h:427
uint8_t digiPin2() const
Definition: Ports.h:70
void timer(byte task, word tenths)
set a task timer, in tenths of seconds
Definition: Ports.cpp:1236
Interface for the Memory Plug - see https://jeelabs.org/mp.
Definition: Ports.h:416
BlinkPlug(byte port)
Constructor for the BlinkPlug class.
Definition: Ports.h:402
void begin()
Setup GravityPlug. Call during setup()
Definition: Ports.h:542
char poll()
Return next task to run, -1 if there are none ready to run, but there are tasks waiting, or -2 if there are no tasks waiting (i.e.
Definition: Ports.cpp:1187
Port(uint8_t num)
Contructor for a Port.
Definition: Ports.h:82
char temperature()
Read out the temperature (only for BMA150, not the older BMA020)
Definition: Ports.cpp:644
Interface for the UART Plug - see https://jeelabs.org/up.
Definition: Ports.h:444
uint8_t portNum
The port number is a small integer mathing the hardware port used.
Definition: Ports.h:37
Interface for the Blink Plug - see https://jeelabs.org/bp.
Definition: Ports.h:393
static uint8_t digiPin3()
Definition: Ports.h:73
void stop() const
Create a stop condition on the I2C bus, ending the current transfer.
Definition: Ports.h:287
void mode(uint8_t value) const
Set the pin mode of a Port's D pin.
Definition: Ports.h:89
Interface for the Input Plug - see https://jeelabs.org/ip.
Definition: Ports.h:557
InfraredPlug(uint8_t num)
Initialize with default values for NEC protocol.
Definition: Ports.cpp:817
Definition: Ports.h:521
byte available()
Test if UartPlug has incoming data.
Definition: Ports.cpp:470
uint8_t send() const
Create a start condition on the I2C bus, and set things up for sending data to this device...
Definition: Ports.h:279
uint8_t digiPin() const
Definition: Ports.h:67
byte idle() const
Returns true if the timer is not armed.
Definition: Ports.h:325
virtual WRITE_RESULT write(byte)
Write data on the serial port of the UartPlug.
Definition: Ports.cpp:503
uint32_t pulse2(uint8_t state, uint32_t timeout=1000000L) const
Applies the Arduino pulseIn() function on a Port's A pin.
Definition: Ports.h:127
uint8_t read(uint8_t last) const
Read a byte using I2C protocol on a JeeNode port.
Definition: Ports.cpp:217
uint8_t read(uint8_t last) const
Read a byte from the currently addressed device.
Definition: Ports.h:300
void begin(long)
Initialize a UartPlug.
Definition: Ports.cpp:457
byte state()
Read entire BlinkPlug state.
Definition: Ports.cpp:306
uint8_t digiRead() const
Reads the value of a Port's D pin.
Definition: Ports.h:93
uint32_t pulse(uint8_t state, uint32_t timeout=1000000L) const
Applies the Arduino pulseIn() function on a Port's D pin.
Definition: Ports.h:103
byte pushed()
Definition: Ports.cpp:315
void flush()
Clear the RX and TX queues.
Definition: Ports.cpp:494
int read()
Read two bytes from the UartPlug's serial input.
Definition: Ports.cpp:489
Interface for the Heading Board - see https://jeelabs.org/hb.
Definition: Ports.h:596
void select(byte channel)
Select channel (1..4), must wait to read it out (up to 270 ms for 18-bit)
Definition: Ports.cpp:940
void ledOn(byte mask)
Turn on the corresponding leds.
Definition: Ports.cpp:273
Interface for the Analog Plug - see https://jeelabs.org/ap.
Definition: Ports.h:647
void digiWrite2(uint8_t value) const
Write High or Low to a Port's A pin.
Definition: Ports.h:123
word remaining() const
Return the number of milliseconds before the timer will fire.
Definition: Ports.cpp:258
Interface for the DHT11 and DHT22 sensors, does not use floating point.
Definition: Ports.h:662