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