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