eBoard šŸ‰  ā‘ ā‘§ā‘Ø
Written for SIA 2017/2018
eBoard.h
Go to the documentation of this file.
1 
7  #pragma GCC diagnostic push
8  #pragma GCC diagnostic ignored "-Wall"
9  #pragma GCC diagnostic ignored "-Wextra"
10  #pragma pack(push)
11  #pragma pack(16)
12 
14  #define EBOARD_VERSION "3.1m"
15  #define VALUE_TO_STRING(x) #x
17 #ifdef DOC
19 #define PREPROCESS_DEBUG 1
21 #endif
22  #define VALUE(x) VALUE_TO_STRING(x)
24  #ifndef PREPROCESS_DEBUG
26  #define PREPROCESS_DEBUG 0
27  #endif
28  #define PPERFORM_PRAGMA(str) _Pragma(#str)
30  #if PREPROCESS_DEBUG == 1
31  #define DEBUG_MSG(str) PPERFORM_PRAGMA(message ("" #str))
32 
33  #define MACRO_MSG(mac,str) PPERFORM_PRAGMA(message("You set " #mac " to " VALUE(mac) ": " #str))
34  #else
35  #define DEBUG_MSG(str) ;
36  #define MACRO_MSG(mac,str) ;
37  #endif
38  DEBUG_MSG("If you do not want any preprocessing information from this eBoard-Header set PREPROCESS_DEBUG to 0");
40  DEBUG_MSG("You are using eBoard-header v3.1m written by EagleoutIce");
41 
481 //i am a guard... leave me alone :D
482 #ifndef EBOARD_HEADER_GUARD
483  #define EBOARD_HEADER_GUARD
484 
485  #ifdef DOC
486  DEBUG_MSG("Documentation macro SET => Full doc features enabled");
487  #define ARDUINO 200
488 
491  #define EBOARD_I2C 0x1
492 
496  #define EBOARD_LCD 0x1
497 
500  #define EBOARD_SHIFT_REGISTER 0x1
501 
504  #define EBOARD_BLUETOOTH 0x1
505 
508  #define REPT_TASK
509 
512  #define __AVR_ATmega2560__
513 
516  #define __AVR_ATmega328P__
517 
520  #define EBOARD_NEO 0x1
521 
527  #define HIGHSPEED
528  #define __AVR__
530  #endif
531 
532  #include <avr/pgmspace.h>
537  namespace eagle_impl {}
538  using namespace eagle_impl;
539  #ifndef EBOARD_GUESSPATH
540  DEBUG_MSG("You are using Guesspath! Necessary libraries for eBoard will be included automatically");
544  #define EBOARD_GUESSPATH 0x1
545  #else
546  DEBUG_MSG("You are not using Guesspath! Necessary libraries for eBoard have to be included manually");
547  #endif
548 
549  #if defined(ARDUINO) //general platform-check [No tab]
550 
554  #define main eVirtual_main //main has a different meaning^^
555 
556  #if ARDUINO >= 100 //this could be only Arduino.h but this snippet is portable :D
557  #include "Arduino.h"
558  #else
559  #include <wiring.h>
560  #endif
561 
562  #if not ( defined(__AVR_ATmega2560__) || defined(__AVR_ATmega328P__))
563  #error "This library was build for ARDUINO UNO R3 Aand ARDUINO MEGA 2560!"
564  #endif
565 
566  #if defined(__AVR_ATmega2560__)
567  DEBUG_MSG("Building for Arduino Mega with ATmega2560");
571  #define PIN_MAX 0x32 //53 pins to address - 4 !!53 is SS
572  #else
573  DEBUG_MSG("Building for Arduino Uno or Nano with ATmega328P");
574  #define PIN_MAX 0xA // 13 Pins to address - 4 !!10 is SS
575  #endif
576 
577  #include <avr/io.h>
578  #include <avr/interrupt.h>
579 
580  #if EBOARD_I2C > 0x0 && EBOARD_GUESSPATH > 0x0
581  DEBUG_MSG("You enabled I²C feature"s);
583  #define twi_h
584 
585  //#define ATMEGA8
586 
587  #ifndef TWI_FREQ
588  #define TWI_FREQ 100000L
589  #endif
590 
591  # ifndef TWI_BUFFER_LENGTH
592  #define TWI_BUFFER_LENGTH 32
593  #endif
594 
595  #define TWI_READY 0
596  #define TWI_MRX 1
597  #define TWI_MTX 2
598  #define TWI_SRX 3
599  #define TWI_STX 4
600 
601  //#include <inttypes.h>
602  //#include <avr/io.h>
603  #include <avr/interrupt.h>
604  #include <compat/twi.h>
605 
606  #ifndef cbi
607  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
608  #endif
609 
610  #ifndef sbi
611  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
612  #endif
613 
614  #include "pins_arduino.h"
615 
616  static volatile uint8_t twi_state;
617  static volatile uint8_t twi_slarw;
618  static volatile uint8_t twi_sendStop;
619  static volatile uint8_t twi_inRepStart;
620 
621  static void (*twi_onSlaveTransmit)(void);
622  static void (*twi_onSlaveReceive)(uint8_t*, int);
623 
624  static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
625  static volatile uint8_t twi_masterBufferIndex;
626  static volatile uint8_t twi_masterBufferLength;
627 
628  static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
629  static volatile uint8_t twi_txBufferIndex;
630  static volatile uint8_t twi_txBufferLength;
631 
632  static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
633  static volatile uint8_t twi_rxBufferIndex;
634 
635  static volatile uint8_t twi_error;
636 
637  void twi_init(void) {
638  twi_state = TWI_READY;
639  twi_sendStop = true;
640  twi_inRepStart = false;
641 
642  digitalWrite(SDA, 1);
643  digitalWrite(SCL, 1);
644 
645  cbi(TWSR, TWPS0);
646  cbi(TWSR, TWPS1);
647  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
648 
649  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
650  }
651 
652  inline void twi_setAddress(uint8_t address) {
653  TWAR = address << 1;
654  }
655 
656  uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) {
657  uint8_t i;
658 
659  if(TWI_BUFFER_LENGTH < length) return 0;
660 
661  while(TWI_READY != twi_state) continue;
662 
663  twi_state = TWI_MRX;
664  twi_sendStop = sendStop;
665 
666  twi_error = 0xFF;
667 
668  twi_masterBufferIndex = 0;
669  twi_masterBufferLength = length-1;
670  twi_slarw = TW_READ;
671  twi_slarw |= address << 1;
672 
673  if (true == twi_inRepStart) {
674  twi_inRepStart = false;
675  TWDR = twi_slarw;
676  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
677  }
678  else
679  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
680 
681  while(TWI_MRX == twi_state) continue;
682 
683  if (twi_masterBufferIndex < length)
684  length = twi_masterBufferIndex;
685 
686  for(i = 0; i < length; ++i) data[i] = twi_masterBuffer[i];
687 
688  return length;
689  }
690 
691  uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) {
692  uint8_t i;
693 
694  if(TWI_BUFFER_LENGTH < length) return 1;
695 
696  while(TWI_READY != twi_state) continue;
697 
698  twi_state = TWI_MTX;
699  twi_sendStop = sendStop;
700  twi_error = 0xFF;
701 
702  twi_masterBufferIndex = 0;
703  twi_masterBufferLength = length;
704 
705  for(i = 0; i < length; ++i) twi_masterBuffer[i] = data[i];
706 
707  twi_slarw = TW_WRITE;
708  twi_slarw |= address << 1;
709 
710  if (true == twi_inRepStart) {
711  twi_inRepStart = false;
712  TWDR = twi_slarw;
713  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
714  }
715  else
716  TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
717 
718  while(wait && (TWI_MTX == twi_state)) continue;
719 
720  if (twi_error == 0xFF) return 0;
721  else if (twi_error == TW_MT_SLA_NACK) return 2;
722  else if (twi_error == TW_MT_DATA_NACK) return 3;
723  else return 4;
724  }
725 
726  uint8_t twi_transmit(const uint8_t* data, uint8_t length) {
727  uint8_t i;
728 
729  if(TWI_BUFFER_LENGTH < length) return 1;
730 
731  if(TWI_STX != twi_state) return 2;
732 
733  twi_txBufferLength = length;
734  for(i = 0; i < length; ++i) twi_txBuffer[i] = data[i];
735 
736  return 0;
737  }
738 
739  void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) {
740  twi_onSlaveReceive = function;
741  }
742 
743  void twi_attachSlaveTxEvent( void (*function)(void) ) {
744  twi_onSlaveTransmit = function;
745  }
746 
747  void twi_reply(uint8_t ack) {
748  if(ack){
749  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
750  }else{
751  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
752  }
753  }
754 
755 
756  void twi_stop(void) {
757  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
758 
759  while(TWCR & _BV(TWSTO)) continue;
760 
761  twi_state = TWI_READY;
762  }
763 
764  void twi_releaseBus(void){
765  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
766  twi_state = TWI_READY;
767  }
768 
769  ISR(TWI_vect) {
770  switch(TW_STATUS){
771  case TW_START:
772  case TW_REP_START:
773  TWDR = twi_slarw;
774  twi_reply(1);
775  break;
776 
777  case TW_MT_SLA_ACK:
778  case TW_MT_DATA_ACK:
779  if(twi_masterBufferIndex < twi_masterBufferLength){
780  TWDR = twi_masterBuffer[twi_masterBufferIndex++];
781  twi_reply(1);
782  }else{
783  if (twi_sendStop) twi_stop();
784  else {
785  twi_inRepStart = true;
786  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
787  twi_state = TWI_READY;
788  }
789  }
790  break;
791  case TW_MT_SLA_NACK:
792  twi_error = TW_MT_SLA_NACK;
793  twi_stop();
794  break;
795  case TW_MT_DATA_NACK:
796  twi_error = TW_MT_DATA_NACK;
797  twi_stop();
798  break;
799  case TW_MT_ARB_LOST:
800  twi_error = TW_MT_ARB_LOST;
801  twi_releaseBus();
802  break;
803  case TW_MR_DATA_ACK:
804  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
805  case TW_MR_SLA_ACK:
806  if(twi_masterBufferIndex < twi_masterBufferLength) twi_reply(1);
807  else twi_reply(0);
808  break;
809  case TW_MR_DATA_NACK:
810  twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
811  if (twi_sendStop) twi_stop();
812  else {
813  twi_inRepStart = true;
814  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
815  twi_state = TWI_READY;
816  }
817  break;
818  case TW_MR_SLA_NACK:
819  twi_stop();
820  break;
821  case TW_SR_SLA_ACK:
822  case TW_SR_GCALL_ACK:
823  case TW_SR_ARB_LOST_SLA_ACK:
824  case TW_SR_ARB_LOST_GCALL_ACK:
825  twi_state = TWI_SRX;
826  twi_rxBufferIndex = 0;
827  twi_reply(1);
828  break;
829  case TW_SR_DATA_ACK:
830  case TW_SR_GCALL_DATA_ACK:
831  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){
832  twi_rxBuffer[twi_rxBufferIndex++] = TWDR;
833  twi_reply(1);
834  } else twi_reply(0);
835 
836  break;
837  case TW_SR_STOP:
838  if(twi_rxBufferIndex < TWI_BUFFER_LENGTH) twi_rxBuffer[twi_rxBufferIndex] = '\0';
839  twi_stop();
840  twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
841  twi_rxBufferIndex = 0;
842  twi_releaseBus();
843  break;
844  case TW_SR_DATA_NACK:
845  case TW_SR_GCALL_DATA_NACK:
846  twi_reply(0);
847  break;
848  case TW_ST_SLA_ACK:
849  case TW_ST_ARB_LOST_SLA_ACK:
850  twi_state = TWI_STX;
851  twi_txBufferIndex = 0;
852  twi_txBufferLength = 0;
853  twi_onSlaveTransmit();
854  if(0 == twi_txBufferLength){
855  twi_txBufferLength = 1;
856  twi_txBuffer[0] = 0x00;
857  }
858  case TW_ST_DATA_ACK:
859  TWDR = twi_txBuffer[twi_txBufferIndex++];
860  if(twi_txBufferIndex < twi_txBufferLength) twi_reply(1);
861  else twi_reply(0);
862  break;
863  case TW_ST_DATA_NACK:
864  case TW_ST_LAST_DATA:
865  twi_reply(1);
866  twi_state = TWI_READY;
867  break;
868 
869  case TW_NO_INFO:
870  break;
871  case TW_BUS_ERROR:
872  twi_error = TW_BUS_ERROR;
873  twi_stop();
874  break;
875  }
876  }
878 
879  #include <inttypes.h>
880  #include "Stream.h"
881 
882  #define BUFFER_LENGTH 32
883  namespace eagle_impl {
900  class TwoWire : public Stream {
901  private:
903  static uint8_t rxBuffer[];
905  static uint8_t rxBufferIndex;
907  static uint8_t rxBufferLength;
908 
910  static uint8_t txAddress;
912  static uint8_t txBuffer[];
914  static uint8_t txBufferIndex;
916  static uint8_t txBufferLength;
917 
919  static uint8_t transmitting;
921  static void (*user_onRequest)(void);
926  static void (*user_onReceive)(int numBytes);
928  static void onRequestService(void);
934  static void onReceiveService(uint8_t* inBytes, int numBytes);
935 
936  public:
938  TwoWire();
940  void begin();
945  void begin(uint8_t address);
951  inline void begin(int address);
956  void beginTransmission(uint8_t address);
962  inline void beginTransmission(int address);
973  inline uint8_t endTransmission(void);
984  uint8_t endTransmission(uint8_t sendStop);
992  inline uint8_t requestFrom(uint8_t address, uint8_t quantity);
1000  uint8_t requestFrom(uint8_t address , uint8_t quantity, uint8_t sendStop);
1008  inline uint8_t requestFrom(int address, int quantity);
1017  inline uint8_t requestFrom(int address, int quantity, int sendStop);
1026  virtual size_t write(uint8_t data);
1034  virtual size_t write(const uint8_t *data, size_t quantity);
1039  virtual int available(void);
1045  virtual int read(void);
1051  virtual int peek(void);
1058  void onReceive( void (*function)(int) );
1065  void onRequest( void (*function)(void) );
1066 
1067  /* Removed due to: not needed
1068  inline size_t write(unsigned long n) { return write((uint8_t)n); }
1069  inline size_t write(long n) { return write((uint8_t)n); }
1070  inline size_t write(unsigned int n) { return write((uint8_t)n); }
1071  inline size_t write(int n) { return write((uint8_t)n); }
1072  */
1073  using Print::write;
1074  };
1075  }
1076  extern "C" {
1077  #include <stdlib.h>
1078  #include <string.h>
1079  #include <inttypes.h>
1080  //#include "twi.h"
1081  }
1082 
1085  uint8_t TwoWire::rxBufferIndex = 0;
1086  uint8_t TwoWire::rxBufferLength = 0;
1087 
1088  uint8_t TwoWire::txAddress = 0;
1090  uint8_t TwoWire::txBufferIndex = 0;
1091  uint8_t TwoWire::txBufferLength = 0;
1092 
1093  uint8_t TwoWire::transmitting = 0;
1094  void (*TwoWire::user_onRequest)(void);
1095  void (*TwoWire::user_onReceive)(int);
1096 
1097  TwoWire::TwoWire() {}
1098 
1099  void TwoWire::begin(void) {
1100  rxBufferIndex = 0;
1101  rxBufferLength = 0;
1102 
1103  txBufferIndex = 0;
1104  txBufferLength = 0;
1105 
1106  twi_init();
1107  }
1108 
1109  void TwoWire::begin(uint8_t address) {
1110  twi_setAddress(address);
1111  twi_attachSlaveTxEvent(onRequestService);
1112  twi_attachSlaveRxEvent(onReceiveService);
1113  begin();
1114  }
1115 
1116  void TwoWire::begin(int address) {
1117  begin((uint8_t)address);
1118  }
1119 
1120  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) {
1121  if(quantity > BUFFER_LENGTH){
1122  quantity = BUFFER_LENGTH;
1123  }
1124  uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
1125  rxBufferIndex = 0;
1126  rxBufferLength = read;
1127 
1128  return read;
1129  }
1130 
1131  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) {
1132  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
1133  }
1134 
1135  uint8_t TwoWire::requestFrom(int address, int quantity) {
1136  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
1137  }
1138 
1139  uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) {
1140  return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
1141  }
1142 
1143  void TwoWire::beginTransmission(uint8_t address) {
1144  transmitting = 1;
1145  txAddress = address;
1146  txBufferIndex = 0;
1147  txBufferLength = 0;
1148  }
1149 
1150  void TwoWire::beginTransmission(int address) {
1151  beginTransmission((uint8_t)address);
1152  }
1153 
1154  uint8_t TwoWire::endTransmission(uint8_t sendStop) {
1155  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
1156  txBufferIndex = 0;
1157  txBufferLength = 0;
1158  transmitting = 0;
1159  return ret;
1160  }
1161 
1162  uint8_t TwoWire::endTransmission(void){
1163  return endTransmission(true);
1164  }
1165 
1166  size_t TwoWire::write(uint8_t data) {
1167  if(transmitting) {
1168  if(txBufferLength >= BUFFER_LENGTH) {
1169  setWriteError();
1170  return 0;
1171  }
1172  txBuffer[txBufferIndex] = data;
1173  ++txBufferIndex;
1175  }else{
1176  twi_transmit(&data, 1);
1177  }
1178  return 1;
1179  }
1180 
1181  size_t TwoWire::write(const uint8_t *data, size_t quantity) {
1182  if(transmitting){
1183  for(size_t i = 0; i < quantity; ++i) {
1184  write(data[i]);
1185  }
1186  }else{
1187  twi_transmit(data, quantity);
1188  }
1189  return quantity;
1190  }
1191 
1192  int TwoWire::available(void) {
1193  return rxBufferLength - rxBufferIndex;
1194  }
1195 
1196  int TwoWire::read(void) {
1197  int8_t value = -1;
1198 
1200  value = rxBuffer[rxBufferIndex];
1201  ++rxBufferIndex;
1202  }
1203 
1204  return value;
1205  }
1206 
1207  int TwoWire::peek(void) {
1208  int value = -1;
1209 
1211  value = rxBuffer[rxBufferIndex];
1212  }
1213 
1214  return value;
1215  }
1216 
1217  void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) {
1218  if(!user_onReceive){
1219  return;
1220  }
1221 
1223  return;
1224  }
1225 
1226  for(uint8_t i = 0; i < numBytes; ++i) {
1227  rxBuffer[i] = inBytes[i];
1228  }
1229  rxBufferIndex = 0;
1230  rxBufferLength = numBytes;
1231  user_onReceive(numBytes);
1232  }
1233 
1234  void TwoWire::onRequestService(void) {
1235  if(!user_onRequest) return;
1236 
1237  txBufferIndex = 0;
1238  txBufferLength = 0;
1239  user_onRequest();
1240  }
1241 
1242  void TwoWire::onReceive( void (*function)(int) ) {
1243  user_onReceive = function;
1244  }
1245 
1246  void TwoWire::onRequest( void (*function)(void) ) {
1247  user_onRequest = function;
1248  }
1249 
1251 
1254 
1255  #else
1256  DEBUG_MSG("You disabled I²C");
1257  #endif
1258 
1261  #ifndef EBOARD_USE_SPI
1262  #define EBOARD_USE_SPI 0x1
1263  #endif
1264  #if EBOARD_USE_SPI > 0x0
1265  DEBUG_MSG("You enabled SPI");
1267  #define _SPI_H_INCLUDED
1268 
1269  #include <stdio.h>
1271  #define SPI_CLOCK_DIV4 0x00
1272  #define SPI_CLOCK_DIV16 0x01
1274  #define SPI_CLOCK_DIV64 0x02
1276  #define SPI_CLOCK_DIV128 0x03
1278  #define SPI_CLOCK_DIV2 0x04
1280  #define SPI_CLOCK_DIV8 0x05
1282  #define SPI_CLOCK_DIV32 0x06
1284 
1286  #define SPI_MODE0 0x00
1287  #define SPI_MODE1 0x04
1289  #define SPI_MODE2 0x08
1291  #define SPI_MODE3 0x0C
1293 
1295  #define SPI_MODE_MASK 0x0C
1296  #define SPI_CLOCK_MASK 0x03
1298  #define SPI_2XCLOCK_MASK 0x01
1300  namespace eagle_impl {
1314  struct SPIClass {
1320  inline static byte transfer(byte _data);
1324  inline static void attachInterrupt(void);
1328  inline static void detachInterrupt(void); // Default
1332  static void begin(void); // Default
1336  inline static void end(void);
1341  inline static void setBitOrder(uint8_t bitOrder);
1346  inline static void setDataMode(uint8_t mode);
1351  inline static void setClockDivider(uint8_t rate);
1352  };
1353  }
1355  byte SPIClass::transfer(byte _data) {
1356  SPDR = _data;
1357  while (!(SPSR & _BV(SPIF)));
1358  return SPDR;
1359  }
1360 
1361  void SPIClass::attachInterrupt() { SPCR |= _BV(SPIE);}
1362 
1363  void SPIClass::detachInterrupt() { SPCR &= ~_BV(SPIE);}
1364 
1365  void SPIClass::begin() {
1366  digitalWrite(SS, HIGH);
1367  pinMode(SS, OUTPUT); //doesn't block common use as_ OUTPUT!
1368  SPCR |= _BV(MSTR);
1369  SPCR |= _BV(SPE);
1370  pinMode(SCK, OUTPUT);
1371  pinMode(MOSI, OUTPUT);
1372  }
1373 
1374  void SPIClass::end() {SPCR &= ~_BV(SPE);}
1375 
1376  void SPIClass::setBitOrder(uint8_t bitOrder) {
1377  if(bitOrder == LSBFIRST) SPCR |= _BV(DORD);
1378  else SPCR &= ~(_BV(DORD));
1379  }
1380 
1381  void SPIClass::setDataMode(uint8_t mode) { SPCR = (SPCR & ~SPI_MODE_MASK) | mode; }
1382 
1383  void SPIClass::setClockDivider(uint8_t rate) {
1384  SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
1385  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
1386  }
1388 
1390 
1391  #else
1392  DEBUG_MSG("You disabled SPI");
1393  #endif
1394 
1395  #if (EBOARD_I2C > 0x0) && (EBOARD_LCD > 0x0)
1396  #include <avr/pgmspace.h>
1397  DEBUG_MSG("You enabled LCD");
1398  #endif
1399 
1405  static bool STOP = false;
1406 
1410  #ifdef IGNORE_SIZE
1411  DEBUG_MSG("You defined IGNORE_SIZE: byte will be used");
1412  typedef byte optVAL_t;
1413  #else
1414  DEBUG_MSG("You did not define IGNORE_SIZE: int will be used");
1415  typedef int optVAL_t;
1416  #endif
1417 
1421  #ifndef EBOARD_DEBUG_MODE
1422  #define EBOARD_DEBUG_MODE 0x1
1423  #endif
1424 
1425  #if EBOARD_DEBUG_MODE > 0x0
1426  MACRO_MSG(EBOARD_DEBUG_MODE,"Serial feedback will be send to Computer");
1427  #else
1428  MACRO_MSG(EBOARD_DEBUG_MODE, "No Serial feedback!");
1429  #endif
1430 
1431 
1435  #ifndef EBOARD_NANO
1436  #define EBOARD_NANO 0x0
1437  #endif
1438 
1439  #if EBOARD_NANO > 0x0 || defined(DOC)
1440  #ifndef EBOARD_NANO_STEER
1441 
1444  #define EBOARD_NANO_STEER 12
1445  #endif
1446  #ifndef EBOARD_NANO_MAIN
1447 
1450  #define EBOARD_NANO_MAIN 13
1451  #endif
1452  MACRO_MSG(EBOARD_NANO,"Using Arduino NANO environment [e.g. remove SoccerBoard]");
1453  #if PREPROCESS_DEBUG > 0x1
1454  #pragma message("Using " VALUE(EBOARD_NANO_STEER) " as data pin for STEERING MOTOR")
1455  #pragma message("Using " VALUE(EBOARD_NANO_MAIN) " as data pin for MAIN (Driving) MOTOR")
1456  #endif
1457  #else
1458  MACRO_MSG(EBOARD_NANO,"Using Arduino UNO/MEGA environment");
1459  #endif
1460 
1464  #ifndef EBOARD_CHECK_PINS
1465  #define EBOARD_CHECK_PINS 0x1
1466  #endif
1467 
1468  #if EBOARD_CHECK_PINS > 0x0
1469  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins enabled");
1470  #else
1471  MACRO_MSG(EBOARD_CHECK_PINS,"Check for Pins disabled");
1472  #endif
1473 
1474  #ifndef EBOARD_SHIFT_REGISTER
1475 
1478  #define EBOARD_SHIFT_REGISTER 0x0
1479  #endif
1480 
1481  #if EBOARD_SHIFT_REGISTER > 0x0
1482  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister enabled");
1483  #else
1484  MACRO_MSG(EBOARD_SHIFT_REGISTER,"Shiftregister disabled");
1485  #endif
1486 
1490  #ifndef EBOARD_CHECK_PINS_PWM
1491  #define EBOARD_CHECK_PINS_PWM 0x1
1492  #endif
1493 
1494  #if EBOARD_CHECK_PINS_PWM > 0x0
1495  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins enabled");
1496  #else
1497  MACRO_MSG(EBOARD_CHECK_PINS_PWM,"Check for PWM-Pins disabled");
1498  #endif
1499 
1503  #ifndef EBOARD_DEBUG_SPEED
1504  #define EBOARD_DEBUG_SPEED 9600
1505  #endif
1506  #if PREPROCESS_DEBUG > 0x0
1507  #pragma message("Set Debugging speed to " VALUE(EBOARD_DEBUG_SPEED))
1508  #endif
1509 
1510 
1514  #ifndef EBOARD_SPI_SERVO_MAX
1515  #define EBOARD_SPI_SERVO_MAX 2
1516  #endif
1517  #if PREPROCESS_DEBUG > 0x0
1518  #pragma message("Set amount of used Servos to " VALUE(EBOARD_SPI_SERVO_MAX))
1519  #endif
1520 
1523  #ifndef EBOARD_USE_UTILITY
1524  #define EBOARD_USE_UTILITY 0x1
1525  #endif
1526  #if EBOARD_USE_UTILITY > 0x0
1527  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will be implemented");
1528  #else
1529  MACRO_MSG(EBOARD_USE_UTILITY,"Utility features will not be implemented");
1530  #endif
1531 
1535  #define EBOARD_COPY_AND_PASTE 0x1
1536 
1539  #ifndef EBOARD_PWM_SPE
1540  #define EBOARD_PWM_SPE 1
1541  #endif
1542  #if PREPROCESS_DEBUG > 0x0
1543  #pragma message("Set PWM interval to " VALUE(EBOARD_PWM_SPE) "s")
1544  #endif
1545 
1546  #ifndef EBOARD_I2C
1547 
1550  #define EBOARD_I2C 0x0 //disabled by default
1551  #endif
1552 
1553  #ifndef EBOARD_BLUETOOTH
1554 
1557  #define EBOARD_BLUETOOTH 0x0
1558  #endif
1559 
1560  #if EBOARD_BLUETOOTH > 0x0
1561  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls enabled");
1562  #else
1563  MACRO_MSG(EBOARD_BLUETOOTH,"Bluetooth controls disabled");
1564  #endif
1565 
1569  #ifndef EBOARD_CLAMP
1570  #define EBOARD_CLAMP 0x1
1571  #endif
1572  #if EBOARD_CLAMP > 0x0
1573  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [0;1023]");
1574  #else
1575  MACRO_MSG(EBOARD_CLAMP,"Motor Range is set to [-300;300]");
1576  #endif
1577 
1578  #ifndef EBOARD_NEO
1579 
1582  #define EBOARD_NEO 0x0
1583  #endif
1584  #if EBOARD_NEO > 0x0
1585  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support enabled");
1586  #else
1587  MACRO_MSG(EBOARD_NEO,"Adafruit Neo-Pixel support disabled");
1588  #endif
1589 
1593  #ifndef EBOARD_USE_RESET
1594  #define EBOARD_USE_RESET 0x1
1595  #endif
1596 
1597  #if EBOARD_USE_RESET > 0x0
1598  #include <avr/wdt.h>
1599  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is available" );
1600  #else
1601  MACRO_MSG(EBOARD_USE_RESET,"Software-Reset is not available" );
1602  #endif
1603 
1607  #ifndef PIN_BLUETOOTH_STATE
1608  #if defined(__AVR_ATmega2560__)
1609  #define PIN_BLUETOOTH_STATE 0x13 // 19
1610  #else
1611  #define PIN_BLUETOOTH_STATE 0x2
1612  #endif
1613  #endif
1614 
1618  #ifndef PIN_BLUETOOTH_RX
1619  #if defined(__AVR_ATmega2560__)
1620  #define PIN_BLUETOOTH_RX 0x13 // 19
1621  #else
1622  #define PIN_BLUETOOTH_RX 0x2
1623  #endif
1624  #endif
1625 
1629  #ifndef PIN_BLUETOOTH_TX
1630  #if defined(__AVR_ATmega2560__)
1631  #define PIN_BLUETOOTH_TX 0x12 // 18
1632  #else
1633  #define PIN_BLUETOOTH_TX 0x3
1634  #endif
1635  #endif
1636 
1640  #ifndef PIN_MOTOR_DIR
1641  #define PIN_MOTOR_DIR 0x4
1642  #endif
1643 
1647  #ifndef PIN_MOTOR_SPE
1648  #define PIN_MOTOR_SPE 0x5
1649  #endif
1650 
1654  #ifndef PIN_SHIFT_CLK
1655  #define PIN_SHIFT_CLK 0x6
1656  #endif
1657 
1660  #ifndef PIN_SHIFT_DAT
1661  #define PIN_SHIFT_DAT 0x7
1662  #endif
1663 
1666  #ifndef PIN_SHIFT_LAT
1667  #define PIN_SHIFT_LAT 0x8
1668  #endif
1669 
1670 
1671  //done by arduino
1672  //if this has an effect... something went wrong :D
1673  #ifndef HIGH
1674  #define HIGH 1
1675  #endif
1676  #ifndef LOW
1677  #define LOW 0
1678  #endif
1679 
1680  #if (EBOARD_BLUETOOTH > 0x0) && defined(__AVR_ATmega328P__)
1681  #if EBOARD_GUESSPATH > 0x0
1682  //again to resolve including errors we'll include the SoftwareSerial cpp file
1683 
1684  #define _SS_MAX_RX_BUFF 64 // RX buffer size
1685  #ifndef GCC_VERSION
1686  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1687  #endif
1688  namespace eagle_impl {
1710  class SoftwareSerial : public Stream {
1711  private:
1713  uint8_t _receivePin;
1717  volatile uint8_t *_receivePortRegister;
1721  volatile uint8_t *_transmitPortRegister;
1722 
1730  uint16_t _tx_delay;
1731 
1733  uint16_t _buffer_overflow:1;
1735  uint16_t _inverse_logic:1;
1739  static volatile uint8_t _receive_buffer_tail;
1741  static volatile uint8_t _receive_buffer_head;
1744 
1746  void recv(void);
1751  inline uint8_t rx_pin_read(void);
1756  inline void tx_pin_write(uint8_t pin_state);
1761  void setTX(uint8_t transmitPin);
1766  void setRX(uint8_t receivePin);
1771  static inline void tunedDelay(uint16_t delay);
1772 
1773  public:
1774  // public methods
1781  SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
1787  ~SoftwareSerial(void);
1803  void begin(long speed);
1808  bool listen(void);
1810  inline void end(void);
1815  inline bool isListening(void);
1820  inline bool overflow(void);
1825  int peek(void);
1832  virtual size_t write(uint8_t byte);
1837  virtual int read(void);
1842  virtual int available(void);
1846  virtual void flush(void);
1847  //used to save codespace
1848  using Print::write;
1850  static inline void handle_interrupt(void);
1851  };
1852  }
1854 
1855  bool SoftwareSerial::isListening(void) {
1856  return this == active_object;
1857  }
1858 
1859  bool SoftwareSerial::overflow(void) {
1860  bool ret = _buffer_overflow;
1861  _buffer_overflow = false;
1862  return ret;
1863  }
1864  /* was a workaround for arduino 0012 but not needed
1865  #undef int
1866  #undef char
1867  #undef long
1868  #undef byte
1869  #undef float
1870  #undef abs
1871  #undef round
1872  */
1873  #if EBOARD_DEBUG_MODE > 0x0
1874  #define _DEBUG 0
1875  #define _DEBUG_PIN1 11
1876  #define _DEBUG_PIN2 13
1877  #endif
1878  typedef struct _DELAY_TABLE {
1879  long baud;
1880  unsigned short rx_delay_centering;
1881  unsigned short rx_delay_intrabit;
1882  unsigned short rx_delay_stopbit;
1883  unsigned short tx_delay;
1884  } DELAY_TABLE;
1885  #if F_CPU == 16000000
1886 
1887  static const DELAY_TABLE PROGMEM table[] = {
1888  // baud rxcenter rxintra rxstop tx
1889  { 115200, 1, 17, 17, 12, },
1890  { 57600, 10, 37, 37, 33, },
1891  { 38400, 25, 57, 57, 54, },
1892  { 31250, 31, 70, 70, 68, },
1893  { 28800, 34, 77, 77, 74, },
1894  { 19200, 54, 117, 117, 114, },
1895  { 14400, 74, 156, 156, 153, },
1896  { 9600, 114, 236, 236, 233, },
1897  { 4800, 233, 474, 474, 471, },
1898  { 2400, 471, 950, 950, 947, },
1899  { 1200, 947, 1902, 1902, 1899, },
1900  { 600, 1902, 3804, 3804, 3800, },
1901  { 300, 3804, 7617, 7617, 7614, },
1902  };
1903 
1904  const int XMIT_START_ADJUSTMENT = 5;
1905 
1906  #elif F_CPU == 8000000
1907 
1908  static const DELAY_TABLE table[] PROGMEM = {
1909  // baud rxcenter rxintra rxstop tx
1910  { 115200, 1, 5, 5, 3, },
1911  { 57600, 1, 15, 15, 13, },
1912  { 38400, 2, 25, 26, 23, },
1913  { 31250, 7, 32, 33, 29, },
1914  { 28800, 11, 35, 35, 32, },
1915  { 19200, 20, 55, 55, 52, },
1916  { 14400, 30, 75, 75, 72, },
1917  { 9600, 50, 114, 114, 112, },
1918  { 4800, 110, 233, 233, 230, },
1919  { 2400, 229, 472, 472, 469, },
1920  { 1200, 467, 948, 948, 945, },
1921  { 600, 948, 1895, 1895, 1890, },
1922  { 300, 1895, 3805, 3805, 3802, },
1923  };
1924 
1925  const int XMIT_START_ADJUSTMENT = 4;
1926 
1927  #elif F_CPU == 20000000
1928 
1929  static const DELAY_TABLE PROGMEM table[] = {
1930  // baud rxcenter rxintra rxstop tx
1931  { 115200, 3, 21, 21, 18, },
1932  { 57600, 20, 43, 43, 41, },
1933  { 38400, 37, 73, 73, 70, },
1934  { 31250, 45, 89, 89, 88, },
1935  { 28800, 46, 98, 98, 95, },
1936  { 19200, 71, 148, 148, 145, },
1937  { 14400, 96, 197, 197, 194, },
1938  { 9600, 146, 297, 297, 294, },
1939  { 4800, 296, 595, 595, 592, },
1940  { 2400, 592, 1189, 1189, 1186, },
1941  { 1200, 1187, 2379, 2379, 2376, },
1942  { 600, 2379, 4759, 4759, 4755, },
1943  { 300, 4759, 9523, 9523, 9520, },
1944  };
1945 
1946  const int XMIT_START_ADJUSTMENT = 6;
1947 
1948  #else
1949  #error This version of SoftwareSerial supports only 20, 16 and 8MHz processors
1950  #endif
1951 
1954  volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
1955  volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
1956  #if EBOARD_DEBUG_MODE > 0x0
1957  inline void DebugPulse(uint8_t pin, uint8_t count) {
1958  #if _DEBUG
1959  volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
1960 
1961  uint8_t val = *pport;
1962  while (count--)
1963  {
1964  *pport = val | digitalPinToBitMask(pin);
1965  *pport = val;
1966  }
1967  #endif
1968  }
1969  #endif
1970  inline void SoftwareSerial::tunedDelay(uint16_t delay) {
1971  uint8_t tmp=0;
1972 
1973  asm volatile("sbiw %0, 0x01 \n\t"
1974  "ldi %1, 0xFF \n\t"
1975  "cpi %A0, 0xFF \n\t"
1976  "cpc %B0, %1 \n\t"
1977  "brne .-10 \n\t"
1978  : "+r" (delay), "+a" (tmp)
1979  : "0" (delay)
1980  );
1981  }
1982 
1983  bool SoftwareSerial::listen() {
1984  if (active_object != this)
1985  {
1986  _buffer_overflow = false;
1987  uint8_t oldSREG = SREG;
1988  cli();
1990  active_object = this;
1991  SREG = oldSREG;
1992  return true;
1993  }
1994 
1995  return false;
1996  }
1997 
1998  void SoftwareSerial::recv() {
1999 
2000  #if GCC_VERSION < 40302
2001  asm volatile(
2002  "push r18 \n\t"
2003  "push r19 \n\t"
2004  "push r20 \n\t"
2005  "push r21 \n\t"
2006  "push r22 \n\t"
2007  "push r23 \n\t"
2008  "push r26 \n\t"
2009  "push r27 \n\t"
2010  ::);
2011  #endif
2012 
2013  uint8_t d = 0;
2014 
2015  if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) {
2016  // Wait approximately 1/2 of a bit width to "center" the sample
2018  #if EBOARD_DEBUG_MODE > 0x0
2019  DebugPulse(_DEBUG_PIN2, 1);
2020  #endif
2021  // Read each of the 8 bits
2022  for (uint8_t i=0x1; i; i <<= 1)
2023  {
2025  #if EBOARD_DEBUG_MODE > 0x0
2026  DebugPulse(_DEBUG_PIN2, 1);
2027  #endif
2028  uint8_t noti = ~i;
2029  if (rx_pin_read())
2030  d |= i;
2031  else
2032  d &= noti;
2033  }
2034 
2035  // skip the stop bit
2037  #if EBOARD_DEBUG_MODE > 0x0
2038  DebugPulse(_DEBUG_PIN2, 1);
2039  #endif
2040  if (_inverse_logic)
2041  d = ~d;
2042 
2044  _receive_buffer[_receive_buffer_tail] = d; // save new byte
2046  }
2047  else {
2048  #if EBOARD_DEBUG_MODE > 0x0
2049  #if _DEBUG // for scope: pulse pin as overflow indictator
2050  DebugPulse(_DEBUG_PIN1, 1);
2051  #endif
2052  #endif
2053  _buffer_overflow = true;
2054  }
2055  }
2056 
2057  #if GCC_VERSION < 40302
2058  asm volatile(
2059  "pop r27 \n\t"
2060  "pop r26 \n\t"
2061  "pop r23 \n\t"
2062  "pop r22 \n\t"
2063  "pop r21 \n\t"
2064  "pop r20 \n\t"
2065  "pop r19 \n\t"
2066  "pop r18 \n\t"
2067  ::);
2068  #endif
2069  }
2070 
2071  void SoftwareSerial::tx_pin_write(uint8_t pin_state) {
2072  if (pin_state == LOW)
2074  else
2076  }
2077 
2078  uint8_t SoftwareSerial::rx_pin_read() {
2080  }
2081 
2082  inline void SoftwareSerial::handle_interrupt() {
2083  if (active_object) {
2084  active_object->recv();
2085  }
2086  }
2087 
2088  #if defined(PCINT0_vect)
2089  ISR(PCINT0_vect) {
2091  }
2092  #endif
2093 
2094  #if defined(PCINT1_vect)
2095  ISR(PCINT1_vect) {
2097  }
2098  #endif
2099 
2100  #if defined(PCINT2_vect)
2101  ISR(PCINT2_vect) {
2103  }
2104  #endif
2105 
2106  #if defined(PCINT3_vect)
2107  ISR(PCINT3_vect) {
2109  }
2110  #endif
2111 
2112  SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
2113  _rx_delay_centering(0),
2114  _rx_delay_intrabit(0),
2115  _rx_delay_stopbit(0),
2116  _tx_delay(0),
2117  _buffer_overflow(false),
2118  _inverse_logic(inverse_logic) {
2119  setTX(transmitPin);
2120  setRX(receivePin);
2121  }
2122 
2124  end();
2125  }
2126 
2127  void SoftwareSerial::setTX(uint8_t tx) {
2128  pinMode(tx, OUTPUT);
2129  digitalWrite(tx, HIGH);
2130  _transmitBitMask = digitalPinToBitMask(tx);
2131  uint8_t port = digitalPinToPort(tx);
2132  _transmitPortRegister = portOutputRegister(port);
2133  }
2134 
2135  void SoftwareSerial::setRX(uint8_t rx) {
2136  pinMode(rx, INPUT);
2137  if (!_inverse_logic)
2138  digitalWrite(rx, HIGH);
2139  _receivePin = rx;
2140  _receiveBitMask = digitalPinToBitMask(rx);
2141  uint8_t port = digitalPinToPort(rx);
2142  _receivePortRegister = portInputRegister(port);
2143  }
2144 
2145  void SoftwareSerial::begin(long speed) {
2147 
2148  for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
2149  long baud = pgm_read_dword(&table[i].baud);
2150  if (baud == speed) {
2151  _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
2152  _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
2153  _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
2154  _tx_delay = pgm_read_word(&table[i].tx_delay);
2155  break;
2156  }
2157  }
2158 
2159  if (_rx_delay_stopbit) {
2160  if (digitalPinToPCICR(_receivePin)) {
2161  *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
2162  *digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin));
2163  }
2165  }
2166 
2167  #if _DEBUG
2168  pinMode(_DEBUG_PIN1, OUTPUT);
2169  pinMode(_DEBUG_PIN2, OUTPUT);
2170  #endif
2171 
2172  listen();
2173  }
2174 
2175  void SoftwareSerial::end() {
2176  if (digitalPinToPCMSK(_receivePin))
2177  *digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
2178  }
2179 
2180 
2181  int SoftwareSerial::read() {
2182  if (!isListening())
2183  return -1;
2184 
2186  return -1;
2187 
2188  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
2190  return d;
2191  }
2192 
2194  if (!isListening())
2195  return 0;
2196 
2198  }
2199 
2200  size_t SoftwareSerial::write(uint8_t b) {
2201  if (_tx_delay == 0) {
2202  setWriteError();
2203  return 0;
2204  }
2205 
2206  uint8_t oldSREG = SREG;
2207  cli();
2208 
2209  tx_pin_write(_inverse_logic ? HIGH : LOW);
2210  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
2211 
2212  if (_inverse_logic) {
2213  for (byte mask = 0x01; mask; mask <<= 1) {
2214  if (b & mask)
2215  tx_pin_write(LOW);
2216  else
2217  tx_pin_write(HIGH);
2218 
2220  }
2221 
2222  tx_pin_write(LOW);
2223  }
2224  else {
2225  for (byte mask = 0x01; mask; mask <<= 1) {
2226  if (b & mask)
2227  tx_pin_write(HIGH);
2228  else
2229  tx_pin_write(LOW);
2231  }
2232 
2233  tx_pin_write(HIGH);
2234  }
2235 
2236  SREG = oldSREG;
2238 
2239  return 1;
2240  }
2241 
2242  void SoftwareSerial::flush() {
2243  if (!isListening())
2244  return;
2245 
2246  uint8_t oldSREG = SREG;
2247  cli();
2249  SREG = oldSREG;
2250  }
2251 
2252  int SoftwareSerial::peek() {
2253  if (!isListening())
2254  return -1;
2255 
2257  return -1;
2258 
2260  }
2262  #endif
2263 
2269  #endif
2270 
2271  #if EBOARD_DEBUG_MODE > 0x0
2272 
2275  #define __ASSERT_USE_STDERR
2276  #include <assert.h>
2294  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp);
2296  void __assert (const char *__func, const char *__file, optVAL_t __lineno, const char *__sexp){
2297  Serial.print("Error with: "); Serial.print(__func);
2298  Serial.print(" in "); Serial.print(__file);
2299  Serial.print(" >>");
2300  Serial.println(__sexp);
2301  if(strcmp(__func,"checkIdx")==0){
2302  Serial.println(" This happens if an out of bounds exception");
2303  Serial.println(" has occured. Following pins shouldn't be used:");
2304  Serial.print(" D" + PIN_BLUETOOTH_RX);Serial.print("&");
2305  Serial.print("D");Serial.print(PIN_BLUETOOTH_TX);
2306  Serial.println(" : Used for Bluetooth communication");
2307  Serial.print(" D");Serial.print(PIN_MOTOR_DIR);Serial.print("&");
2308  Serial.print("D");Serial.print(PIN_MOTOR_SPE);
2309  Serial.println(" : Used for main motor control");
2310  #if EBOARD_USE_SPI > 0x0
2311  Serial.print(" D10-13");
2312  Serial.println(": Used for smart-servo-shield");
2313  #endif
2314  } else if (strcmp(__func,"readPin")==0){
2315  Serial.println("You've tried to access an analogPin that isn't present on the board you're currently working on!");
2316  }
2317  Serial.flush();
2318  abort(); // halt after outputting information
2319  }
2321  #endif
2322 
2329  inline void checkIdx(optVAL_t idx);
2331  inline void checkIdx(optVAL_t idx){
2332  #if EBOARD_DEBUG_MODE > 0x0
2333  assert(idx>=0x0 && idx < PIN_MAX); //changed pins? change me! (didn't want to use macros)
2334  assert(idx!=PIN_BLUETOOTH_RX&&idx!=PIN_BLUETOOTH_TX);
2335  #endif
2336  }
2338 
2339  #if EBOARD_COPY_AND_PASTE > 0x0
2340  #if EBOARD_CHECK_PINS_PWM > 0x0
2341 
2350  optVAL_t count; //dont't want to overuse global space^^
2351  for (count = 0; x; count++)
2352  x &= x - 1;
2353  return count;
2354  }
2356  #endif
2357 
2358  #if EBOARD_CHECK_PINS > 0x0
2359 
2364  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
2365  uint16_t pin_out = 0x0;
2366  #elif defined(__AVR_ATmega2560__)
2367  uint64_t pin_out = 0x0;
2368  #endif
2369 
2372  #if defined(__AVR_ATmega328P__) && not defined(__AVR_ATmega2560__)
2373  uint16_t pin_in = 0x0;
2374  #elif defined(__AVR_ATmega2560__)
2375  uint64_t pin_in = 0x0;
2376  #endif
2377 
2387  inline bool checkPin(optVAL_t idx, optVAL_t mode = OUTPUT);
2389  inline bool checkPin(optVAL_t idx, optVAL_t mode){
2390  checkIdx(idx);
2391  return (mode == OUTPUT)? ((pin_out & (1<<idx))>0x0):((pin_in & (1<<idx))>0x0);
2392  }
2394  #endif
2395 
2401  void setPin(optVAL_t idx, optVAL_t mode = OUTPUT);
2403  void setPin(optVAL_t idx, optVAL_t mode){
2404  #if EBOARD_CHECK_PINS > 0x0
2405  checkIdx(idx);
2406  if(mode==OUTPUT) { //possible to read from OUTPUT digital ... we won't do it
2407  pin_out |= (1<<idx);
2408  pin_in &= ~(1<<idx);
2409  }
2410  else {
2411  pin_in |= (1<<idx);
2412  pin_out &= ~(1<<idx);
2413  }
2414  #endif
2415  pinMode(idx, mode);
2416  }
2418  #endif
2419 
2420  #if EBOARD_BLUETOOTH > 0x0
2421 
2429  inline char readVal(char oF = '.');
2437  inline bool checkOverflow(void);
2442  template <typename T>
2443  inline void writeVal(const T& val);
2444 
2456  inline bool isConnected(void);
2458  inline bool checkOverflow(void) {
2459  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2460  return false; //there is no hardware provided control for hardwareserial overflow
2461  #else
2462  return (_serial.overflow());
2463  #endif
2464  }
2465  inline char readVal(char oF) {
2466  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2467  return ((Serial1.available())?(Serial1.read()):(oF));
2468  #else
2469  return ((_serial.available())?(_serial.read()):(oF));
2470  #endif
2471  }
2472  template<typename T>
2473  inline void writeVal(const T& val){
2474  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
2475  Serial1.write(val);
2476  #else
2477  _serial.write(val);
2478  #endif
2479  }
2480  inline bool isConnected(void) {
2481  #if PIN_BLUETOOTH_RX != PIN_BLUETOOTH_STATE
2482  return digitalRead(PIN_BLUETOOTH_STATE);
2483  #else
2484  return true;
2485  #endif
2486  }
2488  #endif
2489 
2490  #if EBOARD_SHIFT_REGISTER > 0x0
2491 
2494  long store_bits = 0L;
2503  inline void shiftSingle(optVAL_t idx, bool val);
2507  void shiftAll(void);
2509  inline void shiftSingle(optVAL_t idx, bool val) {
2510  bitWrite(store_bits,idx,val);
2511  shiftAll();
2512  }
2513 
2514  void shiftAll(void){
2515  digitalWrite(PIN_SHIFT_LAT,LOW);
2516  for(optVAL_t c = 0; (c<32 && !STOP); c++){
2517  digitalWrite(PIN_SHIFT_CLK,LOW);
2518  shiftOut(PIN_SHIFT_DAT,PIN_SHIFT_CLK,MSBFIRST,bitRead(store_bits,c));
2519  }
2520  digitalWrite(PIN_SHIFT_LAT,LOW);
2521  }
2523  #endif
2524 
2527 
2535  inline void writePWM (optVAL_t val);
2537  inline void writePWM(optVAL_t val){
2538  val = min(val,0xFF); val = max(0x0,val);
2539  _pwmValue = val;
2540  }
2541 
2542  #ifdef REPT_TASK
2543  extern void rept_task(void);
2544  DEBUG_MSG("You defined REPT_TASK: you have to define rept_task(void)!");
2545  #else
2546  DEBUG_MSG("You did not define REPT_TASK: rept_task(void) will not have any effect");
2547  #endif
2548 
2549 
2551 
2560  inline void writePin(optVAL_t idx,bool val);
2562  inline void writePin(optVAL_t idx,bool val){
2563  #if EBOARD_SHIFT_REGISTER > 0x0
2564  if(idx>0x63) {
2565  idx -= 0x64;
2566  shiftSingle(idx,val);
2567  return;
2568  }
2569  #endif
2570  #if EBOARD_CHECK_PINS > 0x0
2571  checkIdx(idx);
2572  if(!checkPin(idx))
2573  #endif
2574  #if EBOARD_COPY_AND_PASTE > 0x0
2575  setPin(idx);
2576  #else
2577  pinMode(idx,OUTPUT);
2578  #endif
2579  digitalWrite(idx,val);
2580  }
2582 
2592  inline optVAL_t readPin(optVAL_t idx,bool dig = true);
2594  inline optVAL_t readPin(optVAL_t idx,bool dig){
2595  #if EBOARD_CHECK_PINS > 0x0
2596  if(dig) checkIdx(idx);
2597  #if defined (__AVR_ATmega2560__)
2598  else if (idx<0||idx>0xF){ //use I2C? change => Wire
2599  #else
2600  else if (idx<0||idx>0x7){ //use I2C? change => Wire
2601  #endif
2602  #if EBOARD_DEBUG_MODE > 0x0
2603  assert(false);
2604  #endif
2605  return 0;
2606  }
2607  if(dig && !checkPin(idx,INPUT))
2608  #endif
2609  #if EBOARD_COPY_AND_PASTE > 0x0
2610  setPin(idx,INPUT);
2611  #else
2612  pinMode(idx,INPUT);
2613  #endif
2614  return((dig)? digitalRead(idx) : analogRead(idx));
2615  }
2617 
2618  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0x0)
2619 
2621  //won't be commented
2622  struct ServoCds55 {
2623  public:
2624  #if defined(__AVR_ATmega2560__)
2625  ServoCds55(int CS=53);
2626  #else
2627  ServoCds55(int CS=10);
2628  #endif
2629  void begin();
2630  void WritePos(int ID,int Pos);
2631  void write(int ID,int Pos);
2632  inline void setVelocity(int velocity);
2633  inline void setPoslimit(int posLimit);
2634  void rotate(int ID,int velocity);
2635  void SetServoLimit(int ID,int upperLimit);
2636  void SetMotormode(int ID, int velocity);
2637  void SetID(int ID, int newID);
2638  void Reset(int ID);
2639  byte sendWait (const byte what);
2640 
2641  int velocity_temp;
2642  int upperLimit_temp;
2643  int cs;
2644  };
2645  ServoCds55::ServoCds55 (int CS):cs(CS) {
2646  velocity_temp = 150;
2647  upperLimit_temp = 300;
2648  }
2649 
2650  void ServoCds55::begin() {
2651  pinMode(cs,OUTPUT);
2652  digitalWrite(cs,HIGH);
2653  SPI.begin ();
2655  }
2656 
2657  byte ServoCds55::sendWait (const byte what) {
2658  byte a = SPI.transfer (what);
2659  delayMicroseconds (20);
2660  return a;
2661  }
2662 
2663  void ServoCds55::setVelocity(int velocity){ //set servo velocity
2664  velocity_temp = velocity;
2665  }
2666 
2667  void ServoCds55::setPoslimit(int posLimit){ // set servo pos limit
2668  upperLimit_temp = posLimit;
2669  }
2670 
2671  void ServoCds55::write(int ID,int Pos){ // Servo Mode
2672  SetServoLimit(ID,upperLimit_temp);
2673  WritePos(ID,Pos);// default velocity:150
2674  }
2675 
2676  void ServoCds55::rotate(int ID,int velocity){ // Motor Mode
2677  SetServoLimit(ID,0);
2678  delay(100);
2679  SetMotormode(ID,velocity);
2680  }
2681 
2682  void ServoCds55::WritePos(int ID,int Pos){
2683  int PosB = (Pos>>8 & 0xff);//low
2684  int PosS = (Pos & 0xff);//high
2685  int velocityB = (velocity_temp>>8 & 0xff);
2686  int velocityS = (velocity_temp & 0xff);
2687  digitalWrite(cs, LOW);
2688  sendWait ('p'); sendWait (ID);
2689  sendWait (PosB); sendWait (PosS);
2690  sendWait (velocityB); sendWait (velocityS);
2691  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2692  digitalWrite(cs, HIGH);
2693  delay(10);
2694  }
2695 
2696  void ServoCds55::SetServoLimit(int ID,int upperLimit_temp){
2697  int upperLimitB = (upperLimit_temp>>8 & 0xff);
2698  int upperLimitS = (upperLimit_temp & 0xff);
2699  digitalWrite(cs, LOW);
2700  sendWait ('s'); sendWait (ID);
2701  sendWait (upperLimitB); sendWait (upperLimitS);
2702  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2703  digitalWrite(cs, HIGH);
2704  delay(10);
2705  }
2706 
2707  void ServoCds55::SetMotormode(int ID, int velocity){
2708  int velocityB = (velocity>>8 & 0xff);
2709  int velocityS = (velocity & 0xff);
2710  digitalWrite(cs, LOW);
2711  sendWait ('m'); sendWait (ID);
2712  sendWait (velocityB); sendWait (velocityS);
2713  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2714  digitalWrite(cs, HIGH);
2715  delay(10);
2716  }
2717 
2718  void ServoCds55::SetID(int ID, int newID){
2719  digitalWrite(cs, LOW);
2720  sendWait ('i'); sendWait (ID);
2721  sendWait (newID);
2722  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2723  digitalWrite(cs, HIGH);
2724  delay(10);
2725  }
2726 
2727  void ServoCds55::Reset(int ID){
2728  digitalWrite(cs, LOW);
2729  sendWait ('r'); sendWait (ID);
2730  sendWait ('\t'); sendWait ('\r'); sendWait ('\n');
2731  digitalWrite(cs, HIGH);
2732  delay(10);
2733  }
2735 
2737  ServoCds55 _servoHandler;
2738  #endif
2739 
2740  #if EBOARD_COPY_AND_PASTE > 0x0 && EBOARD_NANO == 0
2741 
2766  struct SoccerBoard {
2771  inline SoccerBoard(void);
2772  //inline ~SoccerBoard(void) {}
2773  #if EBOARD_USE_UTILITY > 0x0 or defined(__AVR_ATmega2560__) //won't shrink space... just speed things up
2774 
2782  inline void led(int idx,bool state);
2790  inline void ledOn(int idx);
2798  inline void ledOff(int idx);
2804  inline void ledsOff(void);
2810  inline void ledMeter(int);
2811 
2812  #endif
2813  #if EBOARD_USE_UTILITY > 0x0
2814  inline void /*bool*/ button(int);
2817  inline void waitForButton(int);
2818  #endif
2819 
2829  inline void motor(uint8_t id,int16_t val);
2831  inline void motorsOff(void);
2832  //ARDUINO UNO PINOUT
2833  //D0,D1 => Bluetooth connection
2834  //D4,D5 => MotorControl (D5: 980Hz)
2835  //D10,D13 => SPI
2836 
2846  inline void power(optVAL_t id, bool state);
2856  inline void powerOn(optVAL_t id);
2866  inline void powerOff(optVAL_t id);
2872  inline void sleep(uint16_t t);
2878  inline void msleep(uint16_t t);
2886  inline bool digital (optVAL_t id);
2894  inline optVAL_t analog (optVAL_t id);
2896  inline void reset(void); /* use crash-reset? =>*/ /* wdt_enable(WDTO_15MS); while(1) {} */
2897  };
2899  SoccerBoard::SoccerBoard(void) {}
2900 
2901  #if defined(__AVR_ATmega2560__)
2902  inline void SoccerBoard::led(int idx, bool state) {writePin(13,state);}
2903  void SoccerBoard::ledOn(int) {writePin(13,HIGH);}
2904  void SoccerBoard::ledOff(int) {writePin(13,LOW);}
2905  void SoccerBoard::ledsOff(void) {writePin(13,LOW);}
2906  void SoccerBoard::ledMeter(int) {writePin(13,HIGH);}
2907  #elif EBOARD_USE_UTILITY > 0x0
2908  void SoccerBoard::led(int, bool) {}
2909  void SoccerBoard::ledOn(int) {}
2910  void SoccerBoard::ledOff(int) {}
2911  void SoccerBoard::ledsOff(void) {}
2912  void SoccerBoard::ledMeter(int) {}
2913  #endif
2914 
2915  #if EBOARD_USE_UTILITY > 0x0
2916  void SoccerBoard::button(int) {}
2917  void SoccerBoard::waitForButton(int) {}
2918  #endif
2919 
2920  void SoccerBoard::motor(uint8_t id,int16_t val) {
2921  if(id==0&&(val>-256 && val < 256)) {setPin(PIN_MOTOR_DIR,val<0); writePWM(abs(val));}
2922  else if(id>0&&id<3&&(val>-0 && val < 1024)) {_servoHandler.write((id-1),(val *600/1023 - 300));}
2923  }
2924  void SoccerBoard::motorsOff(void) {writePWM(0);}
2925 
2926  void SoccerBoard::reset(void) {
2927  #if EBOARD_USE_RESET > 0x0
2928  wdt_enable(WDTO_15MS);
2929  for(;;) {}
2930  #endif
2931  }
2932 
2933  void SoccerBoard::power(optVAL_t id, bool state) {writePin(id,state);}
2934  void SoccerBoard::powerOn(optVAL_t id) {this->power(id,1);}
2935  void SoccerBoard::powerOff(optVAL_t id) {this->power(id,0);}
2936  void SoccerBoard::sleep(uint16_t t) {delay(1000*t);}
2937  void SoccerBoard::msleep(uint16_t t) {delay(t);}
2938  bool SoccerBoard::digital (optVAL_t id) {return readPin(id);}
2939  optVAL_t SoccerBoard::analog (optVAL_t id) {return readPin(id,0);}
2940 
2942  //To avoid not_found issues
2944  #define DIGITAL_IN 0x0
2945  #define DIGITAL_IN_INV 0x1
2947  #define DIGITAL_IN_PULLUP 0x2
2949  #define DIGITAL_IN_PULLUP_INV 0x3
2951  #define DIGITAL_OUT 0x4
2953  #define DIGITAL_OUT_INV 0x5
2955  #define DIGITAL_OUT_LOW 0x6
2957  #define DIGITAL_OUT_HIGH 0x7
2959  #define ANALOG_IN_8_BIT 0x8
2961  #define ANALOG_IN_10_BIT 0x9
2963  #define ANALOG_IN_MEAN_8_BIT 0xA
2965  #define ANALOG_IN_MEAN_10_BIT 0xB
2967  #define COUNTER_8_BIT 0xC
2969  #define COUNTER_16_BIT 0xD
2971  #define COUNTER_RISE_8_BIT 0xE
2973  #define COUNTER_RISE_16_BIT 0xF
2975  #define PWM_SLOW 0x8
2977  #define PWM_FAST 0x9
2979  #define FREQ_LOW 0xA
2981  #define FREQ_HIGH 0xB
2983  #define COUNTER_B_DIR 0xC
2985  #define COUNTER_B_DIR_PULLUP 0xD
2987  #define COUNTER_MEAN_8_BIT 0xE
2989  #define COUNTER_MEAN_16_BIT 0xF
2991 
3015  struct I2CInOut{
3022  #if EBOARD_USE_UTILITY > 0x0
3023  inline void read(void);
3026  inline void changeAddress(optVAL_t);
3028  inline void changeModes(optVAL_t,optVAL_t,optVAL_t);
3029  #endif
3030 
3034  inline void write(void);
3035 
3037  optVAL_t A; //if you've used uint16_t values you'll have to replace it here
3038  //we only have B - DiOut and C - AO [OUT]
3043  };
3046  this->A=0x0;this->B=0x0;this->C=0x0;
3047  }
3048  #if EBOARD_USE_UTILITY > 0x0
3049  void I2CInOut::read(void) {}
3050  void I2CInOut::changeAddress(optVAL_t){}
3052  #endif
3053  void I2CInOut::write(void){
3054  setPin(PIN_MOTOR_DIR,((this->B)!=0x0));
3055  writePWM(this->C);
3056  }
3058 
3060  struct DynamixelBoard;
3062 
3086  struct AX12Servo {
3091  AX12Servo(void);
3098  AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID); //if borders => setPosLimit
3099 
3101 
3102  #if EBOARD_USE_UTILITY > 0x0
3103 
3110  inline void setID(optVAL_t newID);
3119  inline void changeMotorID(optVAL_t newID); //this should change the hardwareaddress...
3125  inline void setPositionMode(void);
3131  inline void setSpeedMode(void);
3137  inline void setSpeed(optVAL_t);
3139  inline void ledOff(void);
3141  inline void ledOn(void);
3143  inline void setTorque(uint16_t);
3144  #endif
3145 
3153  void setPosition(int pos, int speed=0x3FF);
3161  inline void storePosition(int pos, int speed = 0x3FF);
3167  inline optVAL_t getPosition(void);
3175  inline bool isMoving(void);
3188 
3189  //bool posMode; //we don't care wich mode we are in ^^
3190 
3193  private:
3195  int actPos;
3197  int actSpe;
3198 
3199  }; //shield //set limits auto register for begin
3200 
3202  AX12Servo::AX12Servo(void) {}
3203  #if EBOARD_USE_UTILITY > 0x0
3204  void AX12Servo::setID(optVAL_t newID) {this->id = newID;_servoHandler.SetServoLimit(this->id,_servoHandler.upperLimit_temp);}
3205  void AX12Servo::changeMotorID(optVAL_t newID) {this->id = newID;} //this should change the hardwareaddress...
3206  //IF needed: _servoHandler.setID(this->id, newID);
3207  void AX12Servo::setPositionMode(void) {}
3208  void AX12Servo::setSpeedMode(void) {}
3209  void AX12Servo::setSpeed(optVAL_t) {} //i won't use the rotate functions...
3210  void AX12Servo::ledOff(void) {} //noone needs the AX12-Servo LED
3211  void AX12Servo::ledOn(void) {} //really.... noone ^^
3212  void AX12Servo::setTorque(uint16_t) {} //which damn register? xD
3213  #endif
3214 
3215  void AX12Servo::setPosition(int pos, int speed) {
3216  #if EBOARD_CLAMP > 0x0
3217  if(pos>1023 || speed > 1023) return;
3218  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
3219  speed = speed*600/1023 - 300;
3220  pos = pos *600/1023 - 300;
3221 
3222  #else
3223  if(pos>300 || speed > 300) return;
3224  this->actPos=pos; this->storedPos=pos; this->storedSpe = speed;
3225  #endif
3226  if(speed != actSpe){ _servoHandler.setVelocity(speed); this->actSpe=speed;}
3227  _servoHandler.write(this->id,pos);
3228  }
3230  return this->actPos; //when moving... false value;
3231  }
3232  bool AX12Servo::isMoving(void) {return false;} //we don't know^^
3234 
3262  inline DynamixelBoard(SoccerBoard&);
3263  //inline ~DynamixelBoard(void) {}
3264  #if EBOARD_USE_UTILITY > 0x0
3265  inline void changeId(optVAL_t);
3268  inline void changeMotorID(optVAL_t);
3270  inline void ledOn(optVAL_t);
3272  inline void ledOff(optVAL_t);
3273  #endif
3274  inline void action(void);
3276 
3278  friend struct AX12Servo;
3279  protected:
3286  };
3289  for(optVAL_t i = 0; i < EBOARD_SPI_SERVO_MAX; i++ ) {this->connected[i] = NULL;} //wanna use nullptr... wanna have c++11^^
3290  }
3291  //inline ~DynamixelBoard(void) {}
3292  #if EBOARD_USE_UTILITY > 0x0
3297  #endif
3298  void DynamixelBoard::action(void) {
3299  for(optVAL_t i = 0; (i < EBOARD_SPI_SERVO_MAX && !STOP); i++ ){
3300  if(this->connected[i] != NULL)
3301  (*connected[i]).setPosition((*connected[i]).storedPos,(*connected[i]).storedSpe);
3302  }
3303  }
3304 
3305 
3306  void AX12Servo::storePosition(int pos, int speed){
3307  if(this->id < EBOARD_SPI_SERVO_MAX) _conBoard->connected[this->id] = this;
3308  this->storedPos=pos;this->storedSpe=speed;
3309  }
3310  AX12Servo::AX12Servo(DynamixelBoard &dBoard, optVAL_t servoID): _conBoard( &dBoard),id(servoID-1), actSpe(0x96) {
3311  //#if EBOARD_DEBUG_MODE > 0x0
3312  // assert(servoID<EBOARD_SPI_SERVO_MAX);
3313  //#endif
3314  }
3316  #endif
3317  #if EBOARD_BLUETOOTH > 0x0
3318 
3347  struct RB14Scan {
3351  inline RB14Scan(void);
3354  inline int raw(optVAL_t);
3357  inline char channel(optVAL_t);
3363  inline void write(const char* const val);
3364  };
3365 
3367  inline RB14Scan::RB14Scan(void) {}
3368  inline int RB14Scan::raw(optVAL_t) {return isConnected();}
3369  inline char RB14Scan::channel(optVAL_t) {return ((isConnected())?(readVal()):(-1));}
3370  inline void RB14Scan::write(const char* const val) {writeVal(val);}
3372 
3380  #endif
3381 #if EBOARD_I2C > 0x0
3382 
3397  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len);
3398 
3413  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf);
3414 
3423  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len);
3425  inline void pingI2C(optVAL_t ret[], optVAL_t ret_len){
3426  optVAL_t count = 0;
3427  for (byte i = 1; (i < 255 && !STOP); i++) /*ignore special*/ {
3428  if(i==200)continue; //internal
3429  Wire.beginTransmission (i);
3430  if (Wire.endTransmission () == 0) {
3431  if(count < ret_len) ret[count] = i;
3432  count++;
3433  delay (1);
3434  }
3435  }
3436  }
3437  inline optVAL_t sendI2C(optVAL_t deviceID,byte *buf, byte buf_len) {
3438  Wire.beginTransmission(deviceID);
3439  Wire.write(buf,buf_len);
3440  return Wire.endTransmission();
3441  }
3442 
3443  inline optVAL_t sendI2C(optVAL_t deviceID, byte buf){
3444  Wire.beginTransmission(deviceID);
3445  Wire.write(buf);
3446  return Wire.endTransmission();
3447  }
3449 
3460  inline void readI2C(optVAL_t deviceID, optVAL_t ret[], optVAL_t ret_len,bool blocking=true);
3462  inline void readI2C(optVAL_t deviceID,optVAL_t ret[] , optVAL_t ret_len,bool blocking) {
3463  for(optVAL_t rect = 0x0; (Wire.available() || (((blocking && (rect < ret_len))) && (!STOP))); rect++)
3464  ret[rect] = Wire.read();
3465  }
3467 
3468  //Beginof LCD configuration
3469  #if EBOARD_LCD > 0x0
3470 
3471  PROGMEM const byte basicFont[][8] = {
3472  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
3473  {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
3474  {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
3475  {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
3476  {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
3477  {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
3478  {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
3479  {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
3480  {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
3481  {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
3482  {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
3483  {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
3484  {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
3485  {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
3486  {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
3487  {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
3488  {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
3489  {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
3490  {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
3491  {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
3492  {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
3493  {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
3494  {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
3495  {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
3496  {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
3497  {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
3498  {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
3499  {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
3500  {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
3501  {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
3502  {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
3503  {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
3504  {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
3505  {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
3506  {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
3507  {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
3508  {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
3509  {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
3510  {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
3511  {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
3512  {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
3513  {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
3514  {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
3515  {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
3516  {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
3517  {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
3518  {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
3519  {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
3520  {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
3521  {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
3522  {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
3523  {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
3524  {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
3525  {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
3526  {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
3527  {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
3528  {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
3529  {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
3530  {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
3531  {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
3532  {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
3533  {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
3534  {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
3535  {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
3536  {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
3537  {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
3538  {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
3539  {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
3540  {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
3541  {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
3542  {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
3543  {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
3544  {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
3545  {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
3546  {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
3547  {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
3548  {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
3549  {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
3550  {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
3551  {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
3552  {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
3553  {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
3554  {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
3555  {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
3556  {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
3557  {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
3558  {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
3559  {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
3560  {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
3561  {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
3562  {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
3563  {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
3564  {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
3565  {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
3566  {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
3567  {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00}
3568  };
3569  /*
3570  * @note if you don't mind the space this is the extended font set!
3571  *
3572  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
3573  {0x7E,0x81,0x95,0xB1,0xB1,0x95,0x81,0x7E}, // 0x01
3574  {0x7E,0xFF,0xEB,0xCF,0xCF,0xEB,0xFF,0x7E}, // 0x02
3575  {0x0E,0x1F,0x3F,0x7E,0x3F,0x1F,0x0E,0x00}, // 0x03
3576  {0x08,0x1C,0x3E,0x7F,0x3E,0x1C,0x08,0x00}, // 0x04
3577  {0x38,0x3A,0x9F,0xFF,0x9F,0x3A,0x38,0x00}, // 0x05
3578  {0x10,0x38,0xBC,0xFF,0xBC,0x38,0x10,0x00}, // 0x06
3579  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
3580  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
3581  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
3582  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
3583  {0x70,0xF8,0x88,0x88,0xFD,0x7F,0x07,0x0F}, // 0x0B
3584  {0x00,0x4E,0x5F,0xF1,0xF1,0x5F,0x4E,0x00}, // 0x0C
3585  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
3586  {0xC0,0xFF,0x7F,0x05,0x05,0x65,0x7F,0x3F}, // 0x0E
3587  {0x99,0x5A,0x3C,0xE7,0xE7,0x3C,0x5A,0x99}, // 0x0F
3588  {0x7F,0x3E,0x3E,0x1C,0x1C,0x08,0x08,0x00}, // 0x10
3589  {0x08,0x08,0x1C,0x1C,0x3E,0x3E,0x7F,0x00}, // 0x11
3590  {0x00,0x24,0x66,0xFF,0xFF,0x66,0x24,0x00}, // 0x12
3591  {0x00,0x5F,0x5F,0x00,0x00,0x5F,0x5F,0x00}, // 0x13
3592  {0x06,0x0F,0x09,0x7F,0x7F,0x01,0x7F,0x7F}, // 0x14
3593  {0xDA,0xBF,0xA5,0xA5,0xFD,0x59,0x03,0x02}, // 0x15
3594  {0x00,0x70,0x70,0x70,0x70,0x70,0x70,0x00}, // 0x16
3595  {0x80,0x94,0xB6,0xFF,0xFF,0xB6,0x94,0x80}, // 0x17
3596  {0x00,0x04,0x06,0x7F,0x7F,0x06,0x04,0x00}, // 0x18
3597  {0x00,0x10,0x30,0x7F,0x7F,0x30,0x10,0x00}, // 0x19
3598  {0x08,0x08,0x08,0x2A,0x3E,0x1C,0x08,0x00}, // 0x1A
3599  {0x08,0x1C,0x3E,0x2A,0x08,0x08,0x08,0x00}, // 0x1B
3600  {0x3C,0x3C,0x20,0x20,0x20,0x20,0x20,0x00}, // 0x1C
3601  {0x08,0x1C,0x3E,0x08,0x08,0x3E,0x1C,0x08}, // 0x1D
3602  {0x30,0x38,0x3C,0x3E,0x3E,0x3C,0x38,0x30}, // 0x1E
3603  {0x06,0x0E,0x1E,0x3E,0x3E,0x1E,0x0E,0x06}, // 0x1F
3604  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
3605  {0x00,0x06,0x5F,0x5F,0x06,0x00,0x00,0x00}, // 0x21
3606  {0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x00}, // 0x22
3607  {0x14,0x7F,0x7F,0x14,0x7F,0x7F,0x14,0x00}, // 0x23
3608  {0x24,0x2E,0x6B,0x6B,0x3A,0x12,0x00,0x00}, // 0x24
3609  {0x46,0x66,0x30,0x18,0x0C,0x66,0x62,0x00}, // 0x25
3610  {0x30,0x7A,0x4F,0x5D,0x37,0x7A,0x48,0x00}, // 0x26
3611  {0x04,0x07,0x03,0x00,0x00,0x00,0x00,0x00}, // 0x27
3612  {0x00,0x1C,0x3E,0x63,0x41,0x00,0x00,0x00}, // 0x28
3613  {0x00,0x41,0x63,0x3E,0x1C,0x00,0x00,0x00}, // 0x29
3614  {0x08,0x2A,0x3E,0x1C,0x1C,0x3E,0x2A,0x08}, // 0x2A
3615  {0x08,0x08,0x3E,0x3E,0x08,0x08,0x00,0x00}, // 0x2B
3616  {0x00,0xA0,0xE0,0x60,0x00,0x00,0x00,0x00}, // 0x2C
3617  {0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, // 0x2D
3618  {0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00}, // 0x2E
3619  {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // 0x2F
3620  {0x3E,0x7F,0x59,0x4D,0x7F,0x3E,0x00,0x00}, // 0x30
3621  {0x42,0x42,0x7F,0x7F,0x40,0x40,0x00,0x00}, // 0x31
3622  {0x62,0x73,0x59,0x49,0x6F,0x66,0x00,0x00}, // 0x32
3623  {0x22,0x63,0x49,0x49,0x7F,0x36,0x00,0x00}, // 0x33
3624  {0x18,0x1C,0x16,0x13,0x7F,0x7F,0x10,0x00}, // 0x34
3625  {0x27,0x67,0x45,0x45,0x7D,0x39,0x00,0x00}, // 0x35
3626  {0x3C,0x7E,0x4B,0x49,0x79,0x30,0x00,0x00}, // 0x36
3627  {0x03,0x63,0x71,0x19,0x0F,0x07,0x00,0x00}, // 0x37
3628  {0x36,0x7F,0x49,0x49,0x7F,0x36,0x00,0x00}, // 0x38
3629  {0x06,0x4F,0x49,0x69,0x3F,0x1E,0x00,0x00}, // 0x39
3630  {0x00,0x00,0x6C,0x6C,0x00,0x00,0x00,0x00}, // 0x3A
3631  {0x00,0xA0,0xEC,0x6C,0x00,0x00,0x00,0x00}, // 0x3B
3632  {0x08,0x1C,0x36,0x63,0x41,0x00,0x00,0x00}, // 0x3C
3633  {0x14,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, // 0x3D
3634  {0x00,0x41,0x63,0x36,0x1C,0x08,0x00,0x00}, // 0x3E
3635  {0x02,0x03,0x51,0x59,0x0F,0x06,0x00,0x00}, // 0x3F
3636  {0x3E,0x7F,0x41,0x5D,0x5D,0x1F,0x1E,0x00}, // 0x40
3637  {0x7C,0x7E,0x13,0x13,0x7E,0x7C,0x00,0x00}, // 0x41
3638  {0x41,0x7F,0x7F,0x49,0x49,0x7F,0x36,0x00}, // 0x42
3639  {0x1C,0x3E,0x63,0x41,0x41,0x63,0x22,0x00}, // 0x43
3640  {0x41,0x7F,0x7F,0x41,0x63,0x7F,0x1C,0x00}, // 0x44
3641  {0x41,0x7F,0x7F,0x49,0x5D,0x41,0x63,0x00}, // 0x45
3642  {0x41,0x7F,0x7F,0x49,0x1D,0x01,0x03,0x00}, // 0x46
3643  {0x1C,0x3E,0x63,0x41,0x51,0x73,0x72,0x00}, // 0x47
3644  {0x7F,0x7F,0x08,0x08,0x7F,0x7F,0x00,0x00}, // 0x48
3645  {0x00,0x41,0x7F,0x7F,0x41,0x00,0x00,0x00}, // 0x49
3646  {0x30,0x70,0x40,0x41,0x7F,0x3F,0x01,0x00}, // 0x4A
3647  {0x41,0x7F,0x7F,0x08,0x1C,0x77,0x63,0x00}, // 0x4B
3648  {0x41,0x7F,0x7F,0x41,0x40,0x60,0x70,0x00}, // 0x4C
3649  {0x7F,0x7F,0x06,0x0C,0x06,0x7F,0x7F,0x00}, // 0x4D
3650  {0x7F,0x7F,0x06,0x0C,0x18,0x7F,0x7F,0x00}, // 0x4E
3651  {0x1C,0x3E,0x63,0x41,0x63,0x3E,0x1C,0x00}, // 0x4F
3652  {0x41,0x7F,0x7F,0x49,0x09,0x0F,0x06,0x00}, // 0x50
3653  {0x1E,0x3F,0x21,0x71,0x7F,0x5E,0x00,0x00}, // 0x51
3654  {0x41,0x7F,0x7F,0x19,0x39,0x6F,0x46,0x00}, // 0x52
3655  {0x26,0x67,0x4D,0x59,0x7B,0x32,0x00,0x00}, // 0x53
3656  {0x03,0x41,0x7F,0x7F,0x41,0x03,0x00,0x00}, // 0x54
3657  {0x7F,0x7F,0x40,0x40,0x7F,0x7F,0x00,0x00}, // 0x55
3658  {0x1F,0x3F,0x60,0x60,0x3F,0x1F,0x00,0x00}, // 0x56
3659  {0x7F,0x7F,0x30,0x18,0x30,0x7F,0x7F,0x00}, // 0x57
3660  {0x63,0x77,0x1C,0x08,0x1C,0x77,0x63,0x00}, // 0x58
3661  {0x07,0x4F,0x78,0x78,0x4F,0x07,0x00,0x00}, // 0x59
3662  {0x67,0x73,0x59,0x4D,0x47,0x63,0x71,0x00}, // 0x5A
3663  {0x00,0x7F,0x7F,0x41,0x41,0x00,0x00,0x00}, // 0x5B
3664  {0x01,0x03,0x06,0x0C,0x18,0x30,0x60,0x00}, // 0x5C
3665  {0x00,0x41,0x41,0x7F,0x7F,0x00,0x00,0x00}, // 0x5D
3666  {0x08,0x0C,0x06,0x03,0x06,0x0C,0x08,0x00}, // 0x5E
3667  {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, // 0x5F
3668  {0x00,0x00,0x03,0x07,0x04,0x00,0x00,0x00}, // 0x60
3669  {0x20,0x74,0x54,0x54,0x3C,0x78,0x40,0x00}, // 0x61
3670  {0x41,0x3F,0x7F,0x44,0x44,0x7C,0x38,0x00}, // 0x62
3671  {0x38,0x7C,0x44,0x44,0x6C,0x28,0x00,0x00}, // 0x63
3672  {0x30,0x78,0x48,0x49,0x3F,0x7F,0x40,0x00}, // 0x64
3673  {0x38,0x7C,0x54,0x54,0x5C,0x18,0x00,0x00}, // 0x65
3674  {0x48,0x7E,0x7F,0x49,0x03,0x02,0x00,0x00}, // 0x66
3675  {0x98,0xBC,0xA4,0xA4,0xF8,0x7C,0x04,0x00}, // 0x67
3676  {0x41,0x7F,0x7F,0x08,0x04,0x7C,0x78,0x00}, // 0x68
3677  {0x00,0x44,0x7D,0x7D,0x40,0x00,0x00,0x00}, // 0x69
3678  {0x40,0xC4,0x84,0xFD,0x7D,0x00,0x00,0x00}, // 0x6A
3679  {0x41,0x7F,0x7F,0x10,0x38,0x6C,0x44,0x00}, // 0x6B
3680  {0x00,0x41,0x7F,0x7F,0x40,0x00,0x00,0x00}, // 0x6C
3681  {0x7C,0x7C,0x0C,0x18,0x0C,0x7C,0x78,0x00}, // 0x6D
3682  {0x7C,0x7C,0x04,0x04,0x7C,0x78,0x00,0x00}, // 0x6E
3683  {0x38,0x7C,0x44,0x44,0x7C,0x38,0x00,0x00}, // 0x6F
3684  {0x84,0xFC,0xF8,0xA4,0x24,0x3C,0x18,0x00}, // 0x70
3685  {0x18,0x3C,0x24,0xA4,0xF8,0xFC,0x84,0x00}, // 0x71
3686  {0x44,0x7C,0x78,0x44,0x1C,0x18,0x00,0x00}, // 0x72
3687  {0x48,0x5C,0x54,0x54,0x74,0x24,0x00,0x00}, // 0x73
3688  {0x00,0x04,0x3E,0x7F,0x44,0x24,0x00,0x00}, // 0x74
3689  {0x3C,0x7C,0x40,0x40,0x3C,0x7C,0x40,0x00}, // 0x75
3690  {0x1C,0x3C,0x60,0x60,0x3C,0x1C,0x00,0x00}, // 0x76
3691  {0x3C,0x7C,0x60,0x30,0x60,0x7C,0x3C,0x00}, // 0x77
3692  {0x44,0x6C,0x38,0x10,0x38,0x6C,0x44,0x00}, // 0x78
3693  {0x9C,0xBC,0xA0,0xA0,0xFC,0x7C,0x00,0x00}, // 0x79
3694  {0x4C,0x64,0x74,0x5C,0x4C,0x64,0x00,0x00}, // 0x7A
3695  {0x08,0x08,0x3E,0x77,0x41,0x41,0x00,0x00}, // 0x7B
3696  {0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00}, // 0x7C
3697  {0x41,0x41,0x77,0x3E,0x08,0x08,0x00,0x00}, // 0x7D
3698  {0x02,0x03,0x01,0x03,0x02,0x03,0x01,0x00}, // 0x7E
3699  {0x78,0x7C,0x46,0x43,0x46,0x7C,0x78,0x00}, // 0x7F
3700  {0x1E,0xBF,0xE1,0x61,0x33,0x12,0x00,0x00}, // 0x80
3701  {0x3A,0x7A,0x40,0x40,0x7A,0x7A,0x40,0x00}, // 0x81
3702  {0x38,0x7C,0x56,0x57,0x5D,0x18,0x00,0x00}, // 0x82
3703  {0x02,0x23,0x75,0x55,0x55,0x7D,0x7B,0x42}, // 0x83
3704  {0x21,0x75,0x54,0x54,0x7D,0x79,0x40,0x00}, // 0x84
3705  {0x20,0x75,0x57,0x56,0x7C,0x78,0x40,0x00}, // 0x85
3706  {0x00,0x22,0x77,0x55,0x55,0x7F,0x7A,0x40}, // 0x86
3707  {0x1C,0xBE,0xE2,0x62,0x36,0x14,0x00,0x00}, // 0x87
3708  {0x02,0x3B,0x7D,0x55,0x55,0x5D,0x1B,0x02}, // 0x88
3709  {0x39,0x7D,0x54,0x54,0x5D,0x19,0x00,0x00}, // 0x89
3710  {0x38,0x7D,0x57,0x56,0x5C,0x18,0x00,0x00}, // 0x8A
3711  {0x01,0x45,0x7C,0x7C,0x41,0x01,0x00,0x00}, // 0x8B
3712  {0x02,0x03,0x45,0x7D,0x7D,0x43,0x02,0x00}, // 0x8C
3713  {0x00,0x45,0x7F,0x7E,0x40,0x00,0x00,0x00}, // 0x8D
3714  {0x79,0x7D,0x26,0x26,0x7D,0x79,0x00,0x00}, // 0x8E
3715  {0x70,0x7A,0x2D,0x2D,0x7A,0x70,0x00,0x00}, // 0x8F
3716  {0x44,0x7C,0x7E,0x57,0x55,0x44,0x00,0x00}, // 0x90
3717  {0x20,0x74,0x54,0x54,0x7C,0x7C,0x54,0x54}, // 0x91
3718  {0x7C,0x7E,0x0B,0x09,0x7F,0x7F,0x49,0x00}, // 0x92
3719  {0x32,0x7B,0x49,0x49,0x7B,0x32,0x00,0x00}, // 0x93
3720  {0x32,0x7A,0x48,0x48,0x7A,0x32,0x00,0x00}, // 0x94
3721  {0x30,0x79,0x4B,0x4A,0x78,0x30,0x00,0x00}, // 0x95
3722  {0x3A,0x7B,0x41,0x41,0x7B,0x7A,0x40,0x00}, // 0x96
3723  {0x38,0x79,0x43,0x42,0x78,0x78,0x40,0x00}, // 0x97
3724  {0xBA,0xBA,0xA0,0xA0,0xFA,0x7A,0x00,0x00}, // 0x98
3725  {0x39,0x7D,0x44,0x44,0x44,0x7D,0x39,0x00}, // 0x99
3726  {0x3D,0x7D,0x40,0x40,0x7D,0x3D,0x00,0x00}, // 0x9A
3727  {0x38,0x7C,0x64,0x54,0x4C,0x7C,0x38,0x00}, // 0x9B
3728  {0x68,0x7E,0x7F,0x49,0x43,0x66,0x20,0x00}, // 0x9C
3729  {0x5C,0x3E,0x73,0x49,0x67,0x3E,0x1D,0x00}, // 0x9D
3730  {0x44,0x6C,0x38,0x38,0x6C,0x44,0x00,0x00}, // 0x9E
3731  {0x40,0xC8,0x88,0xFE,0x7F,0x09,0x0B,0x02}, // 0x9F
3732  {0x20,0x74,0x56,0x57,0x7D,0x78,0x40,0x00}, // 0xA0
3733  {0x00,0x44,0x7E,0x7F,0x41,0x00,0x00,0x00}, // 0xA1
3734  {0x30,0x78,0x48,0x4A,0x7B,0x31,0x00,0x00}, // 0xA2
3735  {0x38,0x78,0x40,0x42,0x7B,0x79,0x40,0x00}, // 0xA3
3736  {0x7A,0x7B,0x09,0x0B,0x7A,0x73,0x01,0x00}, // 0xA4
3737  {0x7A,0x7B,0x19,0x33,0x7A,0x7B,0x01,0x00}, // 0xA5
3738  {0x00,0x26,0x2F,0x29,0x2F,0x2F,0x28,0x00}, // 0xA6
3739  {0x00,0x26,0x2F,0x29,0x29,0x2F,0x26,0x00}, // 0xA7
3740  {0x30,0x78,0x4D,0x45,0x60,0x20,0x00,0x00}, // 0xA8
3741  {0x1C,0x22,0x7D,0x4B,0x5B,0x65,0x22,0x1C}, // 0xA9
3742  {0x08,0x08,0x08,0x08,0x38,0x38,0x00,0x00}, // 0xAA
3743  {0x61,0x3F,0x1F,0xCC,0xEE,0xAB,0xB9,0x90}, // 0xAB
3744  {0x61,0x3F,0x1F,0x4C,0x66,0x73,0xD9,0xF8}, // 0xAC
3745  {0x00,0x00,0x60,0xFA,0xFA,0x60,0x00,0x00}, // 0xAD
3746  {0x08,0x1C,0x36,0x22,0x08,0x1C,0x36,0x22}, // 0xAE
3747  {0x22,0x36,0x1C,0x08,0x22,0x36,0x1C,0x08}, // 0xAF
3748  {0xAA,0x00,0x55,0x00,0xAA,0x00,0x55,0x00}, // 0xB0
3749  {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55}, // 0xB1
3750  {0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF}, // 0xB2
3751  {0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00}, // 0xB3
3752  {0x10,0x10,0x10,0xFF,0xFF,0x00,0x00,0x00}, // 0xB4
3753  {0x70,0x78,0x2C,0x2E,0x7B,0x71,0x00,0x00}, // 0xB5
3754  {0x72,0x79,0x2D,0x2D,0x79,0x72,0x00,0x00}, // 0xB6
3755  {0x71,0x7B,0x2E,0x2C,0x78,0x70,0x00,0x00}, // 0xB7
3756  {0x1C,0x22,0x5D,0x55,0x55,0x41,0x22,0x1C}, // 0xB8
3757  {0x14,0x14,0xF7,0xF7,0x00,0xFF,0xFF,0x00}, // 0xB9
3758  {0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0x00}, // 0xBA
3759  {0x14,0x14,0xF4,0xF4,0x04,0xFC,0xFC,0x00}, // 0xBB
3760  {0x14,0x14,0x17,0x17,0x10,0x1F,0x1F,0x00}, // 0xBC
3761  {0x18,0x3C,0x24,0xE7,0xE7,0x24,0x24,0x00}, // 0xBD
3762  {0x2B,0x2F,0xFC,0xFC,0x2F,0x2B,0x00,0x00}, // 0xBE
3763  {0x10,0x10,0x10,0xF0,0xF0,0x00,0x00,0x00}, // 0xBF
3764  {0x00,0x00,0x00,0x1F,0x1F,0x10,0x10,0x10}, // 0xC0
3765  {0x10,0x10,0x10,0x1F,0x1F,0x10,0x10,0x10}, // 0xC1
3766  {0x10,0x10,0x10,0xF0,0xF0,0x10,0x10,0x10}, // 0xC2
3767  {0x00,0x00,0x00,0xFF,0xFF,0x10,0x10,0x10}, // 0xC3
3768  {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, // 0xC4
3769  {0x10,0x10,0x10,0xFF,0xFF,0x10,0x10,0x10}, // 0xC5
3770  {0x22,0x77,0x55,0x57,0x7E,0x7B,0x41,0x00}, // 0xC6
3771  {0x72,0x7B,0x2D,0x2F,0x7A,0x73,0x01,0x00}, // 0xC7
3772  {0x00,0x00,0x1F,0x1F,0x10,0x17,0x17,0x14}, // 0xC8
3773  {0x00,0x00,0xFC,0xFC,0x04,0xF4,0xF4,0x14}, // 0xC9
3774  {0x14,0x14,0x17,0x17,0x10,0x17,0x17,0x14}, // 0xCA
3775  {0x14,0x14,0xF4,0xF4,0x04,0xF4,0xF4,0x14}, // 0xCB
3776  {0x00,0x00,0xFF,0xFF,0x00,0xF7,0xF7,0x14}, // 0xCC
3777  {0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14}, // 0xCD
3778  {0x14,0x14,0xF7,0xF7,0x00,0xF7,0xF7,0x14}, // 0xCE
3779  {0x66,0x3C,0x3C,0x24,0x3C,0x3C,0x66,0x00}, // 0xCF
3780  {0x05,0x27,0x72,0x57,0x7D,0x38,0x00,0x00}, // 0xD0
3781  {0x49,0x7F,0x7F,0x49,0x63,0x7F,0x1C,0x00}, // 0xD1
3782  {0x46,0x7D,0x7D,0x55,0x55,0x46,0x00,0x00}, // 0xD2
3783  {0x45,0x7D,0x7C,0x54,0x55,0x45,0x00,0x00}, // 0xD3
3784  {0x44,0x7D,0x7F,0x56,0x54,0x44,0x00,0x00}, // 0xD4
3785  {0x0A,0x0E,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xD5
3786  {0x00,0x44,0x7E,0x7F,0x45,0x00,0x00,0x00}, // 0xD6
3787  {0x02,0x45,0x7D,0x7D,0x45,0x02,0x00,0x00}, // 0xD7
3788  {0x01,0x45,0x7C,0x7C,0x45,0x01,0x00,0x00}, // 0xD8
3789  {0x10,0x10,0x10,0x1F,0x1F,0x00,0x00,0x00}, // 0xD9
3790  {0x00,0x00,0x00,0xF0,0xF0,0x10,0x10,0x10}, // 0xDA
3791  {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB
3792  {0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0}, // 0xDC
3793  {0x00,0x00,0x00,0x77,0x77,0x00,0x00,0x00}, // 0xDD
3794  {0x00,0x45,0x7F,0x7E,0x44,0x00,0x00,0x00}, // 0xDE
3795  {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}, // 0xDF
3796  {0x38,0x7C,0x46,0x47,0x45,0x7C,0x38,0x00}, // 0xE0
3797  {0xFC,0xFE,0x2A,0x2A,0x3E,0x14,0x00,0x00}, // 0xE1
3798  {0x3A,0x7D,0x45,0x45,0x45,0x7D,0x3A,0x00}, // 0xE2
3799  {0x38,0x7C,0x45,0x47,0x46,0x7C,0x38,0x00}, // 0xE3
3800  {0x32,0x7B,0x49,0x4B,0x7A,0x33,0x01,0x00}, // 0xE4
3801  {0x3A,0x7F,0x45,0x47,0x46,0x7F,0x39,0x00}, // 0xE5
3802  {0x80,0xFE,0x7E,0x20,0x20,0x3E,0x1E,0x00}, // 0xE6
3803  {0x42,0x7E,0x7E,0x54,0x1C,0x08,0x00,0x00}, // 0xE7
3804  {0x41,0x7F,0x7F,0x55,0x14,0x1C,0x08,0x00}, // 0xE8
3805  {0x3C,0x7C,0x42,0x43,0x7D,0x3C,0x00,0x00}, // 0xE9
3806  {0x3A,0x79,0x41,0x41,0x79,0x3A,0x00,0x00}, // 0xEA
3807  {0x3C,0x7D,0x43,0x42,0x7C,0x3C,0x00,0x00}, // 0xEB
3808  {0xB8,0xB8,0xA2,0xA3,0xF9,0x78,0x00,0x00}, // 0xEC
3809  {0x0C,0x5C,0x72,0x73,0x5D,0x0C,0x00,0x00}, // 0xED
3810  {0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00}, // 0xEE
3811  {0x00,0x00,0x02,0x03,0x01,0x00,0x00,0x00}, // 0xEF
3812  {0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00}, // 0xF0
3813  {0x44,0x44,0x5F,0x5F,0x44,0x44,0x00,0x00}, // 0xF1
3814  {0x28,0x28,0x28,0x28,0x28,0x28,0x00,0x00}, // 0xF2
3815  {0x71,0x35,0x1F,0x4C,0x66,0x73,0xD9,0xF8}, // 0xF3
3816  {0x06,0x0F,0x09,0x7F,0x7F,0x01,0x7F,0x7F}, // 0xF4
3817  {0xDA,0xBF,0xA5,0xA5,0xFD,0x59,0x03,0x02}, // 0xF5
3818  {0x08,0x08,0x6B,0x6B,0x08,0x08,0x00,0x00}, // 0xF6
3819  {0x00,0x80,0xC0,0x40,0x00,0x00,0x00,0x00}, // 0xF7
3820  {0x00,0x06,0x0F,0x09,0x0F,0x06,0x00,0x00}, // 0xF8
3821  {0x02,0x02,0x00,0x00,0x02,0x02,0x00,0x00}, // 0xF9
3822  {0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00}, // 0xFA
3823  {0x00,0x12,0x13,0x1F,0x1F,0x10,0x10,0x00}, // 0xFB
3824  {0x00,0x11,0x15,0x15,0x1F,0x1F,0x0A,0x00}, // 0xFC
3825  {0x00,0x19,0x1D,0x15,0x17,0x12,0x00,0x00}, // 0xFD
3826  {0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00}, // 0xFE
3827  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
3828  */
3829 
3830  //Definition of OLED Constants
3832  #define LCD_COMMAND_MODE 0x80
3833  #define LCD_DATA_MODE 0x40
3835  #define LCD_COMMAND_DISPLAY_OFF 0xAE
3837  #define LCD_COMMAND_DISPLAY_ON 0xAF
3839  #define LCD_COMMAND_BLACK_BACKGROUND 0xA6
3841  #define LCD_COMMAND_WHITE_BACKGROUND 0xA7
3843  #define LCD_COMMAND_SET_BRIGHTNESS 0x81
3845  #define LCD_PAGE_ADDRESSING 0x02
3847  #define LCD_HORIZONTAL_ADDRESSING 0x00
3849  //The regulator
3851  #define LCD_COMMAND_CHARGE_PUMP_SETTING 0x8d
3852  #define LCD_COMMAND_CHARGE_PUMP_ENABLE 0x14
3854 
3855  #ifndef LCD_WIDTH
3856  #define LCD_WIDTH 128
3858  #endif
3859  #ifndef LCD_HEIGHT
3860  #define LCD_HEIGHT 64
3862  #endif
3863 
3904  struct LCD {
3905  #if EBOARD_NANO == 0
3906 
3914  LCD(SoccerBoard &soccerBoard, optVAL_t id=0x3C);
3915  #else
3916  LCD(optVAL_t id=0x3C);
3917  #endif
3918 
3932  inline bool changeID(optVAL_t newID = 0x3C);
3943  inline bool clear(void);
3949  inline void print(const char* data);
3955  inline void print(int data);
3963  inline void print(optVAL_t line, optVAL_t col, const char* data);
3971  inline void print(optVAL_t line, optVAL_t col, int data);
3980  inline void lightOn(void);
3989  inline void lightOff(void);
4000  inline bool reset(void);
4001 
4002  //added features
4015  inline bool init(void);
4025  inline void drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY);
4033  inline void changeMode(bool newMode = true);
4047  inline bool setCursor(byte posX = 0x0, byte posY = 0x0);
4060  inline bool changeBrightness (byte val = 0x64);
4070  inline void changeBackground(bool newBackground = false);
4073  private:
4079  byte pX;
4082  byte pY;
4084  bool _cI;
4085 
4092  inline void s2Cmd(optVAL_t o, optVAL_t t);
4105  inline bool s1Cmd(optVAL_t o);
4111  inline void s1Dat(optVAL_t o);
4112 
4113  };
4115  #if EBOARD_NANO == 0x0
4116  LCD::LCD(SoccerBoard &soccerBoard, optVAL_t id) {
4117  this->_cI = false;
4118  this->ID = id;
4119  //this->init();
4120  }
4121  #else
4122  LCD::LCD( optVAL_t id) {
4123  this->_cI = false;
4124  this->ID = id;
4125  //this->init();
4126  }
4127  #endif
4128  inline bool LCD::changeID(optVAL_t newID) {
4129  this->ID = newID;
4130  return this->init();
4131  }
4132  inline bool LCD::clear(void) {
4133  if(!this->_cI) this->init();
4134  for(byte i = 0; i < 8; i++){
4135  //maybe *8
4136  setCursor(0,i);
4137 
4138  for (byte j = 0; j < 128; j++)
4139  this->s1Dat(0);
4140  }
4141  return setCursor(0,0);
4142  }
4143  void LCD::print(optVAL_t line, optVAL_t col, const char *data) {
4144  if(!this->_cI) this->init();
4145  byte i = 0x0;
4146  if(col < ((LCD_WIDTH-1)/8.0) && line < ((LCD_HEIGHT-1)/8.0)) {
4147  setCursor(col,line);
4148  }
4149  while(data[i] && (pX*8) < LCD_WIDTH){
4150  //Serial.print(data[i]); Serial.print(" ");
4151  //Serial.print(i); Serial.print(" "); Serial.print(pX); Serial.print(" ");
4152  //Serial.println(this->pY);
4153  if(data[i] == '\n' || this->pX >= LCD_WIDTH) {
4154  setCursor(0,(pY+1));
4155  } else if (this->pY >= LCD_HEIGHT){
4156  setCursor(0,0);
4157  }
4158  if(data[i] < 32 || data[i] > 127){ i++; continue;}
4159  for (byte j = 0; j < 8; j++){
4160  this->s1Dat(pgm_read_byte(&basicFont[data[i]-32][j]));
4161  }
4162  i++;this->pX++;
4163  }
4164  }
4165  void LCD::print(optVAL_t line, optVAL_t col, int data){
4166  char buffer[11] = "";
4167  itoa(data,buffer,10);
4168  this->print(line,col,buffer);
4169  }
4170  inline void LCD::lightOn(void) {
4171  this->changeBrightness(255);
4172  }
4173  inline void LCD::lightOff(void) {
4174  this->changeBrightness(0);
4175  }
4176  inline bool LCD::reset(void) {
4177  return this->clear();
4178  }
4179  inline void LCD::print(int data) {this->print(255,255,data);}
4180  inline void LCD::print(const char* data) {this->print(255,255,data);}
4181  inline bool LCD::init() {
4182  #ifdef HIGHSPEED
4183  TWBR = 0xC;
4184  #endif
4185  this->_cI = true;
4187  this->changeMode(false);
4188  this->changeBackground(false);
4189  this->changeBrightness(255);
4190  this->s2Cmd(0x20,LCD_PAGE_ADDRESSING);
4191  this->changeMode(true);
4192 
4193  //this->print("eBoard \n written by \n EagleoutIce");
4194  return this->clear();
4195  }
4196 
4197  inline void LCD::drawBitmap(const unsigned char *bitmap, byte posX, byte posY, byte hiX, byte hiY){
4198  if(!this->_cI) this->init();
4199  setCursor(posX,posY);
4200  byte col = 0x0;
4201  for(int i = 0x0; i < (hiX * 8 * hiY); i++){
4202  this->s1Dat(pgm_read_byte(&bitmap[i]));
4203  if(++col == (hiX * 8)) {
4204  col = 0x0;
4205  setCursor(posX,++posY);
4206  }
4207  }
4208  }
4209  inline void LCD::changeMode(bool newMode) {
4210  if(!this->_cI) this->init();
4211  if(newMode) this->s1Cmd(LCD_COMMAND_DISPLAY_ON);
4212  else this->s1Cmd(LCD_COMMAND_DISPLAY_OFF);
4213  }
4214  inline bool LCD::setCursor(byte posX, byte posY) {
4215  if(!this->_cI) this->init();
4216  this->s2Cmd((0x00 + (8 *posX & 0x0F)),(0x10 + ((8 * posX >> 4) & 0x0F))); //lower and higher address
4217  this->pX = posX; this->pY = posY;
4218  return this->s1Cmd(0xB0 + posY);
4219  }
4220 
4221  inline bool LCD::changeBrightness(byte val) {
4222  if(!this->_cI) this->init();
4223  this->s2Cmd(0x81,val); //brightness mode
4224  Wire.beginTransmission(this->ID);
4225  return (Wire.endTransmission() == 0);
4226  }
4227  inline void LCD::changeBackground(bool newBackground) {
4228  if(!this->_cI) this->init();
4229  if(newBackground) this->s1Cmd(LCD_COMMAND_WHITE_BACKGROUND);
4230  else this->s1Cmd(LCD_COMMAND_BLACK_BACKGROUND);
4231  }
4232 
4233  inline void LCD::s2Cmd(optVAL_t o, optVAL_t t){
4234  if(!this->_cI) this->init();
4235  this->s1Cmd(o); this->s1Cmd(t);
4236  }
4237 
4238  inline bool LCD::s1Cmd(optVAL_t C) {
4239  if(!this->_cI) this->init();
4240  Wire.beginTransmission(this->ID);
4241  Wire.write(LCD_COMMAND_MODE); Wire.write(C);
4242  return (Wire.endTransmission()==0);
4243  }
4244  inline void LCD::s1Dat(optVAL_t o){
4245  if(!this->_cI) this->init();
4246  Wire.beginTransmission(this->ID);
4247  Wire.write(LCD_DATA_MODE); Wire.write(o);
4249  }
4250 
4252  #endif
4253  #endif
4254  #if EBOARD_NEO > 0x0
4255  // Codesection based on official NeoPixel library
4256  // RGB NeoPixel permutations; white and red offsets are always same
4257  // Offset: W R G B
4259  #define EBOARD_NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
4260  #define EBOARD_NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
4262  #define EBOARD_NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
4264  #define EBOARD_NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
4266  #define EBOARD_NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
4268  #define EBOARD_NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
4270 
4271  // RGBW NeoPixel permutations; all 4 offsets are distinct
4272  // Offset: W R G B
4274  #define EBOARD_NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
4275  #define EBOARD_NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
4277  #define EBOARD_NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
4279  #define EBOARD_NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
4281  #define EBOARD_NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
4283  #define EBOARD_NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
4285  #define EBOARD_NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
4287  #define EBOARD_NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
4289  #define EBOARD_NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
4291  #define EBOARD_NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
4293  #define EBOARD_NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
4295  #define EBOARD_NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
4297  #define EBOARD_NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
4299  #define EBOARD_NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
4301  #define EBOARD_NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
4303  #define EBOARD_NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
4305  #define EBOARD_NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
4307  #define EBOARD_NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
4309  #define EBOARD_NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
4311  #define EBOARD_NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
4313  #define EBOARD_NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
4315  #define EBOARD_NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
4317  #define EBOARD_NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
4319  #define EBOARD_NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
4321 
4322 
4324  #define EBOARD_NEO_800KHZ 0x0000
4325  #define EBOARD_NEO_400KHZ 0x0100
4327 
4328  // uint16_t can be uint8_t in 800Khz mode ^^
4367  struct NeoPixel{
4375  NeoPixel(uint16_t n, uint8_t p = 6, uint16_t t = EBOARD_NEO_GRB + EBOARD_NEO_800KHZ);
4383  NeoPixel(void);
4385  ~NeoPixel(void);
4389  void begin(void);
4393  void show(void);
4398  void setPin(uint8_t p);
4406  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
4415  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
4421  void setPixelColor(uint16_t n, uint32_t c);
4429  void setBrightness(uint8_t val);
4433  void clear(void);
4438  void updateLength(uint16_t n);
4443  void updateType(uint16_t t);
4448  inline uint8_t *getPixels(void) const;
4453  inline uint8_t getBrightness(void) const;
4459  uint8_t sine8(uint8_t x) const;
4465  uint8_t gamma8(uint8_t x) const;
4470  inline int8_t getPin(void);
4475  inline uint16_t numPixels(void) const;
4482  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b);
4490  static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
4495  uint32_t getPixelColor(uint16_t n) const;
4500  inline bool canShow(void);
4501  protected:
4503  bool is800KHz;
4505  bool begun;
4507  uint16_t numLEDs; //maybe shorten with PrepConst 'extendetLED'?
4509  uint16_t numBytes;
4514  int8_t pin;
4516  uint8_t brightness;
4518  uint8_t *pixels;
4520  uint8_t aOffset[4];
4522  uint32_t endTime; //used for diff calc
4523  #ifdef __AVR__ //not needed (rem?)
4524  volatile uint8_t *port;// Output PORT register
4527  uint8_t pinMask; // Output PORT bitmask
4528  #endif
4529 
4530  };
4531 
4533 
4534 
4535  NeoPixel::NeoPixel(uint16_t n, uint8_t p, uint16_t t) :
4536  begun(false), brightness(0), pixels(NULL), endTime(0) {
4537  updateType(t);
4538  updateLength(n);
4539  setPin(p);
4540  }
4541 
4542  inline bool NeoPixel::canShow(void) { return (micros() - endTime) >= 300L; }
4543 
4544  NeoPixel::NeoPixel() :
4545  is800KHz(true),
4546  begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0), pixels(NULL),
4547  endTime(0)
4548  {aOffset[0]=1;aOffset[1]=0;aOffset[2]=2;aOffset[3]=1;}
4549 
4551  if(pixels) free(pixels);
4552  if(pin >= 0) pinMode(pin, INPUT);
4553  }
4554 
4555  void NeoPixel::begin(void) {
4556  if(pin >= 0) {
4557  pinMode(pin, OUTPUT);
4558  digitalWrite(pin, LOW);
4559  }
4560  begun = true;
4561 
4562  }
4563 
4564  void NeoPixel::updateLength(uint16_t n) {
4565  if(pixels) free(pixels);
4566  numBytes = n * ((aOffset[3] == aOffset[0]) ? 3 : 4);
4567  if((pixels = (uint8_t *)malloc(numBytes))) {
4568  memset(pixels, 0, numBytes);
4569  numLEDs = n;
4570  } else {
4571  numLEDs = numBytes = 0;
4572  }
4573  }
4574 
4575  void NeoPixel::updateType(uint16_t t) {
4576  boolean oldThreeBytesPerPixel = (aOffset[3] == aOffset[0]); // false if RGBW
4577 
4578  aOffset[3] = (t >> 6) & 0b11;
4579  aOffset[0] = (t >> 4) & 0b11;
4580  aOffset[1] = (t >> 2) & 0b11;
4581  aOffset[2] = t & 0b11;
4582  is800KHz = (t < 256); // 400 KHz flag is 1<<8
4583 
4584  if(pixels) {
4585  boolean newThreeBytesPerPixel = (aOffset[3] == aOffset[0]);
4586  if(newThreeBytesPerPixel != oldThreeBytesPerPixel) updateLength(numLEDs);
4587  }
4588  }
4589 
4590  #if defined(ESP8266)
4591  // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
4592  extern "C" void ICACHE_RAM_ATTR espShow(
4593  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
4594  #elif defined(ESP32)
4595  extern "C" void espShow(
4596  uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type);
4597  #endif
4598 
4599  void NeoPixel::show(void) {
4600  if(!pixels) return;
4601  while(!canShow()); //maybe timeout ?
4602  noInterrupts(); // Need 100% focus on instruction timing
4603 
4604  #ifdef __AVR__
4605  volatile uint16_t
4606  i = numBytes;
4607  volatile uint8_t
4608  *ptr = pixels,
4609  b = *ptr++,
4610  hi,
4611  lo;
4612 
4613  #if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
4614 
4615  if(is800KHz) {
4616  volatile uint8_t n1, n2 = 0;
4617 
4618  #if defined(PORTD)
4619  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
4620  if(port == &PORTD) {
4621  #endif
4622 
4623  hi = PORTD | pinMask;
4624  lo = PORTD & ~pinMask;
4625  n1 = lo;
4626  if(b & 0x80) n1 = hi;
4627 
4628  asm volatile(
4629  "headD:" "\n\t" // Clk Pseudocode
4630  // Bit 7:
4631  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4632  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4633  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4634  "rjmp .+0" "\n\t" // 2 nop nop
4635  "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40)
4636  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4637  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4638  "rjmp .+0" "\n\t" // 2 nop nop
4639  // Bit 6:
4640  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4641  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4642  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4643  "rjmp .+0" "\n\t" // 2 nop nop
4644  "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20)
4645  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4646  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4647  "rjmp .+0" "\n\t" // 2 nop nop
4648  // Bit 5:
4649  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4650  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4651  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4652  "rjmp .+0" "\n\t" // 2 nop nop
4653  "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10)
4654  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4655  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4656  "rjmp .+0" "\n\t" // 2 nop nop
4657  // Bit 4:
4658  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4659  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4660  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4661  "rjmp .+0" "\n\t" // 2 nop nop
4662  "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08)
4663  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4664  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4665  "rjmp .+0" "\n\t" // 2 nop nop
4666  // Bit 3:
4667  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4668  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4669  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4670  "rjmp .+0" "\n\t" // 2 nop nop
4671  "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04)
4672  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4673  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4674  "rjmp .+0" "\n\t" // 2 nop nop
4675  // Bit 2:
4676  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4677  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4678  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4679  "rjmp .+0" "\n\t" // 2 nop nop
4680  "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02)
4681  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4682  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4683  "rjmp .+0" "\n\t" // 2 nop nop
4684  // Bit 1:
4685  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4686  "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
4687  "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
4688  "rjmp .+0" "\n\t" // 2 nop nop
4689  "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01)
4690  "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
4691  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4692  "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
4693  // Bit 0:
4694  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
4695  "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
4696  "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
4697  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
4698  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80)
4699  "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
4700  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
4701  "brne headD" "\n" // 2 while(i) (Z flag set above)
4702  : [byte] "+r" (b),
4703  [n1] "+r" (n1),
4704  [n2] "+r" (n2),
4705  [count] "+w" (i)
4706  : [port] "I" (_SFR_IO_ADDR(PORTD)),
4707  [ptr] "e" (ptr),
4708  [hi] "r" (hi),
4709  [lo] "r" (lo));
4710 
4711  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
4712  } else
4713  #endif
4714  #endif
4715  #if defined(PORTB)
4716  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
4717  if(port == &PORTB) {
4718  #endif // defined(PORTD/C/F)
4719  hi = PORTB | pinMask;
4720  lo = PORTB & ~pinMask;
4721  n1 = lo;
4722  if(b & 0x80) n1 = hi;
4723 
4724  asm volatile(
4725  "headB:" "\n\t"
4726  "out %[port] , %[hi]" "\n\t"
4727  "mov %[n2] , %[lo]" "\n\t"
4728  "out %[port] , %[n1]" "\n\t"
4729  "rjmp .+0" "\n\t"
4730  "sbrc %[byte] , 6" "\n\t"
4731  "mov %[n2] , %[hi]" "\n\t"
4732  "out %[port] , %[lo]" "\n\t"
4733  "rjmp .+0" "\n\t"
4734  "out %[port] , %[hi]" "\n\t"
4735  "mov %[n1] , %[lo]" "\n\t"
4736  "out %[port] , %[n2]" "\n\t"
4737  "rjmp .+0" "\n\t"
4738  "sbrc %[byte] , 5" "\n\t"
4739  "mov %[n1] , %[hi]" "\n\t"
4740  "out %[port] , %[lo]" "\n\t"
4741  "rjmp .+0" "\n\t"
4742  "out %[port] , %[hi]" "\n\t"
4743  "mov %[n2] , %[lo]" "\n\t"
4744  "out %[port] , %[n1]" "\n\t"
4745  "rjmp .+0" "\n\t"
4746  "sbrc %[byte] , 4" "\n\t"
4747  "mov %[n2] , %[hi]" "\n\t"
4748  "out %[port] , %[lo]" "\n\t"
4749  "rjmp .+0" "\n\t"
4750  "out %[port] , %[hi]" "\n\t"
4751  "mov %[n1] , %[lo]" "\n\t"
4752  "out %[port] , %[n2]" "\n\t"
4753  "rjmp .+0" "\n\t"
4754  "sbrc %[byte] , 3" "\n\t"
4755  "mov %[n1] , %[hi]" "\n\t"
4756  "out %[port] , %[lo]" "\n\t"
4757  "rjmp .+0" "\n\t"
4758  "out %[port] , %[hi]" "\n\t"
4759  "mov %[n2] , %[lo]" "\n\t"
4760  "out %[port] , %[n1]" "\n\t"
4761  "rjmp .+0" "\n\t"
4762  "sbrc %[byte] , 2" "\n\t"
4763  "mov %[n2] , %[hi]" "\n\t"
4764  "out %[port] , %[lo]" "\n\t"
4765  "rjmp .+0" "\n\t"
4766  "out %[port] , %[hi]" "\n\t"
4767  "mov %[n1] , %[lo]" "\n\t"
4768  "out %[port] , %[n2]" "\n\t"
4769  "rjmp .+0" "\n\t"
4770  "sbrc %[byte] , 1" "\n\t"
4771  "mov %[n1] , %[hi]" "\n\t"
4772  "out %[port] , %[lo]" "\n\t"
4773  "rjmp .+0" "\n\t"
4774  "out %[port] , %[hi]" "\n\t"
4775  "mov %[n2] , %[lo]" "\n\t"
4776  "out %[port] , %[n1]" "\n\t"
4777  "rjmp .+0" "\n\t"
4778  "sbrc %[byte] , 0" "\n\t"
4779  "mov %[n2] , %[hi]" "\n\t"
4780  "out %[port] , %[lo]" "\n\t"
4781  "sbiw %[count], 1" "\n\t"
4782  "out %[port] , %[hi]" "\n\t"
4783  "mov %[n1] , %[lo]" "\n\t"
4784  "out %[port] , %[n2]" "\n\t"
4785  "ld %[byte] , %a[ptr]+" "\n\t"
4786  "sbrc %[byte] , 7" "\n\t"
4787  "mov %[n1] , %[hi]" "\n\t"
4788  "out %[port] , %[lo]" "\n\t"
4789  "brne headB" "\n"
4790  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
4791  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
4792  [lo] "r" (lo));
4793 
4794  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
4795  }
4796  #endif
4797  #if defined(PORTC) || defined(PORTF)
4798  else
4799  #endif
4800  #endif
4801 
4802  #if defined(PORTC)
4803  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
4804  if(port == &PORTC) {
4805  #endif
4806 
4807  hi = PORTC | pinMask;
4808  lo = PORTC & ~pinMask;
4809  n1 = lo;
4810  if(b & 0x80) n1 = hi;
4811 
4812  asm volatile(
4813  "headC:" "\n\t"
4814  "out %[port] , %[hi]" "\n\t"
4815  "mov %[n2] , %[lo]" "\n\t"
4816  "out %[port] , %[n1]" "\n\t"
4817  "rjmp .+0" "\n\t"
4818  "sbrc %[byte] , 6" "\n\t"
4819  "mov %[n2] , %[hi]" "\n\t"
4820  "out %[port] , %[lo]" "\n\t"
4821  "rjmp .+0" "\n\t"
4822  "out %[port] , %[hi]" "\n\t"
4823  "mov %[n1] , %[lo]" "\n\t"
4824  "out %[port] , %[n2]" "\n\t"
4825  "rjmp .+0" "\n\t"
4826  "sbrc %[byte] , 5" "\n\t"
4827  "mov %[n1] , %[hi]" "\n\t"
4828  "out %[port] , %[lo]" "\n\t"
4829  "rjmp .+0" "\n\t"
4830  "out %[port] , %[hi]" "\n\t"
4831  "mov %[n2] , %[lo]" "\n\t"
4832  "out %[port] , %[n1]" "\n\t"
4833  "rjmp .+0" "\n\t"
4834  "sbrc %[byte] , 4" "\n\t"
4835  "mov %[n2] , %[hi]" "\n\t"
4836  "out %[port] , %[lo]" "\n\t"
4837  "rjmp .+0" "\n\t"
4838  "out %[port] , %[hi]" "\n\t"
4839  "mov %[n1] , %[lo]" "\n\t"
4840  "out %[port] , %[n2]" "\n\t"
4841  "rjmp .+0" "\n\t"
4842  "sbrc %[byte] , 3" "\n\t"
4843  "mov %[n1] , %[hi]" "\n\t"
4844  "out %[port] , %[lo]" "\n\t"
4845  "rjmp .+0" "\n\t"
4846  "out %[port] , %[hi]" "\n\t"
4847  "mov %[n2] , %[lo]" "\n\t"
4848  "out %[port] , %[n1]" "\n\t"
4849  "rjmp .+0" "\n\t"
4850  "sbrc %[byte] , 2" "\n\t"
4851  "mov %[n2] , %[hi]" "\n\t"
4852  "out %[port] , %[lo]" "\n\t"
4853  "rjmp .+0" "\n\t"
4854  "out %[port] , %[hi]" "\n\t"
4855  "mov %[n1] , %[lo]" "\n\t"
4856  "out %[port] , %[n2]" "\n\t"
4857  "rjmp .+0" "\n\t"
4858  "sbrc %[byte] , 1" "\n\t"
4859  "mov %[n1] , %[hi]" "\n\t"
4860  "out %[port] , %[lo]" "\n\t"
4861  "rjmp .+0" "\n\t"
4862  "out %[port] , %[hi]" "\n\t"
4863  "mov %[n2] , %[lo]" "\n\t"
4864  "out %[port] , %[n1]" "\n\t"
4865  "rjmp .+0" "\n\t"
4866  "sbrc %[byte] , 0" "\n\t"
4867  "mov %[n2] , %[hi]" "\n\t"
4868  "out %[port] , %[lo]" "\n\t"
4869  "sbiw %[count], 1" "\n\t"
4870  "out %[port] , %[hi]" "\n\t"
4871  "mov %[n1] , %[lo]" "\n\t"
4872  "out %[port] , %[n2]" "\n\t"
4873  "ld %[byte] , %a[ptr]+" "\n\t"
4874  "sbrc %[byte] , 7" "\n\t"
4875  "mov %[n1] , %[hi]" "\n\t"
4876  "out %[port] , %[lo]" "\n\t"
4877  "brne headC" "\n"
4878  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
4879  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
4880  [lo] "r" (lo));
4881 
4882  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
4883  }
4884  #endif
4885  #if defined(PORTF)
4886  else
4887  #endif
4888  #endif
4889 
4890  #if defined(PORTF)
4891  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
4892  if(port == &PORTF) {
4893  #endif // defined(PORTD/B/C)
4894 
4895  hi = PORTF | pinMask;
4896  lo = PORTF & ~pinMask;
4897  n1 = lo;
4898  if(b & 0x80) n1 = hi;
4899 
4900  asm volatile(
4901  "headF:" "\n\t"
4902  "out %[port] , %[hi]" "\n\t"
4903  "mov %[n2] , %[lo]" "\n\t"
4904  "out %[port] , %[n1]" "\n\t"
4905  "rjmp .+0" "\n\t"
4906  "sbrc %[byte] , 6" "\n\t"
4907  "mov %[n2] , %[hi]" "\n\t"
4908  "out %[port] , %[lo]" "\n\t"
4909  "rjmp .+0" "\n\t"
4910  "out %[port] , %[hi]" "\n\t"
4911  "mov %[n1] , %[lo]" "\n\t"
4912  "out %[port] , %[n2]" "\n\t"
4913  "rjmp .+0" "\n\t"
4914  "sbrc %[byte] , 5" "\n\t"
4915  "mov %[n1] , %[hi]" "\n\t"
4916  "out %[port] , %[lo]" "\n\t"
4917  "rjmp .+0" "\n\t"
4918  "out %[port] , %[hi]" "\n\t"
4919  "mov %[n2] , %[lo]" "\n\t"
4920  "out %[port] , %[n1]" "\n\t"
4921  "rjmp .+0" "\n\t"
4922  "sbrc %[byte] , 4" "\n\t"
4923  "mov %[n2] , %[hi]" "\n\t"
4924  "out %[port] , %[lo]" "\n\t"
4925  "rjmp .+0" "\n\t"
4926  "out %[port] , %[hi]" "\n\t"
4927  "mov %[n1] , %[lo]" "\n\t"
4928  "out %[port] , %[n2]" "\n\t"
4929  "rjmp .+0" "\n\t"
4930  "sbrc %[byte] , 3" "\n\t"
4931  "mov %[n1] , %[hi]" "\n\t"
4932  "out %[port] , %[lo]" "\n\t"
4933  "rjmp .+0" "\n\t"
4934  "out %[port] , %[hi]" "\n\t"
4935  "mov %[n2] , %[lo]" "\n\t"
4936  "out %[port] , %[n1]" "\n\t"
4937  "rjmp .+0" "\n\t"
4938  "sbrc %[byte] , 2" "\n\t"
4939  "mov %[n2] , %[hi]" "\n\t"
4940  "out %[port] , %[lo]" "\n\t"
4941  "rjmp .+0" "\n\t"
4942  "out %[port] , %[hi]" "\n\t"
4943  "mov %[n1] , %[lo]" "\n\t"
4944  "out %[port] , %[n2]" "\n\t"
4945  "rjmp .+0" "\n\t"
4946  "sbrc %[byte] , 1" "\n\t"
4947  "mov %[n1] , %[hi]" "\n\t"
4948  "out %[port] , %[lo]" "\n\t"
4949  "rjmp .+0" "\n\t"
4950  "out %[port] , %[hi]" "\n\t"
4951  "mov %[n2] , %[lo]" "\n\t"
4952  "out %[port] , %[n1]" "\n\t"
4953  "rjmp .+0" "\n\t"
4954  "sbrc %[byte] , 0" "\n\t"
4955  "mov %[n2] , %[hi]" "\n\t"
4956  "out %[port] , %[lo]" "\n\t"
4957  "sbiw %[count], 1" "\n\t"
4958  "out %[port] , %[hi]" "\n\t"
4959  "mov %[n1] , %[lo]" "\n\t"
4960  "out %[port] , %[n2]" "\n\t"
4961  "ld %[byte] , %a[ptr]+" "\n\t"
4962  "sbrc %[byte] , 7" "\n\t"
4963  "mov %[n1] , %[hi]" "\n\t"
4964  "out %[port] , %[lo]" "\n\t"
4965  "brne headF" "\n"
4966  : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
4967  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
4968  [lo] "r" (lo));
4969 
4970  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
4971  }
4972  #endif // defined(PORTD/B/C)
4973  #endif // defined(PORTF)
4974  } else {
4975 
4976  volatile uint8_t next, bit;
4977 
4978  hi = *port | pinMask;
4979  lo = *port & ~pinMask;
4980  next = lo;
4981  bit = 8;
4982 
4983  asm volatile(
4984  "head20:" "\n\t" // Clk Pseudocode (T = 0)
4985  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
4986  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
4987  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
4988  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6)
4989  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
4990  "dec %[bit]" "\n\t" // 1 bit-- (T = 8)
4991  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0)
4992  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
4993  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
4994  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
4995  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
4996  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
4997  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
4998  "nextbyte20:" "\n\t" // (T = 10)
4999  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
5000  "nop" "\n\t" // 1 nop (T = 13)
5001  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14)
5002  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16)
5003  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
5004  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
5005  : [port] "+e" (port),
5006  [byte] "+r" (b),
5007  [bit] "+r" (bit),
5008  [next] "+r" (next),
5009  [count] "+w" (i)
5010  : [hi] "r" (hi),
5011  [lo] "r" (lo),
5012  [ptr] "e" (ptr));
5013  }
5014  #elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
5015  if(is800KHz) {
5016  volatile uint8_t next;
5017 
5018  // PORTD OUTPUT ----------------------------------------------------
5019 
5020  #if defined(PORTD)
5021  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
5022  if(port == &PORTD) {
5023  #endif
5024 
5025  hi = PORTD | pinMask;
5026  lo = PORTD & ~pinMask;
5027  next = lo;
5028  if(b & 0x80) next = hi;
5029  asm volatile(
5030  "headD:" "\n\t" // (T = 0)
5031  "out %[port], %[hi]" "\n\t" // (T = 1)
5032  "rcall bitTimeD" "\n\t" // Bit 7 (T = 15)
5033  "out %[port], %[hi]" "\n\t"
5034  "rcall bitTimeD" "\n\t" // Bit 6
5035  "out %[port], %[hi]" "\n\t"
5036  "rcall bitTimeD" "\n\t" // Bit 5
5037  "out %[port], %[hi]" "\n\t"
5038  "rcall bitTimeD" "\n\t" // Bit 4
5039  "out %[port], %[hi]" "\n\t"
5040  "rcall bitTimeD" "\n\t" // Bit 3
5041  "out %[port], %[hi]" "\n\t"
5042  "rcall bitTimeD" "\n\t" // Bit 2
5043  "out %[port], %[hi]" "\n\t"
5044  "rcall bitTimeD" "\n\t" // Bit 1
5045  // Bit 0:
5046  "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1)
5047  "rjmp .+0" "\n\t" // 2 nop nop (T = 3)
5048  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5)
5049  "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6)
5050  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
5051  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
5052  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
5053  "nop" "\n\t" // 1 (T = 10)
5054  "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11)
5055  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
5056  "brne headD" "\n\t" // 2 if(i != 0) -> (next byte)
5057  "rjmp doneD" "\n\t"
5058  "bitTimeD:" "\n\t" // nop nop nop (T = 4)
5059  "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
5060  "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
5061  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
5062  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
5063  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
5064  "nop" "\n\t" // 1 (T = 10)
5065  "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
5066  "ret" "\n\t" // 4 nop nop nop nop (T = 15)
5067  "doneD:" "\n"
5068  : [byte] "+r" (b),
5069  [next] "+r" (next),
5070  [count] "+w" (i)
5071  : [port] "I" (_SFR_IO_ADDR(PORTD)),
5072  [ptr] "e" (ptr),
5073  [hi] "r" (hi),
5074  [lo] "r" (lo));
5075 
5076  #if defined(PORTB) || defined(PORTC) || defined(PORTF)
5077  } else
5078  #endif
5079  #endif
5080 
5081  #if defined(PORTB)
5082  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
5083  if(port == &PORTB) {
5084  #endif
5085 
5086  hi = PORTB | pinMask;
5087  lo = PORTB & ~pinMask;
5088  next = lo;
5089  if(b & 0x80) next = hi;
5090 
5091  asm volatile(
5092  "headB:" "\n\t"
5093  "out %[port], %[hi]" "\n\t"
5094  "rcall bitTimeB" "\n\t"
5095  "out %[port], %[hi]" "\n\t"
5096  "rcall bitTimeB" "\n\t"
5097  "out %[port], %[hi]" "\n\t"
5098  "rcall bitTimeB" "\n\t"
5099  "out %[port], %[hi]" "\n\t"
5100  "rcall bitTimeB" "\n\t"
5101  "out %[port], %[hi]" "\n\t"
5102  "rcall bitTimeB" "\n\t"
5103  "out %[port], %[hi]" "\n\t"
5104  "rcall bitTimeB" "\n\t"
5105  "out %[port], %[hi]" "\n\t"
5106  "rcall bitTimeB" "\n\t"
5107  "out %[port] , %[hi]" "\n\t"
5108  "rjmp .+0" "\n\t"
5109  "ld %[byte] , %a[ptr]+" "\n\t"
5110  "out %[port] , %[next]" "\n\t"
5111  "mov %[next] , %[lo]" "\n\t"
5112  "sbrc %[byte] , 7" "\n\t"
5113  "mov %[next] , %[hi]" "\n\t"
5114  "nop" "\n\t"
5115  "out %[port] , %[lo]" "\n\t"
5116  "sbiw %[count], 1" "\n\t"
5117  "brne headB" "\n\t"
5118  "rjmp doneB" "\n\t"
5119  "bitTimeB:" "\n\t"
5120  "out %[port], %[next]" "\n\t"
5121  "mov %[next], %[lo]" "\n\t"
5122  "rol %[byte]" "\n\t"
5123  "sbrc %[byte], 7" "\n\t"
5124  "mov %[next], %[hi]" "\n\t"
5125  "nop" "\n\t"
5126  "out %[port], %[lo]" "\n\t"
5127  "ret" "\n\t"
5128  "doneB:" "\n"
5129  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5130  : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
5131  [lo] "r" (lo));
5132 
5133  #if defined(PORTD) || defined(PORTC) || defined(PORTF)
5134  }
5135  #endif
5136  #if defined(PORTC) || defined(PORTF)
5137  else
5138  #endif
5139  #endif
5140 
5141  #if defined(PORTC)
5142  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
5143  if(port == &PORTC) {
5144  #endif
5145 
5146  hi = PORTC | pinMask;
5147  lo = PORTC & ~pinMask;
5148  next = lo;
5149  if(b & 0x80) next = hi;
5150 
5151  asm volatile(
5152  "headC:" "\n\t"
5153  "out %[port], %[hi]" "\n\t"
5154  "rcall bitTimeC" "\n\t"
5155  "out %[port], %[hi]" "\n\t"
5156  "rcall bitTimeC" "\n\t"
5157  "out %[port], %[hi]" "\n\t"
5158  "rcall bitTimeC" "\n\t"
5159  "out %[port], %[hi]" "\n\t"
5160  "rcall bitTimeC" "\n\t"
5161  "out %[port], %[hi]" "\n\t"
5162  "rcall bitTimeC" "\n\t"
5163  "out %[port], %[hi]" "\n\t"
5164  "rcall bitTimeC" "\n\t"
5165  "out %[port], %[hi]" "\n\t"
5166  "rcall bitTimeC" "\n\t"
5167  "out %[port] , %[hi]" "\n\t"
5168  "rjmp .+0" "\n\t"
5169  "ld %[byte] , %a[ptr]+" "\n\t"
5170  "out %[port] , %[next]" "\n\t"
5171  "mov %[next] , %[lo]" "\n\t"
5172  "sbrc %[byte] , 7" "\n\t"
5173  "mov %[next] , %[hi]" "\n\t"
5174  "nop" "\n\t"
5175  "out %[port] , %[lo]" "\n\t"
5176  "sbiw %[count], 1" "\n\t"
5177  "brne headC" "\n\t"
5178  "rjmp doneC" "\n\t"
5179  "bitTimeC:" "\n\t"
5180  "out %[port], %[next]" "\n\t"
5181  "mov %[next], %[lo]" "\n\t"
5182  "rol %[byte]" "\n\t"
5183  "sbrc %[byte], 7" "\n\t"
5184  "mov %[next], %[hi]" "\n\t"
5185  "nop" "\n\t"
5186  "out %[port], %[lo]" "\n\t"
5187  "ret" "\n\t"
5188  "doneC:" "\n"
5189  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5190  : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
5191  [lo] "r" (lo));
5192 
5193  #if defined(PORTD) || defined(PORTB) || defined(PORTF)
5194  }
5195  #endif
5196  #if defined(PORTF)
5197  else
5198  #endif
5199  #endif
5200 
5201  #if defined(PORTF)
5202  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
5203  if(port == &PORTF) {
5204  #endif
5205 
5206  hi = PORTF | pinMask;
5207  lo = PORTF & ~pinMask;
5208  next = lo;
5209  if(b & 0x80) next = hi;
5210 
5211  asm volatile(
5212  "headF:" "\n\t"
5213  "out %[port], %[hi]" "\n\t"
5214  "rcall bitTimeC" "\n\t"
5215  "out %[port], %[hi]" "\n\t"
5216  "rcall bitTimeC" "\n\t"
5217  "out %[port], %[hi]" "\n\t"
5218  "rcall bitTimeC" "\n\t"
5219  "out %[port], %[hi]" "\n\t"
5220  "rcall bitTimeC" "\n\t"
5221  "out %[port], %[hi]" "\n\t"
5222  "rcall bitTimeC" "\n\t"
5223  "out %[port], %[hi]" "\n\t"
5224  "rcall bitTimeC" "\n\t"
5225  "out %[port], %[hi]" "\n\t"
5226  "rcall bitTimeC" "\n\t"
5227  "out %[port] , %[hi]" "\n\t"
5228  "rjmp .+0" "\n\t"
5229  "ld %[byte] , %a[ptr]+" "\n\t"
5230  "out %[port] , %[next]" "\n\t"
5231  "mov %[next] , %[lo]" "\n\t"
5232  "sbrc %[byte] , 7" "\n\t"
5233  "mov %[next] , %[hi]" "\n\t"
5234  "nop" "\n\t"
5235  "out %[port] , %[lo]" "\n\t"
5236  "sbiw %[count], 1" "\n\t"
5237  "brne headF" "\n\t"
5238  "rjmp doneC" "\n\t"
5239  "bitTimeC:" "\n\t"
5240  "out %[port], %[next]" "\n\t"
5241  "mov %[next], %[lo]" "\n\t"
5242  "rol %[byte]" "\n\t"
5243  "sbrc %[byte], 7" "\n\t"
5244  "mov %[next], %[hi]" "\n\t"
5245  "nop" "\n\t"
5246  "out %[port], %[lo]" "\n\t"
5247  "ret" "\n\t"
5248  "doneC:" "\n"
5249  : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
5250  : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
5251  [lo] "r" (lo));
5252 
5253  #if defined(PORTD) || defined(PORTB) || defined(PORTC)
5254  }
5255  #endif
5256  #endif
5257  } else {
5258  volatile uint8_t next, bit;
5259 
5260  hi = *port | pinMask;
5261  lo = *port & ~pinMask;
5262  next = lo;
5263  bit = 8;
5264 
5265  asm volatile(
5266  "head30:" "\n\t" // Clk Pseudocode (T = 0)
5267  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5268  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
5269  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5270  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
5271  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8)
5272  "rjmp .+0" "\n\t" // 2 nop nop (T = 10)
5273  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5274  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
5275  "nop" "\n\t" // 1 nop (T = 15)
5276  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17)
5277  "rjmp .+0" "\n\t" // 2 nop nop (T = 19)
5278  "dec %[bit]" "\n\t" // 1 bit-- (T = 20)
5279  "breq nextbyte30" "\n\t" // 1-2 if(bit == 0)
5280  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
5281  "rjmp .+0" "\n\t" // 2 nop nop (T = 24)
5282  "rjmp .+0" "\n\t" // 2 nop nop (T = 26)
5283  "rjmp .+0" "\n\t" // 2 nop nop (T = 28)
5284  "rjmp head30" "\n\t" // 2 -> head30 (next bit out)
5285  "nextbyte30:" "\n\t" // (T = 22)
5286  "nop" "\n\t" // 1 nop (T = 23)
5287  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24)
5288  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26)
5289  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
5290  "brne head30" "\n" // 1-2 if(i != 0) -> (next byte)
5291  : [port] "+e" (port),
5292  [byte] "+r" (b),
5293  [bit] "+r" (bit),
5294  [next] "+r" (next),
5295  [count] "+w" (i)
5296  : [hi] "r" (hi),
5297  [lo] "r" (lo),
5298  [ptr] "e" (ptr));
5299  }
5300  #elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
5301  if(is800KHz) {
5302  volatile uint8_t next, bit;
5303 
5304  hi = *port | pinMask;
5305  lo = *port & ~pinMask;
5306  next = lo;
5307  bit = 8;
5308 
5309  asm volatile(
5310  "head20:" "\n\t" // Clk Pseudocode (T = 0)
5311  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5312  "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128)
5313  "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5314  "dec %[bit]" "\n\t" // 1 bit-- (T = 5)
5315  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7)
5316  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
5317  "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above)
5318  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
5319  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5320  "nop" "\n\t" // 1 nop (T = 13)
5321  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
5322  "nop" "\n\t" // 1 nop (T = 16)
5323  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
5324  "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
5325  "nextbyte20:" "\n\t" // (T = 10)
5326  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
5327  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
5328  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
5329  "nop" "\n\t" // 1 nop (T = 16)
5330  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
5331  "brne head20" "\n" // 2 if(i != 0) -> (next byte)
5332  : [port] "+e" (port),
5333  [byte] "+r" (b),
5334  [bit] "+r" (bit),
5335  [next] "+r" (next),
5336  [count] "+w" (i)
5337  : [ptr] "e" (ptr),
5338  [hi] "r" (hi),
5339  [lo] "r" (lo));
5340  } else {
5341 
5342  volatile uint8_t next, bit;
5343 
5344  hi = *port | pinMask;
5345  lo = *port & ~pinMask;
5346  next = lo;
5347  bit = 8;
5348 
5349  asm volatile(
5350  "head40:" "\n\t" // Clk Pseudocode (T = 0)
5351  "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
5352  "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
5353  "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4)
5354  "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
5355  "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
5356  "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10)
5357  "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
5358  "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
5359  "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
5360  "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
5361  "rjmp .+0" "\n\t" // 2 nop nop (T = 20)
5362  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22)
5363  "nop" "\n\t" // 1 nop (T = 23)
5364  "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24)
5365  "dec %[bit]" "\n\t" // 1 bit-- (T = 25)
5366  "breq nextbyte40" "\n\t" // 1-2 if(bit == 0)
5367  "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
5368  "nop" "\n\t" // 1 nop (T = 28)
5369  "rjmp .+0" "\n\t" // 2 nop nop (T = 30)
5370  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
5371  "rjmp .+0" "\n\t" // 2 nop nop (T = 34)
5372  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
5373  "rjmp .+0" "\n\t" // 2 nop nop (T = 38)
5374  "rjmp head40" "\n\t" // 2 -> head40 (next bit out)
5375  "nextbyte40:" "\n\t" // (T = 27)
5376  "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28)
5377  "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30)
5378  "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
5379  "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34)
5380  "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
5381  "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
5382  "brne head40" "\n" // 1-2 if(i != 0) -> (next byte)
5383  : [port] "+e" (port),
5384  [byte] "+r" (b),
5385  [bit] "+r" (bit),
5386  [next] "+r" (next),
5387  [count] "+w" (i)
5388  : [ptr] "e" (ptr),
5389  [hi] "r" (hi),
5390  [lo] "r" (lo));
5391  }
5392  #else
5393  #error "CPU SPEED NOT SUPPORTED"
5394  #endif
5395  #elif defined(__arm__)
5396 
5397 
5398  #if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
5399  #define CYCLES_800_T0H (F_CPU / 4000000)
5400  #define CYCLES_800_T1H (F_CPU / 1250000)
5401  #define CYCLES_800 (F_CPU / 800000)
5402  #define CYCLES_400_T0H (F_CPU / 2000000)
5403  #define CYCLES_400_T1H (F_CPU / 833333)
5404  #define CYCLES_400 (F_CPU / 400000)
5405 
5406  uint8_t *p = pixels,
5407  *end = p + numBytes, pix, mask;
5408  volatile uint8_t *set = portSetRegister(pin),
5409  *clr = portClearRegister(pin);
5410  uint32_t cyc;
5411 
5412  ARM_DEMCR |= ARM_DEMCR_TRCENA;
5413  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
5414 
5415  if(is800KHz) {
5416  cyc = ARM_DWT_CYCCNT + CYCLES_800;
5417  while(p < end) {
5418  pix = *p++;
5419  for(mask = 0x80; mask; mask >>= 1) {
5420  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
5421  cyc = ARM_DWT_CYCCNT;
5422  *set = 1;
5423  if(pix & mask) {
5424  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
5425  } else {
5426  while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
5427  }
5428  *clr = 1;
5429  }
5430  }
5431  while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
5432  } else {
5433  cyc = ARM_DWT_CYCCNT + CYCLES_400;
5434  while(p < end) {
5435  pix = *p++;
5436  for(mask = 0x80; mask; mask >>= 1) {
5437  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
5438  cyc = ARM_DWT_CYCCNT;
5439  *set = 1;
5440  if(pix & mask) {
5441  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
5442  } else {
5443  while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
5444  }
5445  *clr = 1;
5446  }
5447  }
5448  while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
5449  }
5450  #else
5451  #error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
5452  #endif
5453  #elif defined(ESP8266) || defined(ESP32)
5454 
5455  espShow(pin, pixels, numBytes, is800KHz);
5456 
5457  #elif defined(__ARDUINO_ARC__)
5458 
5459  // Arduino 101 -----------------------------------------------------------
5460 
5461  #define NOPx7 { __builtin_arc_nop(); \
5462  __builtin_arc_nop(); __builtin_arc_nop(); \
5463  __builtin_arc_nop(); __builtin_arc_nop(); \
5464  __builtin_arc_nop(); __builtin_arc_nop(); }
5465 
5466  PinDescription *pindesc = &g_APinDescription[pin];
5467  register uint32_t loop = 8 * numBytes; // one loop to handle all bytes and all bits
5468  register uint8_t *p = pixels;
5469  register uint32_t currByte = (uint32_t) (*p);
5470  register uint32_t currBit = 0x80 & currByte;
5471  register uint32_t bitCounter = 0;
5472  register uint32_t first = 1;
5473 
5474  if (pindesc->ulGPIOType == SS_GPIO) {
5475  register uint32_t reg = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR;
5476  uint32_t reg_val = __builtin_arc_lr((volatile uint32_t)reg);
5477  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
5478  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
5479 
5480  loop += 1;
5481  while(loop--) {
5482  if(!first) {
5483  currByte <<= 1;
5484  bitCounter++;
5485  }
5486 
5487  // 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
5488  __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile uint32_t)reg);
5489  if(currBit) { // ~400ns HIGH (740ns overall)
5490  NOPx7
5491  NOPx7
5492  }
5493  // ~340ns HIGH
5494  NOPx7
5495  __builtin_arc_nop();
5496 
5497  // 820ns LOW; per spec, max allowed low here is 5000ns */
5498  __builtin_arc_sr(reg_bit_low, (volatile uint32_t)reg);
5499  NOPx7
5500  NOPx7
5501 
5502  if(bitCounter >= 8) {
5503  bitCounter = 0;
5504  currByte = (uint32_t) (*++p);
5505  }
5506 
5507  currBit = 0x80 & currByte;
5508  first = 0;
5509  }
5510  } else if(pindesc->ulGPIOType == SOC_GPIO) {
5511  register uint32_t reg = pindesc->ulGPIOBase + SOC_GPIO_SWPORTA_DR;
5512  uint32_t reg_val = MMIO_REG_VAL(reg);
5513  register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
5514  register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId);
5515 
5516  loop += 1; // include first, special iteration
5517  while(loop--) {
5518  if(!first) {
5519  currByte <<= 1;
5520  bitCounter++;
5521  }
5522  MMIO_REG_VAL(reg) = first ? reg_bit_low : reg_bit_high;
5523  if(currBit) { // ~430ns HIGH (740ns overall)
5524  NOPx7
5525  NOPx7
5526  __builtin_arc_nop();
5527  }
5528  // ~310ns HIGH
5529  NOPx7
5530 
5531  // 850ns LOW; per spec, max allowed low here is 5000ns */
5532  MMIO_REG_VAL(reg) = reg_bit_low;
5533  NOPx7
5534  NOPx7
5535 
5536  if(bitCounter >= 8) {
5537  bitCounter = 0;
5538  currByte = (uint32_t) (*++p);
5539  }
5540 
5541  currBit = 0x80 & currByte;
5542  first = 0;
5543  }
5544  }
5545 
5546  #else
5547  #error Architecture not supported
5548  #endif
5549 
5550  interrupts();
5551 
5552  endTime = micros();
5553  }
5554 
5555  void NeoPixel::setPin(uint8_t p) {
5556  if(begun && (pin >= 0)) pinMode(pin, INPUT);
5557  pin = p;
5558  if(begun) {
5559  pinMode(p, OUTPUT);
5560  digitalWrite(p, LOW);
5561  }
5562  #ifdef __AVR__
5563  port = portOutputRegister(digitalPinToPort(p));
5564  pinMask = digitalPinToBitMask(p);
5565  #endif
5566  }
5567 
5569  uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
5570 
5571  if(n < numLEDs) {
5572  if(brightness) { // See notes in setBrightness()
5573  r = (r * brightness) >> 8;
5574  g = (g * brightness) >> 8;
5575  b = (b * brightness) >> 8;
5576  }
5577  uint8_t *p;
5578  if(aOffset[3] == aOffset[0]) {
5579  p = &pixels[n * 3];
5580  } else {
5581  p = &pixels[n * 4];
5582  p[aOffset[3]] = 0;
5583  }
5584  p[aOffset[0]] = r;
5585  p[aOffset[1]] = g;
5586  p[aOffset[2]] = b;
5587  }
5588  }
5589 
5591  uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
5592 
5593  if(n < numLEDs) {
5594  if(brightness) {
5595  r = (r * brightness) >> 8;
5596  g = (g * brightness) >> 8;
5597  b = (b * brightness) >> 8;
5598  w = (w * brightness) >> 8;
5599  }
5600  uint8_t *p;
5601  if(aOffset[3] == aOffset[0]) {
5602  p = &pixels[n * 3];
5603  } else {
5604  p = &pixels[n * 4];
5605  p[aOffset[3]] = w;
5606  }
5607  p[aOffset[0]] = r;
5608  p[aOffset[1]] = g;
5609  p[aOffset[2]] = b;
5610  }
5611  }
5612 
5613  void NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
5614  if(n < numLEDs) {
5615  uint8_t *p,
5616  r = (uint8_t)(c >> 16),
5617  g = (uint8_t)(c >> 8),
5618  b = (uint8_t)c;
5619  if(brightness) {
5620  r = (r * brightness) >> 8;
5621  g = (g * brightness) >> 8;
5622  b = (b * brightness) >> 8;
5623  }
5624  if(aOffset[3] == aOffset[0]) {
5625  p = &pixels[n * 3];
5626  } else {
5627  p = &pixels[n * 4];
5628  uint8_t w = (uint8_t)(c >> 24);
5629  p[aOffset[3]] = brightness ? ((w * brightness) >> 8) : w;
5630  }
5631  p[aOffset[0]] = r;
5632  p[aOffset[1]] = g;
5633  p[aOffset[2]] = b;
5634  }
5635  }
5636 
5637  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
5638  return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
5639  }
5640 
5641  uint32_t NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
5642  return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
5643  }
5644 
5645  uint32_t NeoPixel::getPixelColor(uint16_t n) const {
5646  if(n >= numLEDs) return 0;
5647 
5648  uint8_t *p;
5649 
5650  if(aOffset[3] == aOffset[0]) {
5651  p = &pixels[n * 3];
5652  if(brightness) {
5653 
5654  return (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
5655  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
5656  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
5657  } else {
5658  return ((uint32_t)p[aOffset[0]] << 16) |
5659  ((uint32_t)p[aOffset[1]] << 8) |
5660  (uint32_t)p[aOffset[2]];
5661  }
5662  } else {
5663  p = &pixels[n * 4];
5664  if(brightness) {
5665  return (((uint32_t)(p[aOffset[3]] << 8) / brightness) << 24) |
5666  (((uint32_t)(p[aOffset[0]] << 8) / brightness) << 16) |
5667  (((uint32_t)(p[aOffset[1]] << 8) / brightness) << 8) |
5668  ( (uint32_t)(p[aOffset[2]] << 8) / brightness );
5669  } else {
5670  return ((uint32_t)p[aOffset[3]] << 24) |
5671  ((uint32_t)p[aOffset[0]] << 16) |
5672  ((uint32_t)p[aOffset[1]] << 8) |
5673  (uint32_t)p[aOffset[2]];
5674  }
5675  }
5676  }
5677 
5678 
5679  uint8_t *NeoPixel::getPixels(void) const {
5680  return pixels;
5681  }
5682 
5683  uint16_t NeoPixel::numPixels(void) const {
5684  return numLEDs;
5685  }
5686 
5687  void NeoPixel::setBrightness(uint8_t b) {
5688 
5689  uint8_t newBrightness = b + 1;
5690  if(newBrightness != brightness) {
5691  uint8_t c,
5692  *ptr = pixels,
5693  oldBrightness = brightness - 1;
5694  uint16_t scale;
5695  if(oldBrightness == 0) scale = 0; // Avoid /0
5696  else if(b == 255) scale = 65535 / oldBrightness;
5697  else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
5698  for(uint16_t i=0; i<numBytes; i++) {
5699  c = *ptr;
5700  *ptr++ = (c * scale) >> 8;
5701  }
5702  brightness = newBrightness;
5703  }
5704  }
5705 
5706  uint8_t NeoPixel::getBrightness(void) const {
5707  return brightness - 1;
5708  }
5709 
5710  void NeoPixel::clear() {
5711  memset(pixels, 0, numBytes);
5712  }
5713 
5714  static const uint8_t PROGMEM _sineTable[256] = {
5715  128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,
5716  176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
5717  218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,
5718  245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
5719  255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
5720  245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
5721  218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,
5722  176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
5723  128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82,
5724  79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
5725  37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
5726  10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0,
5727  0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
5728  10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
5729  37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
5730  79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124};
5731 
5732  static const uint8_t PROGMEM _gammaTable[256] = {
5733  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5734  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
5735  1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
5736  3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7,
5737  7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12,
5738  13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
5739  20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
5740  30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
5741  42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
5742  58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
5743  76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
5744  97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
5745  122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
5746  150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
5747  182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
5748  218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255};
5749 
5750  uint8_t NeoPixel::sine8(uint8_t x) const {
5751  return pgm_read_byte(&_sineTable[x]); // 0-255 in, 0-255 out
5752  }
5753 
5754  uint8_t NeoPixel::gamma8(uint8_t x) const {
5755  return pgm_read_byte(&_gammaTable[x]); // 0-255 in, 0-255 out
5756  }
5757 
5758  #endif
5759 
6126 #if EBOARD_NANO > 0x0 || defined(DOC)
6127 //offer more functions
6128  #if EBOARD_GUESSPATH > 0x0
6129  //import servo-class
6131  //shameless copy paste :D
6132  #define _useTimer1
6133  typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
6134  #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
6135  #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
6136  #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
6137  #define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
6138 
6139  #define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
6140  #define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
6141 
6142  #define INVALID_SERVO 255 // flag indicating an invalid servo index
6143  typedef struct {
6144  uint8_t nbr :6 ; // a pin number from 0 to 63
6145  uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
6146  } ServoPin_t;
6147 
6148  typedef struct {
6149  ServoPin_t Pin;
6150  volatile unsigned int ticks;
6151  } servo_t;
6152 
6153  class Servo {
6154  public:
6155  Servo();
6156  uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
6157  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
6158  void detach();
6159  void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
6160  void writeMicroseconds(int value); // Write pulse width in microseconds
6161  inline int read(); // returns current pulse width as an angle between 0 and 180 degrees
6162  int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
6163  inline bool attached(); // return true if this servo is attached, otherwise false
6164  private:
6165  uint8_t servoIndex; // index into the channel data for this servo
6166  int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
6167  int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
6168  };
6169  #define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
6170  #define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
6171 
6172 
6173  #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
6174 
6175  //#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
6176 
6177  static servo_t servos[MAX_SERVOS]; // static array of servo structures
6178  static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
6179 
6180  uint8_t ServoCount = 0; // the total number of attached servos
6181 
6182  // convenience macros
6183  #define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
6184  #define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
6185  #define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
6186  #define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
6187 
6188  #define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
6189  #define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
6190 
6191  static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
6192  {
6193  if( Channel[timer] < 0 )
6194  *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
6195  else{
6196  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
6197  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
6198  }
6199 
6200  Channel[timer]++; // increment to the next channel
6201  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
6202  *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
6203  if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
6204  digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
6205  }
6206  else {
6207  // finished all channels so wait for the refresh period to expire before starting over
6208  if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
6209  *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
6210  else
6211  *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
6212  Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
6213  }
6214  }
6215 
6216  #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
6217  // Interrupt handlers for Arduino
6218  #if defined(_useTimer1)
6219  SIGNAL (TIMER1_COMPA_vect)
6220  {
6221  handle_interrupts(_timer1, &TCNT1, &OCR1A);
6222  }
6223  #endif
6224  #elif defined WIRING
6225  // Interrupt handlers for Wiring
6226  #if defined(_useTimer1)
6227  void Timer1Service()
6228  {
6229  handle_interrupts(_timer1, &TCNT1, &OCR1A);
6230  }
6231  #endif
6232  #endif
6233 
6234  static void initISR(timer16_Sequence_t timer) {
6235  if(timer == _timer1) {
6236  TCCR1A = 0; // normal counting mode
6237  TCCR1B = _BV(CS11); // set prescaler of 8
6238  TCNT1 = 0; // clear the timer count
6239  TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
6240  TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
6241  #if defined(WIRING)
6242  timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
6243  #endif
6244  }
6245  }
6246 
6247  static void finISR(timer16_Sequence_t timer) {
6248  #if defined WIRING // Wiring
6249  if(timer == _timer1) {
6250  TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
6251  timerDetach(TIMER1OUTCOMPAREA_INT);
6252  }
6253  else if(timer == _timer3) {
6254  ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
6255  timerDetach(TIMER3OUTCOMPAREA_INT);
6256  }
6257  #else
6258  //For arduino - in future: call here to a currently undefined function to reset the timer
6259  (void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning
6260  #endif
6261  }
6262 
6263  static boolean isTimerActive(timer16_Sequence_t timer) {
6264  // returns true if any servo is active on this timer
6265  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
6266  if(SERVO(timer,channel).Pin.isActive == true)
6267  return true;
6268  }
6269  return false;
6270  }
6271 
6272  Servo::Servo() {
6273  if( ServoCount < MAX_SERVOS) {
6274  this->servoIndex = ServoCount++; // assign a servo index to this instance
6275  servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
6276  }
6277  else
6278  this->servoIndex = INVALID_SERVO ; // too many servos
6279  }
6280 
6281  uint8_t Servo::attach(int pin) {
6282  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
6283  }
6284 
6285  uint8_t Servo::attach(int pin, int min, int max) {
6286  if(this->servoIndex < MAX_SERVOS ) {
6287  pinMode( pin, OUTPUT) ; // set servo pin to output
6288  servos[this->servoIndex].Pin.nbr = pin;
6289  // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
6290  this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
6291  this->max = (MAX_PULSE_WIDTH - max)/4;
6292  // initialize the timer if it has not already been initialized
6293  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
6294  if(isTimerActive(timer) == false)
6295  initISR(timer);
6296  servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
6297  }
6298  return this->servoIndex ;
6299  }
6300 
6301  void Servo::detach() {
6302  servos[this->servoIndex].Pin.isActive = false;
6303  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
6304  if(isTimerActive(timer) == false) {
6305  finISR(timer);
6306  }
6307  }
6308 
6309  void Servo::write(int value) {
6310  if(value < MIN_PULSE_WIDTH)
6311  { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
6312  if(value < 0) value = 0;
6313  if(value > 180) value = 180;
6314  value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
6315  }
6316  this->writeMicroseconds(value);
6317  }
6318 
6319  void Servo::writeMicroseconds(int value) {
6320  // calculate and store the values for the given channel
6321  byte channel = this->servoIndex;
6322  if( (channel < MAX_SERVOS) ) // ensure channel is valid
6323  {
6324  if( value < SERVO_MIN() ) // ensure pulse width is valid
6325  value = SERVO_MIN();
6326  else if( value > SERVO_MAX() )
6327  value = SERVO_MAX();
6328 
6329  value = value - TRIM_DURATION;
6330  value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
6331 
6332  uint8_t oldSREG = SREG;
6333  cli();
6334  servos[channel].ticks = value;
6335  SREG = oldSREG;
6336  }
6337  }
6338 
6339  inline int Servo::read() // return the value as degrees
6340  {
6341  return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
6342  }
6343 
6344  int Servo::readMicroseconds() {
6345  unsigned int pulsewidth;
6346  if( this->servoIndex != INVALID_SERVO )
6347  pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
6348  else
6349  pulsewidth = 0;
6350 
6351  return pulsewidth;
6352  }
6353 
6354  inline bool Servo::attached() {
6355  return servos[this->servoIndex].Pin.isActive ;
6356  }
6358  #endif
6359 #endif
6360 
6361 #if EBOARD_COPY_AND_PASTE > 0x0
6363  if (_pwmValue!=_OpwmValue){
6364  analogWrite(PIN_MOTOR_SPE,_pwmValue);
6366  }
6367  #ifdef REPT_TASK
6368  rept_task();
6369  #endif
6370  }
6371  #if EBOARD_NANO > 0x0
6372  Servo mainMotor,steerMotor;
6373  #endif
6374  int timer_count = 0;
6375  bool timer_ofl = false;
6376  ISR(TIMER2_OVF_vect) {
6377  timer_count++;
6378  if(timer_count >= EBOARD_PWM_SPE*1000 && !timer_ofl){
6379  timer_ofl = true;
6380  timer_count -= EBOARD_PWM_SPE*1000;
6381  trig_rept_task();
6382  timer_ofl = false;
6383  }
6384  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
6385  }
6386 
6387 
6389  extern int eVirtual_main();
6391 
6393  void setup(void);
6394 
6396  void setup(void) {
6397  //setup of RX and TX should be handled manually - in everyCase ^^
6400  #if EBOARD_DEBUG_MODE > 0x0
6401  Serial.begin(EBOARD_DEBUG_SPEED);
6402  #endif
6403  //this will initialize the interrupt handling!
6404  cli();
6405  TIMSK2 &= ~(1<<TOIE2);
6406  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
6407  TCCR2B &= ~(1<<WGM22);
6408  ASSR &= ~(1<<AS2);
6409  TIMSK2 &= ~(1<<OCIE2A);
6410  TCCR2B |= (1<<CS22);
6411  TCCR2B &= ~((1<<CS21) | (1<<CS20));
6412  TCNT2 = 256 - (int)((float)F_CPU * 0.001 / 64);
6413  TIMSK2 |= (1<<TOIE2);
6414  sei();
6415  #if EBOARD_BLUETOOTH > 0x0
6416  #if (EBOARD_BLUETOOTH > 0x0) && (((PIN_BLUETOOTH_RX==0x13) && (PIN_BLUETOOTH_TX==0x12)) && defined(__AVR_ATmega2560__))
6419  Serial1.begin(38400);
6420  #else
6421  _serial.begin(38400);
6422  #endif
6424  #endif
6425  #if EBOARD_I2C > 0x0
6426  Wire.begin();
6427  #endif
6428  #if EBOARD_SHIFT_REGISTER > 0x0
6429  pinMode(PIN_SHIFT_CLK,OUTPUT);
6430  pinMode(PIN_SHIFT_DAT,OUTPUT);
6431  pinMode(PIN_SHIFT_LAT,OUTPUT);
6432  shiftAll(); //set all to 0
6433  #endif
6434  #if EBOARD_USE_SPI > 0x0 && (EBOARD_NANO == 0)
6435  _servoHandler.begin(); //Setup SPI
6436  #endif
6437  #if EBOARD_NANO > 0x0
6438  mainMotor.attach(EBOARD_NANO_MAIN);
6439  steerMotor.attach(EBOARD_NANO_STEER);
6440  #if EBOARD_DEBUG_MODE > 0x0
6441  Serial.println("Initializing main driving motor (3s)");
6442  #endif
6443  mainMotor.write(90);
6444  delay(3005);
6445  #if EBOARD_DEBUG_MODE > 0x0
6446  Serial.println("Initializing of main driving motor completed");
6447  #endif
6448  #endif
6449  #if EBOARD_DEBUG_MODE > 0x0
6450  Serial.print((char) eVirtual_main());
6451  Serial.println("fin");
6452  #else
6453  eVirtual_main();
6454  #endif
6455  if (STOP) {} //prevent unused error
6456  delay(200);
6457  #if EBOARD_NANO > 0x0
6458  mainMotor.write(90);
6459  #endif
6460  cli(); //disable timers after running the program :D
6461  #if EBOARD_NANO == 0x0
6462  writePWM(0);analogWrite(PIN_MOTOR_SPE,0);
6463  #endif
6464  }
6467  void loop(void);
6469  void loop(void){
6470  //shall be empty
6471  }
6473 
6474 #endif
6475 
6476 #if EBOARD_NANO > 0x0 || defined(DOC)
6477 
6481  inline void set_motor_speed(optVAL_t spe);
6482 
6483 
6488  inline void set_steer_angle(optVAL_t ang);
6489 
6491  inline void set_motor_speed(optVAL_t spe){
6492  if(spe < 0 || spe > 180) return;
6493  mainMotor.write(spe);
6494  }
6495  inline void set_steer_angle(optVAL_t ang){
6496  if(ang < 0 || ang > 180) return;
6497  steerMotor.write(ang);
6498  }
6500 #endif
6501 
6502 #else
6503  #error This library is build for arduino-devices and should be used only in the Arduino IDE or with a similar linking process
6504 #endif
6505 #pragma GCC diagnostic pop
6506 #pragma pack(pop)
6507 
6508 #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