eBoard šŸ‰  ā‘ ā‘§ā‘Ø
Written for SIA 2017/2018
The source code

Welcome to the matrix (:

1 //This was created by EagleoutIce 'document creator: create_doc' using doxygen 1.8.15 and python 3.5.2
2 //Created: 17.04.2018 16:01:21
3 #ifndef EBOARD_HEADER_GUARD
4  #define EBOARD_HEADER_GUARD
5  #pragma GCC diagnostic push
6  #pragma GCC diagnostic ignored "-Wall"
7  #pragma GCC diagnostic ignored "-Wextra"
8  #pragma pack(push)
9  #pragma pack(16)
10 #define EBOARD_VERSION "3.1m"
11 #define VALUE_TO_STRING(x) #x
12 
13  #ifdef DOC
14 
15  #define PREPROCESS_DEBUG 1
16  #endif
17 #define VALUE(x) VALUE_TO_STRING(x)
18 #ifndef PREPROCESS_DEBUG
19  #define PREPROCESS_DEBUG 0
20  #endif
21 
22  #define PPERFORM_PRAGMA(str) _Pragma(#str)
23  #if PREPROCESS_DEBUG == 1
24  #define DEBUG_MSG(str) PPERFORM_PRAGMA(message ("" #str))
25  #define MACRO_MSG(mac,str) PPERFORM_PRAGMA(message("You set " #mac " to " VALUE(mac) ": " #str))
26  #else
27  #define DEBUG_MSG(str) ;
28  #define MACRO_MSG(mac,str) ;
29  #endif
30 DEBUG_MSG("If you do not want any preprocessing information from this eBoard-Header set PREPROCESS_DEBUG to 0");
31  DEBUG_MSG("You are using eBoard-header v3.1m written by EagleoutIce");
32 
33 
34 
35 
36 
37  //i am a guard... leave me alone :D
38  #ifdef DOC
39  DEBUG_MSG("Documentation macro SET => Full doc features enabled");
40  #define ARDUINO 200
41 
42  #define EBOARD_I2C 0x1
43 
44  #define EBOARD_LCD 0x1
45 
46  #define EBOARD_SHIFT_REGISTER 0x1
47 
48  #define EBOARD_BLUETOOTH 0x1
49 
50  #define REPT_TASK
51 
52  #define __AVR_ATmega2560__
53 
54  #define __AVR_ATmega328P__
55 
56  #define EBOARD_NEO 0x1
57 
58  #define HIGHSPEED
59 
60  #define __AVR__
61  #endif
62 
63  inline int sine8(uint8_t val){
64  return int((__builtin_sin((val/128.0*PI))+1)*127.5+0.5);
65  }
66 
67  inline int gamma8(uint8_t val){
68  return int(pow((val)/255.0,2.6)*255.0+0.5);
69  }
70  #include <avr/pgmspace.h>
71 
72  namespace eagle_impl {}
73  using namespace eagle_impl;
74  #ifndef EBOARD_GUESSPATH
75  DEBUG_MSG("You are using Guesspath! Necessary libraries for eBoard will be included automatically");
76 
77  #define EBOARD_GUESSPATH 0x1
78  #else
79  DEBUG_MSG("You are not using Guesspath! Necessary libraries for eBoard have to be included manually");
80  #endif
81  #if defined(ARDUINO) //general platform-check [No tab]
82 
83  #define main eVirtual_main //main has a different meaning^^
84  #if ARDUINO >= 100 //this could be only Arduino.h but this snippet is portable :D
85  #include "Arduino.h"
86  #else
87  #include <wiring.h>
88  #endif
89  #if not ( defined(__AVR_ATmega2560__) || defined(__AVR_ATmega328P__))
90  #error "This library was build for ARDUINO UNO R3 Aand ARDUINO MEGA 2560!"
91  #endif
92  #if defined(__AVR_ATmega2560__)
93  DEBUG_MSG("Building for Arduino Mega with ATmega2560");
94 
95  #define PIN_MAX 0x32 //53 pins to address - 4 !!53 is SS
96  #else
97  DEBUG_MSG("Building for Arduino Uno or Nano with ATmega328P");
98  #define PIN_MAX 0xA // 13 Pins to address - 4 !!10 is SS
99  #endif
100  #include <avr/io.h>
101  #include <avr/interrupt.h>
102  #if EBOARD_I2C > 0x0 && EBOARD_GUESSPATH > 0x0
103  DEBUG_MSG("You enabled I²C featurea");
104 
105  #define twi_h
106  //#define ATMEGA8
107  #ifndef TWI_FREQ
108  #define TWI_FREQ 100000L
109  #endif
110  # ifndef TWI_BUFFER_LENGTH
111  #define TWI_BUFFER_LENGTH 32
112  #endif
113  #define TWI_READY 0
114  #define TWI_MRX 1
115  #define TWI_MTX 2
116  #define TWI_SRX 3
117  #define TWI_STX 4
118  //#include <inttypes.h>
119  //#include <avr/io.h>
120  #include <avr/interrupt.h>
121  #include <compat/twi.h>
122  #ifndef cbi
123  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
124  #endif
125  #ifndef sbi
126  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
127  #endif
128  #include "pins_arduino.h"
129  static volatile uint8_t twi_state;
130  static volatile uint8_t twi_slarw;
131  static volatile uint8_t twi_sendStop;
132  static volatile uint8_t twi_inRepStart;
133  static void (*twi_onSlaveTransmit)(void);
134  static void (*twi_onSlaveReceive)(uint8_t*, int);
135  static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
136  static volatile uint8_t twi_masterBufferIndex;
137  static volatile uint8_t twi_masterBufferLength;
138  static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
139  static volatile uint8_t twi_txBufferIndex;
140  static volatile uint8_t twi_txBufferLength;
141  static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
142  static volatile uint8_t twi_rxBufferIndex;
143  static volatile uint8_t twi_error;
144  void twi_init(void) {
145  twi_state = TWI_READY;
146  twi_sendStop = true;
147  twi_inRepStart = false;
148  digitalWrite(SDA, 1);
149  digitalWrite(SCL, 1);
150  cbi(TWSR, TWPS0);
151  cbi(TWSR, TWPS1);
152  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
153  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
154  }
155  inline void twi_setAddress(uint8_t address) {
156  TWAR = address << 1;
157  }
158  uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) {
159  uint8_t i;
160  if(TWI_BUFFER_LENGTH < length) return 0;
161  while(TWI_READY != twi_state) continue;
162  twi_state = TWI_MRX;
163  twi_sendStop = sendStop;
164  twi_error = 0xFF;
165  twi_masterBufferIndex = 0;
166  twi_masterBufferLength = length-1;
167  twi_slarw = TW_READ;
168  twi_slarw |= address << 1;
169  if (true == twi_inRepStart) {
170  twi_inRepStart = false;
171  TWDR = twi_slarw;
172  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
173  }
174  else
175  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
176  while(TWI_MRX == twi_state) continue;
177  if (twi_masterBufferIndex < length)
178  length = twi_masterBufferIndex;
179  for(i = 0; i < length; ++i) data[i] = twi_masterBuffer[i];
180  return length;
181  }
182  uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) {
183  uint8_t i;
184  if(TWI_BUFFER_LENGTH < length) return 1;
185  while(TWI_READY != twi_state) continue;
186  twi_state = TWI_MTX;
187  twi_sendStop = sendStop;
188  twi_error = 0xFF;
189  twi_masterBufferIndex = 0;
190  twi_masterBufferLength = length;
191  for(i = 0; i < length; ++i) twi_masterBuffer[i] = data[i];
192  twi_slarw = TW_WRITE;
193  twi_slarw |= address << 1;
194  if (true == twi_inRepStart) {
195  twi_inRepStart = false;
196  TWDR = twi_slarw;
197  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
198  }
199  else
200  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
201  while(wait && (TWI_MTX == twi_state)) continue;
202  if (twi_error == 0xFF) return 0;
203  else if (twi_error == TW_MT_SLA_NACK) return 2;
204  else if (twi_error == TW_MT_DATA_NACK) return 3;
205  else return 4;
206  }
207  uint8_t twi_transmit(const uint8_t* data, uint8_t length) {
208  uint8_t i;
209  if(TWI_BUFFER_LENGTH < length) return 1;
210  if(TWI_STX != twi_state) return 2;
211  twi_txBufferLength = length;
212  for(i = 0; i < length; ++i) twi_txBuffer[i] = data[i];
213  return 0;
214  }
215  void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) {
216  twi_onSlaveReceive = function;
217  }
218  void twi_attachSlaveTxEvent( void (*function)(void) ) {
219  twi_onSlaveTransmit = function;
220  }
221  void twi_reply(uint8_t ack) {
222  if(ack){
223  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
224  }else{
225  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
226  }
227  }
228  void twi_stop(void) {
229  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
230  while(TWCR & _BV(TWSTO)) continue;
231  twi_state = TWI_READY;
232  }
233  void twi_releaseBus(void){
234  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
235  twi_state = TWI_READY;
236  }
237  ISR(TWI_vect) {
238  switch(TW_STATUS){
239  case TW_START:
240  case TW_REP_START:
241  TWDR = twi_slarw;
242  twi_reply(1);
243  break;
244  case TW_MT_SLA_ACK:
245  case TW_MT_DATA_ACK:
246  if(twi_masterBufferIndex < twi_masterBufferLength){
247  TWDR = twi_masterBuffer[twi_masterBufferIndex++];
248  twi_reply(1);
249  }else{
250  if (twi_sendStop) twi_stop();
251  else {
252  twi_inRepStart = true;
253  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
254  twi_state = TWI_READY;
255  }
256  }
257  break;
258  case TW_MT_SLA_NACK:
259  twi_error = TW_MT_SLA_NACK;
260  twi_stop();
261  break;
262  case TW_MT_DATA_NACK:
263  twi_error = TW_MT_DATA_NACK;
264  twi_stop();
265  break;
266  case TW_MT_ARB_LOST:
267  twi_error = TW_MT_ARB_LOST;
268  twi_releaseBus();
269  break;
270  case TW_MR_DATA_ACK:
271  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
272  case TW_MR_SLA_ACK:
273  if(twi_masterBufferIndex < twi_masterBufferLength) twi_reply(1);
274  else twi_reply(0);
275  break;
276  case TW_MR_DATA_NACK:
277  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
278  if (twi_sendStop) twi_stop();
279  else {
280  twi_inRepStart = true;
281  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
282  twi_state = TWI_READY;
283  }
284  break;
285  case TW_MR_SLA_NACK:
286  twi_stop();
287  break;
288  case TW_SR_SLA_ACK:
289  case TW_SR_GCALL_ACK:
290  case TW_SR_ARB_LOST_SLA_ACK:
291  case TW_SR_ARB_LOST_GCALL_ACK:
292  twi_state = TWI_SRX;
293  twi_rxBufferIndex = 0;
294  twi_reply(1);
295  break;
296  case TW_SR_DATA_ACK:
297  case TW_SR_GCALL_DATA_ACK:
298  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
299  twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
300  twi_reply(1);
301  } else twi_reply(0);
302  break;
303  case TW_SR_STOP:
304  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH) twi_rxBuffer[twi_rxBufferIndex] = '\0';
305  twi_stop();
306  twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
307  twi_rxBufferIndex = 0;
308  twi_releaseBus();
309  break;
310  case TW_SR_DATA_NACK:
311  case TW_SR_GCALL_DATA_NACK:
312  twi_reply(0);
313  break;
314  case TW_ST_SLA_ACK:
315  case TW_ST_ARB_LOST_SLA_ACK:
316  twi_state = TWI_STX;
317  twi_txBufferIndex = 0;
318  twi_txBufferLength = 0;
319  twi_onSlaveTransmit();
320  if(0 == twi_txBufferLength){
321  twi_txBufferLength = 1;
322  twi_txBuffer[0] = 0x00;
323  }
324  case TW_ST_DATA_ACK:
325  TWDR = twi_txBuffer[twi_txBufferIndex++];
326  if(twi_txBufferIndex < twi_txBufferLength) twi_reply(1);
327  else twi_reply(0);
328  break;
329  case TW_ST_DATA_NACK:
330  case TW_ST_LAST_DATA:
331  twi_reply(1);
332  twi_state = TWI_READY;
333  break;
334  case TW_NO_INFO:
335  break;
336  case TW_BUS_ERROR:
337  twi_error = TW_BUS_ERROR;
338  twi_stop();
339  break;
340  }
341  }
342 
343  #include <inttypes.h>
344  #include "Stream.h"
345  #define BUFFER_LENGTH 32
346  namespace eagle_impl {
347 
348  class TwoWire : public Stream {
349  private:
350 
351  static uint8_t rxBuffer[];
352 
353  static uint8_t rxBufferIndex;
354 
355  static uint8_t rxBufferLength;
356 
357  static uint8_t txAddress;
358 
359  static uint8_t txBuffer[];
360 
361  static uint8_t txBufferIndex;
362 
363  static uint8_t txBufferLength;
364 
365  static uint8_t transmitting;
366 
367  static void (*user_onRequest)(void);
368 
369  static void (*user_onReceive)(int numBytes);
370 
371  static void onRequestService(void);
372 
373  static void onReceiveService(uint8_t* inBytes, int numBytes);
374  public:
375 
376  TwoWire();
377 
378  void begin();
379 
380  void begin(uint8_t address);
381 
382  inline void begin(int address);
383 
384  void beginTransmission(uint8_t address);
385 
386  inline void beginTransmission(int address);
387 
388  inline uint8_t endTransmission(void);
389 
390  uint8_t endTransmission(uint8_t sendStop);
391 
392  inline uint8_t requestFrom(uint8_t address, uint8_t quantity);
393 
394  uint8_t requestFrom(uint8_t address , uint8_t quantity, uint8_t sendStop);
395 
396  inline uint8_t requestFrom(int address, int quantity);
397 
398  inline uint8_t requestFrom(int address, int quantity, int sendStop);
399 
400  virtual size_t write(uint8_t data);
401 
402  virtual size_t write(const uint8_t *data, size_t quantity);
403 
404  virtual int available(void);
405 
406  virtual int read(void);
407 
408  virtual int peek(void);
409 
410  void onReceive( void (*function)(int) );
411 
412  void onRequest( void (*function)(void) );
413 
414  using Print::write;
415  };
416  }
417  extern "C" {
418  #include <stdlib.h>
419  #include <string.h>
420  #include <inttypes.h>
421  //#include "twi.h"
422  }
423 
425  uint8_t TwoWire::rxBufferIndex = 0;
426  uint8_t TwoWire::rxBufferLength = 0;
427  uint8_t TwoWire::txAddress = 0;
429  uint8_t TwoWire::txBufferIndex = 0;
430  uint8_t TwoWire::txBufferLength = 0;
431  uint8_t TwoWire::transmitting = 0;
432  void (*TwoWire::user_onRequest)(void);
433  void (*TwoWire::user_onReceive)(int);
434  TwoWire::TwoWire() {}
435  void TwoWire::begin(void) {
436  rxBufferIndex = 0;
437  rxBufferLength = 0;
438  txBufferIndex = 0;
439  txBufferLength = 0;
440  twi_init();
441  }
442  void TwoWire::begin(uint8_t address) {
443  twi_setAddress(address);
444  twi_attachSlaveTxEvent(onRequestService);
445  twi_attachSlaveRxEvent(onReceiveService);
446  begin();
447  }
448  void TwoWire::begin(int address) {
449  begin((uint8_t)address);
450  }
451  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
452  if(quantity > BUFFER_LENGTH){
453  quantity = BUFFER_LENGTH;
454  }
455  uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
456  rxBufferIndex = 0;
458  return read;
459  }
460  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) {
461  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
462  }
463  uint8_t TwoWire::requestFrom(int address, int quantity) {
464  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
465  }
466  uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) {
467  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
468  }
469  void TwoWire::beginTransmission(uint8_t address) {
470  transmitting = 1;
471  txAddress = address;
472  txBufferIndex = 0;
473  txBufferLength = 0;
474  }
475  void TwoWire::beginTransmission(int address) {
476  beginTransmission((uint8_t)address);
477  }
478  uint8_t TwoWire::endTransmission(uint8_t sendStop) {
479  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
480  txBufferIndex = 0;
481  txBufferLength = 0;
482  transmitting = 0;
483  return ret;
484  }
485  uint8_t TwoWire::endTransmission(void){
486  return endTransmission(true);
487  }
488  size_t TwoWire::write(uint8_t data) {
489  if(transmitting) {
491  setWriteError();
492  return 0;
493  }
494  txBuffer[txBufferIndex] = data;
495  ++txBufferIndex;
497  }else{
498  twi_transmit(&data, 1);
499  }
500  return 1;
501  }
502  size_t TwoWire::write(const uint8_t *data, size_t quantity) {
503  if(transmitting){
504  for(size_t i = 0; i < quantity; ++i) {
505  write(data[i]);
506  }
507  }else{
508  twi_transmit(data, quantity);
509  }
510  return quantity;
511  }
512  int TwoWire::available(void) {
513  return rxBufferLength - rxBufferIndex;
514  }
515  int TwoWire::read(void) {
516  int8_t value = -1;
518  value = rxBuffer[rxBufferIndex];
519  ++rxBufferIndex;
520  }
521  return value;
522  }
523  int TwoWire::peek(void) {
524  int value = -1;
526  value = rxBuffer[rxBufferIndex];
527  }
528  return value;
529  }
530  void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) {
531  if(!user_onReceive){
532  return;
533  }
535  return;
536  }
537  for(uint8_t i = 0; i < numBytes; ++i) {
538  rxBuffer[i] = inBytes[i];
539  }
540  rxBufferIndex = 0;
541  rxBufferLength = numBytes;
542  user_onReceive(numBytes);
543  }
544  void TwoWire::onRequestService(void) {
545  if(!user_onRequest) return;
546  txBufferIndex = 0;
547  txBufferLength = 0;
548  user_onRequest();
549  }
550  void TwoWire::onReceive( void (*function)(int) ) {
551  user_onReceive = function;
552  }
553  void TwoWire::onRequest( void (*function)(void) ) {
554  user_onRequest = function;
555  }
556 
557 
558  TwoWire Wire = TwoWire();
559  #else
560  DEBUG_MSG("You disabled I²C");
561  #endif
562 
563  #ifndef EBOARD_USE_SPI
564  #define EBOARD_USE_SPI 0x1
565  #endif
566  #if EBOARD_USE_SPI > 0x0
567  DEBUG_MSG("You enabled SPI");
568 
569  #define _SPI_H_INCLUDED
570  #include <stdio.h>
571 
572  #define SPI_CLOCK_DIV4 0x00
573 
574  #define SPI_CLOCK_DIV16 0x01
575 
576  #define SPI_CLOCK_DIV64 0x02
577 
578  #define SPI_CLOCK_DIV128 0x03
579 
580  #define SPI_CLOCK_DIV2 0x04
581 
582  #define SPI_CLOCK_DIV8 0x05
583 
584  #define SPI_CLOCK_DIV32 0x06
585 
586  #define SPI_MODE0 0x00
587 
588  #define SPI_MODE1 0x04
589 
590  #define SPI_MODE2 0x08
591 
592  #define SPI_MODE3 0x0C
593 
594  #define SPI_MODE_MASK 0x0C
595 
596  #define SPI_CLOCK_MASK 0x03
597 
598  #define SPI_2XCLOCK_MASK 0x01
599  namespace eagle_impl {
600 
601  struct SPIClass {
602 
603  inline static byte transfer(byte _data);
604 
605  inline static void attachInterrupt(void);
606 
607  inline static void detachInterrupt(void); // Default
608 
609  static void begin(void); // Default
610 
611  inline static void end(void);
612 
613  inline static void setBitOrder(uint8_t bitOrder);
614 
615  inline static void setDataMode(uint8_t mode);
616 
617  inline static void setClockDivider(uint8_t rate);
618  };
619  }
620 
621  byte SPIClass::transfer(byte _data) {
622  SPDR = _data;
623  while (!(SPSR & _BV(SPIF)));
624  return SPDR;
625  }
626  void SPIClass::attachInterrupt() { SPCR |= _BV(SPIE);}
627  void SPIClass::detachInterrupt() { SPCR &= ~_BV(SPIE);}
628  void SPIClass::begin() {
629  digitalWrite(SS, HIGH);
630  pinMode(SS, OUTPUT); //doesn't block common use as_ OUTPUT!
631  SPCR |= _BV(MSTR);
632  SPCR |= _BV(SPE);
633  pinMode(SCK, OUTPUT);
634  pinMode(MOSI, OUTPUT);
635  }
636  void SPIClass::end() {SPCR &= ~_BV(SPE);}
637  void SPIClass::setBitOrder(uint8_t bitOrder) {
638  if(bitOrder == LSBFIRST) SPCR |= _BV(DORD);
639  else SPCR &= ~(_BV(DORD));
640  }
641  void SPIClass::setDataMode(uint8_t mode) { SPCR = (SPCR & ~SPI_MODE_MASK) | mode; }
642  void SPIClass::setClockDivider(uint8_t rate) {
643  SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
644  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
645  }
646 
647  SPIClass SPI;
648  #else
649  DEBUG_MSG("You disabled SPI");
650  #endif
651  #if (EBOARD_I2C > 0x0) && (EBOARD_LCD > 0x0)
652  #include <avr/pgmspace.h>
653  DEBUG_MSG("You enabled LCD");
654  #endif
655 
656  static bool STOP = false;
657 
658  #ifdef IGNORE_SIZE
659  DEBUG_MSG("You defined IGNORE_SIZE: byte will be used");
660  typedef byte optVAL_t;
661  #else
662  DEBUG_MSG("You did not define IGNORE_SIZE: int will be used");
663  typedef int optVAL_t;
664  #endif
665 
666  #ifndef EBOARD_DEBUG_MODE
667  #define EBOARD_DEBUG_MODE 0x1
668  #endif
669  #if EBOARD_DEBUG_MODE > 0x0
670  MACRO_MSG(EBOARD_DEBUG_MODE,"Serial feedback will be send to Computer");
671  #else
672  MACRO_MSG(EBOARD_DEBUG_MODE, "No Serial feedback!");
673  #endif
674 
675  #ifndef EBOARD_NANO
676  #define EBOARD_NANO 0x0
677  #endif
678  #if EBOARD_NANO > 0x0 || defined(DOC)
679  #ifndef EBOARD_NANO_STEER
680 
681  #define EBOARD_NANO_STEER 12
682  #endif
683  #ifndef EBOARD_NANO_MAIN
684 
685  #define EBOARD_NANO_MAIN 13
686  #endif
687  MACRO_MSG(EBOARD_NANO,"Using Arduino NANO environment [e.g. remove SoccerBoard]");
688  #if PREPROCESS_DEBUG > 0x1
689  #pragma message("Using " VALUE(EBOARD_NANO_STEER) " as data pin for STEERING MOTOR")
690  #pragma message("Using " VALUE(EBOARD_NANO_MAIN) " as data pin for MAIN (Driving) MOTOR")
691  #endif
692  #else
693  MACRO_MSG(EBOARD_NANO,"Using Arduino UNO/MEGA environment");
694  #endif
695 
696  #ifndef EBOARD_CHECK_PINS
697  #define EBOARD_CHECK_PINS 0x1
698  #endif
699  #if EBOARD_CHECK_PINS > 0x0
700  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins enabled");
701  #else
702  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins disabled");
703  #endif
704  #ifndef EBOARD_SHIFT_REGISTER
705 
706  #define EBOARD_SHIFT_REGISTER 0x0
707  #endif
708  #if EBOARD_SHIFT_REGISTER > 0x0
709  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister enabled");
710  #else
711  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister disabled");
712  #endif
713 
714  #ifndef EBOARD_CHECK_PINS_PWM
715  #define EBOARD_CHECK_PINS_PWM 0x1
716  #endif
717  #if EBOARD_CHECK_PINS_PWM > 0x0
718  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins enabled");
719  #else
720  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins disabled");
721  #endif
722 
723  #ifndef EBOARD_DEBUG_SPEED
724  #define EBOARD_DEBUG_SPEED 9600
725  #endif
726  #if PREPROCESS_DEBUG > 0x0
727  #pragma message("Set Debugging speed to " VALUE(EBOARD_DEBUG_SPEED))
728  #endif
729 
730  #ifndef EBOARD_SPI_SERVO_MAX
731  #define EBOARD_SPI_SERVO_MAX 2
732  #endif
733  #if PREPROCESS_DEBUG > 0x0
734  #pragma message("Set amount of used Servos to " VALUE(EBOARD_SPI_SERVO_MAX))
735  #endif
736 
737  #ifndef EBOARD_USE_UTILITY
738  #define EBOARD_USE_UTILITY 0x1
739  #endif
740  #if EBOARD_USE_UTILITY > 0x0
741  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will be implemented");
742  #else
743  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will not be implemented");
744  #endif
745 
746  #define EBOARD_COPY_AND_PASTE 0x1
747 
748  #ifndef EBOARD_PWM_SPE
749  #define EBOARD_PWM_SPE 1
750  #endif
751  #if PREPROCESS_DEBUG > 0x0
752  #pragma message("Set PWM interval to " VALUE(EBOARD_PWM_SPE) "s")
753  #endif
754  #ifndef EBOARD_I2C
755 
756  #define EBOARD_I2C 0x0 //disabled by default
757  #endif
758  #ifndef EBOARD_BLUETOOTH
759 
760  #define EBOARD_BLUETOOTH 0x0
761  #endif
762  #if EBOARD_BLUETOOTH > 0x0
763  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls enabled");
764  #else
765  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls disabled");
766  #endif
767 
768  #ifndef EBOARD_CLAMP
769  #define EBOARD_CLAMP 0x1
770  #endif
771  #if EBOARD_CLAMP > 0x0
772  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [0;1023]");
773  #else
774  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [-300;300]");
775  #endif
776  #ifndef EBOARD_NEO
777 
778  #define EBOARD_NEO 0x0
779  #endif
780  #if EBOARD_NEO > 0x0
781  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support enabled");
782  #else
783  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support disabled");
784  #endif
785 
786  #ifndef EBOARD_USE_RESET
787  #define EBOARD_USE_RESET 0x1
788  #endif
789  #if EBOARD_USE_RESET > 0x0
790  #include <avr/wdt.h>
791  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is available" );
792  #else
793  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is not available" );
794  #endif
795 
796  #ifndef PIN_BLUETOOTH_STATE
797  #if defined(__AVR_ATmega2560__)
798  #define PIN_BLUETOOTH_STATE 0x13 // 19
799  #else
800  #define PIN_BLUETOOTH_STATE 0x2
801  #endif
802  #endif
803 
804  #ifndef PIN_BLUETOOTH_RX
805  #if defined(__AVR_ATmega2560__)
806  #define PIN_BLUETOOTH_RX 0x13 // 19
807  #else
808  #define PIN_BLUETOOTH_RX 0x2
809  #endif
810  #endif
811 
812  #ifndef PIN_BLUETOOTH_TX
813  #if defined(__AVR_ATmega2560__)
814  #define PIN_BLUETOOTH_TX 0x12 // 18
815  #else
816  #define PIN_BLUETOOTH_TX 0x3
817  #endif
818  #endif
819 
820  #ifndef PIN_MOTOR_DIR
821  #define PIN_MOTOR_DIR 0x4
822  #endif
823 
824  #ifndef PIN_MOTOR_SPE
825  #define PIN_MOTOR_SPE 0x5
826  #endif
827 
828  #ifndef PIN_SHIFT_CLK
829  #define PIN_SHIFT_CLK 0x6
830  #endif
831 
832  #ifndef PIN_SHIFT_DAT
833  #define PIN_SHIFT_DAT 0x7
834  #endif
835 
836  #ifndef PIN_SHIFT_LAT
837  #define PIN_SHIFT_LAT 0x8
838  #endif
839  //done by arduino
840  //if this has an effect... something went wrong :D
841  #ifndef HIGH
842  #define HIGH 1
843  #endif
844  #ifndef LOW
845  #define LOW 0
846  #endif
847  #if (EBOARD_BLUETOOTH > 0x0) && defined(__AVR_ATmega328P__)
848  #if EBOARD_GUESSPATH > 0x0
849  //again to resolve including errors we'll include the SoftwareSerial cpp file
850  #define _SS_MAX_RX_BUFF 64 // RX buffer size
851  #ifndef GCC_VERSION
852  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
853  #endif
854  namespace eagle_impl {
855 
856  class SoftwareSerial : public Stream {
857  private:
858 
859  uint8_t _receivePin;
860 
861  uint8_t _receiveBitMask;
862 
863  volatile uint8_t *_receivePortRegister;
864 
865  uint8_t _transmitBitMask;
866 
867  volatile uint8_t *_transmitPortRegister;
868 
869  uint16_t _rx_delay_centering;
870 
871  uint16_t _rx_delay_intrabit;
872 
873  uint16_t _rx_delay_stopbit;
874 
875  uint16_t _tx_delay;
876 
877  uint16_t _buffer_overflow:1;
878 
879  uint16_t _inverse_logic:1;
880 
881  static char _receive_buffer[_SS_MAX_RX_BUFF];
882 
883  static volatile uint8_t _receive_buffer_tail;
884 
885  static volatile uint8_t _receive_buffer_head;
886 
888 
889  void recv(void);
890 
891  inline uint8_t rx_pin_read(void);
892 
893  inline void tx_pin_write(uint8_t pin_state);
894 
895  void setTX(uint8_t transmitPin);
896 
897  void setRX(uint8_t receivePin);
898 
899  static inline void tunedDelay(uint16_t delay);
900  public:
901  // public methods
902 
903  SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
904 
905  ~SoftwareSerial(void);
906 
907  void begin(long speed);
908 
909  bool listen(void);
910 
911  inline void end(void);
912 
913  inline bool isListening(void);
914 
915  inline bool overflow(void);
916 
917  int peek(void);
918 
919  virtual size_t write(uint8_t byte);
920 
921  virtual int read(void);
922 
923  virtual int available(void);
924 
925  virtual void flush(void);
926  //used to save codespace
927  using Print::write;
928 
929  static inline void handle_interrupt(void);
930  };
931  }
932 
933  bool SoftwareSerial::isListening(void) {
934  return this == active_object;
935  }
936  bool SoftwareSerial::overflow(void) {
937  bool ret = _buffer_overflow;
938  _buffer_overflow = false;
939  return ret;
940  }
941 
942  #if EBOARD_DEBUG_MODE > 0x0
943  #define _DEBUG 0
944  #define _DEBUG_PIN1 11
945  #define _DEBUG_PIN2 13
946  #endif
947  typedef struct _DELAY_TABLE {
948  long baud;
949  unsigned short rx_delay_centering;
950  unsigned short rx_delay_intrabit;
951  unsigned short rx_delay_stopbit;
952  unsigned short tx_delay;
953  } DELAY_TABLE;
954  #if F_CPU == 16000000
955  static const DELAY_TABLE PROGMEM table[] = {
956  // baud rxcenter rxintra rxstop tx
957  { 115200, 1, 17, 17, 12, },
958  { 57600, 10, 37, 37, 33, },
959  { 38400, 25, 57, 57, 54, },
960  { 31250, 31, 70, 70, 68, },
961  { 28800, 34, 77, 77, 74, },
962  { 19200, 54, 117, 117, 114, },
963  { 14400, 74, 156, 156, 153, },
964  { 9600, 114, 236, 236, 233, },
965  { 4800, 233, 474, 474, 471, },
966  { 2400, 471, 950, 950, 947, },
967  { 1200, 947, 1902, 1902, 1899, },
968  { 600, 1902, 3804, 3804, 3800, },
969  { 300, 3804, 7617, 7617, 7614, },
970  };
971  const int XMIT_START_ADJUSTMENT = 5;
972  #elif F_CPU == 8000000
973  static const DELAY_TABLE table[] PROGMEM = {
974  // baud rxcenter rxintra rxstop tx
975  { 115200, 1, 5, 5, 3, },
976  { 57600, 1, 15, 15, 13, },
977  { 38400, 2, 25, 26, 23, },
978  { 31250, 7, 32, 33, 29, },
979  { 28800, 11, 35, 35, 32, },
980  { 19200, 20, 55, 55, 52, },
981  { 14400, 30, 75, 75, 72, },
982  { 9600, 50, 114, 114, 112, },
983  { 4800, 110, 233, 233, 230, },
984  { 2400, 229, 472, 472, 469, },
985  { 1200, 467, 948, 948, 945, },
986  { 600, 948, 1895, 1895, 1890, },
987  { 300, 1895, 3805, 3805, 3802, },
988  };
989  const int XMIT_START_ADJUSTMENT = 4;
990  #elif F_CPU == 20000000
991  static const DELAY_TABLE PROGMEM table[] = {
992  // baud rxcenter rxintra rxstop tx
993  { 115200, 3, 21, 21, 18, },
994  { 57600, 20, 43, 43, 41, },
995  { 38400, 37, 73, 73, 70, },
996  { 31250, 45, 89, 89, 88, },
997  { 28800, 46, 98, 98, 95, },
998  { 19200, 71, 148, 148, 145, },
999  { 14400, 96, 197, 197, 194, },
1000  { 9600, 146, 297, 297, 294, },
1001  { 4800, 296, 595, 595, 592, },
1002  { 2400, 592, 1189, 1189, 1186, },
1003  { 1200, 1187, 2379, 2379, 2376, },
1004  { 600, 2379, 4759, 4759, 4755, },
1005  { 300, 4759, 9523, 9523, 9520, },
1006  };
1007  const int XMIT_START_ADJUSTMENT = 6;
1008  #else
1009  #error This version of SoftwareSerial supports only 20, 16 and 8MHz processors
1010  #endif
1013  volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
1014  volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
1015  #if EBOARD_DEBUG_MODE > 0x0
1016  inline void DebugPulse(uint8_t pin, uint8_t count) {
1017  #if _DEBUG
1018  volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
1019  uint8_t val = *pport;
1020  while (count--)
1021  {
1022  *pport = val | digitalPinToBitMask(pin);
1023  *pport = val;
1024  }
1025  #endif
1026  }
1027  #endif
1028  inline void SoftwareSerial::tunedDelay(uint16_t delay) {
1029  uint8_t tmp=0;
1030  asm volatile("sbiw %0, 0x01 \n\t"
1031  "ldi %1, 0xFF \n\t"
1032  "cpi %A0, 0xFF \n\t"
1033  "cpc %B0, %1 \n\t"
1034  "brne .-10 \n\t"
1035  : "+r" (delay), "+a" (tmp)
1036  : "0" (delay)
1037  );
1038  }
1039  bool SoftwareSerial::listen() {
1040  if (active_object != this)
1041  {
1042  _buffer_overflow = false;
1043  uint8_t oldSREG = SREG;
1044  cli();
1046  active_object = this;
1047  SREG = oldSREG;
1048  return true;
1049  }
1050  return false;
1051  }
1052  void SoftwareSerial::recv() {
1053  #if GCC_VERSION < 40302
1054  asm volatile(
1055  "push r18 \n\t"
1056  "push r19 \n\t"
1057  "push r20 \n\t"
1058  "push r21 \n\t"
1059  "push r22 \n\t"
1060  "push r23 \n\t"
1061  "push r26 \n\t"
1062  "push r27 \n\t"
1063  ::);
1064  #endif
1065  uint8_t d = 0;
1066  if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) {
1067  // Wait approximately 1/2 of a bit width to "center" the sample
1069  #if EBOARD_DEBUG_MODE > 0x0
1070  DebugPulse(_DEBUG_PIN2, 1);
1071  #endif
1072  // Read each of the 8 bits
1073  for (uint8_t i=0x1; i; i <<= 1)
1074  {
1076  #if EBOARD_DEBUG_MODE > 0x0
1077  DebugPulse(_DEBUG_PIN2, 1);
1078  #endif
1079  uint8_t noti = ~i;
1080  if (rx_pin_read())
1081  d |= i;
1082  else
1083  d &= noti;
1084  }
1085  // skip the stop bit
1087  #if EBOARD_DEBUG_MODE > 0x0
1088  DebugPulse(_DEBUG_PIN2, 1);
1089  #endif
1090  if (_inverse_logic)
1091  d = ~d;
1093  _receive_buffer[_receive_buffer_tail] = d; // save new byte
1095  }
1096  else {
1097  #if EBOARD_DEBUG_MODE > 0x0
1098  #if _DEBUG // for scope: pulse pin as overflow indictator
1099  DebugPulse(_DEBUG_PIN1, 1);
1100  #endif
1101  #endif
1102  _buffer_overflow = true;
1103  }
1104  }
1105  #if GCC_VERSION < 40302
1106  asm volatile(
1107  "pop r27 \n\t"
1108  "pop r26 \n\t"
1109  "pop r23 \n\t"
1110  "pop r22 \n\t"
1111  "pop r21 \n\t"
1112  "pop r20 \n\t"
1113  "pop r19 \n\t"
1114  "pop r18 \n\t"
1115  ::);
1116  #endif
1117  }
1118  void SoftwareSerial::tx_pin_write(uint8_t pin_state) {
1119  if (pin_state == LOW)
1121  else
1123  }
1124  uint8_t SoftwareSerial::rx_pin_read() {
1126  }
1127  inline void SoftwareSerial::handle_interrupt() {
1128  if (active_object) {
1129  active_object->recv();
1130  }
1131  }
1132  #if defined(PCINT0_vect)
1133  ISR(PCINT0_vect) {
1135  }
1136  #endif
1137  #if defined(PCINT1_vect)
1138  ISR(PCINT1_vect) {
1140  }
1141  #endif
1142  #if defined(PCINT2_vect)
1143  ISR(PCINT2_vect) {
1145  }
1146  #endif
1147  #if defined(PCINT3_vect)
1148  ISR(PCINT3_vect) {
1150  }
1151  #endif
1152  SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic ) :
1153  _rx_delay_centering(0),
1154  _rx_delay_intrabit(0),
1155  _rx_delay_stopbit(0),
1156  _tx_delay(0),
1157  _buffer_overflow(false),
1158  _inverse_logic(inverse_logic) {
1159  setTX(transmitPin);
1160  setRX(receivePin);
1161  }
1162  SoftwareSerial::~SoftwareSerial() {
1163  end();
1164  }
1165  void SoftwareSerial::setTX(uint8_t tx) {
1166  pinMode(tx, OUTPUT);
1167  digitalWrite(tx, HIGH);
1168  _transmitBitMask = digitalPinToBitMask(tx);
1169  uint8_t port = digitalPinToPort(tx);
1170  _transmitPortRegister = portOutputRegister(port);
1171  }
1172  void SoftwareSerial::setRX(uint8_t rx) {
1173  pinMode(rx, INPUT);
1174  if (!_inverse_logic)
1175  digitalWrite(rx, HIGH);
1176  _receivePin = rx;
1177  _receiveBitMask = digitalPinToBitMask(rx);
1178  uint8_t port = digitalPinToPort(rx);
1179  _receivePortRegister = portInputRegister(port);
1180  }
1181  void SoftwareSerial::begin(long speed) {
1183  for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
1184  long baud = pgm_read_dword(&table[i].baud);
1185  if (baud == speed) {
1186  _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
1187  _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
1188  _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
1189  _tx_delay = pgm_read_word(&table[i].tx_delay);
1190  break;
1191  }
1192  }
1193  if (_rx_delay_stopbit) {
1194  if (digitalPinToPCICR(_receivePin)) {
1195  *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
1196  *digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin));
1197  }
1199  }
1200  #if _DEBUG
1201  pinMode(_DEBUG_PIN1, OUTPUT);
1202  pinMode(_DEBUG_PIN2, OUTPUT);
1203  #endif
1204  listen();
1205  }
1206  void SoftwareSerial::end() {
1207  if (digitalPinToPCMSK(_receivePin))
1208  *digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
1209  }
1210  int SoftwareSerial::read() {
1211  if (!isListening())
1212  return -1;
1214  return -1;
1215  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
1217  return d;
1218  }
1220  if (!isListening())
1221  return 0;
1223  }
1224  size_t SoftwareSerial::write(uint8_t b) {
1225  if (_tx_delay == 0) {
1226  setWriteError();
1227  return 0;
1228  }
1229  uint8_t oldSREG = SREG;
1230  cli();
1231  tx_pin_write(_inverse_logic ? HIGH : LOW);
1232  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
1233  if (_inverse_logic) {
1234  for (byte mask = 0x01; mask; mask <<= 1) {
1235  if (b & mask)
1236  tx_pin_write(LOW);
1237  else
1238  tx_pin_write(HIGH);
1240  }
1241  tx_pin_write(LOW);
1242  }
1243  else {
1244  for (byte mask = 0x01; mask; mask <<= 1) {
1245  if (b & mask)
1246  tx_pin_write(HIGH);
1247  else
1248  tx_pin_write(LOW);
1250  }
1251  tx_pin_write(HIGH);
1252  }
1253  SREG = oldSREG;
1255  return 1;
1256  }
1257  void SoftwareSerial::flush() {
1258  if (!isListening())
1259  return;
1260  uint8_t oldSREG = SREG;
1261  cli();
1263  SREG = oldSREG;
1264  }
1265  int SoftwareSerial::peek() {
1266  if (!isListening())
1267  return -1;
1269  return -1;
1271  }
1272 
1273  #endif
1274 
1276  #endif
1277  #if EBOARD_DEBUG_MODE > 0x0
1278 
1279  #define __ASSERT_USE_STDERR
1280  #include <assert.h>
1281 
1282  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp);
1283 
1284  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp){
1285  Serial.print("Error with: "); Serial.print(__func);
1286  Serial.print(" in "); Serial.print(__file);
1287  Serial.print(" >>");
1288  Serial.println(__sexp);
1289  if(strcmp(__func,"checkIdx")==0){
1290  Serial.println(" This happens if an out of bounds exception");
1291  Serial.println(" has occured. Following pins shouldn't be used:");
1292  Serial.print(" D" + PIN_BLUETOOTH_RX);Serial.print("&");
1293  Serial.print("D");Serial.print(PIN_BLUETOOTH_TX);
1294  Serial.println(" : Used for Bluetooth communication");
1295  Serial.print(" D");Serial.print(PIN_MOTOR_DIR);Serial.print("&");
1296  Serial.print("D");Serial.print(PIN_MOTOR_SPE);
1297  Serial.println(" : Used for main motor control");
1298  #if EBOARD_USE_SPI > 0x0
1299  Serial.print(" D10-13");
1300  Serial.println(": Used for smart-servo-shield");
1301  #endif
1302  } else if (strcmp(__func,"readPin")==0){
1303  Serial.println("You've tried to access an analogPin that isn't present on the board you're currently working on!");
1304  }
1305  Serial.flush();
1306  abort(); // halt after outputting information
1307  }
1308 
1309  #endif
1310 
1311  inline void checkIdx(optVAL_t idx);
1312 
1313  inline void checkIdx(optVAL_t idx){
1314  #if EBOARD_DEBUG_MODE > 0x0
1315  assert(idx>=0x0 && idx < PIN_MAX); //changed pins? change me! (didn't want to use macros)
1316  assert(idx!=PIN_BLUETOOTH_RX&&idx!=PIN_BLUETOOTH_TX);
1317  #endif
1318  }
1319 
1320  #if EBOARD_COPY_AND_PASTE > 0x0
1321  #if EBOARD_CHECK_PINS_PWM > 0x0
1322 
1324 
1326  optVAL_t count; //dont't want to overuse global space^^
1327  for (count = 0; x; count++)
1328  x &= x - 1;
1329  return count;
1330  }
1331 
1332  #endif
1333  #if EBOARD_CHECK_PINS > 0x0
1334 
1335  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
1336  uint16_t pin_out = 0x0;
1337  #elif defined(__AVR_ATmega2560__)
1338  uint64_t pin_out = 0x0;
1339  #endif
1340 
1341  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
1342  uint16_t pin_in = 0x0;
1343  #elif defined(__AVR_ATmega2560__)
1344  uint64_t pin_in = 0x0;
1345  #endif
1346 
1347  inline bool checkPin(optVAL_t idx, optVAL_t mode = OUTPUT);
1348 
1349  inline bool checkPin(optVAL_t idx, optVAL_t mode){
1350  checkIdx(idx);
1351  return (mode == OUTPUT)? ((pin_out & (1<<idx))>0x0):((pin_in & (1<<idx))>0x0);
1352  }
1353 
1354  #endif
1355 
1356  void setPin(optVAL_t idx, optVAL_t mode = OUTPUT);
1357 
1358  void setPin(optVAL_t idx, optVAL_t mode){
1359  #if EBOARD_CHECK_PINS > 0x0
1360  checkIdx(idx);
1361  if(mode==OUTPUT) { //possible to read from OUTPUT digital ... we won't do it
1362  pin_out |= (1<<idx);
1363  pin_in &= ~(1<<idx);
1364  }
1365  else {
1366  pin_in |= (1<<idx);
1367  pin_out &= ~(1<<idx);
1368  }
1369  #endif
1370  pinMode(idx, mode);
1371  }
1372 
1373  #endif
1374  #if EBOARD_BLUETOOTH > 0x0
1375 
1376  inline char readVal(char oF = '.');
1377 
1378  inline bool checkOverflow(void);
1379 
1380  template <typename T>
1381  inline void writeVal(const T& val);
1382 
1383  inline bool isConnected(void);
1384 
1385  inline bool checkOverflow(void) {
1386  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
1387  return false; //there is no hardware provided control for hardwareserial overflow
1388  #else
1389  return (_serial.overflow());
1390  #endif
1391  }
1392  inline char readVal(char oF) {
1393  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
1394  return ((Serial1.available())?(Serial1.read()):(oF));
1395  #else
1396  return ((_serial.available())?(_serial.read()):(oF));
1397  #endif
1398  }
1399  template<typename T>
1400  inline void writeVal(const T& val){
1401  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
1402  Serial1.write(val);
1403  #else
1404  _serial.write(val);
1405  #endif
1406  }
1407  inline bool isConnected(void) {
1408  #if PIN_BLUETOOTH_RX != PIN_BLUETOOTH_STATE
1409  return digitalRead(PIN_BLUETOOTH_STATE);
1410  #else
1411  return true;
1412  #endif
1413  }
1414 
1415  #endif
1416  #if EBOARD_SHIFT_REGISTER > 0x0
1417 
1418  long store_bits = 0L;
1419 
1420  inline void shiftSingle(optVAL_t idx, bool val);
1421 
1422  void shiftAll(void);
1423 
1424  inline void shiftSingle(optVAL_t idx, bool val) {
1425  bitWrite(store_bits,idx,val);
1426  shiftAll();
1427  }
1428  void shiftAll(void){
1429  digitalWrite(PIN_SHIFT_LAT,LOW);
1430  for(optVAL_t c = 0; (c<32 && !STOP); c++){
1431  digitalWrite(PIN_SHIFT_CLK,LOW);
1432  shiftOut(PIN_SHIFT_DAT,PIN_SHIFT_CLK,MSBFIRST,bitRead(store_bits,c));
1433  }
1434  digitalWrite(PIN_SHIFT_LAT,LOW);
1435  }
1436 
1437  #endif
1438 
1439  optVAL_t _pwmValue = 0x0, _OpwmValue = 0x0;
1440 
1441  inline void writePWM (optVAL_t val);
1442 
1443  inline void writePWM(optVAL_t val){
1444  val = min(val,0xFF); val = max(0x0,val);
1445  _pwmValue = val;
1446  }
1447  #ifdef REPT_TASK
1448  extern void rept_task(void);
1449  DEBUG_MSG("You defined REPT_TASK: you have to define rept_task(void)!");
1450  #else
1451  DEBUG_MSG("You did not define REPT_TASK: rept_task(void) will not have any effect");
1452  #endif
1453 
1454 
1455  inline void writePin(optVAL_t idx,bool val);
1456 
1457  inline void writePin(optVAL_t idx,bool val){
1458  #if EBOARD_SHIFT_REGISTER > 0x0
1459  if(idx>0x63) {
1460  idx -= 0x64;
1461  shiftSingle(idx,val);
1462  return;
1463  }
1464  #endif
1465  #if EBOARD_CHECK_PINS > 0x0
1466  checkIdx(idx);
1467  if(!checkPin(idx))
1468  #endif
1469  #if EBOARD_COPY_AND_PASTE > 0x0
1470  setPin(idx);
1471  #else
1472  pinMode(idx,OUTPUT);
1473  #endif
1474  digitalWrite(idx,val);
1475  }
1476 
1477 
1478  inline optVAL_t readPin(optVAL_t idx,bool dig = true);
1479 
1480  inline optVAL_t readPin(optVAL_t idx,bool dig){
1481  #if EBOARD_CHECK_PINS > 0x0
1482  if(dig) checkIdx(idx);
1483  #if defined (__AVR_ATmega2560__)
1484  else if (idx<0||idx>0xF){ //use I2C? change => Wire
1485  #else
1486  else if (idx<0||idx>0x7){ //use I2C? change => Wire
1487  #endif
1488  #if EBOARD_DEBUG_MODE > 0x0
1489  assert(false);
1490  #endif
1491  return 0;
1492  }
1493  if(dig && !checkPin(idx,INPUT))
1494  #endif
1495  #if EBOARD_COPY_AND_PASTE > 0x0
1496  setPin(idx,INPUT);
1497  #else
1498  pinMode(idx,INPUT);
1499  #endif
1500  return((dig)? digitalRead(idx) : analogRead(idx));
1501  }
1502 
1503  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0x0)
1504 
1505  //won't be commented
1506  struct ServoCds55 {
1507  public:
1508  #if defined(__AVR_ATmega2560__)
1509  ServoCds55(int CS=53);
1510  #else
1511  ServoCds55(int CS=10);
1512  #endif
1513  void begin();
1514  void WritePos(int ID,int Pos);
1515  void write(int ID,int Pos);
1516  inline void setVelocity(int velocity);
1517  inline void setPoslimit(int posLimit);
1518  inline void rotate(int ID,int velocity);
1519  void SetServoLimit(int ID,int upperLimit);
1520  void SetMotormode(int ID, int velocity);
1521  void SetID(int ID, int newID);
1522  void Reset(int ID);
1523  byte sendWait (const byte what);
1524  int velocity_temp;
1525  int upperLimit_temp;
1526  optVAL_t cs;
1527  };
1528  ServoCds55::ServoCds55 (int CS):cs(CS) {
1529  velocity_temp = 150;
1530  upperLimit_temp = 300;
1531  }
1532  void ServoCds55::begin() {
1533  pinMode(cs,OUTPUT);
1534  digitalWrite(cs,HIGH);
1535  SPI.begin ();
1537  }
1538  byte ServoCds55::sendWait (const byte what) {
1539  byte a = SPI.transfer (what);
1540  delayMicroseconds (20);
1541  return a;
1542  }
1543  void ServoCds55::setVelocity(int velocity){ //set servo velocity
1544  velocity_temp = velocity;
1545  }
1546  void ServoCds55::setPoslimit(int posLimit){ // set servo pos limit
1547  upperLimit_temp = posLimit;
1548  }
1549  void ServoCds55::write(int ID,int Pos){ // Servo Mode
1550  SetServoLimit(ID,upperLimit_temp);
1551  WritePos(ID,Pos);// default velocity:150
1552  }
1553  inline void ServoCds55::rotate(int ID,int velocity){ // Motor Mode
1554  SetServoLimit(ID,0);
1555  delay(100);
1556  SetMotormode(ID,velocity);
1557  }
1558  void ServoCds55::WritePos(int ID,int Pos){
1559  int PosB = (Pos>>8 & 0xff);//low
1560  int PosS = (Pos & 0xff);//high
1561  int velocityB = (velocity_temp>>8 & 0xff);
1562  int velocityS = (velocity_temp & 0xff);
1563  digitalWrite(cs, LOW);
1564  sendWait ('p'); sendWait (ID);
1565  sendWait (PosB); sendWait (PosS);
1566  sendWait (velocityB); sendWait (velocityS);
1567  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
1568  digitalWrite(cs, HIGH);
1569  delay(10);
1570  }
1571  void ServoCds55::SetServoLimit(int ID,int upperLimit_temp){
1572  int upperLimitB = (upperLimit_temp>>8 & 0xff);
1573  int upperLimitS = (upperLimit_temp & 0xff);
1574  digitalWrite(cs, LOW);
1575  sendWait ('s'); sendWait (ID);
1576  sendWait (upperLimitB); sendWait (upperLimitS);
1577  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
1578  digitalWrite(cs, HIGH);
1579  delay(10);
1580  }
1581  void ServoCds55::SetMotormode(int ID, int velocity){
1582  int velocityB = (velocity>>8 & 0xff);
1583  int velocityS = (velocity & 0xff);
1584  digitalWrite(cs, LOW);
1585  sendWait ('m'); sendWait (ID);
1586  sendWait (velocityB); sendWait (velocityS);
1587  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
1588  digitalWrite(cs, HIGH);
1589  delay(10);
1590  }
1591  void ServoCds55::SetID(int ID, int newID){
1592  digitalWrite(cs, LOW);
1593  sendWait ('i'); sendWait (ID);
1594  sendWait (newID);
1595  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
1596  digitalWrite(cs, HIGH);
1597  delay(10);
1598  }
1599  void ServoCds55::Reset(int ID){
1600  digitalWrite(cs, LOW);
1601  sendWait ('r'); sendWait (ID);
1602  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
1603  digitalWrite(cs, HIGH);
1604  delay(10);
1605  }
1606 
1607 
1608  ServoCds55 _servoHandler;
1609  #endif
1610  #if EBOARD_COPY_AND_PASTE > 0x0 && EBOARD_NANO == 0
1611 
1612  struct SoccerBoard {
1613 
1614  inline SoccerBoard(void);
1615  //inline ~SoccerBoard(void) {}
1616  #if EBOARD_USE_UTILITY > 0x0 or defined(__AVR_ATmega2560__) //won't shrink space... just speed things up
1617 
1618  inline void led(int idx,bool state);
1619 
1620  inline void ledOn(int idx);
1621 
1622  inline void ledOff(int idx);
1623 
1624  inline void ledsOff(void);
1625 
1626  inline void ledMeter(int);
1627  #endif
1628  #if EBOARD_USE_UTILITY > 0x0
1629 
1630  inline void button(int);
1631 
1632  inline void waitForButton(int);
1633  #endif
1634 
1635  inline void motor(uint8_t id,int16_t val);
1636 
1637  inline void motorsOff(void);
1638  //ARDUINO UNO PINOUT
1639  //D0,D1 => Bluetooth connection
1640  //D4,D5 => MotorControl (D5: 980Hz)
1641  //D10,D13 => SPI
1642 
1643  inline void power(optVAL_t id, bool state);
1644 
1645  inline void powerOn(optVAL_t id);
1646 
1647  inline void powerOff(optVAL_t id);
1648 
1649  inline void sleep(uint16_t t);
1650 
1651  inline void msleep(uint16_t t);
1652 
1653  inline bool digital (optVAL_t id);
1654 
1655  inline optVAL_t analog (optVAL_t id);
1656 
1657  inline void reset(void);
1658  };
1659 
1660  SoccerBoard::SoccerBoard(void) {}
1661  #if defined(__AVR_ATmega2560__)
1662  inline void SoccerBoard::led(int idx, bool state) {writePin(13,state);}
1663  void SoccerBoard::ledOn(int) {writePin(13,HIGH);}
1664  void SoccerBoard::ledOff(int) {writePin(13,LOW);}
1665  void SoccerBoard::ledsOff(void) {writePin(13,LOW);}
1666  void SoccerBoard::ledMeter(int) {writePin(13,HIGH);}
1667  #elif EBOARD_USE_UTILITY > 0x0
1668  void SoccerBoard::led(int, bool) {}
1669  void SoccerBoard::ledOn(int) {}
1670  void SoccerBoard::ledOff(int) {}
1671  void SoccerBoard::ledsOff(void) {}
1672  void SoccerBoard::ledMeter(int) {}
1673  #endif
1674  #if EBOARD_USE_UTILITY > 0x0
1675  void SoccerBoard::button(int) {}
1676  void SoccerBoard::waitForButton(int) {}
1677  #endif
1678  void SoccerBoard::motor(uint8_t id,int16_t val) {
1679  if(id==0&&(val>-256 && val < 256)) {setPin(PIN_MOTOR_DIR,val<0); writePWM(abs(val));}
1680  else if(id>0&&id<3&&(val>-0 && val < 1024)) {_servoHandler.write((id-1),(val *600/1023 - 300));}
1681  }
1682  void SoccerBoard::motorsOff(void) {writePWM(0);}
1683  void SoccerBoard::reset(void) {
1684  #if EBOARD_USE_RESET > 0x0
1685  wdt_enable(WDTO_15MS);
1686  for(;;) {}
1687  #endif
1688  }
1689  void SoccerBoard::power(optVAL_t id, bool state) {writePin(id,state);}
1690  void SoccerBoard::powerOn(optVAL_t id) {this->power(id,1);}
1691  void SoccerBoard::powerOff(optVAL_t id) {this->power(id,0);}
1692  void SoccerBoard::sleep(uint16_t t) {delay(1000*t);}
1693  void SoccerBoard::msleep(uint16_t t) {delay(t);}
1694  bool SoccerBoard::digital (optVAL_t id) {return readPin(id);}
1695  optVAL_t SoccerBoard::analog (optVAL_t id) {return readPin(id,0);}
1696 
1697  //To avoid not_found issues
1698 
1699  #define DIGITAL_IN 0x0
1700 
1701  #define DIGITAL_IN_INV 0x1
1702 
1703  #define DIGITAL_IN_PULLUP 0x2
1704 
1705  #define DIGITAL_IN_PULLUP_INV 0x3
1706 
1707  #define DIGITAL_OUT 0x4
1708 
1709  #define DIGITAL_OUT_INV 0x5
1710 
1711  #define DIGITAL_OUT_LOW 0x6
1712 
1713  #define DIGITAL_OUT_HIGH 0x7
1714 
1715  #define ANALOG_IN_8_BIT 0x8
1716 
1717  #define ANALOG_IN_10_BIT 0x9
1718 
1719  #define ANALOG_IN_MEAN_8_BIT 0xA
1720 
1721  #define ANALOG_IN_MEAN_10_BIT 0xB
1722 
1723  #define COUNTER_8_BIT 0xC
1724 
1725  #define COUNTER_16_BIT 0xD
1726 
1727  #define COUNTER_RISE_8_BIT 0xE
1728 
1729  #define COUNTER_RISE_16_BIT 0xF
1730 
1731  #define PWM_SLOW 0x8
1732 
1733  #define PWM_FAST 0x9
1734 
1735  #define FREQ_LOW 0xA
1736 
1737  #define FREQ_HIGH 0xB
1738 
1739  #define COUNTER_B_DIR 0xC
1740 
1741  #define COUNTER_B_DIR_PULLUP 0xD
1742 
1743  #define COUNTER_MEAN_8_BIT 0xE
1744 
1745  #define COUNTER_MEAN_16_BIT 0xF
1746 
1747  struct I2CInOut{
1748 
1750  #if EBOARD_USE_UTILITY > 0x0
1751 
1752  inline void read(void);
1753 
1754  inline void changeAddress(optVAL_t);
1755 
1756  inline void changeModes(optVAL_t,optVAL_t,optVAL_t);
1757  #endif
1758 
1759  inline void write(void);
1760 
1761  optVAL_t A; //if you've used uint16_t values you'll have to replace it here
1762  //we only have B - DiOut and C - AO [OUT]
1763 
1764  optVAL_t B;
1765 
1766  optVAL_t C;
1767  };
1768 
1770  this->A=0x0;this->B=0x0;this->C=0x0;
1771  }
1772  #if EBOARD_USE_UTILITY > 0x0
1773  void I2CInOut::read(void) {}
1774  void I2CInOut::changeAddress(optVAL_t){}
1776  #endif
1777  void I2CInOut::write(void){
1778  setPin(PIN_MOTOR_DIR,((this->B)!=0x0));
1779  writePWM(this->C);
1780  }
1781 
1782 
1783  struct DynamixelBoard;
1784 
1785 
1786  struct AX12Servo {
1787 
1788  AX12Servo(void);
1789 
1790  AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID); //if borders => setPosLimit
1792  #if EBOARD_USE_UTILITY > 0x0
1793 
1794  inline void setID(optVAL_t newID);
1795 
1796  inline void changeMotorID(optVAL_t newID); //this should change the hardwareaddress...
1797 
1798  inline void setPositionMode(void);
1799 
1800  inline void setSpeedMode(void);
1801 
1802  inline void setSpeed(optVAL_t);
1803 
1804  inline void ledOff(void);
1805 
1806  inline void ledOn(void);
1807 
1808  inline void setTorque(uint16_t);
1809  #endif
1810 
1811  void setPosition(int pos, int speed=0x3FF);
1812 
1813  inline void storePosition(int pos, int speed = 0x3FF);
1814 
1815  inline optVAL_t getPosition(void);
1816 
1817  inline bool isMoving(void);
1818 
1819  int storedPos;
1820 
1821  int storedSpe;
1822  //bool posMode; //we don't care wich mode we are in ^^
1823 
1824  optVAL_t id;
1825  private:
1826 
1827  int actPos;
1828 
1829  int actSpe;
1830  }; //shield //set limits auto register for begin
1831 
1832  AX12Servo::AX12Servo(void) {}
1833  #if EBOARD_USE_UTILITY > 0x0
1834  void AX12Servo::setID(optVAL_t newID) {this->id = newID;_servoHandler.SetServoLimit(this->id,_servoHandler.upperLimit_temp);}
1835  void AX12Servo::changeMotorID(optVAL_t newID) {this->id = newID; _servoHandler.SetID(this->id, newID);} //this -should- *does now* change the hardwareaddress...
1836  //IF needed: _servoHandler.setID(this->id, newID);
1837  void AX12Servo::setPositionMode(void) {}
1838  void AX12Servo::setSpeedMode(void) {}
1839  void AX12Servo::setSpeed(optVAL_t) {} //i won't use the rotate functions...
1840  void AX12Servo::ledOff(void) {} //noone needs the AX12-Servo LED
1841  void AX12Servo::ledOn(void) {} //really.... noone ^^
1842  void AX12Servo::setTorque(uint16_t) {} //which damn register? xD
1843  #endif
1844  void AX12Servo::setPosition(int pos, int speed) {
1845  #if EBOARD_CLAMP > 0x0
1846  if(pos>1023 || speed > 1023) return;
1847  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
1848  speed = speed*600/1023 - 300;
1849  pos = pos *600/1023 - 300;
1850  #else
1851  if(pos>300 || speed > 300) return;
1852  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
1853  #endif
1854  if(speed != actSpe){ _servoHandler.setVelocity(speed); this->actSpe=speed;}
1855  _servoHandler.write(this->id,pos);
1856  }
1858  return this->actPos; //when moving... false value;
1859  }
1860  bool AX12Servo::isMoving(void) {return false;} //we don't know^^
1861 
1862 
1863  struct DynamixelBoard {
1864 
1865  inline DynamixelBoard(SoccerBoard&);
1866  //inline ~DynamixelBoard(void) {}
1867  #if EBOARD_USE_UTILITY > 0x0
1868 
1869  inline void changeId(optVAL_t);
1870 
1871  inline void changeMotorID(optVAL_t);
1872 
1873  inline void ledOn(optVAL_t);
1874 
1875  inline void ledOff(optVAL_t);
1876  #endif
1877 
1878  inline void action(void);
1879 
1880  friend struct AX12Servo;
1881  protected:
1882 
1884  };
1885 
1887  for(optVAL_t i = 0; i < EBOARD_SPI_SERVO_MAX; i++ ) {this->connected[i] = NULL;} //wanna use nullptr... wanna have c++11^^
1888  }
1889  //inline ~DynamixelBoard(void) {}
1890  #if EBOARD_USE_UTILITY > 0x0
1895  #endif
1896  void DynamixelBoard::action(void) {
1897  for(optVAL_t i = 0; (i < EBOARD_SPI_SERVO_MAX && !STOP); i++ ){
1898  if(this->connected[i] != NULL)
1899  (*connected[i]).setPosition((*connected[i]).storedPos,(*connected[i]).storedSpe);
1900  }
1901  }
1902  void AX12Servo::storePosition(int pos, int speed){
1903  if(this->id < EBOARD_SPI_SERVO_MAX) _conBoard->connected[this->id] = this;
1904  this->storedPos=pos;this->storedSpe=speed;
1905  }
1906  AX12Servo::AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID): _conBoard( &dBoard),id(servoID-1), actSpe(0x96) {
1907  //#if EBOARD_DEBUG_MODE > 0x0
1908  // assert(servoID<EBOARD_SPI_SERVO_MAX);
1909  //#endif
1910  }
1911 
1912  #endif
1913  #if EBOARD_BLUETOOTH > 0x0
1914 
1915  struct RB14Scan {
1916 
1917  inline RB14Scan(void);
1918 
1919 
1920  inline int raw(optVAL_t);
1921 
1922 
1923  inline char channel(optVAL_t);
1924 
1925  inline void write(const char* const val);
1926  };
1927 
1928  inline RB14Scan::RB14Scan(void) {}
1929  inline int RB14Scan::raw(optVAL_t) {return isConnected();}
1930  inline char RB14Scan::channel(optVAL_t) {return ((isConnected())?(readVal()):(-1));}
1931  inline void RB14Scan::write(const char* const val) {writeVal(val);}
1932 
1933 
1934  #endif
1935 #if EBOARD_I2C > 0x0
1936 
1937  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len);
1938 
1939  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf);
1940 
1941  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len);
1942 
1943  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len){
1944  optVAL_t count = 0;
1945  for (byte i = 1; (i < 255 && !STOP); i++) {
1946  if(i==200)continue; //internal
1947  Wire.beginTransmission (i);
1948  if (Wire.endTransmission () == 0) {
1949  if(count < ret_len) ret[count] = i;
1950  count++;
1951  delay (1);
1952  }
1953  }
1954  }
1955  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len) {
1956  Wire.beginTransmission(deviceID);
1957  Wire.write(buf,buf_len);
1958  return Wire.endTransmission();
1959  }
1960  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf){
1961  Wire.beginTransmission(deviceID);
1962  Wire.write(buf);
1963  return Wire.endTransmission();
1964  }
1965 
1966 
1967  inline void readI2C(optVAL_t deviceID, optVAL_t ret[], optVAL_t ret_len,bool blocking=true);
1968 
1969  inline void readI2C(optVAL_t deviceID,optVAL_t ret[] , optVAL_t ret_len,bool blocking) {
1970  for(optVAL_t rect = 0x0; (Wire.available() || (((blocking && (rect < ret_len))) && (!STOP))); rect++)
1971  ret[rect] = Wire.read();
1972  }
1973 
1974  //Beginof LCD configuration
1975  #if EBOARD_LCD > 0x0
1976  PROGMEM const byte basicFont[][8] = {
1977  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
1978  {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
1979  {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
1980  {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
1981  {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
1982  {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
1983  {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
1984  {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
1985  {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
1986  {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
1987  {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
1988  {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
1989  {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
1990  {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
1991  {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
1992  {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
1993  {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
1994  {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
1995  {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
1996  {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
1997  {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
1998  {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
1999  {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
2000  {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
2001  {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
2002  {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
2003  {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
2004  {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
2005  {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
2006  {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
2007  {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
2008  {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
2009  {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
2010  {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
2011  {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
2012  {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
2013  {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
2014  {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
2015  {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
2016  {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
2017  {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
2018  {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
2019  {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
2020  {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
2021  {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
2022  {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
2023  {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
2024  {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
2025  {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
2026  {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
2027  {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
2028  {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
2029  {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
2030  {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
2031  {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
2032  {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
2033  {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
2034  {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
2035  {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
2036  {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
2037  {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
2038  {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
2039  {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
2040  {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
2041  {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
2042  {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
2043  {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
2044  {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
2045  {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
2046  {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
2047  {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
2048  {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
2049  {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
2050  {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
2051  {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
2052  {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
2053  {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
2054  {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
2055  {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
2056  {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
2057  {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
2058  {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
2059  {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
2060  {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
2061  {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
2062  {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
2063  {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
2064  {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
2065  {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
2066  {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
2067  {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
2068  {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
2069  {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
2070  {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
2071  {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
2072  {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00}
2073  };
2074 
2075  //Definition of OLED Constants
2076 
2077  #define LCD_COMMAND_MODE 0x80
2078 
2079  #define LCD_DATA_MODE 0x40
2080 
2081  #define LCD_COMMAND_DISPLAY_OFF 0xAE
2082 
2083  #define LCD_COMMAND_DISPLAY_ON 0xAF
2084 
2085  #define LCD_COMMAND_BLACK_BACKGROUND 0xA6
2086 
2087  #define LCD_COMMAND_WHITE_BACKGROUND 0xA7
2088 
2089  #define LCD_COMMAND_SET_BRIGHTNESS 0x81
2090 
2091  #define LCD_PAGE_ADDRESSING 0x02
2092 
2093  #define LCD_HORIZONTAL_ADDRESSING 0x00
2094  //The regulator
2095 
2096  #define LCD_COMMAND_CHARGE_PUMP_SETTING 0x8d
2097 
2098  #define LCD_COMMAND_CHARGE_PUMP_ENABLE 0x14
2099  #ifndef LCD_WIDTH
2100 
2101  #define LCD_WIDTH 128
2102  #endif
2103  #ifndef LCD_HEIGHT
2104 
2105  #define LCD_HEIGHT 64
2106  #endif
2107 
2108  struct LCD {
2109  #if EBOARD_NANO == 0
2110 
2111  LCD(SoccerBoard &soccerBoard, optVAL_t id=0x3C);
2112  #else
2113  LCD(optVAL_t id=0x3C);
2114  #endif
2115 
2116  inline bool changeID(optVAL_t newID = 0x3C);
2117 
2118  inline bool clear(void);
2119 
2120  inline void print(const char* data);
2121 
2122  inline void print(int data);
2123 
2124  inline void print(optVAL_t line, optVAL_t col, const char* data);
2125 
2126  inline void print(optVAL_t line, optVAL_t col, int data);
2127 
2128  inline void lightOn(void);
2129 
2130  inline void lightOff(void);
2131 
2132  inline bool reset(void);
2133  //added features
2134 
2135  inline bool init(void);
2136 
2137  inline void drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY);
2138 
2139  inline void changeMode(bool newMode = true);
2140 
2141  inline bool setCursor(byte posX = 0x0, byte posY = 0x0);
2142 
2143  inline bool changeBrightness (byte val = 0x64);
2144 
2145  inline void changeBackground(bool newBackground = false);
2146 
2147  optVAL_t ID;
2148  private:
2149 
2150 
2151  byte pX;
2152 
2153  byte pY;
2154 
2155  bool _cI;
2156 
2157  inline void s2Cmd(optVAL_t o, optVAL_t t);
2158 
2159  inline bool s1Cmd(optVAL_t o);
2160 
2161  inline void s1Dat(optVAL_t o);
2162  };
2163 
2164  #if EBOARD_NANO == 0x0
2165  LCD::LCD(SoccerBoard &soccerBoard, optVAL_t id) {
2166  this->_cI = false;
2167  this->ID = id;
2168  //this->init();
2169  }
2170  #else
2171  LCD::LCD( optVAL_t id) {
2172  this->_cI = false;
2173  this->ID = id;
2174  //this->init();
2175  }
2176  #endif
2177  inline bool LCD::changeID(optVAL_t newID) {
2178  this->ID = newID;
2179  return this->init();
2180  }
2181  inline bool LCD::clear(void) {
2182  if(!this->_cI) this->init();
2183  for(byte i = 0; i < 8; i++){
2184  //maybe *8
2185  setCursor(0,i);
2186  for (byte j = 0; j < 128; j++)
2187  this->s1Dat(0);
2188  }
2189  return setCursor(0,0);
2190  }
2191  void LCD::print(optVAL_t line, optVAL_t col, const char *data) {
2192  if(!this->_cI) this->init();
2193  byte i = 0x0;
2194  if(col < ((LCD_WIDTH-1)/8.0) && line < ((LCD_HEIGHT-1)/8.0)) {
2195  setCursor(col,line);
2196  }
2197  while(data[i] && (pX*8) < LCD_WIDTH){
2198  //Serial.print(data[i]); Serial.print(" ");
2199  //Serial.print(i); Serial.print(" "); Serial.print(pX); Serial.print(" ");
2200  //Serial.println(this->pY);
2201  if(data[i] == '\n' || this->pX >= LCD_WIDTH) {
2202  setCursor(0,(pY+1));
2203  } else if (this->pY >= LCD_HEIGHT){
2204  setCursor(0,0);
2205  }
2206  if(data[i] < 32 || data[i] > 127){ i++; continue;}
2207  for (byte j = 0; j < 8; j++){
2208  this->s1Dat(pgm_read_byte(&basicFont[data[i]-32][j]));
2209  }
2210  i++;this->pX++;
2211  }
2212  }
2213  void LCD::print(optVAL_t line, optVAL_t col, int data){
2214  char buffer[11] = "";
2215  itoa(data,buffer,10);
2216  this->print(line,col,buffer);
2217  }
2218  inline void LCD::lightOn(void) {
2219  this->changeBrightness(255);
2220  }
2221  inline void LCD::lightOff(void) {
2222  this->changeBrightness(0);
2223  }
2224  inline bool LCD::reset(void) {
2225  return this->clear();
2226  }
2227  inline void LCD::print(int data) {this->print(255,255,data);}
2228  inline void LCD::print(const char* data) {this->print(255,255,data);}
2229  inline bool LCD::init() {
2230  #ifdef HIGHSPEED
2231  TWBR = 0xC;
2232  #endif
2233  this->_cI = true;
2235  this->changeMode(false);
2236  this->changeBackground(false);
2237  this->changeBrightness(255);
2238  this->s2Cmd(0x20,LCD_PAGE_ADDRESSING);
2239  this->changeMode(true);
2240  //this->print("eBoard \n written by \n EagleoutIce");
2241  return this->clear();
2242  }
2243  inline void LCD::drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY){
2244  if(!this->_cI) this->init();
2245  setCursor(posX,posY);
2246  byte col = 0x0;
2247  for(int i = 0x0; i < (hiX * 8 * hiY); i++){
2248  this->s1Dat(pgm_read_byte(&bitmap[i]));
2249  if(++col == (hiX * 8)) {
2250  col = 0x0;
2251  setCursor(posX,++posY);
2252  }
2253  }
2254  }
2255  inline void LCD::changeMode(bool newMode) {
2256  if(!this->_cI) this->init();
2257  if(newMode) this->s1Cmd(LCD_COMMAND_DISPLAY_ON);
2258  else this->s1Cmd(LCD_COMMAND_DISPLAY_OFF);
2259  }
2260  inline bool LCD::setCursor(byte posX, byte posY) {
2261  if(!this->_cI) this->init();
2262  this->s2Cmd((0x00 + (8 *posX & 0x0F)),(0x10 + ((8 * posX >> 4) & 0x0F))); //lower and higher address
2263  this->pX = posX; this->pY = posY;
2264  return this->s1Cmd(0xB0 + posY);
2265  }
2266  inline bool LCD::changeBrightness(byte val) {
2267  if(!this->_cI) this->init();
2268  this->s2Cmd(0x81,val); //brightness mode
2269  Wire.beginTransmission(this->ID);
2270  return (Wire.endTransmission() == 0);
2271  }
2272  inline void LCD::changeBackground(bool newBackground) {
2273  if(!this->_cI) this->init();
2274  if(newBackground) this->s1Cmd(LCD_COMMAND_WHITE_BACKGROUND);
2275  else this->s1Cmd(LCD_COMMAND_BLACK_BACKGROUND);
2276  }
2277  inline void LCD::s2Cmd(optVAL_t o, optVAL_t t){
2278  if(!this->_cI) this->init();
2279  this->s1Cmd(o); this->s1Cmd(t);
2280  }
2281  inline bool LCD::s1Cmd(optVAL_t C) {
2282  if(!this->_cI) this->init();
2283  Wire.beginTransmission(this->ID);
2284  Wire.write(LCD_COMMAND_MODE); Wire.write(C);
2285  return (Wire.endTransmission()==0);
2286  }
2287  inline void LCD::s1Dat(optVAL_t o){
2288  if(!this->_cI) this->init();
2289  Wire.beginTransmission(this->ID);
2290  Wire.write(LCD_DATA_MODE); Wire.write(o);
2292  }
2293 
2294  #endif
2295  #endif
2296  #if EBOARD_NEO > 0x0
2297  // Codesection based on official NeoPixel library
2298  // RGB NeoPixel permutations; white and red offsets are always same
2299  // Offset: W R G B
2300 
2301  #define EBOARD_NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
2302 
2303  #define EBOARD_NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
2304 
2305  #define EBOARD_NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
2306 
2307  #define EBOARD_NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
2308 
2309  #define EBOARD_NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
2310 
2311  #define EBOARD_NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
2312  // RGBW NeoPixel permutations; all 4 offsets are distinct
2313  // Offset: W R G B
2314 
2315  #define EBOARD_NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
2316 
2317  #define EBOARD_NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
2318 
2319  #define EBOARD_NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
2320 
2321  #define EBOARD_NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
2322 
2323  #define EBOARD_NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
2324 
2325  #define EBOARD_NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
2326 
2327  #define EBOARD_NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
2328 
2329  #define EBOARD_NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
2330 
2331  #define EBOARD_NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
2332 
2333  #define EBOARD_NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
2334 
2335  #define EBOARD_NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
2336 
2337  #define EBOARD_NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
2338 
2339  #define EBOARD_NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
2340 
2341  #define EBOARD_NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
2342 
2343  #define EBOARD_NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
2344 
2345  #define EBOARD_NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
2346 
2347  #define EBOARD_NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
2348 
2349  #define EBOARD_NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
2350 
2351  #define EBOARD_NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
2352 
2353  #define EBOARD_NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
2354 
2355  #define EBOARD_NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
2356 
2357  #define EBOARD_NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
2358 
2359  #define EBOARD_NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
2360 
2361  #define EBOARD_NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
2362 
2363  #define EBOARD_NEO_800KHZ 0x0000
2364 
2365  #define EBOARD_NEO_400KHZ 0x0100
2366  // uint16_t can be uint8_t in 800Khz mode ^^
2367 
2368  struct NeoPixel{
2369 
2370  NeoPixel(uint16_t n, uint8_t p = 6, uint16_t t = EBOARD_NEO_GRB + EBOARD_NEO_800KHZ);
2371 
2372  NeoPixel(void);
2373 
2374  ~NeoPixel(void);
2375 
2376  void begin(void);
2377 
2378  void show(void);
2379 
2380  void setPin(uint8_t p);
2381 
2382  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
2383 
2384  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
2385 
2386  void setPixelColor(uint16_t n, uint32_t c);
2387 
2388  void setBrightness(uint8_t val);
2389 
2390  void clear(void);
2391 
2392  void updateLength(uint16_t n);
2393 
2394  void updateType(uint16_t t);
2395 
2396  inline uint8_t *getPixels(void) const;
2397 
2398  inline uint8_t getBrightness(void) const;
2399 
2400  inline int8_t getPin(void);
2401 
2402  inline uint16_t numPixels(void) const;
2403 
2404  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b);
2405 
2406  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
2407 
2408  uint32_t getPixelColor(uint16_t n) const;
2409 
2410  inline bool canShow(void);
2411  protected:
2412 
2413  bool is800KHz;
2414 
2415  bool begun;
2416 
2417  uint16_t numLEDs; //maybe shorten with PrepConst 'extendetLED'?
2418 
2419  uint16_t numBytes;
2420 
2421  int8_t pin;
2422 
2423  uint8_t brightness;
2424 
2425  uint8_t *pixels;
2426 
2427  uint8_t aOffset[4];
2428 
2429  uint32_t endTime; //used for diff calc
2430  #ifdef __AVR__ //not needed (rem?)
2431 
2432  volatile uint8_t *port;// Output PORT register
2433 
2434  uint8_t pinMask; // Output PORT bitmask
2435  #endif
2436  };
2437 
2438  NeoPixel::NeoPixel(uint16_t n, uint8_t p, uint16_t t) :
2439  begun(false), brightness(0), pixels(NULL), endTime(0) {
2440  updateType(t);
2441  updateLength(n);
2442  setPin(p);
2443  }
2444  inline bool NeoPixel::canShow(void) { return (micros() - endTime) >= 300L; }
2445  NeoPixel::NeoPixel() :
2446  is800KHz(true),
2447  begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0), pixels(NULL),
2448  endTime(0)
2449  {aOffset[0]=1;aOffset[1]=0;aOffset[2]=2;aOffset[3]=1;}
2451  if(pixels) free(pixels);
2452  if(pin >= 0) pinMode(pin, INPUT);
2453  }
2454  void NeoPixel::begin(void) {
2455  if(pin >= 0) {
2456  pinMode(pin, OUTPUT);
2457  digitalWrite(pin, LOW);
2458  }
2459  begun = true;
2460  }
2461  void NeoPixel::updateLength(uint16_t n) {
2462  if(pixels) free(pixels);
2463  numBytes = n * ((aOffset[3] == aOffset[0]) ? 3 : 4);
2464  if((pixels = (uint8_t *)malloc(numBytes))) {
2465  memset(pixels, 0, numBytes);
2466  numLEDs = n;
2467  } else {
2468  numLEDs = numBytes = 0;
2469  }
2470  }
2471  void NeoPixel::updateType(uint16_t t) {
2472  boolean oldThreeBytesPerPixel = (aOffset[3] == aOffset[0]); // false if RGBW
2473  aOffset[3] = (t >> 6) & 0b11;
2474  aOffset[0] = (t >> 4) & 0b11;
2475  aOffset[1] = (t >> 2) & 0b11;
2476  aOffset[2] = t & 0b11;
2477  is800KHz = (t < 256); // 400 KHz flag is 1<<8
2478  if(pixels) {
2479  boolean newThreeBytesPerPixel = (aOffset[3] == aOffset[0]);
2480  if(newThreeBytesPerPixel != oldThreeBytesPerPixel) updateLength(numLEDs);
2481  }
2482  }
2483  #if defined(ESP8266)
2484  // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
2485  extern "C" void ICACHE_RAM_ATTR espShow(
2486  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
2487  #elif defined(ESP32)
2488  extern "C" void espShow(
2489  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
2490  #endif
2491  void NeoPixel::show(void) {
2492  if(!pixels) return;
2493  while(!canShow()); //maybe timeout ?
2494  noInterrupts(); // Need 100% focus on instruction timing
2495  #ifdef __AVR__
2496  volatile uint16_t
2497  i = numBytes;
2498  volatile uint8_t
2499  *ptr = pixels,
2500  b = *ptr++,
2501  hi,
2502  lo;
2503  #if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
2504  if(is800KHz) {
2505  volatile uint8_t n1, n2 = 0;
2506  #if defined(PORTD)
2507  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
2508  if(port == &PORTD) {
2509  #endif
2510  hi = PORTD | pinMask;
2511  lo = PORTD & ~pinMask;
2512  n1 = lo;
2513  if(b & 0x80) n1 = hi;
2514  asm volatile(
2515  "headD:" "\n\t" // Clk Pseudocode
2516  // Bit 7:
2517  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2518  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
2519  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
2520  "rjmp .+0" "\n\t" // 2 nop nop
2521  "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40)
2522  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
2523  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2524  "rjmp .+0" "\n\t" // 2 nop nop
2525  // Bit 6:
2526  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2527  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
2528  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
2529  "rjmp .+0" "\n\t" // 2 nop nop
2530  "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20)
2531  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
2532  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2533  "rjmp .+0" "\n\t" // 2 nop nop
2534  // Bit 5:
2535  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2536  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
2537  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
2538  "rjmp .+0" "\n\t" // 2 nop nop
2539  "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10)
2540  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
2541  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2542  "rjmp .+0" "\n\t" // 2 nop nop
2543  // Bit 4:
2544  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2545  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
2546  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
2547  "rjmp .+0" "\n\t" // 2 nop nop
2548  "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08)
2549  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
2550  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2551  "rjmp .+0" "\n\t" // 2 nop nop
2552  // Bit 3:
2553  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2554  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
2555  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
2556  "rjmp .+0" "\n\t" // 2 nop nop
2557  "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04)
2558  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
2559  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2560  "rjmp .+0" "\n\t" // 2 nop nop
2561  // Bit 2:
2562  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2563  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
2564  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
2565  "rjmp .+0" "\n\t" // 2 nop nop
2566  "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02)
2567  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
2568  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2569  "rjmp .+0" "\n\t" // 2 nop nop
2570  // Bit 1:
2571  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2572  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
2573  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
2574  "rjmp .+0" "\n\t" // 2 nop nop
2575  "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01)
2576  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
2577  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2578  "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
2579  // Bit 0:
2580  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
2581  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
2582  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
2583  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
2584  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80)
2585  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
2586  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
2587  "brne headD" "\n" // 2 while(i) (Z flag set above)
2588  : [byte] "+r" (b),
2589  [n1] "+r" (n1),
2590  [n2] "+r" (n2),
2591  [count] "+w" (i)
2592  : [port] "I" (_SFR_IO_ADDR(PORTD)),
2593  [ptr] "e" (ptr),
2594  [hi] "r" (hi),
2595  [lo] "r" (lo));
2596  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
2597  } else
2598  #endif
2599  #endif
2600  #if defined(PORTB)
2601  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
2602  if(port == &PORTB) {
2603  #endif // defined(PORTD/C/F)
2604  hi = PORTB | pinMask;
2605  lo = PORTB & ~pinMask;
2606  n1 = lo;
2607  if(b & 0x80) n1 = hi;
2608  asm volatile(
2609  "headB:" "\n\t"
2610  "out %[port] , %[hi]" "\n\t"
2611  "mov %[n2] , %[lo]" "\n\t"
2612  "out %[port] , %[n1]" "\n\t"
2613  "rjmp .+0" "\n\t"
2614  "sbrc %[byte] , 6" "\n\t"
2615  "mov %[n2] , %[hi]" "\n\t"
2616  "out %[port] , %[lo]" "\n\t"
2617  "rjmp .+0" "\n\t"
2618  "out %[port] , %[hi]" "\n\t"
2619  "mov %[n1] , %[lo]" "\n\t"
2620  "out %[port] , %[n2]" "\n\t"
2621  "rjmp .+0" "\n\t"
2622  "sbrc %[byte] , 5" "\n\t"
2623  "mov %[n1] , %[hi]" "\n\t"
2624  "out %[port] , %[lo]" "\n\t"
2625  "rjmp .+0" "\n\t"
2626  "out %[port] , %[hi]" "\n\t"
2627  "mov %[n2] , %[lo]" "\n\t"
2628  "out %[port] , %[n1]" "\n\t"
2629  "rjmp .+0" "\n\t"
2630  "sbrc %[byte] , 4" "\n\t"
2631  "mov %[n2] , %[hi]" "\n\t"
2632  "out %[port] , %[lo]" "\n\t"
2633  "rjmp .+0" "\n\t"
2634  "out %[port] , %[hi]" "\n\t"
2635  "mov %[n1] , %[lo]" "\n\t"
2636  "out %[port] , %[n2]" "\n\t"
2637  "rjmp .+0" "\n\t"
2638  "sbrc %[byte] , 3" "\n\t"
2639  "mov %[n1] , %[hi]" "\n\t"
2640  "out %[port] , %[lo]" "\n\t"
2641  "rjmp .+0" "\n\t"
2642  "out %[port] , %[hi]" "\n\t"
2643  "mov %[n2] , %[lo]" "\n\t"
2644  "out %[port] , %[n1]" "\n\t"
2645  "rjmp .+0" "\n\t"
2646  "sbrc %[byte] , 2" "\n\t"
2647  "mov %[n2] , %[hi]" "\n\t"
2648  "out %[port] , %[lo]" "\n\t"
2649  "rjmp .+0" "\n\t"
2650  "out %[port] , %[hi]" "\n\t"
2651  "mov %[n1] , %[lo]" "\n\t"
2652  "out %[port] , %[n2]" "\n\t"
2653  "rjmp .+0" "\n\t"
2654  "sbrc %[byte] , 1" "\n\t"
2655  "mov %[n1] , %[hi]" "\n\t"
2656  "out %[port] , %[lo]" "\n\t"
2657  "rjmp .+0" "\n\t"
2658  "out %[port] , %[hi]" "\n\t"
2659  "mov %[n2] , %[lo]" "\n\t"
2660  "out %[port] , %[n1]" "\n\t"
2661  "rjmp .+0" "\n\t"
2662  "sbrc %[byte] , 0" "\n\t"
2663  "mov %[n2] , %[hi]" "\n\t"
2664  "out %[port] , %[lo]" "\n\t"
2665  "sbiw %[count], 1" "\n\t"
2666  "out %[port] , %[hi]" "\n\t"
2667  "mov %[n1] , %[lo]" "\n\t"
2668  "out %[port] , %[n2]" "\n\t"
2669  "ld %[byte] , %a[ptr]+" "\n\t"
2670  "sbrc %[byte] , 7" "\n\t"
2671  "mov %[n1] , %[hi]" "\n\t"
2672  "out %[port] , %[lo]" "\n\t"
2673  "brne headB" "\n"
2674  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
2675  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
2676  [lo] "r" (lo));
2677  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
2678  }
2679  #endif
2680  #if defined(PORTC) || defined(PORTF)
2681  else
2682  #endif
2683  #endif
2684  #if defined(PORTC)
2685  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
2686  if(port == &PORTC) {
2687  #endif
2688  hi = PORTC | pinMask;
2689  lo = PORTC & ~pinMask;
2690  n1 = lo;
2691  if(b & 0x80) n1 = hi;
2692  asm volatile(
2693  "headC:" "\n\t"
2694  "out %[port] , %[hi]" "\n\t"
2695  "mov %[n2] , %[lo]" "\n\t"
2696  "out %[port] , %[n1]" "\n\t"
2697  "rjmp .+0" "\n\t"
2698  "sbrc %[byte] , 6" "\n\t"
2699  "mov %[n2] , %[hi]" "\n\t"
2700  "out %[port] , %[lo]" "\n\t"
2701  "rjmp .+0" "\n\t"
2702  "out %[port] , %[hi]" "\n\t"
2703  "mov %[n1] , %[lo]" "\n\t"
2704  "out %[port] , %[n2]" "\n\t"
2705  "rjmp .+0" "\n\t"
2706  "sbrc %[byte] , 5" "\n\t"
2707  "mov %[n1] , %[hi]" "\n\t"
2708  "out %[port] , %[lo]" "\n\t"
2709  "rjmp .+0" "\n\t"
2710  "out %[port] , %[hi]" "\n\t"
2711  "mov %[n2] , %[lo]" "\n\t"
2712  "out %[port] , %[n1]" "\n\t"
2713  "rjmp .+0" "\n\t"
2714  "sbrc %[byte] , 4" "\n\t"
2715  "mov %[n2] , %[hi]" "\n\t"
2716  "out %[port] , %[lo]" "\n\t"
2717  "rjmp .+0" "\n\t"
2718  "out %[port] , %[hi]" "\n\t"
2719  "mov %[n1] , %[lo]" "\n\t"
2720  "out %[port] , %[n2]" "\n\t"
2721  "rjmp .+0" "\n\t"
2722  "sbrc %[byte] , 3" "\n\t"
2723  "mov %[n1] , %[hi]" "\n\t"
2724  "out %[port] , %[lo]" "\n\t"
2725  "rjmp .+0" "\n\t"
2726  "out %[port] , %[hi]" "\n\t"
2727  "mov %[n2] , %[lo]" "\n\t"
2728  "out %[port] , %[n1]" "\n\t"
2729  "rjmp .+0" "\n\t"
2730  "sbrc %[byte] , 2" "\n\t"
2731  "mov %[n2] , %[hi]" "\n\t"
2732  "out %[port] , %[lo]" "\n\t"
2733  "rjmp .+0" "\n\t"
2734  "out %[port] , %[hi]" "\n\t"
2735  "mov %[n1] , %[lo]" "\n\t"
2736  "out %[port] , %[n2]" "\n\t"
2737  "rjmp .+0" "\n\t"
2738  "sbrc %[byte] , 1" "\n\t"
2739  "mov %[n1] , %[hi]" "\n\t"
2740  "out %[port] , %[lo]" "\n\t"
2741  "rjmp .+0" "\n\t"
2742  "out %[port] , %[hi]" "\n\t"
2743  "mov %[n2] , %[lo]" "\n\t"
2744  "out %[port] , %[n1]" "\n\t"
2745  "rjmp .+0" "\n\t"
2746  "sbrc %[byte] , 0" "\n\t"
2747  "mov %[n2] , %[hi]" "\n\t"
2748  "out %[port] , %[lo]" "\n\t"
2749  "sbiw %[count], 1" "\n\t"
2750  "out %[port] , %[hi]" "\n\t"
2751  "mov %[n1] , %[lo]" "\n\t"
2752  "out %[port] , %[n2]" "\n\t"
2753  "ld %[byte] , %a[ptr]+" "\n\t"
2754  "sbrc %[byte] , 7" "\n\t"
2755  "mov %[n1] , %[hi]" "\n\t"
2756  "out %[port] , %[lo]" "\n\t"
2757  "brne headC" "\n"
2758  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
2759  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
2760  [lo] "r" (lo));
2761  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
2762  }
2763  #endif
2764  #if defined(PORTF)
2765  else
2766  #endif
2767  #endif
2768  #if defined(PORTF)
2769  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
2770  if(port == &PORTF) {
2771  #endif // defined(PORTD/B/C)
2772  hi = PORTF | pinMask;
2773  lo = PORTF & ~pinMask;
2774  n1 = lo;
2775  if(b & 0x80) n1 = hi;
2776  asm volatile(
2777  "headF:" "\n\t"
2778  "out %[port] , %[hi]" "\n\t"
2779  "mov %[n2] , %[lo]" "\n\t"
2780  "out %[port] , %[n1]" "\n\t"
2781  "rjmp .+0" "\n\t"
2782  "sbrc %[byte] , 6" "\n\t"
2783  "mov %[n2] , %[hi]" "\n\t"
2784  "out %[port] , %[lo]" "\n\t"
2785  "rjmp .+0" "\n\t"
2786  "out %[port] , %[hi]" "\n\t"
2787  "mov %[n1] , %[lo]" "\n\t"
2788  "out %[port] , %[n2]" "\n\t"
2789  "rjmp .+0" "\n\t"
2790  "sbrc %[byte] , 5" "\n\t"
2791  "mov %[n1] , %[hi]" "\n\t"
2792  "out %[port] , %[lo]" "\n\t"
2793  "rjmp .+0" "\n\t"
2794  "out %[port] , %[hi]" "\n\t"
2795  "mov %[n2] , %[lo]" "\n\t"
2796  "out %[port] , %[n1]" "\n\t"
2797  "rjmp .+0" "\n\t"
2798  "sbrc %[byte] , 4" "\n\t"
2799  "mov %[n2] , %[hi]" "\n\t"
2800  "out %[port] , %[lo]" "\n\t"
2801  "rjmp .+0" "\n\t"
2802  "out %[port] , %[hi]" "\n\t"
2803  "mov %[n1] , %[lo]" "\n\t"
2804  "out %[port] , %[n2]" "\n\t"
2805  "rjmp .+0" "\n\t"
2806  "sbrc %[byte] , 3" "\n\t"
2807  "mov %[n1] , %[hi]" "\n\t"
2808  "out %[port] , %[lo]" "\n\t"
2809  "rjmp .+0" "\n\t"
2810  "out %[port] , %[hi]" "\n\t"
2811  "mov %[n2] , %[lo]" "\n\t"
2812  "out %[port] , %[n1]" "\n\t"
2813  "rjmp .+0" "\n\t"
2814  "sbrc %[byte] , 2" "\n\t"
2815  "mov %[n2] , %[hi]" "\n\t"
2816  "out %[port] , %[lo]" "\n\t"
2817  "rjmp .+0" "\n\t"
2818  "out %[port] , %[hi]" "\n\t"
2819  "mov %[n1] , %[lo]" "\n\t"
2820  "out %[port] , %[n2]" "\n\t"
2821  "rjmp .+0" "\n\t"
2822  "sbrc %[byte] , 1" "\n\t"
2823  "mov %[n1] , %[hi]" "\n\t"
2824  "out %[port] , %[lo]" "\n\t"
2825  "rjmp .+0" "\n\t"
2826  "out %[port] , %[hi]" "\n\t"
2827  "mov %[n2] , %[lo]" "\n\t"
2828  "out %[port] , %[n1]" "\n\t"
2829  "rjmp .+0" "\n\t"
2830  "sbrc %[byte] , 0" "\n\t"
2831  "mov %[n2] , %[hi]" "\n\t"
2832  "out %[port] , %[lo]" "\n\t"
2833  "sbiw %[count], 1" "\n\t"
2834  "out %[port] , %[hi]" "\n\t"
2835  "mov %[n1] , %[lo]" "\n\t"
2836  "out %[port] , %[n2]" "\n\t"
2837  "ld %[byte] , %a[ptr]+" "\n\t"
2838  "sbrc %[byte] , 7" "\n\t"
2839  "mov %[n1] , %[hi]" "\n\t"
2840  "out %[port] , %[lo]" "\n\t"
2841  "brne headF" "\n"
2842  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
2843  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
2844  [lo] "r" (lo));
2845  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
2846  }
2847  #endif // defined(PORTD/B/C)
2848  #endif // defined(PORTF)
2849  } else {
2850  volatile uint8_t next, bit;
2851  hi = *port | pinMask;
2852  lo = *port & ~pinMask;
2853  next = lo;
2854  bit = 8;
2855  asm volatile(
2856  "head20:" "\n\t" // Clk Pseudocode (T = 0)
2857  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
2858  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
2859  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
2860  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6)
2861  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
2862  "dec %[bit]" "\n\t" // 1 bit-- (T = 8)
2863  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0)
2864  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
2865  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
2866  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
2867  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
2868  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
2869  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
2870  "nextbyte20:" "\n\t" // (T = 10)
2871  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
2872  "nop" "\n\t" // 1 nop (T = 13)
2873  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14)
2874  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16)
2875  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
2876  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
2877  : [port] "+e" (port),
2878  [byte] "+r" (b),
2879  [bit] "+r" (bit),
2880  [next] "+r" (next),
2881  [count] "+w" (i)
2882  : [hi] "r" (hi),
2883  [lo] "r" (lo),
2884  [ptr] "e" (ptr));
2885  }
2886  #elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
2887  if(is800KHz) {
2888  volatile uint8_t next;
2889  // PORTD OUTPUT ----------------------------------------------------
2890  #if defined(PORTD)
2891  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
2892  if(port == &PORTD) {
2893  #endif
2894  hi = PORTD | pinMask;
2895  lo = PORTD & ~pinMask;
2896  next = lo;
2897  if(b & 0x80) next = hi;
2898  asm volatile(
2899  "headD:" "\n\t" // (T = 0)
2900  "out %[port], %[hi]" "\n\t" // (T = 1)
2901  "rcall bitTimeD" "\n\t" // Bit 7 (T = 15)
2902  "out %[port], %[hi]" "\n\t"
2903  "rcall bitTimeD" "\n\t" // Bit 6
2904  "out %[port], %[hi]" "\n\t"
2905  "rcall bitTimeD" "\n\t" // Bit 5
2906  "out %[port], %[hi]" "\n\t"
2907  "rcall bitTimeD" "\n\t" // Bit 4
2908  "out %[port], %[hi]" "\n\t"
2909  "rcall bitTimeD" "\n\t" // Bit 3
2910  "out %[port], %[hi]" "\n\t"
2911  "rcall bitTimeD" "\n\t" // Bit 2
2912  "out %[port], %[hi]" "\n\t"
2913  "rcall bitTimeD" "\n\t" // Bit 1
2914  // Bit 0:
2915  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1)
2916  "rjmp .+0" "\n\t" // 2 nop nop (T = 3)
2917  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5)
2918  "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6)
2919  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
2920  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
2921  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
2922  "nop" "\n\t" // 1 (T = 10)
2923  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11)
2924  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
2925  "brne headD" "\n\t" // 2 if(i != 0) -> (next byte)
2926  "rjmp doneD" "\n\t"
2927  "bitTimeD:" "\n\t" // nop nop nop (T = 4)
2928  "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
2929  "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
2930  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
2931  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
2932  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
2933  "nop" "\n\t" // 1 (T = 10)
2934  "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
2935  "ret" "\n\t" // 4 nop nop nop nop (T = 15)
2936  "doneD:" "\n"
2937  : [byte] "+r" (b),
2938  [next] "+r" (next),
2939  [count] "+w" (i)
2940  : [port] "I" (_SFR_IO_ADDR(PORTD)),
2941  [ptr] "e" (ptr),
2942  [hi] "r" (hi),
2943  [lo] "r" (lo));
2944  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
2945  } else
2946  #endif
2947  #endif
2948  #if defined(PORTB)
2949  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
2950  if(port == &PORTB) {
2951  #endif
2952  hi = PORTB | pinMask;
2953  lo = PORTB & ~pinMask;
2954  next = lo;
2955  if(b & 0x80) next = hi;
2956  asm volatile(
2957  "headB:" "\n\t"
2958  "out %[port], %[hi]" "\n\t"
2959  "rcall bitTimeB" "\n\t"
2960  "out %[port], %[hi]" "\n\t"
2961  "rcall bitTimeB" "\n\t"
2962  "out %[port], %[hi]" "\n\t"
2963  "rcall bitTimeB" "\n\t"
2964  "out %[port], %[hi]" "\n\t"
2965  "rcall bitTimeB" "\n\t"
2966  "out %[port], %[hi]" "\n\t"
2967  "rcall bitTimeB" "\n\t"
2968  "out %[port], %[hi]" "\n\t"
2969  "rcall bitTimeB" "\n\t"
2970  "out %[port], %[hi]" "\n\t"
2971  "rcall bitTimeB" "\n\t"
2972  "out %[port] , %[hi]" "\n\t"
2973  "rjmp .+0" "\n\t"
2974  "ld %[byte] , %a[ptr]+" "\n\t"
2975  "out %[port] , %[next]" "\n\t"
2976  "mov %[next] , %[lo]" "\n\t"
2977  "sbrc %[byte] , 7" "\n\t"
2978  "mov %[next] , %[hi]" "\n\t"
2979  "nop" "\n\t"
2980  "out %[port] , %[lo]" "\n\t"
2981  "sbiw %[count], 1" "\n\t"
2982  "brne headB" "\n\t"
2983  "rjmp doneB" "\n\t"
2984  "bitTimeB:" "\n\t"
2985  "out %[port], %[next]" "\n\t"
2986  "mov %[next], %[lo]" "\n\t"
2987  "rol %[byte]" "\n\t"
2988  "sbrc %[byte], 7" "\n\t"
2989  "mov %[next], %[hi]" "\n\t"
2990  "nop" "\n\t"
2991  "out %[port], %[lo]" "\n\t"
2992  "ret" "\n\t"
2993  "doneB:" "\n"
2994  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
2995  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
2996  [lo] "r" (lo));
2997  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
2998  }
2999  #endif
3000  #if defined(PORTC) || defined(PORTF)
3001  else
3002  #endif
3003  #endif
3004  #if defined(PORTC)
3005  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
3006  if(port == &PORTC) {
3007  #endif
3008  hi = PORTC | pinMask;
3009  lo = PORTC & ~pinMask;
3010  next = lo;
3011  if(b & 0x80) next = hi;
3012  asm volatile(
3013  "headC:" "\n\t"
3014  "out %[port], %[hi]" "\n\t"
3015  "rcall bitTimeC" "\n\t"
3016  "out %[port], %[hi]" "\n\t"
3017  "rcall bitTimeC" "\n\t"
3018  "out %[port], %[hi]" "\n\t"
3019  "rcall bitTimeC" "\n\t"
3020  "out %[port], %[hi]" "\n\t"
3021  "rcall bitTimeC" "\n\t"
3022  "out %[port], %[hi]" "\n\t"
3023  "rcall bitTimeC" "\n\t"
3024  "out %[port], %[hi]" "\n\t"
3025  "rcall bitTimeC" "\n\t"
3026  "out %[port], %[hi]" "\n\t"
3027  "rcall bitTimeC" "\n\t"
3028  "out %[port] , %[hi]" "\n\t"
3029  "rjmp .+0" "\n\t"
3030  "ld %[byte] , %a[ptr]+" "\n\t"
3031  "out %[port] , %[next]" "\n\t"
3032  "mov %[next] , %[lo]" "\n\t"
3033  "sbrc %[byte] , 7" "\n\t"
3034  "mov %[next] , %[hi]" "\n\t"
3035  "nop" "\n\t"
3036  "out %[port] , %[lo]" "\n\t"
3037  "sbiw %[count], 1" "\n\t"
3038  "brne headC" "\n\t"
3039  "rjmp doneC" "\n\t"
3040  "bitTimeC:" "\n\t"
3041  "out %[port], %[next]" "\n\t"
3042  "mov %[next], %[lo]" "\n\t"
3043  "rol %[byte]" "\n\t"
3044  "sbrc %[byte], 7" "\n\t"
3045  "mov %[next], %[hi]" "\n\t"
3046  "nop" "\n\t"
3047  "out %[port], %[lo]" "\n\t"
3048  "ret" "\n\t"
3049  "doneC:" "\n"
3050  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
3051  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
3052  [lo] "r" (lo));
3053  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
3054  }
3055  #endif
3056  #if defined(PORTF)
3057  else
3058  #endif
3059  #endif
3060  #if defined(PORTF)
3061  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
3062  if(port == &PORTF) {
3063  #endif
3064  hi = PORTF | pinMask;
3065  lo = PORTF & ~pinMask;
3066  next = lo;
3067  if(b & 0x80) next = hi;
3068  asm volatile(
3069  "headF:" "\n\t"
3070  "out %[port], %[hi]" "\n\t"
3071  "rcall bitTimeC" "\n\t"
3072  "out %[port], %[hi]" "\n\t"
3073  "rcall bitTimeC" "\n\t"
3074  "out %[port], %[hi]" "\n\t"
3075  "rcall bitTimeC" "\n\t"
3076  "out %[port], %[hi]" "\n\t"
3077  "rcall bitTimeC" "\n\t"
3078  "out %[port], %[hi]" "\n\t"
3079  "rcall bitTimeC" "\n\t"
3080  "out %[port], %[hi]" "\n\t"
3081  "rcall bitTimeC" "\n\t"
3082  "out %[port], %[hi]" "\n\t"
3083  "rcall bitTimeC" "\n\t"
3084  "out %[port] , %[hi]" "\n\t"
3085  "rjmp .+0" "\n\t"
3086  "ld %[byte] , %a[ptr]+" "\n\t"
3087  "out %[port] , %[next]" "\n\t"
3088  "mov %[next] , %[lo]" "\n\t"
3089  "sbrc %[byte] , 7" "\n\t"
3090  "mov %[next] , %[hi]" "\n\t"
3091  "nop" "\n\t"
3092  "out %[port] , %[lo]" "\n\t"
3093  "sbiw %[count], 1" "\n\t"
3094  "brne headF" "\n\t"
3095  "rjmp doneC" "\n\t"
3096  "bitTimeC:" "\n\t"
3097  "out %[port], %[next]" "\n\t"
3098  "mov %[next], %[lo]" "\n\t"
3099  "rol %[byte]" "\n\t"
3100  "sbrc %[byte], 7" "\n\t"
3101  "mov %[next], %[hi]" "\n\t"
3102  "nop" "\n\t"
3103  "out %[port], %[lo]" "\n\t"
3104  "ret" "\n\t"
3105  "doneC:" "\n"
3106  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
3107  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
3108  [lo] "r" (lo));
3109  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
3110  }
3111  #endif
3112  #endif
3113  } else {
3114  volatile uint8_t next, bit;
3115  hi = *port | pinMask;
3116  lo = *port & ~pinMask;
3117  next = lo;
3118  bit = 8;
3119  asm volatile(
3120  "head30:" "\n\t" // Clk Pseudocode (T = 0)
3121  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
3122  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
3123  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
3124  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
3125  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8)
3126  "rjmp .+0" "\n\t" // 2 nop nop (T = 10)
3127  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
3128  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
3129  "nop" "\n\t" // 1 nop (T = 15)
3130  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17)
3131  "rjmp .+0" "\n\t" // 2 nop nop (T = 19)
3132  "dec %[bit]" "\n\t" // 1 bit-- (T = 20)
3133  "breq nextbyte30" "\n\t" // 1-2 if(bit == 0)
3134  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
3135  "rjmp .+0" "\n\t" // 2 nop nop (T = 24)
3136  "rjmp .+0" "\n\t" // 2 nop nop (T = 26)
3137  "rjmp .+0" "\n\t" // 2 nop nop (T = 28)
3138  "rjmp head30" "\n\t" // 2 -> head30 (next bit out)
3139  "nextbyte30:" "\n\t" // (T = 22)
3140  "nop" "\n\t" // 1 nop (T = 23)
3141  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24)
3142  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26)
3143  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
3144  "brne head30" "\n" // 1-2 if(i != 0) -> (next byte)
3145  : [port] "+e" (port),
3146  [byte] "+r" (b),
3147  [bit] "+r" (bit),
3148  [next] "+r" (next),
3149  [count] "+w" (i)
3150  : [hi] "r" (hi),
3151  [lo] "r" (lo),
3152  [ptr] "e" (ptr));
3153  }
3154  #elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
3155  if(is800KHz) {
3156  volatile uint8_t next, bit;
3157  hi = *port | pinMask;
3158  lo = *port & ~pinMask;
3159  next = lo;
3160  bit = 8;
3161  asm volatile(
3162  "head20:" "\n\t" // Clk Pseudocode (T = 0)
3163  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
3164  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128)
3165  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
3166  "dec %[bit]" "\n\t" // 1 bit-- (T = 5)
3167  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7)
3168  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
3169  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above)
3170  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
3171  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
3172  "nop" "\n\t" // 1 nop (T = 13)
3173  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
3174  "nop" "\n\t" // 1 nop (T = 16)
3175  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
3176  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
3177  "nextbyte20:" "\n\t" // (T = 10)
3178  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
3179  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
3180  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
3181  "nop" "\n\t" // 1 nop (T = 16)
3182  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
3183  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
3184  : [port] "+e" (port),
3185  [byte] "+r" (b),
3186  [bit] "+r" (bit),
3187  [next] "+r" (next),
3188  [count] "+w" (i)
3189  : [ptr] "e" (ptr),
3190  [hi] "r" (hi),
3191  [lo] "r" (lo));
3192  } else {
3193  volatile uint8_t next, bit;
3194  hi = *port | pinMask;
3195  lo = *port & ~pinMask;
3196  next = lo;
3197  bit = 8;
3198  asm volatile(
3199  "head40:" "\n\t" // Clk Pseudocode (T = 0)
3200  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
3201  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
3202  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4)
3203  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
3204  "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
3205  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10)
3206  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
3207  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
3208  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
3209  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
3210  "rjmp .+0" "\n\t" // 2 nop nop (T = 20)
3211  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22)
3212  "nop" "\n\t" // 1 nop (T = 23)
3213  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24)
3214  "dec %[bit]" "\n\t" // 1 bit-- (T = 25)
3215  "breq nextbyte40" "\n\t" // 1-2 if(bit == 0)
3216  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
3217  "nop" "\n\t" // 1 nop (T = 28)
3218  "rjmp .+0" "\n\t" // 2 nop nop (T = 30)
3219  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
3220  "rjmp .+0" "\n\t" // 2 nop nop (T = 34)
3221  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
3222  "rjmp .+0" "\n\t" // 2 nop nop (T = 38)
3223  "rjmp head40" "\n\t" // 2 -> head40 (next bit out)
3224  "nextbyte40:" "\n\t" // (T = 27)
3225  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28)
3226  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30)
3227  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
3228  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34)
3229  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
3230  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
3231  "brne head40" "\n" // 1-2 if(i != 0) -> (next byte)
3232  : [port] "+e" (port),
3233  [byte] "+r" (b),
3234  [bit] "+r" (bit),
3235  [next] "+r" (next),
3236  [count] "+w" (i)
3237  : [ptr] "e" (ptr),
3238  [hi] "r" (hi),
3239  [lo] "r" (lo));
3240  }
3241  #else
3242  #error "CPU SPEED NOT SUPPORTED"
3243  #endif
3244  #elif defined(__arm__)
3245  #if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
3246  #define CYCLES_800_T0H (F_CPU / 4000000)
3247  #define CYCLES_800_T1H (F_CPU / 1250000)
3248  #define CYCLES_800 (F_CPU / 800000)
3249  #define CYCLES_400_T0H (F_CPU / 2000000)
3250  #define CYCLES_400_T1H (F_CPU / 833333)
3251  #define CYCLES_400 (F_CPU / 400000)
3252  uint8_t *p = pixels,
3253  *end = p + numBytes, pix, mask;
3254  volatile uint8_t *set = portSetRegister(pin),
3255  *clr = portClearRegister(pin);
3256  uint32_t cyc;
3257  ARM_DEMCR |= ARM_DEMCR_TRCENA;
3258  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
3259  if(is800KHz) {
3260  cyc = ARM_DWT_CYCCNT + CYCLES_800;
3261  while(p < end) {
3262  pix = *p++;
3263  for(mask = 0x80; mask; mask >>= 1) {
3264  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
3265  cyc = ARM_DWT_CYCCNT;
3266  *set = 1;
3267  if(pix & mask) {
3268  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
3269  } else {
3270  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
3271  }
3272  *clr = 1;
3273  }
3274  }
3275  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
3276  } else {
3277  cyc = ARM_DWT_CYCCNT + CYCLES_400;
3278  while(p < end) {
3279  pix = *p++;
3280  for(mask = 0x80; mask; mask >>= 1) {
3281  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
3282  cyc = ARM_DWT_CYCCNT;
3283  *set = 1;
3284  if(pix & mask) {
3285  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
3286  } else {
3287  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
3288  }
3289  *clr = 1;
3290  }
3291  }
3292  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
3293  }
3294  #else
3295  #error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
3296  #endif
3297  #elif defined(ESP8266) || defined(ESP32)
3298  espShow(pin, pixels, numBytes, is800KHz);
3299  #elif defined(__ARDUINO_ARC__)
3300  // Arduino 101 -----------------------------------------------------------
3301  #define NOPx7 { __builtin_arc_nop(); \
3302  __builtin_arc_nop(); __builtin_arc_nop(); \
3303  __builtin_arc_nop(); __builtin_arc_nop(); \
3304  __builtin_arc_nop(); __builtin_arc_nop(); }
3305  PinDescription *pindesc = &g_APinDescription[pin];
3306  register uint32_t loop = 8 * numBytes; // one loop to handle all bytes and all bits
3307  register uint8_t *p = pixels;
3308  register uint32_t currByte = (uint32_t) (*p);
3309  register uint32_t currBit = 0x80 & currByte;
3310  register uint32_t bitCounter = 0;
3311  register uint32_t first = 1;
3312  if (pindesc->ulGPIOType == SS_GPIO) {
3313  register uint32_t reg = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR;
3314  uint32_t reg_val = __builtin_arc_lr((volatile uint32_t)reg);
3315  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
3316  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
3317  loop += 1;
3318  while(loop--) {
3319  if(!first) {
3320  currByte <<= 1;
3321  bitCounter++;
3322  }
3323  // 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
3324  __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile uint32_t)reg);
3325  if(currBit) { // ~400ns HIGH (740ns overall)
3326  NOPx7
3327  NOPx7
3328  }
3329  // ~340ns HIGH
3330  NOPx7
3331  __builtin_arc_nop();
3332  // 820ns LOW; per spec, max allowed low here is 5000ns */
3333  __builtin_arc_sr(reg_bit_low, (volatile uint32_t)reg);
3334  NOPx7
3335  NOPx7
3336  if(bitCounter >= 8) {
3337  bitCounter = 0;
3338  currByte = (uint32_t) (*++p);
3339  }
3340  currBit = 0x80 & currByte;
3341  first = 0;
3342  }
3343  } else if(pindesc->ulGPIOType == SOC_GPIO) {
3344  register uint32_t reg = pindesc->ulGPIOBase + SOC_GPIO_SWPORTA_DR;
3345  uint32_t reg_val = MMIO_REG_VAL(reg);
3346  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
3347  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
3348  loop += 1; // include first, special iteration
3349  while(loop--) {
3350  if(!first) {
3351  currByte <<= 1;
3352  bitCounter++;
3353  }
3354  MMIO_REG_VAL(reg) = first ? reg_bit_low : reg_bit_high;
3355  if(currBit) { // ~430ns HIGH (740ns overall)
3356  NOPx7
3357  NOPx7
3358  __builtin_arc_nop();
3359  }
3360  // ~310ns HIGH
3361  NOPx7
3362  // 850ns LOW; per spec, max allowed low here is 5000ns */
3363  MMIO_REG_VAL(reg) = reg_bit_low;
3364  NOPx7
3365  NOPx7
3366  if(bitCounter >= 8) {
3367  bitCounter = 0;
3368  currByte = (uint32_t) (*++p);
3369  }
3370  currBit = 0x80 & currByte;
3371  first = 0;
3372  }
3373  }
3374  #else
3375  #error Architecture not supported
3376  #endif
3377  interrupts();
3378  endTime = micros();
3379  }
3380  void NeoPixel::setPin(uint8_t p) {
3381  if(begun && (pin >= 0)) pinMode(pin, INPUT);
3382  pin = p;
3383  if(begun) {
3384  pinMode(p, OUTPUT);
3385  digitalWrite(p, LOW);
3386  }
3387  #ifdef __AVR__
3388  port = portOutputRegister(digitalPinToPort(p));
3389  pinMask = digitalPinToBitMask(p);
3390  #endif
3391  }
3393  uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
3394  if(n < numLEDs) {
3395  if(brightness) { // See notes in setBrightness()
3396  r = (r * brightness) >> 8;
3397  g = (g * brightness) >> 8;
3398  b = (b * brightness) >> 8;
3399  }
3400  uint8_t *p;
3401  if(aOffset[3] == aOffset[0]) {
3402  p = &pixels[n * 3];
3403  } else {
3404  p = &pixels[n * 4];
3405  p[aOffset[3]] = 0;
3406  }
3407  p[aOffset[0]] = r;
3408  p[aOffset[1]] = g;
3409  p[aOffset[2]] = b;
3410  }
3411  }
3413  uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
3414  if(n < numLEDs) {
3415  if(brightness) {
3416  r = (r * brightness) >> 8;
3417  g = (g * brightness) >> 8;
3418  b = (b * brightness) >> 8;
3419  w = (w * brightness) >> 8;
3420  }
3421  uint8_t *p;
3422  if(aOffset[3] == aOffset[0]) {
3423  p = &pixels[n * 3];
3424  } else {
3425  p = &pixels[n * 4];
3426  p[aOffset[3]] = w;
3427  }
3428  p[aOffset[0]] = r;
3429  p[aOffset[1]] = g;
3430  p[aOffset[2]] = b;
3431  }
3432  }
3433  void NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
3434  if(n < numLEDs) {
3435  uint8_t *p,
3436  r = (uint8_t)(c >> 16),
3437  g = (uint8_t)(c >> 8),
3438  b = (uint8_t)c;
3439  if(brightness) {
3440  r = (r * brightness) >> 8;
3441  g = (g * brightness) >> 8;
3442  b = (b * brightness) >> 8;
3443  }
3444  if(aOffset[3] == aOffset[0]) {
3445  p = &pixels[n * 3];
3446  } else {
3447  p = &pixels[n * 4];
3448  uint8_t w = (uint8_t)(c >> 24);
3449  p[aOffset[3]] = brightness ? ((w * brightness) >> 8) : w;
3450  }
3451  p[aOffset[0]] = r;
3452  p[aOffset[1]] = g;
3453  p[aOffset[2]] = b;
3454  }
3455  }
3456  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
3457  return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
3458  }
3459  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
3460  return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
3461  }
3462  uint32_t NeoPixel::getPixelColor(uint16_t n) const {
3463  if(n >= numLEDs) return 0;
3464  uint8_t *p;
3465  if(aOffset[3] == aOffset[0]) {
3466  p = &pixels[n * 3];
3467  if(brightness) {
3468  return (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
3469  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
3470  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
3471  } else {
3472  return ((uint32_t)p[aOffset[0]] << 16) |
3473  ((uint32_t)p[aOffset[1]] << 8) |
3474  (uint32_t)p[aOffset[2]];
3475  }
3476  } else {
3477  p = &pixels[n * 4];
3478  if(brightness) {
3479  return (((uint32_t)(p[aOffset[3]] << 8) / brightness) << 24) |
3480  (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
3481  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
3482  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
3483  } else {
3484  return ((uint32_t)p[aOffset[3]] << 24) |
3485  ((uint32_t)p[aOffset[0]] << 16) |
3486  ((uint32_t)p[aOffset[1]] << 8) |
3487  (uint32_t)p[aOffset[2]];
3488  }
3489  }
3490  }
3491  uint8_t *NeoPixel::getPixels(void) const {
3492  return pixels;
3493  }
3494  uint16_t NeoPixel::numPixels(void) const {
3495  return numLEDs;
3496  }
3497  void NeoPixel::setBrightness(uint8_t b) {
3498  uint8_t newBrightness = b + 1;
3499  if(newBrightness != brightness) {
3500  uint8_t c,
3501  *ptr = pixels,
3502  oldBrightness = brightness - 1;
3503  uint16_t scale;
3504  if(oldBrightness == 0) scale = 0; // Avoid /0
3505  else if(b == 255) scale = 65535 / oldBrightness;
3506  else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
3507  for(uint16_t i=0; i<numBytes; i++) {
3508  c = *ptr;
3509  *ptr++ = (c * scale) >> 8;
3510  }
3511  brightness = newBrightness;
3512  }
3513  }
3514  uint8_t NeoPixel::getBrightness(void) const {
3515  return brightness - 1;
3516  }
3517  void NeoPixel::clear() {
3518  memset(pixels, 0, numBytes);
3519  }
3520  #endif
3521 
3522 
3523 
3524 
3525 
3526 
3527 
3528 
3529 
3530 
3531 
3532 
3533 
3534 
3535 
3536 
3537 #if EBOARD_NANO > 0x0 || defined(DOC)
3538 //offer more functions
3539  #if EBOARD_GUESSPATH > 0x0
3540  //import servo-class
3541 
3542  //shameless copy paste :D
3543  #define _useTimer1
3544  typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
3545  #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
3546  #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
3547  #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
3548  #define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
3549  #define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
3550  #define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
3551  #define INVALID_SERVO 255 // flag indicating an invalid servo index
3552  typedef struct {
3553  uint8_t nbr :6 ; // a pin number from 0 to 63
3554  uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
3555  } ServoPin_t;
3556  typedef struct {
3557  ServoPin_t Pin;
3558  volatile unsigned int ticks;
3559  } servo_t;
3560  class Servo {
3561  public:
3562  Servo();
3563  uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
3564  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
3565  void detach();
3566  void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
3567  void writeMicroseconds(int value); // Write pulse width in microseconds
3568  inline int read(); // returns current pulse width as an angle between 0 and 180 degrees
3569  int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
3570  inline bool attached(); // return true if this servo is attached, otherwise false
3571  private:
3572  uint8_t servoIndex; // index into the channel data for this servo
3573  int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
3574  int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
3575  };
3576  #define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
3577  #define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
3578  #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
3579  //#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
3580  static servo_t servos[MAX_SERVOS]; // static array of servo structures
3581  static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
3582  uint8_t ServoCount = 0; // the total number of attached servos
3583  // convenience macros
3584  #define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
3585  #define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
3586  #define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
3587  #define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
3588  #define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
3589  #define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
3590  static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
3591  {
3592  if( Channel[timer] < 0 )
3593  *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
3594  else{
3595  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
3596  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
3597  }
3598  Channel[timer]++; // increment to the next channel
3599  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
3600  *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
3601  if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
3602  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
3603  }
3604  else {
3605  // finished all channels so wait for the refresh period to expire before starting over
3606  if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
3607  *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
3608  else
3609  *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
3610  Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
3611  }
3612  }
3613  #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
3614  // Interrupt handlers for Arduino
3615  #if defined(_useTimer1)
3616  SIGNAL (TIMER1_COMPA_vect)
3617  {
3618  handle_interrupts(_timer1, &TCNT1, &OCR1A);
3619  }
3620  #endif
3621  #elif defined WIRING
3622  // Interrupt handlers for Wiring
3623  #if defined(_useTimer1)
3624  void Timer1Service()
3625  {
3626  handle_interrupts(_timer1, &TCNT1, &OCR1A);
3627  }
3628  #endif
3629  #endif
3630  static void initISR(timer16_Sequence_t timer) {
3631  if(timer == _timer1) {
3632  TCCR1A = 0; // normal counting mode
3633  TCCR1B = _BV(CS11); // set prescaler of 8
3634  TCNT1 = 0; // clear the timer count
3635  TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
3636  TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
3637  #if defined(WIRING)
3638  timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
3639  #endif
3640  }
3641  }
3642  static void finISR(timer16_Sequence_t timer) {
3643  #if defined WIRING // Wiring
3644  if(timer == _timer1) {
3645  TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
3646  timerDetach(TIMER1OUTCOMPAREA_INT);
3647  }
3648  else if(timer == _timer3) {
3649  ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
3650  timerDetach(TIMER3OUTCOMPAREA_INT);
3651  }
3652  #else
3653  //For arduino - in future: call here to a currently undefined function to reset the timer
3654  (void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning
3655  #endif
3656  }
3657  static boolean isTimerActive(timer16_Sequence_t timer) {
3658  // returns true if any servo is active on this timer
3659  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
3660  if(SERVO(timer,channel).Pin.isActive == true)
3661  return true;
3662  }
3663  return false;
3664  }
3665  Servo::Servo() {
3666  if( ServoCount < MAX_SERVOS) {
3667  this->servoIndex = ServoCount++; // assign a servo index to this instance
3668  servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
3669  }
3670  else
3671  this->servoIndex = INVALID_SERVO ; // too many servos
3672  }
3673  uint8_t Servo::attach(int pin) {
3674  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
3675  }
3676  uint8_t Servo::attach(int pin, int min, int max) {
3677  if(this->servoIndex < MAX_SERVOS ) {
3678  pinMode( pin, OUTPUT) ; // set servo pin to output
3679  servos[this->servoIndex].Pin.nbr = pin;
3680  // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
3681  this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
3682  this->max = (MAX_PULSE_WIDTH - max)/4;
3683  // initialize the timer if it has not already been initialized
3684  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
3685  if(isTimerActive(timer) == false)
3686  initISR(timer);
3687  servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
3688  }
3689  return this->servoIndex ;
3690  }
3691  void Servo::detach() {
3692  servos[this->servoIndex].Pin.isActive = false;
3693  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
3694  if(isTimerActive(timer) == false) {
3695  finISR(timer);
3696  }
3697  }
3698  void Servo::write(int value) {
3699  if(value < MIN_PULSE_WIDTH)
3700  { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
3701  if(value < 0) value = 0;
3702  if(value > 180) value = 180;
3703  value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
3704  }
3705  this->writeMicroseconds(value);
3706  }
3707  void Servo::writeMicroseconds(int value) {
3708  // calculate and store the values for the given channel
3709  byte channel = this->servoIndex;
3710  if( (channel < MAX_SERVOS) ) // ensure channel is valid
3711  {
3712  if( value < SERVO_MIN() ) // ensure pulse width is valid
3713  value = SERVO_MIN();
3714  else if( value > SERVO_MAX() )
3715  value = SERVO_MAX();
3716  value = value - TRIM_DURATION;
3717  value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
3718  uint8_t oldSREG = SREG;
3719  cli();
3720  servos[channel].ticks = value;
3721  SREG = oldSREG;
3722  }
3723  }
3724  inline int Servo::read() // return the value as degrees
3725  {
3726  return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
3727  }
3728  int Servo::readMicroseconds() {
3729  unsigned int pulsewidth;
3730  if( this->servoIndex != INVALID_SERVO )
3731  pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
3732  else
3733  pulsewidth = 0;
3734  return pulsewidth;
3735  }
3736  inline bool Servo::attached() {
3737  return servos[this->servoIndex].Pin.isActive ;
3738  }
3739 
3740  #endif
3741 #endif
3742 #if EBOARD_COPY_AND_PASTE > 0x0
3743  void trig_rept_task() {
3744  if (_pwmValue!=_OpwmValue){
3745  analogWrite(PIN_MOTOR_SPE,_pwmValue);
3747  }
3748  #ifdef REPT_TASK
3749  rept_task();
3750  #endif
3751  }
3752  #if EBOARD_NANO > 0x0
3753  Servo mainMotor,steerMotor;
3754  #endif
3755  int timer_count = 0;
3756  bool timer_ofl = false;
3757  ISR(TIMER2_OVF_vect) {
3758  timer_count++;
3759  if(timer_count >= EBOARD_PWM_SPE*1000 && !timer_ofl){
3760  timer_ofl = true;
3761  timer_count -= EBOARD_PWM_SPE*1000;
3762  trig_rept_task();
3763  timer_ofl = false;
3764  }
3765  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
3766  }
3767 
3768  extern int eVirtual_main();
3769 
3770 
3771  void setup(void);
3772 
3773  void setup(void) {
3774  //setup of RX and TX should be handled manually - in everyCase ^^
3775  #if EBOARD_NANO == 0x0
3778  #endif
3779  #if EBOARD_DEBUG_MODE > 0x0
3780  Serial.begin(EBOARD_DEBUG_SPEED);
3781  #endif
3782  //this will initialize the interrupt handling!
3783  #if (EBOARD_NANO == 0x0) || defined(REPT_TASK)
3784  cli();
3785  TIMSK2 &= ~(1<<TOIE2);
3786  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
3787  TCCR2B &= ~(1<<WGM22);
3788  ASSR &= ~(1<<AS2);
3789  TIMSK2 &= ~(1<<OCIE2A);
3790  TCCR2B |= (1<<CS22);
3791  TCCR2B &= ~((1<<CS21) | (1<<CS20));
3792  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
3793  TIMSK2 |= (1<<TOIE2);
3794  sei();
3795  #endif
3796  #if EBOARD_BLUETOOTH > 0x0
3797 
3798 
3799  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
3800  Serial1.begin(38400);
3801  #else
3802  _serial.begin(38400);
3803  #endif
3805  #endif
3806  #if EBOARD_I2C > 0x0
3807  Wire.begin();
3808  #endif
3809  #if EBOARD_SHIFT_REGISTER > 0x0
3810  pinMode(PIN_SHIFT_CLK,OUTPUT);
3811  pinMode(PIN_SHIFT_DAT,OUTPUT);
3812  pinMode(PIN_SHIFT_LAT,OUTPUT);
3813  shiftAll(); //set all to 0
3814  #endif
3815  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0)
3816  _servoHandler.begin(); //Setup SPI
3817  #endif
3818  #if EBOARD_NANO > 0x0
3819  mainMotor.attach(EBOARD_NANO_MAIN);
3820  steerMotor.attach(EBOARD_NANO_STEER);
3821  #if EBOARD_DEBUG_MODE > 0x0
3822  Serial.println("Initializing main driving motor (3s)");
3823  #endif
3824  mainMotor.write(90);
3825  delay(3005);
3826  #if EBOARD_DEBUG_MODE > 0x0
3827  Serial.println("Initializing of main driving motor completed");
3828  #endif
3829  #endif
3830  #if EBOARD_DEBUG_MODE > 0x0
3831  Serial.print((char) eVirtual_main());
3832  Serial.println("fin");
3833  #else
3834  eVirtual_main();
3835  #endif
3836  if (STOP) {} //prevent unused error
3837  delay(200);
3838  #if EBOARD_NANO > 0x0
3839  mainMotor.write(90);
3840  #endif
3841  cli(); //disable timers after running the program :D
3842  #if EBOARD_NANO == 0x0
3843  writePWM(0);analogWrite(PIN_MOTOR_SPE,0);
3844  #endif
3845  }
3846 
3847 
3848  void loop(void);
3849 
3850  void loop(void){
3851  //shall be empty
3852  }
3853 
3854 #endif
3855 #if EBOARD_NANO > 0x0 || defined(DOC)
3856 
3857  inline void set_motor_speed(optVAL_t spe);
3858 
3859  inline void set_steer_angle(optVAL_t ang);
3860 
3861  inline void set_motor_speed(optVAL_t spe){
3862  if(spe < 0 || spe > 180) return;
3863  mainMotor.write(spe);
3864  }
3865  inline void set_steer_angle(optVAL_t ang){
3866  if(ang < 0 || ang > 180) return;
3867  steerMotor.write(ang);
3868  }
3869 
3870 #endif
3871 #else
3872  #error This library is build for arduino-devices and should be used only in the Arduino IDE or with a similar linking process
3873 #endif
3874 #pragma GCC diagnostic pop
3875 #pragma pack(pop)
3876 #endif
int actPos
stores the actual pos or move-to pos of the AX12Servo
Definition: eBoard.h:3238
uint16_t _rx_delay_intrabit
the rx startbit delay
Definition: eBoard.h:1769
uint8_t * pixels
stores the pixels
Definition: eBoard.h:4549
void onRequest(void(*function)(void))
this will set the user_onRequest method
volatile uint8_t * port
the used port register
Definition: eBoard.h:4556
virtual size_t write(uint8_t data)
this will write a single unsigned 8-bit value to address
void recv(void)
private receive routine called each time interrupt handler gets triggered
#define LCD_COMMAND_DISPLAY_OFF
Definition: eBoard.h:3879
SoccerBoard(void)
The constructor.
void setTX(uint8_t transmitPin)
sets a specific pin to be &#39;the chosen one&#39; as a txPin
int8_t pin
stores the pin -1 if the pin wasn&#39;t set
Definition: eBoard.h:4545
optVAL_t readPin(optVAL_t idx, bool dig=true)
read a digital state from an INPUTpin
optVAL_t C
storing value for C-pin [MOTOR SPE]
Definition: eBoard.h:3085
void begin(long speed)
the start function to setup delay_values etc.
AX12Servo * connected[2]
stores the pointers to the registerd AX12Servo
Definition: eBoard.h:3328
#define LCD_COMMAND_CHARGE_PUMP_ENABLE
Definition: eBoard.h:3896
const unsigned char * buf[11]
to enable &#39;smooth&#39; access (:
uint8_t _transmitBitMask
the pin mask to address the tx pin
Definition: eBoard.h:1762
[COPY&PASTE] This is the SoccerBoard ghost struct :D
Definition: eBoard.h:2809
static void(* user_onReceive)(int numBytes)
twi slave [Rx]receive-event user def handler
Definition: eBoard.h:969
bool checkPin(optVAL_t idx, optVAL_t mode=0x1)
[COPY&PASTE] [CHECK_PINS] Check if a pin is set to a specific mode
#define PIN_MAX
Definition: eBoard.h:614
uint8_t aOffset[4]
stores the offsets in rgbw format
Definition: eBoard.h:4551
#define BUFFER_LENGTH
Definition: eBoard.h:925
#define LCD_COMMAND_MODE
Definition: eBoard.h:3875
#define EBOARD_CHECK_PINS
Definition: eBoard.h:1508
#define LCD_COMMAND_CHARGE_PUMP_SETTING
Definition: eBoard.h:3894
static volatile uint8_t _receive_buffer_head
current location in rxBuffer
Definition: eBoard.h:1784
void checkIdx(optVAL_t idx)
[DEBUG_MODE] used to check if a pin index is in bounds
SoftwareSerial _serial(0x13, 0x12)
this is the recomenned-to-use _serial object for bluetooth communcation :D
optVAL_t _OpwmValue
Definition: eBoard.h:2569
[COPY&PASTE] This is the AX12Servo ghost struct :D
Definition: eBoard.h:3130
static void detachInterrupt(void)
disables the interrupt feature
void write(void)
this will write values stored in B and C
static uint8_t rxBufferIndex
this defines the rxBuffer Index - current position in rxBuffer array
Definition: eBoard.h:948
bool canShow(void)
this will determine if the next show is available [last show finished]
void storePosition(int pos, int speed=0x3FF)
This saves the Servo Position.
int actSpe
stores the actual &#39;would use speed&#39; of the AX12Servo
Definition: eBoard.h:3240
optVAL_t getPosition(void)
This "kind of" returns the Servo-Position.
virtual size_t write(uint8_t byte)
writes a specific value to the tx register
optVAL_t B
storing value for B-pin [MOTOR DIR]
Definition: eBoard.h:3083
void setID(optVAL_t newID)
change the AX-12 Servo this object should speak to
#define PIN_MOTOR_SPE
Definition: eBoard.h:1691
uint8_t getBrightness(void) const
returns the current set brightness
[SPI] This is used to avoid path resolving issues and defines the common known Arduino SPI interface ...
Definition: eBoard.h:1357
void __assert(const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp)
[DEBUG_MODE] custom assert message
uint16_t numLEDs
stores the amount of LEDs
Definition: eBoard.h:4538
I2CInOut(SoccerBoard &, optVAL_t, optVAL_t, optVAL_t, optVAL_t)
The constructor.
void button(int)
šŸ”§ I prevent errors!
bool isListening(void)
checks if this object is the listening object
#define SPI_CLOCK_MASK
Definition: eBoard.h:1340
~NeoPixel(void)
the destructor [calling free on pixel and freeing input pin]
#define EBOARD_BLUETOOTH
Definition: eBoard.h:530
bool timer_ofl
Definition: eBoard.h:6436
byte pY
posY
Definition: eBoard.h:4125
static uint8_t txBufferIndex
this defines the txBuffer Index - current position in txBuffer array
Definition: eBoard.h:957
static void onRequestService(void)
twi slave [Tx]transmitting-event handler
uint16_t _rx_delay_stopbit
the rx stopbit dely
Definition: eBoard.h:1771
char channel(optVAL_t)
will return the next char received by the module. A 64 byte Serial buffer is included! ...
This is used to avoid path resolving issues and defines the common known Arduino Wire-Interface &#160;&#160;&#160;...
Definition: eBoard.h:943
int peek(void)
reads the actual pointed rxBuffer element without dropping it
void led(int idx, bool state)
[MEGA] Control the OnBoard LED
#define PIN_SHIFT_CLK
Definition: eBoard.h:1698
uint8_t rx_pin_read(void)
simple routine to read the rxPin by registers
bool begun
true if NeoPixel::begin has been called
Definition: eBoard.h:4536
static uint8_t transmitting
&#39;boolean&#39; value. Set to 1 if transmitting => in master write mode
Definition: eBoard.h:962
optVAL_t countSetBits(optVAL_t x)
[COPY&PASTE] [CHECK_PWM] counts high-bits in an int/byte (determined by IGNORE_SIZE) ...
RB14Scan(void)
The constructor.
void s2Cmd(optVAL_t o, optVAL_t t)
this function will execute two cmd sends without starting and without ending the transmission ...
void ledOff(int idx)
[MEGA] Deactivate the OnBoard LED
optVAL_t sendI2C(optVAL_t deviceID, byte *buf, byte buf_len)
Sends a buffer of bytes to a certain I²C-Device.
bool checkOverflow(void)
[BLUETOOTH] checks if theres a lack of Data!
void ledMeter(int)
[MEGA] Activate the OnBoard LED
void powerOn(optVAL_t id)
Set the state of a certain D-pin to HIGH.
#define LCD_HEIGHT
Definition: eBoard.h:3904
void changeModes(optVAL_t, optVAL_t, optVAL_t)
šŸ”§ I prevent errors!
static void end(void)
this will end the SPI connection
int8_t getPin(void)
this will return the set data pin
void reset(void)
Resets the Soccerboard if EBOARD_USE_RESET is set to true.
#define EBOARD_USE_UTILITY
Definition: eBoard.h:1567
bool _cI
called_guard
Definition: eBoard.h:4127
void trig_rept_task()
Definition: eBoard.h:6423
#define LCD_WIDTH
Definition: eBoard.h:3900
bool listen(void)
sets the SoftwareSerial object to be the listening one gaining control over the buffers etc...
bool reset(void)
clears the screen
bool isMoving(void)
Use this if you wan&#39;t to have a nice way of writing false.
#define LCD_DATA_MODE
Definition: eBoard.h:3877
void set_steer_angle(optVAL_t ang)
sets the angle of the steering (data pin: EBOARD_NANO_STEER) motor
void sleep(uint16_t t)
Say goodnight!
void setTorque(uint16_t)
šŸ”§ I prevent errors!
long store_bits
[SHIFT] Manipulate me to set Pins via bitSet operations
Definition: eBoard.h:2537
void setup(void)
this is a guard
void changeMode(bool newMode=true)
enable or disable the display
NeoPixel pixels
the NeoPixel-object we use
void ledOn(void)
Noone needs the AX-12 Servo LED^^.
static uint8_t rxBufferLength
this defines the length of rxBuffer
Definition: eBoard.h:950
static uint8_t txAddress
this defines the txAddress the transmitting Dta
Definition: eBoard.h:953
#define SPI_MODE_MASK
Definition: eBoard.h:1338
int storedPos
stores the position the Servo should go to DynamixelBoard::action()
Definition: eBoard.h:3224
void shiftSingle(optVAL_t idx, bool val)
[SHIFT] Changes a single output Pin
void set_motor_speed(optVAL_t spe)
sets the speed of the main (data pin: EBOARD_NANO_MAIN) motor
bool init(void)
initializes the Display called by:
void tx_pin_write(uint8_t pin_state)
writes a bool value on the txPin by registers
static uint8_t txBuffer[]
this defines the txBuffer used to enable delayed read
Definition: eBoard.h:955
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
sets the rgb color of a specific pixel
void changeAddress(optVAL_t)
šŸ”§ I prevent errors!
#define EBOARD_NANO_STEER
Definition: eBoard.h:1487
#define EBOARD_NEO_800KHZ
Definition: eBoard.h:4367
this namespace contains all the Don&#39;t use manually classes ;)
static void attachInterrupt(void)
enables the interrupt feature
SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic=false)
the constructor for the SoftwareSerial object
#define EBOARD_NANO_MAIN
Definition: eBoard.h:1493
virtual void flush(void)
resets the position in buffer and the buffer itself if the object is listening
#define EBOARD_SPI_SERVO_MAX
Definition: eBoard.h:1558
static char _receive_buffer[64]
the buffer for rxBuffer
Definition: eBoard.h:1780
#define PIN_BLUETOOTH_RX
Definition: eBoard.h:1663
PROGMEM const byte basicFont[][8]
Definition: eBoard.h:3514
static void begin(void)
this will setup everything for SPI connection
optVAL_t _pwmValue
Definition: eBoard.h:2569
optVAL_t id
stores the id of the AX12Servo obejct
Definition: eBoard.h:3235
void msleep(uint16_t t)
Say goodnight!
#define LCD_COMMAND_DISPLAY_ON
Definition: eBoard.h:3881
#define SPI_CLOCK_DIV8
Definition: eBoard.h:1324
uint64_t pin_in
Definition: eBoard.h:2418
int sine8(uint8_t val)
will return the mapped 8-bit sin you can use in e.g. NeoPixel
Definition: eBoard.h:563
byte pX
the addressing mode (page/horizontal)
Definition: eBoard.h:4123
DynamixelBoard(SoccerBoard &)
The constructor.
void updateLength(uint16_t n)
this changes the length of the connected LED stripe
ServoCds55 _servoHandler
this is the "to_use" instance of ServoCds55
Definition: eBoard.h:2780
#define EBOARD_CLAMP
Definition: eBoard.h:1613
void pingI2C(optVAL_t ret[], optVAL_t ret_len)
Sends a byte to a certain I²C-Device.
uint16_t numBytes
stores the byte size [pixels] used internally
Definition: eBoard.h:4540
void writeVal(const T &val)
[BLUETOOTH] writes Data to bluetooth
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b)
returns a color value that can be used with NeoPixel::setPixelColor()
void setPin(uint8_t p)
sets pin for communication
virtual int read(void)
this will read a single byte from rxBuffer and increment the Index
void clear(void)
this will reset all set pixels [won&#39;t call NeoPixel::show()]
bool setCursor(byte posX=0x0, byte posY=0x0)
set the position of the cursor
uint8_t * getPixels(void) const
this will give you access to the pixels
static bool STOP
Definition: eBoard.h:1448
~SoftwareSerial(void)
the destructor of the SoftwareSerial object
#define LCD_PAGE_ADDRESSING
Definition: eBoard.h:3889
#define EBOARD_NANO
Definition: eBoard.h:1479
LCD(SoccerBoard &soccerBoard, optVAL_t id=0x3C)
The constructor.
void waitForButton(int)
šŸ”§ I prevent errors!
#define EBOARD_PWM_SPE
Definition: eBoard.h:1583
#define EBOARD_CHECK_PINS_PWM
Definition: eBoard.h:1534
void motorsOff(void)
As requested this is the shortcut to disable the main motor.
int raw(optVAL_t)
this will check for connection status [will return true if pin not connected]
bool overflow(void)
returns the current overflow flag and disables it
static void setDataMode(uint8_t mode)
this will set the Data transfer mode
void updateType(uint16_t t)
this changes the type of communication between arduino and LED stripe
virtual int available(void)
checks if there is data to read available
uint64_t pin_out
Definition: eBoard.h:2410
#define LCD_COMMAND_WHITE_BACKGROUND
Definition: eBoard.h:3885
NeoPixel(void)
the empty constructor
[COPY&PASTE] [BLUETOOTH] This is the RB14Scan ghost struct :D
Definition: eBoard.h:3390
uint8_t requestFrom(uint8_t address, uint8_t quantity)
this will read a specific quantity of bytes from a specific address
void changeBackground(bool newBackground=false)
changes the background of the display
static void onReceiveService(uint8_t *inBytes, int numBytes)
twi slave [Rx]receive-event handler
void begin()
begin the TwoWire communcation without any data set
#define EBOARD_NEO
Definition: eBoard.h:546
optVAL_t ID
ID of the Display.
Definition: eBoard.h:4115
void motor(uint8_t id, int16_t val)
As requested this is the ultimate shortcut ;)
bool digital(optVAL_t id)
Reads a digital value from a pin.
#define PIN_SHIFT_LAT
Definition: eBoard.h:1710
static void handle_interrupt(void)
used to handle interrupts on active listening object
#define EBOARD_SHIFT_REGISTER
Definition: eBoard.h:526
int storedSpe
stores the Speed of the Servo DynamixelBoard::action()
Definition: eBoard.h:3230
[COPY&PASTE] This is the DynamixelBoard ghost struct :D
Definition: eBoard.h:3301
SPIClass SPI
Definition: eBoard.h:1432
TwoWire()
The constructor of the TwoWire class.
#define EBOARD_NEO_GRB
Definition: eBoard.h:4306
volatile uint8_t * _transmitPortRegister
the register the reveice pin is located on
Definition: eBoard.h:1764
static void setClockDivider(uint8_t rate)
this will change the clock devider the
void write(const char *const val)
this will write a constant string to the output
int timer_count
Definition: eBoard.h:6435
void beginTransmission(uint8_t address)
this will start a new transmission to a specific address => master mode
void power(optVAL_t id, bool state)
Set the state of a certain D-pin.
void writePin(optVAL_t idx, bool val)
write a boolean state to an output pin
void s1Dat(optVAL_t o)
this function will execute one dat send without starting and without ending the transmission ...
#define PIN_MOTOR_DIR
Definition: eBoard.h:1684
uint32_t endTime
stores the last call time of show for NeoPixel::canShow()
Definition: eBoard.h:4553
void changeId(optVAL_t)
šŸ”§ I prevent errors!
uint16_t _tx_delay
the (generic) tx delay
Definition: eBoard.h:1773
DynamixelBoard * _conBoard
Definition: eBoard.h:3144
virtual int peek(void)
this will read a single byte from rxBuffer without increment the Index
void setBrightness(uint8_t val)
changes the brightness for all further acceses via NeoPixel::setPixelColor()
void setSpeed(optVAL_t)
šŸ”§ I prevent errors!
void lightOn(void)
enable the backlight
[COPY&PASTE] This is the I2CInOut ghost struct :D
Definition: eBoard.h:3058
#define LCD_COMMAND_BLACK_BACKGROUND
Definition: eBoard.h:3883
void lightOff(void)
disable the backlight
void setRX(uint8_t receivePin)
sets a specific pin to be &#39;the chosen one&#39; as a rxPin
bool clear(void)
clears the LCD
bool s1Cmd(optVAL_t o)
this function will execute one cmd send without starting and without ending the transmission ...
#define PIN_BLUETOOTH_TX
Definition: eBoard.h:1674
void onReceive(void(*function)(int))
this will set the user_onReceive method
void writePWM(optVAL_t val)
write a clamped pwm value to an output pin
void setPin(optVAL_t idx, optVAL_t mode=0x1)
[COPY&PASTE] set a pin to a certain mode => checkPin() will return true then
uint8_t brightness
stores the brightness
Definition: eBoard.h:4547
uint8_t pinMask
the used pinMask
Definition: eBoard.h:4558
char readVal(char oF='.')
[BLUETOOTH] reads a single value from bluetooth if available!
void ledsOff(void)
[MEGA] Deactivate the OnBoard LED
static uint8_t txBufferLength
this defines the length of txBuffer
Definition: eBoard.h:959
static byte transfer(byte _data)
this will send a single bite via the SPI connection
void setPositionMode(void)
set the AX-12 Servo to positionMode
static void setBitOrder(uint8_t bitOrder)
this will set the BitOrder
int gamma8(uint8_t val)
will return the mapped 8-bit gamma correction you can use in e.g. NeoPixel
Definition: eBoard.h:571
void end(void)
ends communcation on the rx pin
void action(void)
will force every AX12Servo to drive to AX12Servo::storedPos with AX12Servo::storedSpeed ...
static SoftwareSerial * active_object
the active SoftwareSerial object to operate on
Definition: eBoard.h:1786
bool changeBrightness(byte val=0x64)
changes the brightness of the display
void read(void)
šŸ”§ I prevent errors!
optVAL_t analog(optVAL_t id)
Reads an analog value from a pin.
void readI2C(optVAL_t deviceID, optVAL_t ret[], optVAL_t ret_len, bool blocking=true)
Reads a special amount of bits from a certain I²C-Device.
void ledOn(int idx)
[MEGA] Activate the OnBoard LED
AX12Servo(void)
The constructor.
void ledOn(optVAL_t)
šŸ”§ I prevent errors!
bool changeID(optVAL_t newID=0x3C)
changes the address of the LCD display talked to
void setPosition(int pos, int speed=0x3FF)
This moves the Servo to the new position.
uint16_t _inverse_logic
determining if all pin reads etc whould be inverted (e.g. no pullup on rx);
Definition: eBoard.h:1778
DynamixelBoard dBoard(board)
the dBoard object
#define EBOARD_USE_RESET
Definition: eBoard.h:1637
bool is800KHz
determines the speed the communcation is working on
Definition: eBoard.h:4534
int optVAL_t
Definition: eBoard.h:1458
uint16_t _rx_delay_centering
the rx center delay
Definition: eBoard.h:1767
#define _SS_MAX_RX_BUFF
Definition: eBoard.h:1727
ISR(TIMER2_OVF_vect)
Definition: eBoard.h:6437
bool isConnected(void)
[BLUETOOTH] this will check if the HC-05 is paired
TwoWire Wire
this is the well-known Arduino Wire Interface, just a little bit &#39;modified&#39; ;P
Definition: eBoard.h:1296
static volatile uint8_t _receive_buffer_tail
size of rxBuffer
Definition: eBoard.h:1782
uint8_t endTransmission(void)
this will end the transmission and send the STOP-sequence
#define PIN_BLUETOOTH_STATE
Definition: eBoard.h:1652
#define EBOARD_DEBUG_MODE
Definition: eBoard.h:1465
void print(const char *data)
prints a string to the display
void setSpeedMode(void)
set the AX-12 Servo NOT to speedMode
int eVirtual_main()
[COPY&PASTE] Assures the existence of the "qfix-code-main-method"
virtual int available(void)
this will return the amount of rxBuffer left
uint8_t _receivePin
the id of the receive pin
Definition: eBoard.h:1756
#define SPI_2XCLOCK_MASK
Definition: eBoard.h:1342
void drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY)
draws a bitmap representet as an array of bytes
void shiftAll(void)
[SHIFT] Changes bits according to store_bits
void ledOff(void)
Noone needs the AX-12 Servo LED^^.
void powerOff(optVAL_t id)
Set the state of a certain D-pin to LOW.
uint16_t _buffer_overflow
determining if an _buffer_overflow occured
Definition: eBoard.h:1776
static void(* user_onRequest)(void)
twi slave [Tx]transmitting-event user def handler
Definition: eBoard.h:964
uint8_t _receiveBitMask
the pin mask to directly read from register (Rx)
Definition: eBoard.h:1758
virtual int read(void)
reads the actual pointed rxBuffer top element
static uint8_t rxBuffer[]
this defines the rxBuffer used to enable delayed read
Definition: eBoard.h:946
volatile uint8_t * _receivePortRegister
the register the reveice pin is located on
Definition: eBoard.h:1760
void begin(void)
this has to be called to start the communcation (you should call NeoPixel::setPin() before) ...
void loop(void)
[COPY&PASTE] As we have an Arduino we need a setup function ;)
[NEO] this allows you to access Adafruit LED-stripes
Definition: eBoard.h:4410
uint32_t getPixelColor(uint16_t n) const
returns the color of a specific pixel
void changeMotorID(optVAL_t)
šŸ”§ I prevent errors!
void show(void)
this will reveal the setPixels [via NeoPixel::setPixelColor() etc...]
uint16_t numPixels(void) const
returns the size of the LED stripe
void ledOff(optVAL_t)
šŸ”§ I prevent errors!
static void tunedDelay(uint16_t delay)
apply a specific delay to achieve higher precision
#define PIN_SHIFT_DAT
Definition: eBoard.h:1704
[I2C] [LCD] This is used to add support for OLED displays connected to the &#39;SoccerBoard&#39; ...
Definition: eBoard.h:3947
void changeMotorID(optVAL_t newID)
change the hardwareID of this AX-12 Servo and will continue speaking to the new [reconnection recomme...
#define EBOARD_DEBUG_SPEED
Definition: eBoard.h:1547
optVAL_t A
storing value for A-pin (šŸ”§ I prevent errors!)
Definition: eBoard.h:3080
This is used to avoid path resolving issues and defines the common known Arduino SoftwareSerial inter...
Definition: eBoard.h:1753